diff --git a/.hgtags b/.hgtags index c0b87cffe37..96eac58d20e 100644 --- a/.hgtags +++ b/.hgtags @@ -349,3 +349,6 @@ f9bcdce2df26678c3fe468130b535c0342c69b89 jdk-9+99 086c682bd8c5f195c324f61e2c61fbcd0226d63b jdk-9+104 db483b34fa7148d257a429acddbde9c13687dcae jdk-9+105 6c644cca3f3fc2763e2ff7d669849a75d34543ba jdk-9+106 +1c076468bf7dad5b8f2ee5dcf66e2279caa3e208 jdk-9+107 +257b579d813201682931d6b42f0445ffe5b4210d jdk-9+108 +c870cb782aca71093d2584376f27f0cfbfec0e3a jdk-9+109 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index aaae670d176..831d5d6213f 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -349,3 +349,6 @@ c4d72a1620835b5d657b7b6792c2879367d0154f jdk-9+101 9a38f8b4ba220708db198d08d82fd2144a64777d jdk-9+104 be58b02c11f90b88c67e4d0e2cb5e4cf2d9b3c57 jdk-9+105 54575d8783b3a39a2d710c28cda675d44261f9d9 jdk-9+106 +4d65eba233a8730f913734a6804910b842d2cb54 jdk-9+107 +c7be2a78c31b3b6132f2f5e9e4b3d3bb1c20245c jdk-9+108 +1787bdaabb2b6f4193406e25a50cb0419ea8e8f3 jdk-9+109 diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index c949c93c5cf..6b08cbb0a4f 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -123,12 +123,16 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], [ # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler + # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder + # commands produced by the link step (currently AIX only) if test "x$TOOLCHAIN_TYPE" = xxlc; then COMPILER_TARGET_BITS_FLAG="-q" COMPILER_COMMAND_FILE_FLAG="-f" + COMPILER_BINDCMD_FILE_FLAG="-bloadmap:" else COMPILER_TARGET_BITS_FLAG="-m" COMPILER_COMMAND_FILE_FLAG="@" + COMPILER_BINDCMD_FILE_FLAG="" # The solstudio linker does not support @-files. if test "x$TOOLCHAIN_TYPE" = xsolstudio; then @@ -152,6 +156,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS], fi AC_SUBST(COMPILER_TARGET_BITS_FLAG) AC_SUBST(COMPILER_COMMAND_FILE_FLAG) + AC_SUBST(COMPILER_BINDCMD_FILE_FLAG) # FIXME: figure out if we should select AR flags depending on OS or toolchain. if test "x$OPENJDK_TARGET_OS" = xmacosx; then @@ -294,10 +299,23 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_LIBS], SET_SHARED_LIBRARY_NAME='-h [$]1' SET_SHARED_LIBRARY_MAPFILE='-M[$]1' elif test "x$TOOLCHAIN_TYPE" = xxlc; then - PICFLAG="-qpic=large" + # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only + # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker + # will have to patch this single instruction with a call to some out-of-order code which + # does the load from the TOC. This is of course slow. But in that case we also would have + # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'. + # With 'qpic=large' the compiler will by default generate a two-instruction sequence which + # can be patched directly by the linker and does not require a jump to out-of-order code. + # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc' + # instead. This creates a distinct TOC for every compilation unit (and thus requires two + # loads for accessing a global variable). But there are rumors that this may be seen as a + # 'performance feature' because of improved code locality of the symbols used in a + # compilation unit. + PICFLAG="-qpic" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" C_FLAG_REORDER='' CXX_FLAG_REORDER='' - SHARED_LIBRARY_FLAGS="-qmkshrobj" + SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry" SET_EXECUTABLE_ORIGIN="" SET_SHARED_LIBRARY_ORIGIN='' SET_SHARED_LIBRARY_NAME='' @@ -835,7 +853,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok" + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" fi @@ -891,6 +909,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK], AC_SUBST(JDKLIB_LIBS) AC_SUBST(JDKEXE_LIBS) AC_SUBST(LDFLAGS_CXX_JDK) + AC_SUBST(LDFLAGS_HASH_STYLE) LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 20d766e7d4e..58beee04e52 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -701,6 +701,7 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG ZERO_ARCHFLAG LDFLAGS_TESTEXE LDFLAGS_TESTLIB +LDFLAGS_HASH_STYLE LDFLAGS_CXX_JDK JDKEXE_LIBS JDKLIB_LIBS @@ -743,6 +744,7 @@ EXE_OUT_OPTION CC_OUT_OPTION STRIPFLAGS ARFLAGS +COMPILER_BINDCMD_FILE_FLAG COMPILER_COMMAND_FILE_FLAG COMPILER_TARGET_BITS_FLAG JT_HOME @@ -4003,7 +4005,7 @@ apt_help() { devkit) PKGHANDLER_COMMAND="sudo apt-get install build-essential" ;; openjdk) - PKGHANDLER_COMMAND="sudo apt-get install openjdk-7-jdk" ;; + PKGHANDLER_COMMAND="sudo apt-get install openjdk-8-jdk" ;; alsa) PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) @@ -4024,7 +4026,7 @@ yum_help() { devkit) PKGHANDLER_COMMAND="sudo yum groupinstall \"Development Tools\"" ;; openjdk) - PKGHANDLER_COMMAND="sudo yum install java-1.7.0-openjdk" ;; + PKGHANDLER_COMMAND="sudo yum install java-1.8.0-openjdk-devel" ;; alsa) PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) @@ -4230,7 +4232,7 @@ pkgadd_help() { # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -4860,7 +4862,7 @@ VS_SDK_PLATFORM_NAME_2013= #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1455271513 +DATE_WHEN_GENERATED=1457684806 ############################################################################### # @@ -15116,6 +15118,10 @@ $as_echo "$COMPILE_TYPE" >&6; } REQUIRED_OS_NAME=Darwin REQUIRED_OS_VERSION=11.2 fi + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + REQUIRED_OS_NAME=AIX + REQUIRED_OS_VERSION=7.1 + fi @@ -45391,12 +45397,16 @@ $as_echo "$tool_specified" >&6; } # COMPILER_TARGET_BITS_FLAG : option for selecting 32- or 64-bit output # COMPILER_COMMAND_FILE_FLAG : option for passing a command file to the compiler + # COMPILER_BINDCMD_FILE_FLAG : option for specifying a file which saves the binder + # commands produced by the link step (currently AIX only) if test "x$TOOLCHAIN_TYPE" = xxlc; then COMPILER_TARGET_BITS_FLAG="-q" COMPILER_COMMAND_FILE_FLAG="-f" + COMPILER_BINDCMD_FILE_FLAG="-bloadmap:" else COMPILER_TARGET_BITS_FLAG="-m" COMPILER_COMMAND_FILE_FLAG="@" + COMPILER_BINDCMD_FILE_FLAG="" # The solstudio linker does not support @-files. if test "x$TOOLCHAIN_TYPE" = xsolstudio; then @@ -45424,6 +45434,7 @@ $as_echo "no" >&6; } + # FIXME: figure out if we should select AR flags depending on OS or toolchain. if test "x$OPENJDK_TARGET_OS" = xmacosx; then ARFLAGS="-r" @@ -46198,10 +46209,23 @@ $as_echo "$ac_cv_c_bigendian" >&6; } SET_SHARED_LIBRARY_NAME='-h $1' SET_SHARED_LIBRARY_MAPFILE='-M$1' elif test "x$TOOLCHAIN_TYPE" = xxlc; then - PICFLAG="-qpic=large" + # '-qpic' defaults to 'qpic=small'. This means that the compiler generates only + # one instruction for accessing the TOC. If the TOC grows larger than 64K, the linker + # will have to patch this single instruction with a call to some out-of-order code which + # does the load from the TOC. This is of course slow. But in that case we also would have + # to use '-bbigtoc' for linking anyway so we could also change the PICFLAG to 'qpic=large'. + # With 'qpic=large' the compiler will by default generate a two-instruction sequence which + # can be patched directly by the linker and does not require a jump to out-of-order code. + # Another alternative instead of using 'qpic=large -bbigtoc' may be to use '-qminimaltoc' + # instead. This creates a distinct TOC for every compilation unit (and thus requires two + # loads for accessing a global variable). But there are rumors that this may be seen as a + # 'performance feature' because of improved code locality of the symbols used in a + # compilation unit. + PICFLAG="-qpic" + JVM_CFLAGS="$JVM_CFLAGS $PICFLAG" C_FLAG_REORDER='' CXX_FLAG_REORDER='' - SHARED_LIBRARY_FLAGS="-qmkshrobj" + SHARED_LIBRARY_FLAGS="-qmkshrobj -bM:SRE -bnoentry" SET_EXECUTABLE_ORIGIN="" SET_SHARED_LIBRARY_ORIGIN='' SET_SHARED_LIBRARY_NAME='' @@ -46824,7 +46848,7 @@ $as_echo "$supports" >&6; } LDFLAGS_CXX_SOLSTUDIO="-norunpath" LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK $LDFLAGS_CXX_SOLSTUDIO -xnolib" elif test "x$TOOLCHAIN_TYPE" = xxlc; then - LDFLAGS_XLC="-brtl -bnolibpath -bexpall -bernotok" + LDFLAGS_XLC="-b64 -brtl -bnolibpath -bexpall -bernotok" LDFLAGS_JDK="${LDFLAGS_JDK} $LDFLAGS_XLC" fi @@ -46881,6 +46905,7 @@ $as_echo "$supports" >&6; } + LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB" LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE" @@ -58630,7 +58655,8 @@ fi # Setup libm (the maths library) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 + if test "x$OPENJDK_TARGET_OS" != "xwindows"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for cos in -lm" >&5 $as_echo_n "checking for cos in -lm... " >&6; } if ${ac_cv_lib_m_cos+:} false; then : $as_echo_n "(cached) " >&6 @@ -58675,12 +58701,15 @@ _ACEOF else - { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: Maths library was not found" >&5 $as_echo "$as_me: Maths library was not found" >&6;} fi - LIBM=-lm + LIBM="-lm" + else + LIBM="" + fi # Setup libdl (for dynamic library loading) diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index e266dbf414b..d0892c56256 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -106,7 +106,7 @@ apt_help() { devkit) PKGHANDLER_COMMAND="sudo apt-get install build-essential" ;; openjdk) - PKGHANDLER_COMMAND="sudo apt-get install openjdk-7-jdk" ;; + PKGHANDLER_COMMAND="sudo apt-get install openjdk-8-jdk" ;; alsa) PKGHANDLER_COMMAND="sudo apt-get install libasound2-dev" ;; cups) @@ -127,7 +127,7 @@ yum_help() { devkit) PKGHANDLER_COMMAND="sudo yum groupinstall \"Development Tools\"" ;; openjdk) - PKGHANDLER_COMMAND="sudo yum install java-1.7.0-openjdk" ;; + PKGHANDLER_COMMAND="sudo yum install java-1.8.0-openjdk-devel" ;; alsa) PKGHANDLER_COMMAND="sudo yum install alsa-lib-devel" ;; cups) diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index 7bae405555e..a6a8bd4f19b 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -160,10 +160,14 @@ AC_DEFUN_ONCE([LIB_SETUP_LLVM], AC_DEFUN_ONCE([LIB_SETUP_MISC_LIBS], [ # Setup libm (the maths library) - AC_CHECK_LIB(m, cos, [], [ - AC_MSG_NOTICE([Maths library was not found]) - ]) - LIBM=-lm + if test "x$OPENJDK_TARGET_OS" != "xwindows"; then + AC_CHECK_LIB(m, cos, [], [ + AC_MSG_NOTICE([Maths library was not found]) + ]) + LIBM="-lm" + else + LIBM="" + fi AC_SUBST(LIBM) # Setup libdl (for dynamic library loading) diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 3b7e3e33e5d..7553dfe0323 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -406,6 +406,10 @@ AC_DEFUN([PLATFORM_SET_RELEASE_FILE_OS_VALUES], REQUIRED_OS_NAME=Darwin REQUIRED_OS_VERSION=11.2 fi + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + REQUIRED_OS_NAME=AIX + REQUIRED_OS_VERSION=7.1 + fi AC_SUBST(REQUIRED_OS_NAME) AC_SUBST(REQUIRED_OS_VERSION) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 2a6c872cf27..d8322ebce9c 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -314,6 +314,10 @@ COMPILER_SUPPORTS_TARGET_BITS_FLAG=@COMPILER_SUPPORTS_TARGET_BITS_FLAG@ # Option used to pass a command file to the compiler COMPILER_COMMAND_FILE_FLAG:=@COMPILER_COMMAND_FILE_FLAG@ +# Option for specifying a file which saves the binder commands +# produced by the link step (for debugging, currently AIX only) +COMPILER_BINDCMD_FILE_FLAG:=@COMPILER_BINDCMD_FILE_FLAG@ + CC_OUT_OPTION:=@CC_OUT_OPTION@ EXE_OUT_OPTION:=@EXE_OUT_OPTION@ LD_OUT_OPTION:=@LD_OUT_OPTION@ @@ -351,6 +355,8 @@ CXXFLAGS_JDKLIB:=@CXXFLAGS_JDKLIB@ CFLAGS_JDKEXE:=@CFLAGS_JDKEXE@ CXXFLAGS_JDKEXE:=@CXXFLAGS_JDKEXE@ +LDFLAGS_HASH_STYLE := @LDFLAGS_HASH_STYLE@ + CXX:=@FIXPATH@ @CCACHE@ @ICECC@ @CXX@ CPP:=@FIXPATH@ @CPP@ diff --git a/common/bin/compare_exceptions.sh.incl b/common/bin/compare_exceptions.sh.incl index fb68ede81d4..30ae49c6fc1 100644 --- a/common/bin/compare_exceptions.sh.incl +++ b/common/bin/compare_exceptions.sh.incl @@ -185,7 +185,6 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "x86_64" ]; ./lib/amd64/libjava.so ./lib/amd64/libjawt.so ./lib/amd64/libjdwp.so - ./lib/amd64/libjfr.so ./lib/amd64/libjpeg.so ./lib/amd64/libjsdt.so ./lib/amd64/libjsound.so @@ -321,7 +320,6 @@ if [ "$OPENJDK_TARGET_OS" = "solaris" ] && [ "$OPENJDK_TARGET_CPU" = "sparcv9" ] ./lib/sparcv9/libjava.so ./lib/sparcv9/libjawt.so ./lib/sparcv9/libjdwp.so - ./lib/sparcv9/libjfr.so ./lib/sparcv9/libjpeg.so ./lib/sparcv9/libjsdt.so ./lib/sparcv9/libjsound.so diff --git a/common/bin/unshuffle_list.txt b/common/bin/unshuffle_list.txt index a419fe43a57..daa919b9444 100644 --- a/common/bin/unshuffle_list.txt +++ b/common/bin/unshuffle_list.txt @@ -1293,12 +1293,8 @@ jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.c : jdk/src/win jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/j2secmod_md.h : jdk/src/windows/native/sun/security/pkcs11/j2secmod_md.h jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.c : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.c jdk/src/jdk.crypto.pkcs11/windows/native/libj2pkcs11/p11_md.h : jdk/src/windows/native/sun/security/pkcs11/wrapper/p11_md.h -jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html : jdk/src/macosx/classes/com/apple/concurrent/package.html -jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent : jdk/src/macosx/classes/com/apple/concurrent -jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m : jdk/src/macosx/native/com/apple/concurrent/Dispatch.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/JavaAppLauncher.m : jdk/src/macosx/native/apple/launcher/JavaAppLauncher.m -jdk/src/jdk.deploy.osx/macosx/native/libosx/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m +jdk/src/java.desktop/macosx/native/libosx/CFileManager.m : jdk/src/macosx/native/com/apple/eio/CFileManager.m +jdk/src/java.base/macosx/native/libosxsecurity/KeystoreImpl.m : jdk/src/macosx/native/apple/security/KeystoreImpl.m jdk/src/jdk.hprof.agent/share/classes/com/sun/demo/jvmti/hprof : jdk/src/share/classes/com/sun/demo/jvmti/hprof jdk/src/jdk.httpserver/share/classes/com/sun/net/httpserver : jdk/src/share/classes/com/sun/net/httpserver jdk/src/jdk.httpserver/share/classes/sun/net/httpserver : jdk/src/share/classes/sun/net/httpserver diff --git a/common/conf/jib-profiles.js b/common/conf/jib-profiles.js index 926fb9d5424..48519cfbe74 100644 --- a/common/conf/jib-profiles.js +++ b/common/conf/jib-profiles.js @@ -311,6 +311,16 @@ var getJibProfilesProfiles = function (input, common) { labels: [ "open" ] }, + "linux-x86-open": { + target_os: mainProfiles["linux-x86"].target_os, + target_cpu: mainProfiles["linux-x86"].target_cpu, + dependencies: mainProfiles["linux-x86"].dependencies, + configure_args: concat(mainProfiles["linux-x86"].configure_args, + "--enable-openjdk-only"), + make_args: mainProfiles["linux-x86"].make_args, + labels: [ "open" ] + }, + "solaris-x64-open": { target_os: mainProfiles["solaris-x64"].target_os, target_cpu: mainProfiles["solaris-x64"].target_cpu, @@ -319,6 +329,16 @@ var getJibProfilesProfiles = function (input, common) { "--enable-openjdk-only"), make_args: mainProfiles["solaris-x64"].make_args, labels: [ "open" ] + }, + + "windows-x86-open": { + target_os: mainProfiles["windows-x86"].target_os, + target_cpu: mainProfiles["windows-x86"].target_cpu, + dependencies: mainProfiles["windows-x86"].dependencies, + configure_args: concat(mainProfiles["windows-x86"].configure_args, + "--enable-openjdk-only"), + make_args: mainProfiles["windows-x86"].make_args, + labels: [ "open" ] } }; profiles = concatObjects(profiles, jprtOpenProfiles); diff --git a/corba/.hgtags b/corba/.hgtags index 88b455ba6fb..5c2b765d93d 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -349,3 +349,6 @@ ea285530245cf4e0edf0479121a41347d3030eba jdk-9+98 e385e95e6101711d5c63e7b1a827e99b6ec7a1cc jdk-9+104 64006ae915b3aa85ac7e6fac679024d2da7fe526 jdk-9+105 8ec4f97943fe56f93e4621f622b56b7144c0181a jdk-9+106 +49202432b69445164a42be7cbdf74ed5fce98157 jdk-9+107 +84f2862a25eb3232ff36c376b4e2bf2a83dfced3 jdk-9+108 +b75afa17aefe480c23c616a6a2497063312f7189 jdk-9+109 diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 30bbd8fe337..cbe0b715f78 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -509,3 +509,6 @@ c5f55130b1b69510d9a6f4a3105b58e21cd7ffe1 jdk-9+103 534c50395957c6025fb6627e93b35756f8d48a08 jdk-9+104 266fa9bb5297bf02cb2a7b038b10a109817d2b48 jdk-9+105 7232de4c17c37f60aecec4f3191090bd3d41d334 jdk-9+106 +c5146d4da417f76edfc43097d2e2ced042a65b4e jdk-9+107 +934f6793f5f7dca44f69b4559d525fa64b31840d jdk-9+108 +7e7e50ac4faf19899fc811569e32cfa478759ebb jdk-9+109 diff --git a/hotspot/make/aix/makefiles/trace.make b/hotspot/make/aix/makefiles/trace.make index c00b0e3383a..549acb21190 100644 --- a/hotspot/make/aix/makefiles/trace.make +++ b/hotspot/make/aix/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,6 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -100,9 +95,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/bsd/makefiles/amd64.make b/hotspot/make/bsd/makefiles/amd64.make index ecdac17ee3a..6512375259e 100644 --- a/hotspot/make/bsd/makefiles/amd64.make +++ b/hotspot/make/bsd/makefiles/amd64.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -37,3 +37,11 @@ ifndef USE_SUNCC endif OPT_CFLAGS/compactingPermGenGen.o = -O1 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/sharedRuntimeTrig.o += -g + OPT_CFLAGS/sharedRuntimeTrans.o += -g + OPT_CFLAGS/compactingPermGenGen.o += -g +endif diff --git a/hotspot/make/bsd/makefiles/arm.make b/hotspot/make/bsd/makefiles/arm.make index f35f70a579b..9e6fdd5abae 100644 --- a/hotspot/make/bsd/makefiles/arm.make +++ b/hotspot/make/bsd/makefiles/arm.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -24,8 +24,4 @@ Obj_Files += bsd_arm.o -ifneq ($(EXT_LIBS_PATH),) - LIBS += $(EXT_LIBS_PATH)/sflt_glibc.a -endif - CFLAGS += -DVM_LITTLE_ENDIAN diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index 05a07052963..1bf6521a892 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -330,6 +330,13 @@ ifeq ($(USE_CLANG), true) ), 1) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) OPT_CFLAGS/unsafe.o += -O1 + + # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides + # of OPT_CFLAGS. Restore it here. + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/loopTransform.o += -g + OPT_CFLAGS/unsafe.o += -g + endif else $(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)") endif diff --git a/hotspot/make/bsd/makefiles/trace.make b/hotspot/make/bsd/makefiles/trace.make index c7ef3d8ea01..88f17a7326e 100644 --- a/hotspot/make/bsd/makefiles/trace.make +++ b/hotspot/make/bsd/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,6 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif @@ -101,9 +96,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/linux/makefiles/amd64.make b/hotspot/make/linux/makefiles/amd64.make index 2b77dbab605..c98a5827820 100644 --- a/hotspot/make/linux/makefiles/amd64.make +++ b/hotspot/make/linux/makefiles/amd64.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,3 +32,11 @@ CFLAGS += -DVM_LITTLE_ENDIAN CFLAGS += -D_LP64=1 OPT_CFLAGS/compactingPermGenGen.o = -O1 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/sharedRuntimeTrig.o += -g + OPT_CFLAGS/sharedRuntimeTrans.o += -g + OPT_CFLAGS/compactingPermGenGen.o += -g +endif diff --git a/hotspot/make/linux/makefiles/gcc.make b/hotspot/make/linux/makefiles/gcc.make index c8ee95d932b..a2e5c6c03b6 100644 --- a/hotspot/make/linux/makefiles/gcc.make +++ b/hotspot/make/linux/makefiles/gcc.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -265,6 +265,11 @@ ifeq "$(shell expr \( $(CC_VER_MAJOR) \> 4 \) \| \( \( $(CC_VER_MAJOR) = 4 \) \& # GCC >= 4.3 # Gcc 4.1.2 does not support this flag, nor does it have problems compiling the file. OPT_CFLAGS/vmStructs.o += -fno-var-tracking-assignments + # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides + # of OPT_CFLAGS. Restore it here. + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/vmStructs.o += -g + endif endif # The gcc compiler segv's on ia64 when compiling bytecodeInterpreter.cpp @@ -277,6 +282,11 @@ endif ifeq ($(USE_CLANG), true) ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) + # The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides + # of OPT_CFLAGS. Restore it here. + ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/loopTransform.o += -g + endif endif else # Do not allow GCC 4.1.1 diff --git a/hotspot/make/linux/makefiles/i486.make b/hotspot/make/linux/makefiles/i486.make index 86e825d3e9d..a1adda6477c 100644 --- a/hotspot/make/linux/makefiles/i486.make +++ b/hotspot/make/linux/makefiles/i486.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -32,3 +32,11 @@ OPT_CFLAGS/sharedRuntimeTrans.o = $(OPT_CFLAGS/NOOPT) CFLAGS += -DVM_LITTLE_ENDIAN OPT_CFLAGS/compactingPermGenGen.o = -O1 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/sharedRuntimeTrig.o += -g + OPT_CFLAGS/sharedRuntimeTrans.o += -g + OPT_CFLAGS/compactingPermGenGen.o += -g +endif diff --git a/hotspot/make/linux/makefiles/trace.make b/hotspot/make/linux/makefiles/trace.make index 7218adc27b3..229b68c434b 100644 --- a/hotspot/make/linux/makefiles/trace.make +++ b/hotspot/make/linux/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -57,11 +57,6 @@ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ traceEventControl.hpp - -ifneq ($(INCLUDE_TRACE), false) -TraceGeneratedNames += traceProducer.cpp -endif - endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -100,9 +95,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/linux/makefiles/zeroshark.make b/hotspot/make/linux/makefiles/zeroshark.make index 240946fee3a..4f9a70c98fa 100644 --- a/hotspot/make/linux/makefiles/zeroshark.make +++ b/hotspot/make/linux/makefiles/zeroshark.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # Copyright 2007, 2008 Red Hat, Inc. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # @@ -29,12 +29,6 @@ ifeq ($(USE_CLANG), true) WARNING_FLAGS += -Wno-undef endif -# Suppress some warning flags that are normally turned on for hotspot, -# because some of the zero code has not been updated accordingly. -WARNING_FLAGS += -Wno-return-type \ - -Wno-format-nonliteral -Wno-format-security \ - -Wno-maybe-uninitialized - # The copied fdlibm routines in sharedRuntimeTrig.o must not be optimized OPT_CFLAGS/sharedRuntimeTrig.o = $(OPT_CFLAGS/NOOPT) diff --git a/hotspot/make/solaris/makefiles/amd64.make b/hotspot/make/solaris/makefiles/amd64.make index f88d743fe7c..3eb6dee9b92 100644 --- a/hotspot/make/solaris/makefiles/amd64.make +++ b/hotspot/make/solaris/makefiles/amd64.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,14 @@ ifeq ("${Platform_compiler}", "sparcWorks") OPT_CFLAGS/generateOptoStub.o = -xO2 # Temporary util SS12u1 C++ compiler is fixed OPT_CFLAGS/c1_LinearScan.o = -xO2 + +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/generateOptoStub.o += -g0 -xs + OPT_CFLAGS/c1_LinearScan.o += -g0 -xs +endif + else ifeq ("${Platform_compiler}", "gcc") diff --git a/hotspot/make/solaris/makefiles/product.make b/hotspot/make/solaris/makefiles/product.make index 7f378b17d95..b36159fdcc8 100644 --- a/hotspot/make/solaris/makefiles/product.make +++ b/hotspot/make/solaris/makefiles/product.make @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -35,11 +35,21 @@ OPT_CFLAGS/BYFILE = $(OPT_CFLAGS/$@)$(OPT_CFLAGS/DEFAULT$(OPT_CFLAGS/$@)) # for this method for now. (fix this when dtrace bug 6258412 is fixed) ifndef USE_GCC OPT_CFLAGS/ciEnv.o = $(OPT_CFLAGS) -xinline=no%__1cFciEnvbFpost_compiled_method_load_event6MpnHnmethod__v_ +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/ciEnv.o += -g0 -xs +endif endif # Need extra inlining to get oop_ps_push_contents functions to perform well enough. ifndef USE_GCC OPT_CFLAGS/psPromotionManager.o = $(OPT_CFLAGS) -W2,-Ainline:inc=1000 +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/psPromotionManager.o += -g0 -xs +endif endif # (OPT_CFLAGS/SLOWER is also available, to alter compilation of buggy files) @@ -55,6 +65,12 @@ endif # COMPILER_REV_NUMERIC == 510 ifeq ($(shell expr $(COMPILER_REV_NUMERIC) \>= 509), 1) # dtrace cannot handle tail call optimization (6672627, 6693876) OPT_CFLAGS/jni.o = $(OPT_CFLAGS/DEFAULT) $(OPT_CCFLAGS/NO_TAIL_CALL_OPT) +# The -g0 -xs flag is added to OPT_CFLAGS in sparcWorks.make, but lost in case of +# per-file overrides of OPT_CFLAGS. Restore it here. This is mainly needed +# to provide a good baseline to compare the new build against. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/jni.o += -g0 -xs +endif endif # COMPILER_NUMERIC_REV >= 509 # Workaround SS11 bug 6345274 (all platforms) (Fixed in SS11 patch and SS12) diff --git a/hotspot/make/solaris/makefiles/sparcWorks.make b/hotspot/make/solaris/makefiles/sparcWorks.make index cbd902ef0fe..5c66b2f3d20 100644 --- a/hotspot/make/solaris/makefiles/sparcWorks.make +++ b/hotspot/make/solaris/makefiles/sparcWorks.make @@ -158,9 +158,20 @@ OPT_CFLAGS/NO_TAIL_CALL_OPT = -Wu,-O~yz OPT_CCFLAGS/NO_TAIL_CALL_OPT = -Qoption ube -O~yz OPT_CFLAGS/stubGenerator_x86_32.o = $(OPT_CFLAGS) -xspace OPT_CFLAGS/stubGenerator_x86_64.o = $(OPT_CFLAGS) -xspace +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/stubGenerator_x86_32.o += -g0 -xs + OPT_CFLAGS/stubGenerator_x86_64.o += -g0 -xs +endif endif # Platform_arch == x86 ifeq ("${Platform_arch}", "sparc") OPT_CFLAGS/stubGenerator_sparc.o = $(OPT_CFLAGS) -xspace +# The debug flag is added to OPT_CFLAGS, but lost in case of per-file overrides +# of OPT_CFLAGS. Restore it here. +ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1) + OPT_CFLAGS/stubGenerator_sparc.o += -g0 -xs +endif endif endif # COMPILER_REV_NUMERIC >= 509 diff --git a/hotspot/make/solaris/makefiles/trace.make b/hotspot/make/solaris/makefiles/trace.make index ab96c7ffd65..09979558ea7 100644 --- a/hotspot/make/solaris/makefiles/trace.make +++ b/hotspot/make/solaris/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -56,8 +56,7 @@ TraceGeneratedNames = \ ifeq ($(HAS_ALT_SRC), true) TraceGeneratedNames += \ traceRequestables.hpp \ - traceEventControl.hpp \ - traceProducer.cpp + traceEventControl.hpp endif TraceGeneratedFiles = $(TraceGeneratedNames:%=$(TraceOutDir)/%) @@ -96,9 +95,6 @@ else $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceEventClasses.xsl $(XML_DEPS) $(GENERATE_CODE) -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - $(GENERATE_CODE) - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) $(GENERATE_CODE) diff --git a/hotspot/make/windows/makefiles/trace.make b/hotspot/make/windows/makefiles/trace.make index 58fee24653c..b32646e3310 100644 --- a/hotspot/make/windows/makefiles/trace.make +++ b/hotspot/make/windows/makefiles/trace.make @@ -1,5 +1,5 @@ # -# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,7 @@ TraceGeneratedNames = \ !if EXISTS($(TraceAltSrcDir)) TraceGeneratedNames = $(TraceGeneratedNames) \ traceRequestables.hpp \ - traceEventControl.hpp \ - traceProducer.cpp + traceEventControl.hpp !endif @@ -58,8 +57,7 @@ TraceGeneratedFiles = \ !if EXISTS($(TraceAltSrcDir)) TraceGeneratedFiles = $(TraceGeneratedFiles) \ $(TraceOutDir)/traceRequestables.hpp \ - $(TraceOutDir)/traceEventControl.hpp \ - $(TraceOutDir)/traceProducer.cpp + $(TraceOutDir)/traceEventControl.hpp !endif XSLT = $(QUIETLY) $(REMOTE) $(RUN_JAVA) -classpath $(JvmtiOutDir) jvmtiGen @@ -98,10 +96,6 @@ $(TraceOutDir)/traceEventClasses.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir) @echo Generating AltSrc $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceEventClasses.xsl -OUT $(TraceOutDir)/traceEventClasses.hpp -$(TraceOutDir)/traceProducer.cpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceProducer.xsl $(XML_DEPS) - @echo Generating AltSrc $@ - @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceProducer.xsl -OUT $(TraceOutDir)/traceProducer.cpp - $(TraceOutDir)/traceRequestables.hpp: $(TraceSrcDir)/trace.xml $(TraceAltSrcDir)/traceRequestables.xsl $(XML_DEPS) @echo Generating AltSrc $@ @$(XSLT) -IN $(TraceSrcDir)/trace.xml -XSL $(TraceAltSrcDir)/traceRequestables.xsl -OUT $(TraceOutDir)/traceRequestables.hpp diff --git a/hotspot/src/cpu/aarch64/vm/aarch64.ad b/hotspot/src/cpu/aarch64/vm/aarch64.ad index 18ba1e44cf3..3288fbedfb8 100644 --- a/hotspot/src/cpu/aarch64/vm/aarch64.ad +++ b/hotspot/src/cpu/aarch64/vm/aarch64.ad @@ -3425,9 +3425,6 @@ const bool Matcher::misaligned_vectors_ok() { // false => size gets scaled to BytesPerLong, ok. const bool Matcher::init_array_count_is_in_bytes = false; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 18 * BytesPerLong; - // Use conditional move (CMOVL) const int Matcher::long_cmove_cost() { // long cmoves are no more expensive than int cmoves @@ -4135,14 +4132,14 @@ encode %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldxr, &MacroAssembler::cmp, &Assembler::stlxr); + Assembler::xword, /*acquire*/ false, /*release*/ true); %} enc_class aarch64_enc_cmpxchgw(memory mem, iRegINoSp oldval, iRegINoSp newval) %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldxrw, &MacroAssembler::cmpw, &Assembler::stlxrw); + Assembler::word, /*acquire*/ false, /*release*/ true); %} @@ -4154,14 +4151,14 @@ encode %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldaxr, &MacroAssembler::cmp, &Assembler::stlxr); + Assembler::xword, /*acquire*/ true, /*release*/ true); %} enc_class aarch64_enc_cmpxchgw_acq(memory mem, iRegINoSp oldval, iRegINoSp newval) %{ MacroAssembler _masm(&cbuf); guarantee($mem$$index == -1 && $mem$$disp == 0, "impossible encoding"); __ cmpxchg($mem$$base$$Register, $oldval$$Register, $newval$$Register, - &Assembler::ldaxrw, &MacroAssembler::cmpw, &Assembler::stlxrw); + Assembler::word, /*acquire*/ true, /*release*/ true); %} @@ -4679,8 +4676,14 @@ encode %{ // Compare object markOop with mark and if equal exchange scratch1 // with object markOop. - { + if (UseLSE) { + __ mov(tmp, disp_hdr); + __ casal(Assembler::xword, tmp, box, oop); + __ cmp(tmp, disp_hdr); + __ br(Assembler::EQ, cont); + } else { Label retry_load; + __ prfm(Address(oop), PSTL1STRM); __ bind(retry_load); __ ldaxr(tmp, oop); __ cmp(tmp, disp_hdr); @@ -4729,8 +4732,13 @@ encode %{ __ add(tmp, disp_hdr, (ObjectMonitor::owner_offset_in_bytes()-markOopDesc::monitor_value)); __ mov(disp_hdr, zr); - { + if (UseLSE) { + __ mov(rscratch1, disp_hdr); + __ casal(Assembler::xword, rscratch1, rthread, tmp); + __ cmp(rscratch1, disp_hdr); + } else { Label retry_load, fail; + __ prfm(Address(tmp), PSTL1STRM); __ bind(retry_load); __ ldaxr(rscratch1, tmp); __ cmp(disp_hdr, rscratch1); @@ -4818,8 +4826,13 @@ encode %{ // see the stack address of the basicLock in the markOop of the // object. - { + if (UseLSE) { + __ mov(tmp, box); + __ casl(Assembler::xword, tmp, disp_hdr, oop); + __ cmp(tmp, box); + } else { Label retry_load; + __ prfm(Address(oop), PSTL1STRM); __ bind(retry_load); __ ldxr(tmp, oop); __ cmp(box, tmp); @@ -13281,7 +13294,7 @@ instruct MoveF2I_reg_reg(iRegINoSp dst, vRegF src) %{ __ fmovs($dst$$Register, as_FloatRegister($src$$reg)); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_f2i); %} @@ -13299,7 +13312,7 @@ instruct MoveI2F_reg_reg(vRegF dst, iRegI src) %{ __ fmovs(as_FloatRegister($dst$$reg), $src$$Register); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_i2f); %} @@ -13317,7 +13330,7 @@ instruct MoveD2L_reg_reg(iRegLNoSp dst, vRegD src) %{ __ fmovd($dst$$Register, as_FloatRegister($src$$reg)); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_d2l); %} @@ -13335,7 +13348,7 @@ instruct MoveL2D_reg_reg(vRegD dst, iRegL src) %{ __ fmovd(as_FloatRegister($dst$$reg), $src$$Register); %} - ins_pipe(pipe_class_memory); + ins_pipe(fp_l2d); %} @@ -14191,6 +14204,25 @@ instruct cmpP_imm0_branch(cmpOp cmp, iRegP op1, immP0 op2, label labl, rFlagsReg ins_pipe(pipe_cmp_branch); %} +instruct cmpN_imm0_branch(cmpOp cmp, iRegN op1, immN0 op2, label labl, rFlagsReg cr) %{ + match(If cmp (CmpN op1 op2)); + predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne + || n->in(1)->as_Bool()->_test._test == BoolTest::eq); + effect(USE labl); + + ins_cost(BRANCH_COST); + format %{ "cbw$cmp $op1, $labl" %} + ins_encode %{ + Label* L = $labl$$label; + Assembler::Condition cond = (Assembler::Condition)$cmp$$cmpcode; + if (cond == Assembler::EQ) + __ cbzw($op1$$Register, *L); + else + __ cbnzw($op1$$Register, *L); + %} + ins_pipe(pipe_cmp_branch); +%} + instruct cmpP_narrowOop_imm0_branch(cmpOp cmp, iRegN oop, immP0 zero, label labl, rFlagsReg cr) %{ match(If cmp (CmpP (DecodeN oop) zero)); predicate(n->in(1)->as_Bool()->_test._test == BoolTest::ne @@ -14783,19 +14815,19 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, %} instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt, - iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr) + iRegI_R0 result, rFlagsReg cr) %{ predicate(!CompactStrings); match(Set result (StrEquals (Binary str1 str2) cnt)); - effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); + effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr); - format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %} + format %{ "String Equals $str1,$str2,$cnt -> $result" %} ins_encode %{ // Count is in 8-bit bytes; non-Compact chars are 16 bits. __ asrw($cnt$$Register, $cnt$$Register, 1); - __ string_equals($str1$$Register, $str2$$Register, - $cnt$$Register, $result$$Register, - $tmp$$Register); + __ arrays_equals($str1$$Register, $str2$$Register, + $result$$Register, $cnt$$Register, + 2, /*is_string*/true); %} ins_pipe(pipe_class_memory); %} @@ -14809,9 +14841,10 @@ instruct array_equalsB(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} ins_encode %{ - __ byte_arrays_equals($ary1$$Register, $ary2$$Register, - $result$$Register, $tmp$$Register); - %} + __ arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, + 1, /*is_string*/false); + %} ins_pipe(pipe_class_memory); %} @@ -14824,12 +14857,14 @@ instruct array_equalsC(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result, format %{ "Array Equals $ary1,ary2 -> $result // KILL $tmp" %} ins_encode %{ - __ char_arrays_equals($ary1$$Register, $ary2$$Register, - $result$$Register, $tmp$$Register); + __ arrays_equals($ary1$$Register, $ary2$$Register, + $result$$Register, $tmp$$Register, + 2, /*is_string*/false); %} ins_pipe(pipe_class_memory); %} + // encode char[] to byte[] in ISO_8859_1 instruct encode_iso_array(iRegP_R2 src, iRegP_R1 dst, iRegI_R3 len, vRegD_V0 Vtmp1, vRegD_V1 Vtmp2, @@ -16480,7 +16515,7 @@ instruct vsll2I(vecD dst, vecD src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift64_imm); + ins_pipe(vshift64); %} instruct vsll4I(vecX dst, vecX src, vecX shift) %{ @@ -16494,7 +16529,7 @@ instruct vsll4I(vecX dst, vecX src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift128_imm); + ins_pipe(vshift128); %} instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ @@ -16507,7 +16542,7 @@ instruct vsrl2I(vecD dst, vecD src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift64_imm); + ins_pipe(vshift64); %} instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ @@ -16520,7 +16555,7 @@ instruct vsrl4I(vecX dst, vecX src, vecX shift) %{ as_FloatRegister($src$$reg), as_FloatRegister($shift$$reg)); %} - ins_pipe(vshift128_imm); + ins_pipe(vshift128); %} instruct vsll2I_imm(vecD dst, vecD src, immI shift) %{ @@ -16638,7 +16673,7 @@ instruct vsll2L_imm(vecX dst, vecX src, immI shift) %{ as_FloatRegister($src$$reg), (int)$shift$$constant & 63); %} - ins_pipe(vshift128); + ins_pipe(vshift128_imm); %} instruct vsra2L_imm(vecX dst, vecX src, immI shift) %{ diff --git a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp index ca617716562..85e0f2e4eca 100644 --- a/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/assembler_aarch64.hpp @@ -972,7 +972,7 @@ public: // System void system(int op0, int op1, int CRn, int CRm, int op2, - Register rt = (Register)0b11111) + Register rt = dummy_reg) { starti; f(0b11010101000, 31, 21); @@ -1082,7 +1082,7 @@ public: #define INSN(NAME, opc) \ void NAME() { \ - branch_reg((Register)0b11111, opc); \ + branch_reg(dummy_reg, opc); \ } INSN(eret, 0b0100); @@ -1094,10 +1094,22 @@ public: enum operand_size { byte, halfword, word, xword }; void load_store_exclusive(Register Rs, Register Rt1, Register Rt2, - Register Rn, enum operand_size sz, int op, int o0) { + Register Rn, enum operand_size sz, int op, bool ordered) { starti; f(sz, 31, 30), f(0b001000, 29, 24), f(op, 23, 21); - rf(Rs, 16), f(o0, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0); + rf(Rs, 16), f(ordered, 15), rf(Rt2, 10), rf(Rn, 5), rf(Rt1, 0); + } + + void load_exclusive(Register dst, Register addr, + enum operand_size sz, bool ordered) { + load_store_exclusive(dummy_reg, dst, dummy_reg, addr, + sz, 0b010, ordered); + } + + void store_exclusive(Register status, Register new_val, Register addr, + enum operand_size sz, bool ordered) { + load_store_exclusive(status, new_val, dummy_reg, addr, + sz, 0b000, ordered); } #define INSN4(NAME, sz, op, o0) /* Four registers */ \ @@ -1109,19 +1121,19 @@ public: #define INSN3(NAME, sz, op, o0) /* Three registers */ \ void NAME(Register Rs, Register Rt, Register Rn) { \ guarantee(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ - load_store_exclusive(Rs, Rt, (Register)0b11111, Rn, sz, op, o0); \ + load_store_exclusive(Rs, Rt, dummy_reg, Rn, sz, op, o0); \ } #define INSN2(NAME, sz, op, o0) /* Two registers */ \ void NAME(Register Rt, Register Rn) { \ - load_store_exclusive((Register)0b11111, Rt, (Register)0b11111, \ + load_store_exclusive(dummy_reg, Rt, dummy_reg, \ Rn, sz, op, o0); \ } #define INSN_FOO(NAME, sz, op, o0) /* Three registers, encoded differently */ \ void NAME(Register Rt1, Register Rt2, Register Rn) { \ guarantee(Rt1 != Rt2, "unpredictable instruction"); \ - load_store_exclusive((Register)0b11111, Rt1, Rt2, Rn, sz, op, o0); \ + load_store_exclusive(dummy_reg, Rt1, Rt2, Rn, sz, op, o0); \ } // bytes @@ -1169,6 +1181,46 @@ public: #undef INSN4 #undef INSN_FOO + // 8.1 Compare and swap extensions + void lse_cas(Register Rs, Register Rt, Register Rn, + enum operand_size sz, bool a, bool r, bool not_pair) { + starti; + if (! not_pair) { // Pair + assert(sz == word || sz == xword, "invalid size"); + /* The size bit is in bit 30, not 31 */ + sz = (operand_size)(sz == word ? 0b00:0b01); + } + f(sz, 31, 30), f(0b001000, 29, 24), f(1, 23), f(a, 22), f(1, 21); + rf(Rs, 16), f(r, 15), f(0b11111, 14, 10), rf(Rn, 5), rf(Rt, 0); + } + + // CAS +#define INSN(NAME, a, r) \ + void NAME(operand_size sz, Register Rs, Register Rt, Register Rn) { \ + assert(Rs != Rn && Rs != Rt, "unpredictable instruction"); \ + lse_cas(Rs, Rt, Rn, sz, a, r, true); \ + } + INSN(cas, false, false) + INSN(casa, true, false) + INSN(casl, false, true) + INSN(casal, true, true) +#undef INSN + + // CASP +#define INSN(NAME, a, r) \ + void NAME(operand_size sz, Register Rs, Register Rs1, \ + Register Rt, Register Rt1, Register Rn) { \ + assert((Rs->encoding() & 1) == 0 && (Rt->encoding() & 1) == 0 && \ + Rs->successor() == Rs1 && Rt->successor() == Rt1 && \ + Rs != Rn && Rs1 != Rn && Rs != Rt, "invalid registers"); \ + lse_cas(Rs, Rt, Rn, sz, a, r, false); \ + } + INSN(casp, false, false) + INSN(caspa, true, false) + INSN(caspl, false, true) + INSN(caspal, true, true) +#undef INSN + // Load register (literal) #define INSN(NAME, opc, V) \ void NAME(Register Rt, address dest) { \ diff --git a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp index e32a3c76b79..082c1505466 100644 --- a/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/c1_LIRAssembler_aarch64.cpp @@ -1556,38 +1556,54 @@ void LIR_Assembler::emit_opTypeCheck(LIR_OpTypeCheck* op) { } void LIR_Assembler::casw(Register addr, Register newval, Register cmpval) { - Label retry_load, nope; - // flush and load exclusive from the memory location - // and fail if it is not what we expect - __ bind(retry_load); - __ ldaxrw(rscratch1, addr); - __ cmpw(rscratch1, cmpval); - __ cset(rscratch1, Assembler::NE); - __ br(Assembler::NE, nope); - // if we store+flush with no intervening write rscratch1 wil be zero - __ stlxrw(rscratch1, newval, addr); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - __ cbnzw(rscratch1, retry_load); - __ bind(nope); + if (UseLSE) { + __ mov(rscratch1, cmpval); + __ casal(Assembler::word, rscratch1, newval, addr); + __ cmpw(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + } else { + Label retry_load, nope; + // flush and load exclusive from the memory location + // and fail if it is not what we expect + __ prfm(Address(addr), PSTL1STRM); + __ bind(retry_load); + __ ldaxrw(rscratch1, addr); + __ cmpw(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + __ br(Assembler::NE, nope); + // if we store+flush with no intervening write rscratch1 wil be zero + __ stlxrw(rscratch1, newval, addr); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + __ cbnzw(rscratch1, retry_load); + __ bind(nope); + } __ membar(__ AnyAny); } void LIR_Assembler::casl(Register addr, Register newval, Register cmpval) { - Label retry_load, nope; - // flush and load exclusive from the memory location - // and fail if it is not what we expect - __ bind(retry_load); - __ ldaxr(rscratch1, addr); - __ cmp(rscratch1, cmpval); - __ cset(rscratch1, Assembler::NE); - __ br(Assembler::NE, nope); - // if we store+flush with no intervening write rscratch1 wil be zero - __ stlxr(rscratch1, newval, addr); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - __ cbnz(rscratch1, retry_load); - __ bind(nope); + if (UseLSE) { + __ mov(rscratch1, cmpval); + __ casal(Assembler::xword, rscratch1, newval, addr); + __ cmp(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + } else { + Label retry_load, nope; + // flush and load exclusive from the memory location + // and fail if it is not what we expect + __ prfm(Address(addr), PSTL1STRM); + __ bind(retry_load); + __ ldaxr(rscratch1, addr); + __ cmp(rscratch1, cmpval); + __ cset(rscratch1, Assembler::NE); + __ br(Assembler::NE, nope); + // if we store+flush with no intervening write rscratch1 wil be zero + __ stlxr(rscratch1, newval, addr); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + __ cbnz(rscratch1, retry_load); + __ bind(nope); + } __ membar(__ AnyAny); } @@ -3156,6 +3172,7 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr } Label again; __ lea(tmp, addr); + __ prfm(Address(tmp), PSTL1STRM); __ bind(again); (_masm->*lda)(dst, tmp); (_masm->*add)(rscratch1, dst, inc); @@ -3175,6 +3192,7 @@ void LIR_Assembler::atomic_op(LIR_Code code, LIR_Opr src, LIR_Opr data, LIR_Opr assert_different_registers(obj, addr.base(), tmp, rscratch2, dst); Label again; __ lea(tmp, addr); + __ prfm(Address(tmp), PSTL1STRM); __ bind(again); (_masm->*lda)(dst, tmp); (_masm->*stl)(rscratch2, obj, tmp); diff --git a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp index 86d2c14ce54..60edc02fc2a 100644 --- a/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/globals_aarch64.hpp @@ -76,6 +76,8 @@ define_pd_global(bool, CompactStrings, false); // avoid biased locking while we are bootstrapping the aarch64 build define_pd_global(bool, UseBiasedLocking, false); +define_pd_global(intx, InitArrayShortSize, 18*BytesPerLong); + #if defined(COMPILER1) || defined(COMPILER2) define_pd_global(intx, InlineSmallCode, 1000); #endif @@ -101,9 +103,13 @@ define_pd_global(intx, InlineSmallCode, 1000); \ product(bool, UseCRC32, false, \ "Use CRC32 instructions for CRC32 computation") \ + \ + product(bool, UseLSE, false, \ + "Use LSE instructions") \ // Don't attempt to use Neon on builtin sim until builtin sim supports it #define UseCRC32 false +#define UseSIMDForMemoryOps false #else #define UseBuiltinSim false @@ -121,6 +127,10 @@ define_pd_global(intx, InlineSmallCode, 1000); "Use Neon for CRC32 computation") \ product(bool, UseCRC32, false, \ "Use CRC32 instructions for CRC32 computation") \ + product(bool, UseSIMDForMemoryOps, false, \ + "Use SIMD instructions in generated memory move code") \ + product(bool, UseLSE, false, \ + "Use LSE instructions") \ product(bool, TraceTraps, false, "Trace all traps the signal handler") #endif diff --git a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp index 3e65f538de5..b302548557b 100644 --- a/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/jvmciCodeInstaller_aarch64.cpp @@ -74,7 +74,7 @@ void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle constant, T void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset, TRAPS) { address pc = _instructions->start() + pc_offset; NativeInstruction* inst = nativeInstruction_at(pc); - if (inst->is_adr_aligned()) { + if (inst->is_adr_aligned() || inst->is_ldr_literal()) { address dest = _constants->start() + data_offset; _instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS)); TRACE_jvmci_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset); diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp index 8c7f9465622..691e6bb29c2 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.cpp @@ -1638,6 +1638,7 @@ Address MacroAssembler::form_address(Register Rd, Register base, long byte_offse void MacroAssembler::atomic_incw(Register counter_addr, Register tmp, Register tmp2) { Label retry_load; + prfm(Address(counter_addr), PSTL1STRM); bind(retry_load); // flush and load exclusive from the memory location ldxrw(tmp, counter_addr); @@ -2070,25 +2071,32 @@ void MacroAssembler::cmpxchgptr(Register oldv, Register newv, Register addr, Reg // oldv holds comparison value // newv holds value to write in exchange // addr identifies memory word to compare against/update - // tmp returns 0/1 for success/failure - Label retry_load, nope; - - bind(retry_load); - // flush and load exclusive from the memory location - // and fail if it is not what we expect - ldaxr(tmp, addr); - cmp(tmp, oldv); - br(Assembler::NE, nope); - // if we store+flush with no intervening write tmp wil be zero - stlxr(tmp, newv, addr); - cbzw(tmp, succeed); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - b(retry_load); - // if the memory word differs we return it in oldv and signal a fail - bind(nope); - membar(AnyAny); - mov(oldv, tmp); + if (UseLSE) { + mov(tmp, oldv); + casal(Assembler::xword, oldv, newv, addr); + cmp(tmp, oldv); + br(Assembler::EQ, succeed); + membar(AnyAny); + } else { + Label retry_load, nope; + prfm(Address(addr), PSTL1STRM); + bind(retry_load); + // flush and load exclusive from the memory location + // and fail if it is not what we expect + ldaxr(tmp, addr); + cmp(tmp, oldv); + br(Assembler::NE, nope); + // if we store+flush with no intervening write tmp wil be zero + stlxr(tmp, newv, addr); + cbzw(tmp, succeed); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + b(retry_load); + // if the memory word differs we return it in oldv and signal a fail + bind(nope); + membar(AnyAny); + mov(oldv, tmp); + } if (fail) b(*fail); } @@ -2099,28 +2107,64 @@ void MacroAssembler::cmpxchgw(Register oldv, Register newv, Register addr, Regis // newv holds value to write in exchange // addr identifies memory word to compare against/update // tmp returns 0/1 for success/failure - Label retry_load, nope; - - bind(retry_load); - // flush and load exclusive from the memory location - // and fail if it is not what we expect - ldaxrw(tmp, addr); - cmp(tmp, oldv); - br(Assembler::NE, nope); - // if we store+flush with no intervening write tmp wil be zero - stlxrw(tmp, newv, addr); - cbzw(tmp, succeed); - // retry so we only ever return after a load fails to compare - // ensures we don't return a stale value after a failed write. - b(retry_load); - // if the memory word differs we return it in oldv and signal a fail - bind(nope); - membar(AnyAny); - mov(oldv, tmp); + if (UseLSE) { + mov(tmp, oldv); + casal(Assembler::word, oldv, newv, addr); + cmp(tmp, oldv); + br(Assembler::EQ, succeed); + membar(AnyAny); + } else { + Label retry_load, nope; + prfm(Address(addr), PSTL1STRM); + bind(retry_load); + // flush and load exclusive from the memory location + // and fail if it is not what we expect + ldaxrw(tmp, addr); + cmp(tmp, oldv); + br(Assembler::NE, nope); + // if we store+flush with no intervening write tmp wil be zero + stlxrw(tmp, newv, addr); + cbzw(tmp, succeed); + // retry so we only ever return after a load fails to compare + // ensures we don't return a stale value after a failed write. + b(retry_load); + // if the memory word differs we return it in oldv and signal a fail + bind(nope); + membar(AnyAny); + mov(oldv, tmp); + } if (fail) b(*fail); } +// A generic CAS; success or failure is in the EQ flag. +void MacroAssembler::cmpxchg(Register addr, Register expected, + Register new_val, + enum operand_size size, + bool acquire, bool release, + Register tmp) { + if (UseLSE) { + mov(tmp, expected); + lse_cas(tmp, new_val, addr, size, acquire, release, /*not_pair*/ true); + cmp(tmp, expected); + } else { + BLOCK_COMMENT("cmpxchg {"); + Label retry_load, done; + prfm(Address(addr), PSTL1STRM); + bind(retry_load); + load_exclusive(tmp, addr, size, acquire); + if (size == xword) + cmp(tmp, expected); + else + cmpw(tmp, expected); + br(Assembler::NE, done); + store_exclusive(tmp, new_val, addr, size, release); + cbnzw(tmp, retry_load); + bind(done); + BLOCK_COMMENT("} cmpxchg"); + } +} + static bool different(Register a, RegisterOrConstant b, Register c) { if (b.is_constant()) return a != c; @@ -2135,6 +2179,7 @@ void MacroAssembler::atomic_##OP(Register prev, RegisterOrConstant incr, Registe result = different(prev, incr, addr) ? prev : rscratch2; \ \ Label retry_load; \ + prfm(Address(addr), PSTL1STRM); \ bind(retry_load); \ LDXR(result, addr); \ OP(rscratch1, result, incr); \ @@ -2157,6 +2202,7 @@ void MacroAssembler::atomic_##OP(Register prev, Register newv, Register addr) { result = different(prev, newv, addr) ? prev : rscratch2; \ \ Label retry_load; \ + prfm(Address(addr), PSTL1STRM); \ bind(retry_load); \ LDXR(result, addr); \ STXR(rscratch1, newv, addr); \ @@ -4481,225 +4527,126 @@ void MacroAssembler::string_compare(Register str1, Register str2, BLOCK_COMMENT("} string_compare"); } +// Compare Strings or char/byte arrays. -void MacroAssembler::string_equals(Register str1, Register str2, - Register cnt, Register result, - Register tmp1) { - Label SAME_CHARS, DONE, SHORT_LOOP, SHORT_STRING, - NEXT_WORD; +// is_string is true iff this is a string comparison. - const Register tmp2 = rscratch1; - assert_different_registers(str1, str2, cnt, result, tmp1, tmp2, rscratch2); +// For Strings we're passed the address of the first characters in a1 +// and a2 and the length in cnt1. - BLOCK_COMMENT("string_equals {"); +// For byte and char arrays we're passed the arrays themselves and we +// have to extract length fields and do null checks here. - // Start by assuming that the strings are not equal. - mov(result, zr); +// elem_size is the element size in bytes: either 1 or 2. - // A very short string - cmpw(cnt, 4); - br(Assembler::LT, SHORT_STRING); +// There are two implementations. For arrays >= 8 bytes, all +// comparisons (including the final one, which may overlap) are +// performed 8 bytes at a time. For arrays < 8 bytes, we compare a +// halfword, then a short, and then a byte. - // Check if the strings start at the same location. - cmp(str1, str2); - br(Assembler::EQ, SAME_CHARS); +void MacroAssembler::arrays_equals(Register a1, Register a2, + Register result, Register cnt1, + int elem_size, bool is_string) +{ + Label SAME, DONE, SHORT, NEXT_WORD, ONE; + Register tmp1 = rscratch1; + Register tmp2 = rscratch2; + Register cnt2 = tmp2; // cnt2 only used in array length compare + int elem_per_word = wordSize/elem_size; + int log_elem_size = exact_log2(elem_size); + int length_offset = arrayOopDesc::length_offset_in_bytes(); + int base_offset + = arrayOopDesc::base_offset_in_bytes(elem_size == 2 ? T_CHAR : T_BYTE); - // Compare longwords - { - subw(cnt, cnt, 4); // The last longword is a special case + assert(elem_size == 1 || elem_size == 2, "must be char or byte"); + assert_different_registers(a1, a2, result, cnt1, rscratch1, rscratch2); - // Move both string pointers to the last longword of their - // strings, negate the remaining count, and convert it to bytes. - lea(str1, Address(str1, cnt, Address::uxtw(1))); - lea(str2, Address(str2, cnt, Address::uxtw(1))); - sub(cnt, zr, cnt, LSL, 1); + BLOCK_COMMENT(is_string ? "string_equals {" : "array_equals {"); - // Loop, loading longwords and comparing them into rscratch2. - bind(NEXT_WORD); - ldr(tmp1, Address(str1, cnt)); - ldr(tmp2, Address(str2, cnt)); - adds(cnt, cnt, wordSize); - eor(rscratch2, tmp1, tmp2); - cbnz(rscratch2, DONE); - br(Assembler::LT, NEXT_WORD); + mov(result, false); - // Last longword. In the case where length == 4 we compare the - // same longword twice, but that's still faster than another - // conditional branch. + if (!is_string) { + // if (a==a2) + // return true; + eor(rscratch1, a1, a2); + cbz(rscratch1, SAME); + // if (a==null || a2==null) + // return false; + cbz(a1, DONE); + cbz(a2, DONE); + // if (a1.length != a2.length) + // return false; + ldrw(cnt1, Address(a1, length_offset)); + ldrw(cnt2, Address(a2, length_offset)); + eorw(tmp1, cnt1, cnt2); + cbnzw(tmp1, DONE); - ldr(tmp1, Address(str1)); - ldr(tmp2, Address(str2)); - eor(rscratch2, tmp1, tmp2); - cbz(rscratch2, SAME_CHARS); - b(DONE); + lea(a1, Address(a1, base_offset)); + lea(a2, Address(a2, base_offset)); } - bind(SHORT_STRING); - // Is the length zero? - cbz(cnt, SAME_CHARS); - - bind(SHORT_LOOP); - load_unsigned_short(tmp1, Address(post(str1, 2))); - load_unsigned_short(tmp2, Address(post(str2, 2))); - subw(tmp1, tmp1, tmp2); + // Check for short strings, i.e. smaller than wordSize. + subs(cnt1, cnt1, elem_per_word); + br(Assembler::LT, SHORT); + // Main 8 byte comparison loop. + bind(NEXT_WORD); { + ldr(tmp1, Address(post(a1, wordSize))); + ldr(tmp2, Address(post(a2, wordSize))); + subs(cnt1, cnt1, elem_per_word); + eor(tmp1, tmp1, tmp2); + cbnz(tmp1, DONE); + } br(GT, NEXT_WORD); + // Last longword. In the case where length == 4 we compare the + // same longword twice, but that's still faster than another + // conditional branch. + // cnt1 could be 0, -1, -2, -3, -4 for chars; -4 only happens when + // length == 4. + if (log_elem_size > 0) + lsl(cnt1, cnt1, log_elem_size); + ldr(tmp1, Address(a1, cnt1)); + ldr(tmp2, Address(a2, cnt1)); + eor(tmp1, tmp1, tmp2); cbnz(tmp1, DONE); - sub(cnt, cnt, 1); - cbnz(cnt, SHORT_LOOP); + b(SAME); - // Strings are equal. - bind(SAME_CHARS); + bind(SHORT); + Label TAIL03, TAIL01; + + tbz(cnt1, 2 - log_elem_size, TAIL03); // 0-7 bytes left. + { + ldrw(tmp1, Address(post(a1, 4))); + ldrw(tmp2, Address(post(a2, 4))); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + bind(TAIL03); + tbz(cnt1, 1 - log_elem_size, TAIL01); // 0-3 bytes left. + { + ldrh(tmp1, Address(post(a1, 2))); + ldrh(tmp2, Address(post(a2, 2))); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + bind(TAIL01); + if (elem_size == 1) { // Only needed when comparing byte arrays. + tbz(cnt1, 0, SAME); // 0-1 bytes left. + { + ldrb(tmp1, a1); + ldrb(tmp2, a2); + eorw(tmp1, tmp1, tmp2); + cbnzw(tmp1, DONE); + } + } + // Arrays are equal. + bind(SAME); mov(result, true); - // That's it + // That's it. bind(DONE); - - BLOCK_COMMENT("} string_equals"); + BLOCK_COMMENT(is_string ? "} string_equals" : "} array_equals"); } -void MacroAssembler::byte_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1) -{ - Register cnt1 = rscratch1; - Register cnt2 = rscratch2; - Register tmp2 = rscratch2; - - Label SAME, DIFFER, NEXT, TAIL07, TAIL03, TAIL01; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_BYTE); - - BLOCK_COMMENT("byte_arrays_equals {"); - - // different until proven equal - mov(result, false); - - // same array? - cmp(ary1, ary2); - br(Assembler::EQ, SAME); - - // ne if either null - cbz(ary1, DIFFER); - cbz(ary2, DIFFER); - - // lengths ne? - ldrw(cnt1, Address(ary1, length_offset)); - ldrw(cnt2, Address(ary2, length_offset)); - cmp(cnt1, cnt2); - br(Assembler::NE, DIFFER); - - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - - subs(cnt1, cnt1, 8); - br(LT, TAIL07); - - BIND(NEXT); - ldr(tmp1, Address(post(ary1, 8))); - ldr(tmp2, Address(post(ary2, 8))); - subs(cnt1, cnt1, 8); - eor(tmp1, tmp1, tmp2); - cbnz(tmp1, DIFFER); - br(GE, NEXT); - - BIND(TAIL07); // 0-7 bytes left, cnt1 = #bytes left - 4 - tst(cnt1, 0b100); - br(EQ, TAIL03); - ldrw(tmp1, Address(post(ary1, 4))); - ldrw(tmp2, Address(post(ary2, 4))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(TAIL03); // 0-3 bytes left, cnt1 = #bytes left - 4 - tst(cnt1, 0b10); - br(EQ, TAIL01); - ldrh(tmp1, Address(post(ary1, 2))); - ldrh(tmp2, Address(post(ary2, 2))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - BIND(TAIL01); // 0-1 byte left - tst(cnt1, 0b01); - br(EQ, SAME); - ldrb(tmp1, ary1); - ldrb(tmp2, ary2); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(SAME); - mov(result, true); - BIND(DIFFER); // result already set - - BLOCK_COMMENT("} byte_arrays_equals"); -} - -// Compare char[] arrays aligned to 4 bytes -void MacroAssembler::char_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1) -{ - Register cnt1 = rscratch1; - Register cnt2 = rscratch2; - Register tmp2 = rscratch2; - - Label SAME, DIFFER, NEXT, TAIL03, TAIL01; - - int length_offset = arrayOopDesc::length_offset_in_bytes(); - int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR); - - BLOCK_COMMENT("char_arrays_equals {"); - - // different until proven equal - mov(result, false); - - // same array? - cmp(ary1, ary2); - br(Assembler::EQ, SAME); - - // ne if either null - cbz(ary1, DIFFER); - cbz(ary2, DIFFER); - - // lengths ne? - ldrw(cnt1, Address(ary1, length_offset)); - ldrw(cnt2, Address(ary2, length_offset)); - cmp(cnt1, cnt2); - br(Assembler::NE, DIFFER); - - lea(ary1, Address(ary1, base_offset)); - lea(ary2, Address(ary2, base_offset)); - - subs(cnt1, cnt1, 4); - br(LT, TAIL03); - - BIND(NEXT); - ldr(tmp1, Address(post(ary1, 8))); - ldr(tmp2, Address(post(ary2, 8))); - subs(cnt1, cnt1, 4); - eor(tmp1, tmp1, tmp2); - cbnz(tmp1, DIFFER); - br(GE, NEXT); - - BIND(TAIL03); // 0-3 chars left, cnt1 = #chars left - 4 - tst(cnt1, 0b10); - br(EQ, TAIL01); - ldrw(tmp1, Address(post(ary1, 4))); - ldrw(tmp2, Address(post(ary2, 4))); - cmp(tmp1, tmp2); - br(NE, DIFFER); - BIND(TAIL01); // 0-1 chars left - tst(cnt1, 0b01); - br(EQ, SAME); - ldrh(tmp1, ary1); - ldrh(tmp2, ary2); - cmp(tmp1, tmp2); - br(NE, DIFFER); - - BIND(SAME); - mov(result, true); - BIND(DIFFER); // result already set - - BLOCK_COMMENT("} char_arrays_equals"); -} - // encode char[] to byte[] in ISO_8859_1 void MacroAssembler::encode_iso_array(Register src, Register dst, Register len, Register result, diff --git a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp index d22c581bc41..64ef4f65eca 100644 --- a/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/macroAssembler_aarch64.hpp @@ -971,21 +971,10 @@ public: } // A generic CAS; success or failure is in the EQ flag. - template void cmpxchg(Register addr, Register expected, Register new_val, - T1 load_insn, - void (MacroAssembler::*cmp_insn)(Register, Register), - T2 store_insn, - Register tmp = rscratch1) { - Label retry_load, done; - bind(retry_load); - (this->*load_insn)(tmp, addr); - (this->*cmp_insn)(tmp, expected); - br(Assembler::NE, done); - (this->*store_insn)(tmp, new_val, addr); - cbnzw(tmp, retry_load); - bind(done); - } + enum operand_size size, + bool acquire, bool release, + Register tmp = rscratch1); // Calls @@ -1186,13 +1175,11 @@ public: void string_compare(Register str1, Register str2, Register cnt1, Register cnt2, Register result, Register tmp1); - void string_equals(Register str1, Register str2, - Register cnt, Register result, - Register tmp1); - void char_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1); - void byte_arrays_equals(Register ary1, Register ary2, - Register result, Register tmp1); + + void arrays_equals(Register a1, Register a2, + Register result, Register cnt1, + int elem_size, bool is_string); + void encode_iso_array(Register src, Register dst, Register len, Register result, FloatRegister Vtmp1, FloatRegister Vtmp2, diff --git a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp index 72c3479659c..d83017c1770 100644 --- a/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/nativeInst_aarch64.hpp @@ -105,13 +105,20 @@ class NativeInstruction VALUE_OBJ_CLASS_SPEC { inline friend NativeInstruction* nativeInstruction_at(address address); static bool is_adrp_at(address instr); + static bool is_ldr_literal_at(address instr); + + bool is_ldr_literal() { + return is_ldr_literal_at(addr_at(0)); + } + static bool is_ldrw_to_zr(address instr); static bool is_call_at(address instr) { const uint32_t insn = (*(uint32_t*)instr); return (insn >> 26) == 0b100101; } + bool is_call() { return is_call_at(addr_at(0)); } diff --git a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp index 762b8b0f1ce..6e935f687b1 100644 --- a/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp +++ b/hotspot/src/cpu/aarch64/vm/register_aarch64.hpp @@ -107,6 +107,9 @@ CONSTANT_REGISTER_DECLARATION(Register, r31_sp, (31)); CONSTANT_REGISTER_DECLARATION(Register, zr, (32)); CONSTANT_REGISTER_DECLARATION(Register, sp, (33)); +// Used as a filler in instructions where a register field is unused. +const Register dummy_reg = r31_sp; + // Use FloatRegister as shortcut class FloatRegisterImpl; typedef FloatRegisterImpl* FloatRegister; diff --git a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp index 64833c5ccc4..30805fb4150 100644 --- a/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/stubGenerator_aarch64.cpp @@ -163,30 +163,20 @@ class StubGenerator: public StubCodeGenerator { sp_after_call_off = -26, d15_off = -26, - d14_off = -25, d13_off = -24, - d12_off = -23, d11_off = -22, - d10_off = -21, d9_off = -20, - d8_off = -19, r28_off = -18, - r27_off = -17, r26_off = -16, - r25_off = -15, r24_off = -14, - r23_off = -13, r22_off = -12, - r21_off = -11, r20_off = -10, - r19_off = -9, call_wrapper_off = -8, result_off = -7, result_type_off = -6, method_off = -5, entry_point_off = -4, - parameters_off = -3, parameter_size_off = -2, thread_off = -1, fp_f = 0, @@ -208,30 +198,20 @@ class StubGenerator: public StubCodeGenerator { const Address result_type (rfp, result_type_off * wordSize); const Address method (rfp, method_off * wordSize); const Address entry_point (rfp, entry_point_off * wordSize); - const Address parameters (rfp, parameters_off * wordSize); const Address parameter_size(rfp, parameter_size_off * wordSize); const Address thread (rfp, thread_off * wordSize); const Address d15_save (rfp, d15_off * wordSize); - const Address d14_save (rfp, d14_off * wordSize); const Address d13_save (rfp, d13_off * wordSize); - const Address d12_save (rfp, d12_off * wordSize); const Address d11_save (rfp, d11_off * wordSize); - const Address d10_save (rfp, d10_off * wordSize); const Address d9_save (rfp, d9_off * wordSize); - const Address d8_save (rfp, d8_off * wordSize); const Address r28_save (rfp, r28_off * wordSize); - const Address r27_save (rfp, r27_off * wordSize); const Address r26_save (rfp, r26_off * wordSize); - const Address r25_save (rfp, r25_off * wordSize); const Address r24_save (rfp, r24_off * wordSize); - const Address r23_save (rfp, r23_off * wordSize); const Address r22_save (rfp, r22_off * wordSize); - const Address r21_save (rfp, r21_off * wordSize); const Address r20_save (rfp, r20_off * wordSize); - const Address r19_save (rfp, r19_off * wordSize); // stub code @@ -254,31 +234,20 @@ class StubGenerator: public StubCodeGenerator { // rthread because we want to sanity check rthread later __ str(c_rarg7, thread); __ strw(c_rarg6, parameter_size); - __ str(c_rarg5, parameters); - __ str(c_rarg4, entry_point); - __ str(c_rarg3, method); - __ str(c_rarg2, result_type); - __ str(c_rarg1, result); - __ str(c_rarg0, call_wrapper); - __ str(r19, r19_save); - __ str(r20, r20_save); - __ str(r21, r21_save); - __ str(r22, r22_save); - __ str(r23, r23_save); - __ str(r24, r24_save); - __ str(r25, r25_save); - __ str(r26, r26_save); - __ str(r27, r27_save); - __ str(r28, r28_save); + __ stp(c_rarg4, c_rarg5, entry_point); + __ stp(c_rarg2, c_rarg3, result_type); + __ stp(c_rarg0, c_rarg1, call_wrapper); - __ strd(v8, d8_save); - __ strd(v9, d9_save); - __ strd(v10, d10_save); - __ strd(v11, d11_save); - __ strd(v12, d12_save); - __ strd(v13, d13_save); - __ strd(v14, d14_save); - __ strd(v15, d15_save); + __ stp(r20, r19, r20_save); + __ stp(r22, r21, r22_save); + __ stp(r24, r23, r24_save); + __ stp(r26, r25, r26_save); + __ stp(r28, r27, r28_save); + + __ stpd(v9, v8, d9_save); + __ stpd(v11, v10, d11_save); + __ stpd(v13, v12, d13_save); + __ stpd(v15, v14, d15_save); // install Java thread in global register now we have saved // whatever value it held @@ -385,33 +354,22 @@ class StubGenerator: public StubCodeGenerator { #endif // restore callee-save registers - __ ldrd(v15, d15_save); - __ ldrd(v14, d14_save); - __ ldrd(v13, d13_save); - __ ldrd(v12, d12_save); - __ ldrd(v11, d11_save); - __ ldrd(v10, d10_save); - __ ldrd(v9, d9_save); - __ ldrd(v8, d8_save); + __ ldpd(v15, v14, d15_save); + __ ldpd(v13, v12, d13_save); + __ ldpd(v11, v10, d11_save); + __ ldpd(v9, v8, d9_save); - __ ldr(r28, r28_save); - __ ldr(r27, r27_save); - __ ldr(r26, r26_save); - __ ldr(r25, r25_save); - __ ldr(r24, r24_save); - __ ldr(r23, r23_save); - __ ldr(r22, r22_save); - __ ldr(r21, r21_save); - __ ldr(r20, r20_save); - __ ldr(r19, r19_save); - __ ldr(c_rarg0, call_wrapper); - __ ldr(c_rarg1, result); + __ ldp(r28, r27, r28_save); + __ ldp(r26, r25, r26_save); + __ ldp(r24, r23, r24_save); + __ ldp(r22, r21, r22_save); + __ ldp(r20, r19, r20_save); + + __ ldp(c_rarg0, c_rarg1, call_wrapper); __ ldrw(c_rarg2, result_type); __ ldr(c_rarg3, method); - __ ldr(c_rarg4, entry_point); - __ ldr(c_rarg5, parameters); - __ ldr(c_rarg6, parameter_size); - __ ldr(c_rarg7, thread); + __ ldp(c_rarg4, c_rarg5, entry_point); + __ ldp(c_rarg6, c_rarg7, parameter_size); #ifndef PRODUCT // tell the simulator we are about to end Java execution @@ -771,7 +729,7 @@ class StubGenerator: public StubCodeGenerator { // // count is a count of words. // - // Precondition: count >= 2 + // Precondition: count >= 8 // // Postconditions: // @@ -783,6 +741,7 @@ class StubGenerator: public StubCodeGenerator { void generate_copy_longs(Label &start, Register s, Register d, Register count, copy_direction direction) { int unit = wordSize * direction; + int bias = (UseSIMDForMemoryOps ? 4:2) * wordSize; int offset; const Register t0 = r3, t1 = r4, t2 = r5, t3 = r6, @@ -792,7 +751,7 @@ class StubGenerator: public StubCodeGenerator { assert_different_registers(rscratch1, t0, t1, t2, t3, t4, t5, t6, t7); assert_different_registers(s, d, count, rscratch1); - Label again, large, small; + Label again, drain; const char *stub_name; if (direction == copy_forwards) stub_name = "foward_copy_longs"; @@ -801,57 +760,35 @@ class StubGenerator: public StubCodeGenerator { StubCodeMark mark(this, "StubRoutines", stub_name); __ align(CodeEntryAlignment); __ bind(start); - __ cmp(count, 8); - __ br(Assembler::LO, small); if (direction == copy_forwards) { - __ sub(s, s, 2 * wordSize); - __ sub(d, d, 2 * wordSize); - } - __ subs(count, count, 16); - __ br(Assembler::GE, large); - - // 8 <= count < 16 words. Copy 8. - __ ldp(t0, t1, Address(s, 2 * unit)); - __ ldp(t2, t3, Address(s, 4 * unit)); - __ ldp(t4, t5, Address(s, 6 * unit)); - __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); - - __ stp(t0, t1, Address(d, 2 * unit)); - __ stp(t2, t3, Address(d, 4 * unit)); - __ stp(t4, t5, Address(d, 6 * unit)); - __ stp(t6, t7, Address(__ pre(d, 8 * unit))); - - if (direction == copy_forwards) { - __ add(s, s, 2 * wordSize); - __ add(d, d, 2 * wordSize); + __ sub(s, s, bias); + __ sub(d, d, bias); } +#ifdef ASSERT + // Make sure we are never given < 8 words { - Label L1, L2; - __ bind(small); - __ tbz(count, exact_log2(4), L1); - __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ ldp(t2, t3, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ stp(t2, t3, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ bind(L1); - - __ tbz(count, 1, L2); - __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ bind(L2); + Label L; + __ cmp(count, 8); + __ br(Assembler::GE, L); + __ stop("genrate_copy_longs called with < 8 words"); + __ bind(L); } - - __ ret(lr); - - __ align(CodeEntryAlignment); - __ bind(large); +#endif // Fill 8 registers - __ ldp(t0, t1, Address(s, 2 * unit)); - __ ldp(t2, t3, Address(s, 4 * unit)); - __ ldp(t4, t5, Address(s, 6 * unit)); - __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(s, 4 * unit)); + __ ldpq(v2, v3, Address(__ pre(s, 8 * unit))); + } else { + __ ldp(t0, t1, Address(s, 2 * unit)); + __ ldp(t2, t3, Address(s, 4 * unit)); + __ ldp(t4, t5, Address(s, 6 * unit)); + __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + } + + __ subs(count, count, 16); + __ br(Assembler::LO, drain); int prefetch = PrefetchCopyIntervalInBytes; bool use_stride = false; @@ -866,38 +803,56 @@ class StubGenerator: public StubCodeGenerator { if (PrefetchCopyIntervalInBytes > 0) __ prfm(use_stride ? Address(s, stride) : Address(s, prefetch), PLDL1KEEP); - __ stp(t0, t1, Address(d, 2 * unit)); - __ ldp(t0, t1, Address(s, 2 * unit)); - __ stp(t2, t3, Address(d, 4 * unit)); - __ ldp(t2, t3, Address(s, 4 * unit)); - __ stp(t4, t5, Address(d, 6 * unit)); - __ ldp(t4, t5, Address(s, 6 * unit)); - __ stp(t6, t7, Address(__ pre(d, 8 * unit))); - __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + if (UseSIMDForMemoryOps) { + __ stpq(v0, v1, Address(d, 4 * unit)); + __ ldpq(v0, v1, Address(s, 4 * unit)); + __ stpq(v2, v3, Address(__ pre(d, 8 * unit))); + __ ldpq(v2, v3, Address(__ pre(s, 8 * unit))); + } else { + __ stp(t0, t1, Address(d, 2 * unit)); + __ ldp(t0, t1, Address(s, 2 * unit)); + __ stp(t2, t3, Address(d, 4 * unit)); + __ ldp(t2, t3, Address(s, 4 * unit)); + __ stp(t4, t5, Address(d, 6 * unit)); + __ ldp(t4, t5, Address(s, 6 * unit)); + __ stp(t6, t7, Address(__ pre(d, 8 * unit))); + __ ldp(t6, t7, Address(__ pre(s, 8 * unit))); + } __ subs(count, count, 8); __ br(Assembler::HS, again); // Drain - __ stp(t0, t1, Address(d, 2 * unit)); - __ stp(t2, t3, Address(d, 4 * unit)); - __ stp(t4, t5, Address(d, 6 * unit)); - __ stp(t6, t7, Address(__ pre(d, 8 * unit))); - - if (direction == copy_forwards) { - __ add(s, s, 2 * wordSize); - __ add(d, d, 2 * wordSize); + __ bind(drain); + if (UseSIMDForMemoryOps) { + __ stpq(v0, v1, Address(d, 4 * unit)); + __ stpq(v2, v3, Address(__ pre(d, 8 * unit))); + } else { + __ stp(t0, t1, Address(d, 2 * unit)); + __ stp(t2, t3, Address(d, 4 * unit)); + __ stp(t4, t5, Address(d, 6 * unit)); + __ stp(t6, t7, Address(__ pre(d, 8 * unit))); } { Label L1, L2; __ tbz(count, exact_log2(4), L1); - __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ ldp(t2, t3, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); - __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); - __ stp(t2, t3, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(__ pre(s, 4 * unit))); + __ stpq(v0, v1, Address(__ pre(d, 4 * unit))); + } else { + __ ldp(t0, t1, Address(s, 2 * unit)); + __ ldp(t2, t3, Address(__ pre(s, 4 * unit))); + __ stp(t0, t1, Address(d, 2 * unit)); + __ stp(t2, t3, Address(__ pre(d, 4 * unit))); + } __ bind(L1); + if (direction == copy_forwards) { + __ add(s, s, bias); + __ add(d, d, bias); + } + __ tbz(count, 1, L2); __ ldp(t0, t1, Address(__ adjust(s, 2 * unit, direction == copy_backwards))); __ stp(t0, t1, Address(__ adjust(d, 2 * unit, direction == copy_backwards))); @@ -973,16 +928,135 @@ class StubGenerator: public StubCodeGenerator { int granularity = uabs(step); const Register t0 = r3, t1 = r4; + // <= 96 bytes do inline. Direction doesn't matter because we always + // load all the data before writing anything + Label copy4, copy8, copy16, copy32, copy80, copy128, copy_big, finish; + const Register t2 = r5, t3 = r6, t4 = r7, t5 = r8; + const Register t6 = r9, t7 = r10, t8 = r11, t9 = r12; + const Register send = r17, dend = r18; + + if (PrefetchCopyIntervalInBytes > 0) + __ prfm(Address(s, 0), PLDL1KEEP); + __ cmp(count, (UseSIMDForMemoryOps ? 96:80)/granularity); + __ br(Assembler::HI, copy_big); + + __ lea(send, Address(s, count, Address::lsl(exact_log2(granularity)))); + __ lea(dend, Address(d, count, Address::lsl(exact_log2(granularity)))); + + __ cmp(count, 16/granularity); + __ br(Assembler::LS, copy16); + + __ cmp(count, 64/granularity); + __ br(Assembler::HI, copy80); + + __ cmp(count, 32/granularity); + __ br(Assembler::LS, copy32); + + // 33..64 bytes + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(s, 0)); + __ ldpq(v2, v3, Address(send, -32)); + __ stpq(v0, v1, Address(d, 0)); + __ stpq(v2, v3, Address(dend, -32)); + } else { + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(s, 16)); + __ ldp(t4, t5, Address(send, -32)); + __ ldp(t6, t7, Address(send, -16)); + + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(d, 16)); + __ stp(t4, t5, Address(dend, -32)); + __ stp(t6, t7, Address(dend, -16)); + } + __ b(finish); + + // 17..32 bytes + __ bind(copy32); + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(send, -16)); + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(dend, -16)); + __ b(finish); + + // 65..80/96 bytes + // (96 bytes if SIMD because we do 32 byes per instruction) + __ bind(copy80); + if (UseSIMDForMemoryOps) { + __ ldpq(v0, v1, Address(s, 0)); + __ ldpq(v2, v3, Address(s, 32)); + __ ldpq(v4, v5, Address(send, -32)); + __ stpq(v0, v1, Address(d, 0)); + __ stpq(v2, v3, Address(d, 32)); + __ stpq(v4, v5, Address(dend, -32)); + } else { + __ ldp(t0, t1, Address(s, 0)); + __ ldp(t2, t3, Address(s, 16)); + __ ldp(t4, t5, Address(s, 32)); + __ ldp(t6, t7, Address(s, 48)); + __ ldp(t8, t9, Address(send, -16)); + + __ stp(t0, t1, Address(d, 0)); + __ stp(t2, t3, Address(d, 16)); + __ stp(t4, t5, Address(d, 32)); + __ stp(t6, t7, Address(d, 48)); + __ stp(t8, t9, Address(dend, -16)); + } + __ b(finish); + + // 0..16 bytes + __ bind(copy16); + __ cmp(count, 8/granularity); + __ br(Assembler::LO, copy8); + + // 8..16 bytes + __ ldr(t0, Address(s, 0)); + __ ldr(t1, Address(send, -8)); + __ str(t0, Address(d, 0)); + __ str(t1, Address(dend, -8)); + __ b(finish); + + if (granularity < 8) { + // 4..7 bytes + __ bind(copy8); + __ tbz(count, 2 - exact_log2(granularity), copy4); + __ ldrw(t0, Address(s, 0)); + __ ldrw(t1, Address(send, -4)); + __ strw(t0, Address(d, 0)); + __ strw(t1, Address(dend, -4)); + __ b(finish); + if (granularity < 4) { + // 0..3 bytes + __ bind(copy4); + __ cbz(count, finish); // get rid of 0 case + if (granularity == 2) { + __ ldrh(t0, Address(s, 0)); + __ strh(t0, Address(d, 0)); + } else { // granularity == 1 + // Now 1..3 bytes. Handle the 1 and 2 byte case by copying + // the first and last byte. + // Handle the 3 byte case by loading and storing base + count/2 + // (count == 1 (s+0)->(d+0), count == 2,3 (s+1) -> (d+1)) + // This does means in the 1 byte case we load/store the same + // byte 3 times. + __ lsr(count, count, 1); + __ ldrb(t0, Address(s, 0)); + __ ldrb(t1, Address(send, -1)); + __ ldrb(t2, Address(s, count)); + __ strb(t0, Address(d, 0)); + __ strb(t1, Address(dend, -1)); + __ strb(t2, Address(d, count)); + } + __ b(finish); + } + } + + __ bind(copy_big); if (is_backwards) { __ lea(s, Address(s, count, Address::lsl(exact_log2(-step)))); __ lea(d, Address(d, count, Address::lsl(exact_log2(-step)))); } - Label tail; - - __ cmp(count, 16/granularity); - __ br(Assembler::LO, tail); - // Now we've got the small case out of the way we can align the // source address on a 2-word boundary. @@ -1028,8 +1102,6 @@ class StubGenerator: public StubCodeGenerator { #endif } - __ cmp(count, 16/granularity); - __ br(Assembler::LT, tail); __ bind(aligned); // s is now 2-word-aligned. @@ -1043,9 +1115,11 @@ class StubGenerator: public StubCodeGenerator { __ bl(copy_b); // And the tail. - - __ bind(tail); copy_memory_small(s, d, count, tmp, step); + + if (granularity >= 8) __ bind(copy8); + if (granularity >= 4) __ bind(copy4); + __ bind(finish); } diff --git a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp index e37c0881d5c..59bdeeeb044 100644 --- a/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/templateInterpreterGenerator_aarch64.cpp @@ -1984,6 +1984,7 @@ void TemplateInterpreterGenerator::count_bytecode() { __ push(rscratch3); Label L; __ mov(rscratch2, (address) &BytecodeCounter::_counter_value); + __ prfm(Address(rscratch2), PSTL1STRM); __ bind(L); __ ldxr(rscratch1, rscratch2); __ add(rscratch1, rscratch1, 1); diff --git a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp index 21859656b52..40275cabfa0 100644 --- a/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp +++ b/hotspot/src/cpu/aarch64/vm/vm_version_aarch64.cpp @@ -61,6 +61,10 @@ #define HWCAP_CRC32 (1<<7) #endif +#ifndef HWCAP_ATOMICS +#define HWCAP_ATOMICS (1<<8) +#endif + int VM_Version::_cpu; int VM_Version::_model; int VM_Version::_model2; @@ -172,6 +176,7 @@ void VM_Version::get_processor_features() { if (auxv & HWCAP_AES) strcat(buf, ", aes"); if (auxv & HWCAP_SHA1) strcat(buf, ", sha1"); if (auxv & HWCAP_SHA2) strcat(buf, ", sha256"); + if (auxv & HWCAP_ATOMICS) strcat(buf, ", lse"); _features_string = os::strdup(buf); @@ -191,6 +196,15 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseVectorizedMismatchIntrinsic, false); } + if (auxv & HWCAP_ATOMICS) { + if (FLAG_IS_DEFAULT(UseLSE)) + FLAG_SET_DEFAULT(UseLSE, true); + } else { + if (UseLSE) { + warning("UseLSE specified, but not supported on this CPU"); + } + } + if (auxv & HWCAP_AES) { UseAES = UseAES || FLAG_IS_DEFAULT(UseAES); UseAESIntrinsics = diff --git a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp index ba981816f4a..f8fe437547d 100644 --- a/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globalDefinitions_ppc.hpp @@ -47,7 +47,7 @@ const bool CCallingConventionRequiresIntsAsLongs = true; // The expected size in bytes of a cache line, used to pad data structures. #define DEFAULT_CACHE_LINE_SIZE 128 -#if defined(COMPILER2) && defined(AIX) +#if defined(COMPILER2) && (defined(AIX) || defined(linux)) // Include Transactional Memory lock eliding optimization #define INCLUDE_RTM_OPT 1 #endif diff --git a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp index 4afb89e1ffb..77f7a491b02 100644 --- a/hotspot/src/cpu/ppc/vm/globals_ppc.hpp +++ b/hotspot/src/cpu/ppc/vm/globals_ppc.hpp @@ -76,6 +76,8 @@ define_pd_global(uintx, TypeProfileLevel, 111); define_pd_global(bool, CompactStrings, true); +define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); + // Platform dependent flag handling: flags only defined on this platform. #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ diff --git a/hotspot/src/cpu/ppc/vm/ppc.ad b/hotspot/src/cpu/ppc/vm/ppc.ad index df119f8bdf1..20521eb8e18 100644 --- a/hotspot/src/cpu/ppc/vm/ppc.ad +++ b/hotspot/src/cpu/ppc/vm/ppc.ad @@ -2137,8 +2137,6 @@ MachTypeNode *Matcher::make_decode_node() { return decode; } */ -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; // false => size gets scaled to BytesPerLong, ok. const bool Matcher::init_array_count_is_in_bytes = false; diff --git a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp index 63c0e30a913..6743b2967f9 100644 --- a/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp +++ b/hotspot/src/cpu/ppc/vm/vm_version_ppc.cpp @@ -255,7 +255,16 @@ void VM_Version::initialize() { } #endif #ifdef linux - // TODO: check kernel version (we currently have too old versions only) + // At least Linux kernel 4.2, as the problematic behavior of syscalls + // being called in the middle of a transaction has been addressed. + // Please, refer to commit b4b56f9ecab40f3b4ef53e130c9f6663be491894 + // in Linux kernel source tree: https://goo.gl/Kc5i7A + if (os::Linux::os_version_is_known()) { + if (os::Linux::os_version() >= 0x040200) + os_too_old = false; + } else { + vm_exit_during_initialization("RTM can not be enabled: kernel version is unknown."); + } #endif if (os_too_old) { vm_exit_during_initialization("RTM is not supported on this OS version."); diff --git a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp index 3b813df0254..66889ae73b3 100644 --- a/hotspot/src/cpu/sparc/vm/globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/globals_sparc.hpp @@ -90,6 +90,8 @@ define_pd_global(uintx, TypeProfileLevel, 111); define_pd_global(bool, CompactStrings, true); +define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ product(intx, UseVIS, 99, \ diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index 6bbef4e5708..f24c1f9b384 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -948,28 +948,28 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n, } #endif - uint instr; - instr = (Assembler::ldst_op << 30) - | (dst_enc << 25) - | (primary << 19) - | (src1_enc << 14); + uint instr = (Assembler::ldst_op << 30) + | (dst_enc << 25) + | (primary << 19) + | (src1_enc << 14); uint index = src2_enc; int disp = disp32; if (src1_enc == R_SP_enc || src1_enc == R_FP_enc) { disp += STACK_BIAS; - // Quick fix for JDK-8029668: check that stack offset fits, bailout if not + // Check that stack offset fits, load into O7 if not if (!Assembler::is_simm13(disp)) { - ra->C->record_method_not_compilable("unable to handle large constant offsets"); - return; + MacroAssembler _masm(&cbuf); + __ set(disp, O7); + if (index != R_G0_enc) { + __ add(O7, reg_to_register_object(index), O7); + } + index = R_O7_enc; + disp = 0; } } - // We should have a compiler bailout here rather than a guarantee. - // Better yet would be some mechanism to handle variable-size matches correctly. - guarantee(Assembler::is_simm13(disp), "Do not match large constant offsets" ); - if( disp == 0 ) { // use reg-reg form // bit 13 is already zero @@ -983,7 +983,7 @@ void emit_form3_mem_reg(CodeBuffer &cbuf, PhaseRegAlloc* ra, const MachNode* n, cbuf.insts()->emit_int32(instr); #ifdef ASSERT - { + if (VerifyOops) { MacroAssembler _masm(&cbuf); if (is_verified_oop_base) { __ verify_oop(reg_to_register_object(src1_enc)); @@ -1342,7 +1342,7 @@ int MachEpilogNode::safepoint_offset() const { // Figure out which register class each belongs in: rc_int, rc_float, rc_stack enum RC { rc_bad, rc_int, rc_float, rc_stack }; static enum RC rc_class( OptoReg::Name reg ) { - if( !OptoReg::is_valid(reg) ) return rc_bad; + if (!OptoReg::is_valid(reg)) return rc_bad; if (OptoReg::is_stack(reg)) return rc_stack; VMReg r = OptoReg::as_VMReg(reg); if (r->is_Register()) return rc_int; @@ -1350,66 +1350,79 @@ static enum RC rc_class( OptoReg::Name reg ) { return rc_float; } -static int impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool do_size, bool is_load, int offset, int reg, int opcode, const char *op_str, int size, outputStream* st ) { +#ifndef PRODUCT +ATTRIBUTE_PRINTF(2, 3) +static void print_helper(outputStream* st, const char* format, ...) { + if (st->position() > 0) { + st->cr(); + st->sp(); + } + va_list ap; + va_start(ap, format); + st->vprint(format, ap); + va_end(ap); +} +#endif // !PRODUCT + +static void impl_helper(const MachNode* mach, CodeBuffer* cbuf, PhaseRegAlloc* ra, bool is_load, int offset, int reg, int opcode, const char *op_str, outputStream* st) { if (cbuf) { emit_form3_mem_reg(*cbuf, ra, mach, opcode, -1, R_SP_enc, offset, 0, Matcher::_regEncode[reg]); } #ifndef PRODUCT - else if (!do_size) { - if (size != 0) st->print("\n\t"); - if (is_load) st->print("%s [R_SP + #%d],R_%s\t! spill",op_str,offset,OptoReg::regname(reg)); - else st->print("%s R_%s,[R_SP + #%d]\t! spill",op_str,OptoReg::regname(reg),offset); + else { + if (is_load) { + print_helper(st, "%s [R_SP + #%d],R_%s\t! spill", op_str, offset, OptoReg::regname(reg)); + } else { + print_helper(st, "%s R_%s,[R_SP + #%d]\t! spill", op_str, OptoReg::regname(reg), offset); + } } #endif - return size+4; } -static int impl_mov_helper( CodeBuffer *cbuf, bool do_size, int src, int dst, int op1, int op2, const char *op_str, int size, outputStream* st ) { - if( cbuf ) emit3( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src] ); +static void impl_mov_helper(CodeBuffer *cbuf, int src, int dst, int op1, int op2, const char *op_str, outputStream* st) { + if (cbuf) { + emit3(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst], op1, 0, op2, Matcher::_regEncode[src]); + } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("%s R_%s,R_%s\t! spill",op_str,OptoReg::regname(src),OptoReg::regname(dst)); + else { + print_helper(st, "%s R_%s,R_%s\t! spill", op_str, OptoReg::regname(src), OptoReg::regname(dst)); } #endif - return size+4; } -uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, - PhaseRegAlloc *ra_, - bool do_size, - outputStream* st ) const { +static void mach_spill_copy_implementation_helper(const MachNode* mach, + CodeBuffer *cbuf, + PhaseRegAlloc *ra_, + outputStream* st) { // Get registers to move - OptoReg::Name src_second = ra_->get_reg_second(in(1)); - OptoReg::Name src_first = ra_->get_reg_first(in(1)); - OptoReg::Name dst_second = ra_->get_reg_second(this ); - OptoReg::Name dst_first = ra_->get_reg_first(this ); + OptoReg::Name src_second = ra_->get_reg_second(mach->in(1)); + OptoReg::Name src_first = ra_->get_reg_first(mach->in(1)); + OptoReg::Name dst_second = ra_->get_reg_second(mach); + OptoReg::Name dst_first = ra_->get_reg_first(mach); enum RC src_second_rc = rc_class(src_second); - enum RC src_first_rc = rc_class(src_first); + enum RC src_first_rc = rc_class(src_first); enum RC dst_second_rc = rc_class(dst_second); - enum RC dst_first_rc = rc_class(dst_first); + enum RC dst_first_rc = rc_class(dst_first); - assert( OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register" ); + assert(OptoReg::is_valid(src_first) && OptoReg::is_valid(dst_first), "must move at least 1 register"); - // Generate spill code! - int size = 0; - - if( src_first == dst_first && src_second == dst_second ) - return size; // Self copy, no move + if (src_first == dst_first && src_second == dst_second) { + return; // Self copy, no move + } // -------------------------------------- // Check for mem-mem move. Load into unused float registers and fall into // the float-store case. - if( src_first_rc == rc_stack && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_stack && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second ) { + if ((src_first&1) == 0 && src_first+1 == src_second) { src_second = OptoReg::Name(R_F31_num); src_second_rc = rc_float; - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::lddf_op3,"LDDF",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::lddf_op3, "LDDF", st); } else { - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F30_num,Assembler::ldf_op3 ,"LDF ",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F30_num, Assembler::ldf_op3, "LDF ", st); } src_first = OptoReg::Name(R_F30_num); src_first_rc = rc_float; @@ -1417,7 +1430,7 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, if( src_second_rc == rc_stack && dst_second_rc == rc_stack ) { int offset = ra_->reg2offset(src_second); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,R_F31_num,Assembler::ldf_op3,"LDF ",size, st); + impl_helper(mach, cbuf, ra_, true, offset, R_F31_num, Assembler::ldf_op3, "LDF ", st); src_second = OptoReg::Name(R_F31_num); src_second_rc = rc_float; } @@ -1427,36 +1440,38 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS < 3) { int offset = frame::register_save_words*wordSize; if (cbuf) { - emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16 ); - impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); - impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); - emit3_simm13( *cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16 ); + emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::sub_op3, R_SP_enc, 16); + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); + emit3_simm13(*cbuf, Assembler::arith_op, R_SP_enc, Assembler::add_op3, R_SP_enc, 16); } #ifndef PRODUCT - else if (!do_size) { - if (size != 0) st->print("\n\t"); - st->print( "SUB R_SP,16,R_SP\n"); - impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); - impl_helper(this,cbuf,ra_,do_size,true ,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); - st->print("\tADD R_SP,16,R_SP\n"); + else { + print_helper(st, "SUB R_SP,16,R_SP"); + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); + print_helper(st, "ADD R_SP,16,R_SP"); } #endif - size += 16; } // Check for float->int copy on T4 if (src_first_rc == rc_float && dst_first_rc == rc_int && UseVIS >= 3) { // Further check for aligned-adjacent pair, so we can use a double move - if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mdtox_opf,"MOVDTOX",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mstouw_opf,"MOVSTOUW",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mdtox_opf, "MOVDTOX", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mstouw_opf, "MOVSTOUW", st); } // Check for int->float copy on T4 if (src_first_rc == rc_int && dst_first_rc == rc_float && UseVIS >= 3) { // Further check for aligned-adjacent pair, so we can use a double move - if ((src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mxtod_opf,"MOVXTOD",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::mftoi_op3,Assembler::mwtos_opf,"MOVWTOS",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mxtod_opf, "MOVXTOD", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::mftoi_op3, Assembler::mwtos_opf, "MOVWTOS", st); } // -------------------------------------- @@ -1466,10 +1481,10 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, // there. Misaligned sources only come from native-long-returns (handled // special below). #ifndef _LP64 - if( src_first_rc == rc_int && // source is already big-endian + if (src_first_rc == rc_int && // source is already big-endian src_second_rc != rc_bad && // 64-bit move - ((dst_first&1)!=0 || dst_second != dst_first+1) ) { // misaligned dst - assert( (src_first&1)==0 && src_second == src_first+1, "source must be aligned" ); + ((dst_first & 1) != 0 || dst_second != dst_first + 1)) { // misaligned dst + assert((src_first & 1) == 0 && src_second == src_first + 1, "source must be aligned"); // Do the big-endian flop. OptoReg::Name tmp = dst_first ; dst_first = dst_second ; dst_second = tmp ; enum RC tmp_rc = dst_first_rc; dst_first_rc = dst_second_rc; dst_second_rc = tmp_rc; @@ -1478,30 +1493,28 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, // -------------------------------------- // Check for integer reg-reg copy - if( src_first_rc == rc_int && dst_first_rc == rc_int ) { + if (src_first_rc == rc_int && dst_first_rc == rc_int) { #ifndef _LP64 - if( src_first == R_O0_num && src_second == R_O1_num ) { // Check for the evil O0/O1 native long-return case + if (src_first == R_O0_num && src_second == R_O1_num) { // Check for the evil O0/O1 native long-return case // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value // as stored in memory. On a big-endian machine like SPARC, this means that the _second // operand contains the least significant word of the 64-bit value and vice versa. OptoReg::Name tmp = OptoReg::Name(R_O7_num); - assert( (dst_first&1)==0 && dst_second == dst_first+1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); + assert((dst_first & 1) == 0 && dst_second == dst_first + 1, "return a native O0/O1 long to an aligned-adjacent 64-bit reg" ); // Shift O0 left in-place, zero-extend O1, then OR them into the dst - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020 ); - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000 ); - emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second] ); + if ( cbuf ) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tmp], Assembler::sllx_op3, Matcher::_regEncode[src_first], 0x1020); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[src_second], Assembler::srl_op3, Matcher::_regEncode[src_second], 0x0000); + emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler:: or_op3, Matcher::_regEncode[tmp], 0, Matcher::_regEncode[src_second]); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); - st->print("SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); - st->print("OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); + } else { + print_helper(st, "SLLX R_%s,32,R_%s\t! Move O0-first to O7-high\n\t", OptoReg::regname(src_first), OptoReg::regname(tmp)); + print_helper(st, "SRL R_%s, 0,R_%s\t! Zero-extend O1\n\t", OptoReg::regname(src_second), OptoReg::regname(src_second)); + print_helper(st, "OR R_%s,R_%s,R_%s\t! spill",OptoReg::regname(tmp), OptoReg::regname(src_second), OptoReg::regname(dst_first)); #endif } - return size+12; - } - else if( dst_first == R_I0_num && dst_second == R_I1_num ) { + return; + } else if (dst_first == R_I0_num && dst_second == R_I1_num) { // returning a long value in I0/I1 // a SpillCopy must be able to target a return instruction's reg_class // Note: The _first and _second suffixes refer to the addresses of the the 2 halves of the 64-bit value @@ -1511,27 +1524,25 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, if (src_first == dst_first) { tdest = OptoReg::Name(R_O7_num); - size += 4; } - if( cbuf ) { - assert( (src_first&1) == 0 && (src_first+1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); + if (cbuf) { + assert((src_first & 1) == 0 && (src_first + 1) == src_second, "return value was in an aligned-adjacent 64-bit reg"); // Shift value in upper 32-bits of src to lower 32-bits of I0; move lower 32-bits to I1 // ShrL_reg_imm6 - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000 ); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[tdest], Assembler::srlx_op3, Matcher::_regEncode[src_second], 32 | 0x1000); // ShrR_reg_imm6 src, 0, dst - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000 ); + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srl_op3, Matcher::_regEncode[src_first], 0x0000); if (tdest != dst_first) { - emit3 ( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest] ); + emit3 (*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_first], Assembler::or_op3, 0/*G0*/, 0/*op2*/, Matcher::_regEncode[tdest]); } } #ifndef PRODUCT - else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); // %%%%% !!!!! - st->print("SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); - st->print("SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); + else { + print_helper(st, "SRLX R_%s,32,R_%s\t! Extract MSW\n\t",OptoReg::regname(src_second),OptoReg::regname(tdest)); + print_helper(st, "SRL R_%s, 0,R_%s\t! Extract LSW\n\t",OptoReg::regname(src_first),OptoReg::regname(dst_second)); if (tdest != dst_first) { - st->print("MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); + print_helper(st, "MOV R_%s,R_%s\t! spill\n\t", OptoReg::regname(tdest), OptoReg::regname(dst_first)); } } #endif // PRODUCT @@ -1539,65 +1550,77 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, } #endif // !_LP64 // Else normal reg-reg copy - assert( src_second != dst_first, "smashed second before evacuating it" ); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::or_op3,0,"MOV ",size, st); - assert( (src_first&1) == 0 && (dst_first&1) == 0, "never move second-halves of int registers" ); + assert(src_second != dst_first, "smashed second before evacuating it"); + impl_mov_helper(cbuf, src_first, dst_first, Assembler::or_op3, 0, "MOV ", st); + assert((src_first & 1) == 0 && (dst_first & 1) == 0, "never move second-halves of int registers"); // This moves an aligned adjacent pair. // See if we are done. - if( src_first+1 == src_second && dst_first+1 == dst_second ) - return size; + if (src_first + 1 == src_second && dst_first + 1 == dst_second) { + return; + } } // Check for integer store - if( src_first_rc == rc_int && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_int && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(dst_first); // Further check for aligned-adjacent pair, so we can use a double store - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stx_op3,"STX ",size, st); - size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stw_op3,"STW ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stx_op3, "STX ", st); + return; + } + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stw_op3, "STW ", st); } // Check for integer load - if( dst_first_rc == rc_int && src_first_rc == rc_stack ) { + if (dst_first_rc == rc_int && src_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldx_op3 ,"LDX ",size, st); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lduw_op3,"LDUW",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldx_op3, "LDX ", st); + return; + } + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lduw_op3, "LDUW", st); } // Check for float reg-reg copy - if( src_first_rc == rc_float && dst_first_rc == rc_float ) { + if (src_first_rc == rc_float && dst_first_rc == rc_float) { // Further check for aligned-adjacent pair, so we can use a double move - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovd_opf,"FMOVD",size, st); - size = impl_mov_helper(cbuf,do_size,src_first,dst_first,Assembler::fpop1_op3,Assembler::fmovs_opf,"FMOVS",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovd_opf, "FMOVD", st); + return; + } + impl_mov_helper(cbuf, src_first, dst_first, Assembler::fpop1_op3, Assembler::fmovs_opf, "FMOVS", st); } // Check for float store - if( src_first_rc == rc_float && dst_first_rc == rc_stack ) { + if (src_first_rc == rc_float && dst_first_rc == rc_stack) { int offset = ra_->reg2offset(dst_first); // Further check for aligned-adjacent pair, so we can use a double store - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stdf_op3,"STDF",size, st); - size = impl_helper(this,cbuf,ra_,do_size,false,offset,src_first,Assembler::stf_op3 ,"STF ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stdf_op3, "STDF", st); + return; + } + impl_helper(mach, cbuf, ra_, false, offset, src_first, Assembler::stf_op3, "STF ", st); } // Check for float load - if( dst_first_rc == rc_float && src_first_rc == rc_stack ) { + if (dst_first_rc == rc_float && src_first_rc == rc_stack) { int offset = ra_->reg2offset(src_first); // Further check for aligned-adjacent pair, so we can use a double load - if( (src_first&1)==0 && src_first+1 == src_second && (dst_first&1)==0 && dst_first+1 == dst_second ) - return impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::lddf_op3,"LDDF",size, st); - size = impl_helper(this,cbuf,ra_,do_size,true,offset,dst_first,Assembler::ldf_op3 ,"LDF ",size, st); + if ((src_first & 1) == 0 && src_first + 1 == src_second && (dst_first & 1) == 0 && dst_first + 1 == dst_second) { + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::lddf_op3, "LDDF", st); + return; + } + impl_helper(mach, cbuf, ra_, true, offset, dst_first, Assembler::ldf_op3, "LDF ", st); } // -------------------------------------------------------------------- // Check for hi bits still needing moving. Only happens for misaligned // arguments to native calls. - if( src_second == dst_second ) - return size; // Self copy; no move - assert( src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad" ); + if (src_second == dst_second) { + return; // Self copy; no move + } + assert(src_second_rc != rc_bad && dst_second_rc != rc_bad, "src_second & dst_second cannot be Bad"); #ifndef _LP64 // In the LP64 build, all registers can be moved as aligned/adjacent @@ -1609,52 +1632,57 @@ uint MachSpillCopyNode::implementation( CodeBuffer *cbuf, // 32-bits of a 64-bit register, but are needed in low bits of another // register (else it's a hi-bits-to-hi-bits copy which should have // happened already as part of a 64-bit move) - if( src_second_rc == rc_int && dst_second_rc == rc_int ) { - assert( (src_second&1)==1, "its the evil O0/O1 native return case" ); - assert( (dst_second&1)==0, "should have moved with 1 64-bit move" ); + if (src_second_rc == rc_int && dst_second_rc == rc_int) { + assert((src_second & 1) == 1, "its the evil O0/O1 native return case"); + assert((dst_second & 1) == 0, "should have moved with 1 64-bit move"); // Shift src_second down to dst_second's low bits. - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 ); + if (cbuf) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[dst_second], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(dst_second)); + } else { + print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second - 1), OptoReg::regname(dst_second)); #endif } - return size+4; + return; } // Check for high word integer store. Must down-shift the hi bits // into a temp register, then fall into the case of storing int bits. - if( src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second&1)==1 ) { + if (src_second_rc == rc_int && dst_second_rc == rc_stack && (src_second & 1) == 1) { // Shift src_second down to dst_second's low bits. - if( cbuf ) { - emit3_simm13( *cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020 ); + if (cbuf) { + emit3_simm13(*cbuf, Assembler::arith_op, Matcher::_regEncode[R_O7_num], Assembler::srlx_op3, Matcher::_regEncode[src_second-1], 0x1020); #ifndef PRODUCT - } else if( !do_size ) { - if( size != 0 ) st->print("\n\t"); - st->print("SRLX R_%s,32,R_%s\t! spill: Move high bits down low",OptoReg::regname(src_second-1),OptoReg::regname(R_O7_num)); + } else { + print_helper(st, "SRLX R_%s,32,R_%s\t! spill: Move high bits down low", OptoReg::regname(src_second-1), OptoReg::regname(R_O7_num)); #endif } - size+=4; src_second = OptoReg::Name(R_O7_num); // Not R_O7H_num! } // Check for high word integer load - if( dst_second_rc == rc_int && src_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,true ,ra_->reg2offset(src_second),dst_second,Assembler::lduw_op3,"LDUW",size, st); + if (dst_second_rc == rc_int && src_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, true, ra_->reg2offset(src_second), dst_second, Assembler::lduw_op3, "LDUW", size, st); // Check for high word integer store - if( src_second_rc == rc_int && dst_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stw_op3 ,"STW ",size, st); + if (src_second_rc == rc_int && dst_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stw_op3, "STW ", size, st); // Check for high word float store - if( src_second_rc == rc_float && dst_second_rc == rc_stack ) - return impl_helper(this,cbuf,ra_,do_size,false,ra_->reg2offset(dst_second),src_second,Assembler::stf_op3 ,"STF ",size, st); + if (src_second_rc == rc_float && dst_second_rc == rc_stack) + return impl_helper(this, cbuf, ra_, false, ra_->reg2offset(dst_second), src_second, Assembler::stf_op3, "STF ", size, st); #endif // !_LP64 Unimplemented(); +} + +uint MachSpillCopyNode::implementation(CodeBuffer *cbuf, + PhaseRegAlloc *ra_, + bool do_size, + outputStream* st) const { + assert(!do_size, "not supported"); + mach_spill_copy_implementation_helper(this, cbuf, ra_, st); return 0; } @@ -1669,19 +1697,19 @@ void MachSpillCopyNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { } uint MachSpillCopyNode::size(PhaseRegAlloc *ra_) const { - return implementation( NULL, ra_, true, NULL ); + return MachNode::size(ra_); } //============================================================================= #ifndef PRODUCT -void MachNopNode::format( PhaseRegAlloc *, outputStream *st ) const { +void MachNopNode::format(PhaseRegAlloc *, outputStream *st) const { st->print("NOP \t# %d bytes pad for loops and calls", 4 * _count); } #endif -void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc * ) const { +void MachNopNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *) const { MacroAssembler _masm(&cbuf); - for(int i = 0; i < _count; i += 1) { + for (int i = 0; i < _count; i += 1) { __ nop(); } } @@ -1952,9 +1980,6 @@ const bool Matcher::isSimpleConstant64(jlong value) { // No scaling for the parameter the ClearArray node. const bool Matcher::init_array_count_is_in_bytes = true; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; - // No additional cost for CMOVL. const int Matcher::long_cmove_cost() { return 0; } @@ -5197,7 +5222,6 @@ instruct stkI_to_regF(regF dst, stackSlotI src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $src,$dst\t! stkI to regF" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -5208,7 +5232,6 @@ instruct stkL_to_regD(regD dst, stackSlotL src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $src,$dst\t! stkL to regD" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -5219,7 +5242,6 @@ instruct regF_to_stkI(stackSlotI dst, regF src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$dst\t! regF to stkI" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -5230,7 +5252,6 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$dst\t! regD to stkL" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -5240,7 +5261,6 @@ instruct regD_to_stkL(stackSlotL dst, regD src) %{ instruct regI_to_stkLHi(stackSlotL dst, iRegI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST*2); - size(8); format %{ "STW $src,$dst.hi\t! long\n\t" "STW R_G0,$dst.lo" %} opcode(Assembler::stw_op3); @@ -5252,7 +5272,6 @@ instruct regL_to_stkD(stackSlotD dst, iRegL src) %{ // No match rule to avoid chain rule match. effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! regL to stkD" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5266,7 +5285,6 @@ instruct stkI_to_regI( iRegI dst, stackSlotI src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $src,$dst\t!stk" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5278,7 +5296,6 @@ instruct regI_to_stkI( stackSlotI dst, iRegI src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$dst\t!stk" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5290,7 +5307,6 @@ instruct stkL_to_regL( iRegL dst, stackSlotL src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t! long" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5302,7 +5318,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! long" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5314,7 +5329,6 @@ instruct regL_to_stkL(stackSlotL dst, iRegL src) %{ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t!ptr" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -5325,7 +5339,6 @@ instruct stkP_to_regP( iRegP dst, stackSlotP src ) %{ instruct regP_to_stkP(stackSlotP dst, iRegP src) %{ match(Set dst src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t!ptr" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -5771,7 +5784,6 @@ instruct loadL_unaligned(iRegL dst, memory mem, o7RegI tmp) %{ match(Set dst (LoadL_unaligned mem)); effect(KILL tmp); ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); - size(16); format %{ "LDUW $mem+4,R_O7\t! misaligned long\n" "\tLDUW $mem ,$dst\n" "\tSLLX #32, $dst, $dst\n" @@ -5786,7 +5798,6 @@ instruct loadRange(iRegI dst, memory mem) %{ match(Set dst (LoadRange mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $mem,$dst\t! range" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -5797,7 +5808,6 @@ instruct loadRange(iRegI dst, memory mem) %{ instruct loadI_freg(regF dst, memory mem) %{ match(Set dst (LoadI mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $mem,$dst\t! for fitos/fitod" %} opcode(Assembler::ldf_op3); @@ -5876,7 +5886,6 @@ instruct loadD(regD dst, memory mem) %{ match(Set dst (LoadD mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $mem,$dst" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -5887,7 +5896,6 @@ instruct loadD(regD dst, memory mem) %{ instruct loadD_unaligned(regD_low dst, memory mem ) %{ match(Set dst (LoadD_unaligned mem)); ins_cost(MEMORY_REF_COST*2+DEFAULT_COST); - size(8); format %{ "LDF $mem ,$dst.hi\t! misaligned double\n" "\tLDF $mem+4,$dst.lo\t!" %} opcode(Assembler::ldf_op3); @@ -5900,7 +5908,6 @@ instruct loadF(regF dst, memory mem) %{ match(Set dst (LoadF mem)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $mem,$dst" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg( mem, dst ) ); @@ -6119,7 +6126,6 @@ instruct prefetchAlloc( memory mem ) %{ predicate(AllocatePrefetchInstr == 0); match( PrefetchAllocation mem ); ins_cost(MEMORY_REF_COST); - size(4); format %{ "PREFETCH $mem,2\t! Prefetch allocation" %} opcode(Assembler::prefetch_op3); @@ -6175,7 +6181,6 @@ instruct storeB(memory mem, iRegI src) %{ match(Set mem (StoreB mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6186,7 +6191,6 @@ instruct storeB0(memory mem, immI0 src) %{ match(Set mem (StoreB mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! byte" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6197,7 +6201,6 @@ instruct storeCM0(memory mem, immI0 src) %{ match(Set mem (StoreCM mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STB $src,$mem\t! CMS card-mark byte 0" %} opcode(Assembler::stb_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6209,7 +6212,6 @@ instruct storeC(memory mem, iRegI src) %{ match(Set mem (StoreC mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6220,7 +6222,6 @@ instruct storeC0(memory mem, immI0 src) %{ match(Set mem (StoreC mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STH $src,$mem\t! short" %} opcode(Assembler::sth_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6232,7 +6233,6 @@ instruct storeI(memory mem, iRegI src) %{ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6243,7 +6243,6 @@ instruct storeI(memory mem, iRegI src) %{ instruct storeL(memory mem, iRegL src) %{ match(Set mem (StoreL mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem\t! long" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6254,7 +6253,6 @@ instruct storeI0(memory mem, immI0 src) %{ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6265,7 +6263,6 @@ instruct storeL0(memory mem, immL0 src) %{ match(Set mem (StoreL mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6277,7 +6274,6 @@ instruct storeI_Freg(memory mem, regF src) %{ match(Set mem (StoreI mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$mem\t! after fstoi/fdtoi" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6288,7 +6284,6 @@ instruct storeI_Freg(memory mem, regF src) %{ instruct storeP(memory dst, sp_ptr_RegP src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); - size(4); #ifndef _LP64 format %{ "STW $src,$dst\t! ptr" %} @@ -6304,7 +6299,6 @@ instruct storeP(memory dst, sp_ptr_RegP src) %{ instruct storeP0(memory dst, immP0 src) %{ match(Set dst (StoreP dst src)); ins_cost(MEMORY_REF_COST); - size(4); #ifndef _LP64 format %{ "STW $src,$dst\t! ptr" %} @@ -6379,7 +6373,6 @@ instruct storeD( memory mem, regD src) %{ match(Set mem (StoreD mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$mem" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6390,7 +6383,6 @@ instruct storeD0( memory mem, immD0 src) %{ match(Set mem (StoreD mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$mem" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -6402,7 +6394,6 @@ instruct storeF( memory mem, regF src) %{ match(Set mem (StoreF mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$mem" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg( mem, src ) ); @@ -6413,7 +6404,6 @@ instruct storeF0( memory mem, immF0 src) %{ match(Set mem (StoreF mem src)); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$mem\t! storeF0" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( mem, R_G0 ) ); @@ -7068,7 +7058,6 @@ instruct loadPLocked(iRegP dst, memory mem) %{ ins_cost(MEMORY_REF_COST); #ifndef _LP64 - size(4); format %{ "LDUW $mem,$dst\t! ptr" %} opcode(Assembler::lduw_op3, 0, REGP_OP); #else @@ -8138,7 +8127,6 @@ instruct MoveF2I_stack_reg(iRegI dst, stackSlotF src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDUW $src,$dst\t! MoveF2I" %} opcode(Assembler::lduw_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -8150,7 +8138,6 @@ instruct MoveI2F_stack_reg(regF dst, stackSlotI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDF $src,$dst\t! MoveI2F" %} opcode(Assembler::ldf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -8162,7 +8149,6 @@ instruct MoveD2L_stack_reg(iRegL dst, stackSlotD src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDX $src,$dst\t! MoveD2L" %} opcode(Assembler::ldx_op3); ins_encode(simple_form3_mem_reg( src, dst ) ); @@ -8174,7 +8160,6 @@ instruct MoveL2D_stack_reg(regD dst, stackSlotL src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "LDDF $src,$dst\t! MoveL2D" %} opcode(Assembler::lddf_op3); ins_encode(simple_form3_mem_reg(src, dst)); @@ -8186,7 +8171,6 @@ instruct MoveF2I_reg_stack(stackSlotI dst, regF src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STF $src,$dst\t! MoveF2I" %} opcode(Assembler::stf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -8198,7 +8182,6 @@ instruct MoveI2F_reg_stack(stackSlotF dst, iRegI src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STW $src,$dst\t! MoveI2F" %} opcode(Assembler::stw_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -8210,7 +8193,6 @@ instruct MoveD2L_reg_stack(stackSlotL dst, regD src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STDF $src,$dst\t! MoveD2L" %} opcode(Assembler::stdf_op3); ins_encode(simple_form3_mem_reg(dst, src)); @@ -8222,7 +8204,6 @@ instruct MoveL2D_reg_stack(stackSlotD dst, iRegL src) %{ effect(DEF dst, USE src); ins_cost(MEMORY_REF_COST); - size(4); format %{ "STX $src,$dst\t! MoveL2D" %} opcode(Assembler::stx_op3); ins_encode(simple_form3_mem_reg( dst, src ) ); @@ -8427,7 +8408,6 @@ instruct convI2D_reg(regD_low dst, iRegI src) %{ instruct convI2D_mem(regD_low dst, memory mem) %{ match(Set dst (ConvI2D (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); format %{ "LDF $mem,$dst\n\t" "FITOD $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitod_opf); @@ -8468,7 +8448,6 @@ instruct convI2F_reg(regF dst, iRegI src) %{ instruct convI2F_mem( regF dst, memory mem ) %{ match(Set dst (ConvI2F (LoadI mem))); ins_cost(DEFAULT_COST + MEMORY_REF_COST); - size(8); format %{ "LDF $mem,$dst\n\t" "FITOS $dst,$dst" %} opcode(Assembler::ldf_op3, Assembler::fitos_opf); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 9a6679d17ab..34041ed9943 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -463,3 +463,37 @@ unsigned int VM_Version::calc_parallel_worker_threads() { } return result; } + + +int VM_Version::parse_features(const char* implementation) { + int features = unknown_m; + // Convert to UPPER case before compare. + char* impl = os::strdup_check_oom(implementation); + + for (int i = 0; impl[i] != 0; i++) + impl[i] = (char)toupper((uint)impl[i]); + + if (strstr(impl, "SPARC64") != NULL) { + features |= sparc64_family_m; + } else if (strstr(impl, "SPARC-M") != NULL) { + // M-series SPARC is based on T-series. + features |= (M_family_m | T_family_m); + } else if (strstr(impl, "SPARC-T") != NULL) { + features |= T_family_m; + if (strstr(impl, "SPARC-T1") != NULL) { + features |= T1_model_m; + } + } else { + if (strstr(impl, "SPARC") == NULL) { +#ifndef PRODUCT + // kstat on Solaris 8 virtual machines (branded zones) + // returns "(unsupported)" implementation. Solaris 8 is not + // supported anymore, but include this check to be on the + // safe side. + warning("Can't parse CPU implementation = '%s', assume generic SPARC", impl); +#endif + } + } + os::free((void*)impl); + return features; +} diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index 0609fa8b9a0..f2c5955905e 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -121,7 +121,7 @@ protected: static bool is_T1_model(int features) { return is_T_family(features) && ((features & T1_model_m) != 0); } static int maximum_niagara1_processor_count() { return 32; } - + static int parse_features(const char* implementation); public: // Initialization static void initialize(); diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.cpp b/hotspot/src/cpu/x86/vm/assembler_x86.cpp index 00ce5c3560c..ffdd9fe2338 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -777,6 +777,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { case 0x6E: // movd case 0x7E: // movd case 0xAE: // ldmxcsr, stmxcsr, fxrstor, fxsave, clflush + case 0xFE: // paddd debug_only(has_disp32 = true); break; @@ -926,6 +927,7 @@ address Assembler::locate_operand(address inst, WhichOperand which) { ip++; // skip P2, move to opcode // To find the end of instruction (which == end_pc_operand). switch (0xFF & *ip) { + case 0x22: // pinsrd r, r/a, #8 case 0x61: // pcmpestri r, r/a, #8 case 0x70: // pshufd r, r/a, #8 case 0x73: // psrldq r, #8 @@ -3953,6 +3955,83 @@ void Assembler::setb(Condition cc, Register dst) { emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::palignr(XMMRegister dst, XMMRegister src, int imm8) { + assert(VM_Version::supports_ssse3(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ _legacy_mode_bw, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0x0F); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(imm8); +} + +void Assembler::pblendw(XMMRegister dst, XMMRegister src, int imm8) { + assert(VM_Version::supports_sse4_1(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0x0E); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8(imm8); +} + +void Assembler::sha1rnds4(XMMRegister dst, XMMRegister src, int imm8) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_3A, &attributes); + emit_int8((unsigned char)0xCC); + emit_int8((unsigned char)(0xC0 | encode)); + emit_int8((unsigned char)imm8); +} + +void Assembler::sha1nexte(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xC8); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha1msg1(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xC9); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha1msg2(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCA); + emit_int8((unsigned char)(0xC0 | encode)); +} + +// xmm0 is implicit additional source to this instruction. +void Assembler::sha256rnds2(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCB); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha256msg1(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCC); + emit_int8((unsigned char)(0xC0 | encode)); +} + +void Assembler::sha256msg2(XMMRegister dst, XMMRegister src) { + assert(VM_Version::supports_sha(), ""); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ false, /* uses_vl */ false); + int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, VEX_OPCODE_0F_38, &attributes); + emit_int8((unsigned char)0xCD); + emit_int8((unsigned char)(0xC0 | encode)); +} + + void Assembler::shll(Register dst, int imm8) { assert(isShiftCount(imm8), "illegal shift count"); int encode = prefix_and_encode(dst->encoding()); @@ -4931,6 +5010,15 @@ void Assembler::paddd(XMMRegister dst, XMMRegister src) { emit_int8((unsigned char)(0xC0 | encode)); } +void Assembler::paddd(XMMRegister dst, Address src) { + NOT_LP64(assert(VM_Version::supports_sse2(), "")); + InstructionMark im(this); + InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); + simd_prefix(dst, xnoreg, src, VEX_SIMD_66, VEX_OPCODE_0F, &attributes); + emit_int8((unsigned char)0xFE); + emit_operand(dst, src); +} + void Assembler::paddq(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ VM_Version::supports_evex(), /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ true); @@ -5611,8 +5699,9 @@ void Assembler::vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_ } -void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { +void Assembler::vinsertf128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; @@ -5621,11 +5710,12 @@ void Assembler::vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src) emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) { +void Assembler::vinsertf64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5633,26 +5723,29 @@ void Assembler::vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 256 bits // 0x01 - insert into upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinsertf64x4h(XMMRegister dst, Address src, int value) { +void Assembler::vinsertf64x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionMark im(this); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); + int nds_enc = nds->is_valid() ? nds->encoding() : 0; attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_64bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x1A); emit_operand(dst, src); // 0x00 - insert into lower 256 bits - // 0x01 - insert into upper 128 bits - emit_int8(value & 0x01); + // 0x01 - insert into upper 256 bits + emit_int8(imm8 & 0x01); } -void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) { +void Assembler::vinsertf32x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5662,57 +5755,64 @@ void Assembler::vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, // 0x01 - insert into q1 128 bits (128..255) // 0x02 - insert into q2 128 bits (256..383) // 0x03 - insert into q3 128 bits (384..511) - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vinsertf32x4h(XMMRegister dst, Address src, int value) { +void Assembler::vinsertf32x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x03, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; + int nds_enc = nds->is_valid() ? nds->encoding() : 0; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x18); emit_operand(dst, src); // 0x00 - insert into q0 128 bits (0..127) // 0x01 - insert into q1 128 bits (128..255) // 0x02 - insert into q2 128 bits (256..383) // 0x03 - insert into q3 128 bits (384..511) - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vinsertf128h(XMMRegister dst, Address src) { +void Assembler::vinsertf128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; + int nds_enc = nds->is_valid() ? nds->encoding() : 0; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x18); emit_operand(dst, src); + // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextractf128h(XMMRegister dst, XMMRegister src) { +void Assembler::vextractf128(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x19); emit_int8((unsigned char)(0xC0 | encode)); - // 0x00 - insert into lower 128 bits - // 0x01 - insert into upper 128 bits - emit_int8(0x01); + // 0x00 - extract from lower 128 bits + // 0x01 - extract from upper 128 bits + emit_int8(imm8 & 0x01); } -void Assembler::vextractf128h(Address dst, XMMRegister src) { +void Assembler::vextractf128(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); @@ -5720,12 +5820,14 @@ void Assembler::vextractf128h(Address dst, XMMRegister src) { vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x19); emit_operand(src, dst); + // 0x00 - extract from lower 128 bits // 0x01 - extract from upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { +void Assembler::vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx2(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; @@ -5734,11 +5836,12 @@ void Assembler::vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value) { +void Assembler::vinserti64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int nds_enc = nds->is_valid() ? nds->encoding() : 0; int encode = vex_prefix_and_encode(dst->encoding(), nds_enc, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5746,39 +5849,44 @@ void Assembler::vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - insert into lower 256 bits // 0x01 - insert into upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vinserti128h(XMMRegister dst, Address src) { +void Assembler::vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { assert(VM_Version::supports_avx2(), ""); assert(dst != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; + int nds_enc = nds->is_valid() ? nds->encoding() : 0; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); // swap src<->dst for encoding - vex_prefix(src, dst->encoding(), dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + vex_prefix(src, nds_enc, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x38); emit_operand(dst, src); + // 0x00 - insert into lower 128 bits // 0x01 - insert into upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextracti128h(XMMRegister dst, XMMRegister src) { +void Assembler::vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x39); emit_int8((unsigned char)(0xC0 | encode)); - // 0x00 - insert into lower 128 bits - // 0x01 - insert into upper 128 bits - emit_int8(0x01); + // 0x00 - extract from lower 128 bits + // 0x01 - extract from upper 128 bits + emit_int8(imm8 & 0x01); } -void Assembler::vextracti128h(Address dst, XMMRegister src) { +void Assembler::vextracti128(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx2(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionMark im(this); InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); @@ -5786,47 +5894,53 @@ void Assembler::vextracti128h(Address dst, XMMRegister src) { vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x39); emit_operand(src, dst); + // 0x00 - extract from lower 128 bits // 0x01 - extract from upper 128 bits - emit_int8(0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextracti64x4h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextracti64x4(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x3B); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - extract from lower 256 bits // 0x01 - extract from upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextracti64x2h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextracti64x2(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ !_legacy_mode_dq, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x39); emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - extract from bits 127:0 // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vextractf64x4h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextractf64x4(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x1B); emit_int8((unsigned char)(0xC0 | encode)); // 0x00 - extract from lower 256 bits // 0x01 - extract from upper 256 bits - emit_int8(value & 0x1); + emit_int8(imm8 & 0x01); } -void Assembler::vextractf64x4h(Address dst, XMMRegister src, int value) { +void Assembler::vextractf64x4(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x01, "imm8: %u", imm8); InstructionMark im(this); InstructionAttr attributes(AVX_512bit, /* vex_w */ true, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4,/* input_size_in_bits */ EVEX_64bit); @@ -5835,11 +5949,12 @@ void Assembler::vextractf64x4h(Address dst, XMMRegister src, int value) { emit_operand(src, dst); // 0x00 - extract from lower 256 bits // 0x01 - extract from upper 256 bits - emit_int8(value & 0x01); + emit_int8(imm8 & 0x01); } -void Assembler::vextractf32x4h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextractf32x4(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_avx(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); int vector_len = VM_Version::supports_evex() ? AVX_512bit : AVX_256bit; InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); @@ -5849,12 +5964,13 @@ void Assembler::vextractf32x4h(XMMRegister dst, XMMRegister src, int value) { // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) { +void Assembler::vextractf32x4(Address dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); assert(src != xnoreg, "sanity"); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionMark im(this); InstructionAttr attributes(AVX_512bit, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); attributes.set_address_attributes(/* tuple_type */ EVEX_T4, /* input_size_in_bits */ EVEX_32bit); @@ -5865,19 +5981,21 @@ void Assembler::vextractf32x4h(Address dst, XMMRegister src, int value) { // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } -void Assembler::vextractf64x2h(XMMRegister dst, XMMRegister src, int value) { +void Assembler::vextractf64x2(XMMRegister dst, XMMRegister src, uint8_t imm8) { assert(VM_Version::supports_evex(), ""); + assert(imm8 <= 0x03, "imm8: %u", imm8); InstructionAttr attributes(AVX_512bit, /* vex_w */ !_legacy_mode_dq, /* legacy_mode */ false, /* no_mask_reg */ false, /* uses_vl */ false); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int8(0x19); emit_int8((unsigned char)(0xC0 | encode)); + // 0x00 - extract from bits 127:0 // 0x01 - extract from bits 255:128 // 0x02 - extract from bits 383:256 // 0x03 - extract from bits 511:384 - emit_int8(value & 0x3); + emit_int8(imm8 & 0x03); } // duplicate 4-bytes integer data from src into 8 locations in dest diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 7712ce02cab..561278599b7 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1672,6 +1672,18 @@ private: void setb(Condition cc, Register dst); + void palignr(XMMRegister dst, XMMRegister src, int imm8); + void pblendw(XMMRegister dst, XMMRegister src, int imm8); + + void sha1rnds4(XMMRegister dst, XMMRegister src, int imm8); + void sha1nexte(XMMRegister dst, XMMRegister src); + void sha1msg1(XMMRegister dst, XMMRegister src); + void sha1msg2(XMMRegister dst, XMMRegister src); + // xmm0 is implicit additional source to the following instruction. + void sha256rnds2(XMMRegister dst, XMMRegister src); + void sha256msg1(XMMRegister dst, XMMRegister src); + void sha256msg2(XMMRegister dst, XMMRegister src); + void shldl(Register dst, Register src); void shldl(Register dst, Register src, int8_t imm8); @@ -1868,6 +1880,7 @@ private: void paddb(XMMRegister dst, XMMRegister src); void paddw(XMMRegister dst, XMMRegister src); void paddd(XMMRegister dst, XMMRegister src); + void paddd(XMMRegister dst, Address src); void paddq(XMMRegister dst, XMMRegister src); void vpaddb(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpaddw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); @@ -1958,33 +1971,31 @@ private: void vpxor(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len); void vpxor(XMMRegister dst, XMMRegister nds, Address src, int vector_len); - // Copy low 128bit into high 128bit of YMM registers. - void vinsertf128h(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src); - void vextractf128h(XMMRegister dst, XMMRegister src); - void vextracti128h(XMMRegister dst, XMMRegister src); + // 128bit copy from/to 256bit (YMM) vector registers + void vinsertf128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vextractf128(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vinsertf128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); + void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); + void vextractf128(Address dst, XMMRegister src, uint8_t imm8); + void vextracti128(Address dst, XMMRegister src, uint8_t imm8); - // Load/store high 128bit of YMM registers which does not destroy other half. - void vinsertf128h(XMMRegister dst, Address src); - void vinserti128h(XMMRegister dst, Address src); - void vextractf128h(Address dst, XMMRegister src); - void vextracti128h(Address dst, XMMRegister src); + // 256bit copy from/to 512bit (ZMM) vector registers + void vinserti64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vinsertf64x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vextracti64x4(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf64x4(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf64x4(Address dst, XMMRegister src, uint8_t imm8); + void vinsertf64x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); - // Copy low 256bit into high 256bit of ZMM registers. - void vinserti64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); - void vinsertf64x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); - void vextracti64x4h(XMMRegister dst, XMMRegister src, int value); - void vextractf64x4h(XMMRegister dst, XMMRegister src, int value); - void vextractf64x4h(Address dst, XMMRegister src, int value); - void vinsertf64x4h(XMMRegister dst, Address src, int value); - - // Copy targeted 128bit segments of the ZMM registers - void vextracti64x2h(XMMRegister dst, XMMRegister src, int value); - void vextractf64x2h(XMMRegister dst, XMMRegister src, int value); - void vextractf32x4h(XMMRegister dst, XMMRegister src, int value); - void vextractf32x4h(Address dst, XMMRegister src, int value); - void vinsertf32x4h(XMMRegister dst, XMMRegister nds, XMMRegister src, int value); - void vinsertf32x4h(XMMRegister dst, Address src, int value); + // 128bit copy from/to 256bit (YMM) or 512bit (ZMM) vector registers + void vextracti64x2(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf64x2(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf32x4(XMMRegister dst, XMMRegister src, uint8_t imm8); + void vextractf32x4(Address dst, XMMRegister src, uint8_t imm8); + void vinsertf32x4(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8); + void vinsertf32x4(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8); // duplicate 4-bytes integer data from src into 8 locations in dest void vpbroadcastd(XMMRegister dst, XMMRegister src); diff --git a/hotspot/src/cpu/x86/vm/globals_x86.hpp b/hotspot/src/cpu/x86/vm/globals_x86.hpp index 7a34048248e..a8d36092b58 100644 --- a/hotspot/src/cpu/x86/vm/globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/globals_x86.hpp @@ -97,6 +97,8 @@ define_pd_global(bool, CompactStrings, true); define_pd_global(bool, PreserveFramePointer, false); +define_pd_global(intx, InitArrayShortSize, 8*BytesPerLong); + #define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \ \ develop(bool, IEEEPrecision, true, \ diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index e1c73024118..8eb6764770f 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -3445,7 +3445,7 @@ void MacroAssembler::movptr(Address dst, Register src) { void MacroAssembler::movdqu(Address dst, XMMRegister src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (src->encoding() > 15)) { - Assembler::vextractf32x4h(dst, src, 0); + Assembler::vextractf32x4(dst, src, 0); } else { Assembler::movdqu(dst, src); } @@ -3453,7 +3453,7 @@ void MacroAssembler::movdqu(Address dst, XMMRegister src) { void MacroAssembler::movdqu(XMMRegister dst, Address src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (dst->encoding() > 15)) { - Assembler::vinsertf32x4h(dst, src, 0); + Assembler::vinsertf32x4(dst, dst, src, 0); } else { Assembler::movdqu(dst, src); } @@ -3478,7 +3478,7 @@ void MacroAssembler::movdqu(XMMRegister dst, AddressLiteral src) { void MacroAssembler::vmovdqu(Address dst, XMMRegister src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (src->encoding() > 15)) { - Assembler::vextractf64x4h(dst, src, 0); + vextractf64x4_low(dst, src); } else { Assembler::vmovdqu(dst, src); } @@ -3486,7 +3486,7 @@ void MacroAssembler::vmovdqu(Address dst, XMMRegister src) { void MacroAssembler::vmovdqu(XMMRegister dst, Address src) { if (UseAVX > 2 && !VM_Version::supports_avx512vl() && (dst->encoding() > 15)) { - Assembler::vinsertf64x4h(dst, src, 0); + vinsertf64x4_low(dst, src); } else { Assembler::vmovdqu(dst, src); } @@ -5649,14 +5649,14 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int // Save upper half of ZMM registers subptr(rsp, 32*num_xmm_regs); for (int n = 0; n < num_xmm_regs; n++) { - vextractf64x4h(Address(rsp, n*32), as_XMMRegister(n), 1); + vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n)); } } assert(UseAVX > 0, "256 bit vectors are supported only with AVX"); // Save upper half of YMM registers subptr(rsp, 16*num_xmm_regs); for (int n = 0; n < num_xmm_regs; n++) { - vextractf128h(Address(rsp, n*16), as_XMMRegister(n)); + vextractf128_high(Address(rsp, n*16), as_XMMRegister(n)); } } #endif @@ -5665,7 +5665,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int #ifdef _LP64 if (VM_Version::supports_evex()) { for (int n = 0; n < num_xmm_regs; n++) { - vextractf32x4h(Address(rsp, n*16), as_XMMRegister(n), 0); + vextractf32x4(Address(rsp, n*16), as_XMMRegister(n), 0); } } else { for (int n = 0; n < num_xmm_regs; n++) { @@ -5753,7 +5753,7 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int #ifdef _LP64 if (VM_Version::supports_evex()) { for (int n = 0; n < num_xmm_regs; n++) { - vinsertf32x4h(as_XMMRegister(n), Address(rsp, n*16), 0); + vinsertf32x4(as_XMMRegister(n), as_XMMRegister(n), Address(rsp, n*16), 0); } } else { for (int n = 0; n < num_xmm_regs; n++) { @@ -5771,12 +5771,12 @@ void MacroAssembler::fp_runtime_fallback(address runtime_entry, int nb_args, int if (MaxVectorSize > 16) { // Restore upper half of YMM registers. for (int n = 0; n < num_xmm_regs; n++) { - vinsertf128h(as_XMMRegister(n), Address(rsp, n*16)); + vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16)); } addptr(rsp, 16*num_xmm_regs); if(UseAVX > 2) { for (int n = 0; n < num_xmm_regs; n++) { - vinsertf64x4h(as_XMMRegister(n), Address(rsp, n*32), 1); + vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32)); } addptr(rsp, 32*num_xmm_regs); } @@ -7198,21 +7198,50 @@ void MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool fp_ } -void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp) { +void MacroAssembler::clear_mem(Register base, Register cnt, Register tmp, bool is_large) { // cnt - number of qwords (8-byte words). // base - start address, qword aligned. + // is_large - if optimizers know cnt is larger than InitArrayShortSize assert(base==rdi, "base register must be edi for rep stos"); assert(tmp==rax, "tmp register must be eax for rep stos"); assert(cnt==rcx, "cnt register must be ecx for rep stos"); + assert(InitArrayShortSize % BytesPerLong == 0, + "InitArrayShortSize should be the multiple of BytesPerLong"); + + Label DONE; xorptr(tmp, tmp); + + if (!is_large) { + Label LOOP, LONG; + cmpptr(cnt, InitArrayShortSize/BytesPerLong); + jccb(Assembler::greater, LONG); + + NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM + + decrement(cnt); + jccb(Assembler::negative, DONE); // Zero length + + // Use individual pointer-sized stores for small counts: + BIND(LOOP); + movptr(Address(base, cnt, Address::times_ptr), tmp); + decrement(cnt); + jccb(Assembler::greaterEqual, LOOP); + jmpb(DONE); + + BIND(LONG); + } + + // Use longer rep-prefixed ops for non-small counts: if (UseFastStosb) { - shlptr(cnt,3); // convert to number of bytes + shlptr(cnt, 3); // convert to number of bytes rep_stosb(); } else { - NOT_LP64(shlptr(cnt,1);) // convert to number of dwords for 32-bit VM + NOT_LP64(shlptr(cnt, 1);) // convert to number of 32-bit words for 32-bit VM rep_stos(); } + + BIND(DONE); } #ifdef COMPILER2 diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp index 95931ad2b24..e325bbcdb2d 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,7 +48,6 @@ class MacroAssembler: public Assembler { // This is the base routine called by the different versions of call_VM_leaf. The interpreter // may customize this version by overriding it for its purposes (e.g., to save/restore // additional registers when doing a VM call). -#define COMMA , virtual void call_VM_leaf_base( address entry_point, // the entry point @@ -903,35 +902,66 @@ class MacroAssembler: public Assembler { void ldmxcsr(Address src) { Assembler::ldmxcsr(src); } void ldmxcsr(AddressLiteral src); + void fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0, + XMMRegister msg1, XMMRegister msg2, XMMRegister msg3, XMMRegister shuf_mask, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block); + +#ifdef _LP64 + void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block, XMMRegister shuf_mask); +#else + void fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block); +#endif + void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, Register rdx, Register tmp); +#ifdef _LP64 void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2)); + Register rax, Register rcx, Register rdx, Register tmp1, Register tmp2); void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, - Register rdx NOT_LP64(COMMA Register tmp) LP64_ONLY(COMMA Register tmp1) - LP64_ONLY(COMMA Register tmp2) LP64_ONLY(COMMA Register tmp3) LP64_ONLY(COMMA Register tmp4)); + Register rdx, Register tmp1, Register tmp2, Register tmp3, Register tmp4); void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rbx LP64_ONLY(COMMA Register rcx), Register rdx - LP64_ONLY(COMMA Register tmp1) LP64_ONLY(COMMA Register tmp2) - LP64_ONLY(COMMA Register tmp3) LP64_ONLY(COMMA Register tmp4)); + Register rax, Register rbx, Register rcx, Register rdx, Register tmp1, Register tmp2, + Register tmp3, Register tmp4); void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, - Register rax, Register rcx, Register rdx NOT_LP64(COMMA Register tmp) - LP64_ONLY(COMMA Register r8) LP64_ONLY(COMMA Register r9) - LP64_ONLY(COMMA Register r10) LP64_ONLY(COMMA Register r11)); + Register rax, Register rcx, Register rdx, Register tmp1, + Register tmp2, Register tmp3, Register tmp4); +#else + void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, + XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, + Register rax, Register rcx, Register rdx, Register tmp1); + + void fast_pow(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, + XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register rax, Register rcx, + Register rdx, Register tmp); + + void fast_sin(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, + XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, + Register rax, Register rbx, Register rdx); + + void fast_cos(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, + XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, + Register rax, Register rcx, Register rdx, Register tmp); -#ifndef _LP64 void libm_sincos_huge(XMMRegister xmm0, XMMRegister xmm1, Register eax, Register ecx, Register edx, Register ebx, Register esi, Register edi, Register ebp, Register esp); + void libm_reduce_pi04l(Register eax, Register ecx, Register edx, Register ebx, Register esi, Register edi, Register ebp, Register esp); #endif @@ -1185,14 +1215,131 @@ public: void vpxor(XMMRegister dst, XMMRegister src) { Assembler::vpxor(dst, dst, src, true); } void vpxor(XMMRegister dst, Address src) { Assembler::vpxor(dst, dst, src, true); } - // Move packed integer values from low 128 bit to hign 128 bit in 256 bit vector. - void vinserti128h(XMMRegister dst, XMMRegister nds, XMMRegister src) { - if (UseAVX > 1) // vinserti128h is available only in AVX2 - Assembler::vinserti128h(dst, nds, src); - else - Assembler::vinsertf128h(dst, nds, src); + void vinserti128(XMMRegister dst, XMMRegister nds, XMMRegister src, uint8_t imm8) { + if (UseAVX > 1) { // vinserti128 is available only in AVX2 + Assembler::vinserti128(dst, nds, src, imm8); + } else { + Assembler::vinsertf128(dst, nds, src, imm8); + } } + void vinserti128(XMMRegister dst, XMMRegister nds, Address src, uint8_t imm8) { + if (UseAVX > 1) { // vinserti128 is available only in AVX2 + Assembler::vinserti128(dst, nds, src, imm8); + } else { + Assembler::vinsertf128(dst, nds, src, imm8); + } + } + + void vextracti128(XMMRegister dst, XMMRegister src, uint8_t imm8) { + if (UseAVX > 1) { // vextracti128 is available only in AVX2 + Assembler::vextracti128(dst, src, imm8); + } else { + Assembler::vextractf128(dst, src, imm8); + } + } + + void vextracti128(Address dst, XMMRegister src, uint8_t imm8) { + if (UseAVX > 1) { // vextracti128 is available only in AVX2 + Assembler::vextracti128(dst, src, imm8); + } else { + Assembler::vextractf128(dst, src, imm8); + } + } + + // 128bit copy to/from high 128 bits of 256bit (YMM) vector registers + void vinserti128_high(XMMRegister dst, XMMRegister src) { + vinserti128(dst, dst, src, 1); + } + void vinserti128_high(XMMRegister dst, Address src) { + vinserti128(dst, dst, src, 1); + } + void vextracti128_high(XMMRegister dst, XMMRegister src) { + vextracti128(dst, src, 1); + } + void vextracti128_high(Address dst, XMMRegister src) { + vextracti128(dst, src, 1); + } + void vinsertf128_high(XMMRegister dst, XMMRegister src) { + vinsertf128(dst, dst, src, 1); + } + void vinsertf128_high(XMMRegister dst, Address src) { + vinsertf128(dst, dst, src, 1); + } + void vextractf128_high(XMMRegister dst, XMMRegister src) { + vextractf128(dst, src, 1); + } + void vextractf128_high(Address dst, XMMRegister src) { + vextractf128(dst, src, 1); + } + + // 256bit copy to/from high 256 bits of 512bit (ZMM) vector registers + void vinserti64x4_high(XMMRegister dst, XMMRegister src) { + vinserti64x4(dst, dst, src, 1); + } + void vinsertf64x4_high(XMMRegister dst, XMMRegister src) { + vinsertf64x4(dst, dst, src, 1); + } + void vextracti64x4_high(XMMRegister dst, XMMRegister src) { + vextracti64x4(dst, src, 1); + } + void vextractf64x4_high(XMMRegister dst, XMMRegister src) { + vextractf64x4(dst, src, 1); + } + void vextractf64x4_high(Address dst, XMMRegister src) { + vextractf64x4(dst, src, 1); + } + void vinsertf64x4_high(XMMRegister dst, Address src) { + vinsertf64x4(dst, dst, src, 1); + } + + // 128bit copy to/from low 128 bits of 256bit (YMM) vector registers + void vinserti128_low(XMMRegister dst, XMMRegister src) { + vinserti128(dst, dst, src, 0); + } + void vinserti128_low(XMMRegister dst, Address src) { + vinserti128(dst, dst, src, 0); + } + void vextracti128_low(XMMRegister dst, XMMRegister src) { + vextracti128(dst, src, 0); + } + void vextracti128_low(Address dst, XMMRegister src) { + vextracti128(dst, src, 0); + } + void vinsertf128_low(XMMRegister dst, XMMRegister src) { + vinsertf128(dst, dst, src, 0); + } + void vinsertf128_low(XMMRegister dst, Address src) { + vinsertf128(dst, dst, src, 0); + } + void vextractf128_low(XMMRegister dst, XMMRegister src) { + vextractf128(dst, src, 0); + } + void vextractf128_low(Address dst, XMMRegister src) { + vextractf128(dst, src, 0); + } + + // 256bit copy to/from low 256 bits of 512bit (ZMM) vector registers + void vinserti64x4_low(XMMRegister dst, XMMRegister src) { + vinserti64x4(dst, dst, src, 0); + } + void vinsertf64x4_low(XMMRegister dst, XMMRegister src) { + vinsertf64x4(dst, dst, src, 0); + } + void vextracti64x4_low(XMMRegister dst, XMMRegister src) { + vextracti64x4(dst, src, 0); + } + void vextractf64x4_low(XMMRegister dst, XMMRegister src) { + vextractf64x4(dst, src, 0); + } + void vextractf64x4_low(Address dst, XMMRegister src) { + vextractf64x4(dst, src, 0); + } + void vinsertf64x4_low(XMMRegister dst, Address src) { + vinsertf64x4(dst, dst, src, 0); + } + + // Carry-Less Multiplication Quadword void vpclmulldq(XMMRegister dst, XMMRegister nds, XMMRegister src) { // 0x00 - multiply lower 64 bits [0:63] @@ -1284,8 +1431,9 @@ public: // C2 compiled method's prolog code. void verified_entry(int framesize, int stack_bang_size, bool fp_mode_24b); - // clear memory of size 'cnt' qwords, starting at 'base'. - void clear_mem(Register base, Register cnt, Register rtmp); + // clear memory of size 'cnt' qwords, starting at 'base'; + // if 'is_large' is set, do not try to produce short loop + void clear_mem(Register base, Register cnt, Register rtmp, bool is_large); #ifdef COMPILER2 void string_indexof_char(Register str1, Register cnt1, Register ch, Register result, diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp new file mode 100644 index 00000000000..bbc96156fe5 --- /dev/null +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86_sha.cpp @@ -0,0 +1,495 @@ +/* +* Copyright (c) 2016, Intel Corporation. +* +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +* +*/ + +#include "precompiled.hpp" +#include "asm/assembler.hpp" +#include "asm/assembler.inline.hpp" +#include "runtime/stubRoutines.hpp" +#include "macroAssembler_x86.hpp" + +// ofs and limit are used for multi-block byte array. +// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) +void MacroAssembler::fast_sha1(XMMRegister abcd, XMMRegister e0, XMMRegister e1, XMMRegister msg0, + XMMRegister msg1, XMMRegister msg2, XMMRegister msg3, XMMRegister shuf_mask, + Register buf, Register state, Register ofs, Register limit, Register rsp, bool multi_block) { + + Label start, done_hash, loop0; + + address upper_word_mask = StubRoutines::x86::upper_word_mask_addr(); + address shuffle_byte_flip_mask = StubRoutines::x86::shuffle_byte_flip_mask_addr(); + + bind(start); + movdqu(abcd, Address(state, 0)); + pinsrd(e0, Address(state, 16), 3); + movdqu(shuf_mask, ExternalAddress(upper_word_mask)); // 0xFFFFFFFF000000000000000000000000 + pand(e0, shuf_mask); + pshufd(abcd, abcd, 0x1B); + movdqu(shuf_mask, ExternalAddress(shuffle_byte_flip_mask)); //0x000102030405060708090a0b0c0d0e0f + + bind(loop0); + // Save hash values for addition after rounds + movdqu(Address(rsp, 0), e0); + movdqu(Address(rsp, 16), abcd); + + + // Rounds 0 - 3 + movdqu(msg0, Address(buf, 0)); + pshufb(msg0, shuf_mask); + paddd(e0, msg0); + movdqa(e1, abcd); + sha1rnds4(abcd, e0, 0); + + // Rounds 4 - 7 + movdqu(msg1, Address(buf, 16)); + pshufb(msg1, shuf_mask); + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1rnds4(abcd, e1, 0); + sha1msg1(msg0, msg1); + + // Rounds 8 - 11 + movdqu(msg2, Address(buf, 32)); + pshufb(msg2, shuf_mask); + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1rnds4(abcd, e0, 0); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 12 - 15 + movdqu(msg3, Address(buf, 48)); + pshufb(msg3, shuf_mask); + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 0); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 16 - 19 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 0); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 20 - 23 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 1); + sha1msg1(msg0, msg1); + pxor(msg3, msg1); + + // Rounds 24 - 27 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 1); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 28 - 31 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 1); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 32 - 35 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 1); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 36 - 39 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 1); + sha1msg1(msg0, msg1); + pxor(msg3, msg1); + + // Rounds 40 - 43 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 2); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 44 - 47 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 2); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 48 - 51 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 2); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 52 - 55 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 2); + sha1msg1(msg0, msg1); + pxor(msg3, msg1); + + // Rounds 56 - 59 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 2); + sha1msg1(msg1, msg2); + pxor(msg0, msg2); + + // Rounds 60 - 63 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1msg2(msg0, msg3); + sha1rnds4(abcd, e1, 3); + sha1msg1(msg2, msg3); + pxor(msg1, msg3); + + // Rounds 64 - 67 + sha1nexte(e0, msg0); + movdqa(e1, abcd); + sha1msg2(msg1, msg0); + sha1rnds4(abcd, e0, 3); + sha1msg1(msg3, msg0); + pxor(msg2, msg0); + + // Rounds 68 - 71 + sha1nexte(e1, msg1); + movdqa(e0, abcd); + sha1msg2(msg2, msg1); + sha1rnds4(abcd, e1, 3); + pxor(msg3, msg1); + + // Rounds 72 - 75 + sha1nexte(e0, msg2); + movdqa(e1, abcd); + sha1msg2(msg3, msg2); + sha1rnds4(abcd, e0, 3); + + // Rounds 76 - 79 + sha1nexte(e1, msg3); + movdqa(e0, abcd); + sha1rnds4(abcd, e1, 3); + + // add current hash values with previously saved + movdqu(msg0, Address(rsp, 0)); + sha1nexte(e0, msg0); + movdqu(msg0, Address(rsp, 16)); + paddd(abcd, msg0); + + if (multi_block) { + // increment data pointer and loop if more to process + addptr(buf, 64); + addptr(ofs, 64); + cmpptr(ofs, limit); + jcc(Assembler::belowEqual, loop0); + movptr(rax, ofs); //return ofs + } + // write hash values back in the correct order + pshufd(abcd, abcd, 0x1b); + movdqu(Address(state, 0), abcd); + pextrd(Address(state, 16), e0, 3); + + bind(done_hash); + +} + +// xmm0 (msg) is used as an implicit argument to sh256rnds2 +// and state0 and state1 can never use xmm0 register. +// ofs and limit are used for multi-block byte array. +// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) +#ifdef _LP64 +void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block, XMMRegister shuf_mask) { +#else +void MacroAssembler::fast_sha256(XMMRegister msg, XMMRegister state0, XMMRegister state1, XMMRegister msgtmp0, + XMMRegister msgtmp1, XMMRegister msgtmp2, XMMRegister msgtmp3, XMMRegister msgtmp4, + Register buf, Register state, Register ofs, Register limit, Register rsp, + bool multi_block) { +#endif + Label start, done_hash, loop0; + + address K256 = StubRoutines::x86::k256_addr(); + address pshuffle_byte_flip_mask = StubRoutines::x86::pshuffle_byte_flip_mask_addr(); + + bind(start); + movdqu(state0, Address(state, 0)); + movdqu(state1, Address(state, 16)); + + pshufd(state0, state0, 0xB1); + pshufd(state1, state1, 0x1B); + movdqa(msgtmp4, state0); + palignr(state0, state1, 8); + pblendw(state1, msgtmp4, 0xF0); + +#ifdef _LP64 + movdqu(shuf_mask, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + lea(rax, ExternalAddress(K256)); + + bind(loop0); + movdqu(Address(rsp, 0), state0); + movdqu(Address(rsp, 16), state1); + + // Rounds 0-3 + movdqu(msg, Address(buf, 0)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp0, msg); + paddd(msg, Address(rax, 0)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + + // Rounds 4-7 + movdqu(msg, Address(buf, 16)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp1, msg); + paddd(msg, Address(rax, 16)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp0, msgtmp1); + + // Rounds 8-11 + movdqu(msg, Address(buf, 32)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp2, msg); + paddd(msg, Address(rax, 32)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp1, msgtmp2); + + // Rounds 12-15 + movdqu(msg, Address(buf, 48)); +#ifdef _LP64 + pshufb(msg, shuf_mask); +#else + pshufb(msg, ExternalAddress(pshuffle_byte_flip_mask)); +#endif + movdqa(msgtmp3, msg); + paddd(msg, Address(rax, 48)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp3); + palignr(msgtmp4, msgtmp2, 4); + paddd(msgtmp0, msgtmp4); + sha256msg2(msgtmp0, msgtmp3); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp2, msgtmp3); + + // Rounds 16-19 + movdqa(msg, msgtmp0); + paddd(msg, Address(rax, 64)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp0); + palignr(msgtmp4, msgtmp3, 4); + paddd(msgtmp1, msgtmp4); + sha256msg2(msgtmp1, msgtmp0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp3, msgtmp0); + + // Rounds 20-23 + movdqa(msg, msgtmp1); + paddd(msg, Address(rax, 80)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp1); + palignr(msgtmp4, msgtmp0, 4); + paddd(msgtmp2, msgtmp4); + sha256msg2(msgtmp2, msgtmp1); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp0, msgtmp1); + + // Rounds 24-27 + movdqa(msg, msgtmp2); + paddd(msg, Address(rax, 96)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp2); + palignr(msgtmp4, msgtmp1, 4); + paddd(msgtmp3, msgtmp4); + sha256msg2(msgtmp3, msgtmp2); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp1, msgtmp2); + + // Rounds 28-31 + movdqa(msg, msgtmp3); + paddd(msg, Address(rax, 112)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp3); + palignr(msgtmp4, msgtmp2, 4); + paddd(msgtmp0, msgtmp4); + sha256msg2(msgtmp0, msgtmp3); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp2, msgtmp3); + + // Rounds 32-35 + movdqa(msg, msgtmp0); + paddd(msg, Address(rax, 128)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp0); + palignr(msgtmp4, msgtmp3, 4); + paddd(msgtmp1, msgtmp4); + sha256msg2(msgtmp1, msgtmp0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp3, msgtmp0); + + // Rounds 36-39 + movdqa(msg, msgtmp1); + paddd(msg, Address(rax, 144)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp1); + palignr(msgtmp4, msgtmp0, 4); + paddd(msgtmp2, msgtmp4); + sha256msg2(msgtmp2, msgtmp1); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp0, msgtmp1); + + // Rounds 40-43 + movdqa(msg, msgtmp2); + paddd(msg, Address(rax, 160)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp2); + palignr(msgtmp4, msgtmp1, 4); + paddd(msgtmp3, msgtmp4); + sha256msg2(msgtmp3, msgtmp2); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp1, msgtmp2); + + // Rounds 44-47 + movdqa(msg, msgtmp3); + paddd(msg, Address(rax, 176)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp3); + palignr(msgtmp4, msgtmp2, 4); + paddd(msgtmp0, msgtmp4); + sha256msg2(msgtmp0, msgtmp3); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp2, msgtmp3); + + // Rounds 48-51 + movdqa(msg, msgtmp0); + paddd(msg, Address(rax, 192)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp0); + palignr(msgtmp4, msgtmp3, 4); + paddd(msgtmp1, msgtmp4); + sha256msg2(msgtmp1, msgtmp0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + sha256msg1(msgtmp3, msgtmp0); + + // Rounds 52-55 + movdqa(msg, msgtmp1); + paddd(msg, Address(rax, 208)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp1); + palignr(msgtmp4, msgtmp0, 4); + paddd(msgtmp2, msgtmp4); + sha256msg2(msgtmp2, msgtmp1); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + + // Rounds 56-59 + movdqa(msg, msgtmp2); + paddd(msg, Address(rax, 224)); + sha256rnds2(state1, state0); + movdqa(msgtmp4, msgtmp2); + palignr(msgtmp4, msgtmp1, 4); + paddd(msgtmp3, msgtmp4); + sha256msg2(msgtmp3, msgtmp2); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + + // Rounds 60-63 + movdqa(msg, msgtmp3); + paddd(msg, Address(rax, 240)); + sha256rnds2(state1, state0); + pshufd(msg, msg, 0x0E); + sha256rnds2(state0, state1); + movdqu(msg, Address(rsp, 0)); + paddd(state0, msg); + movdqu(msg, Address(rsp, 16)); + paddd(state1, msg); + + if (multi_block) { + // increment data pointer and loop if more to process + addptr(buf, 64); + addptr(ofs, 64); + cmpptr(ofs, limit); + jcc(Assembler::belowEqual, loop0); + movptr(rax, ofs); //return ofs + } + + pshufd(state0, state0, 0x1B); + pshufd(state1, state1, 0xB1); + movdqa(msgtmp4, state0); + pblendw(state0, state1, 0xF0); + palignr(state1, msgtmp4, 8); + + movdqu(Address(state, 0), state0); + movdqu(Address(state, 16), state1); + + bind(done_hash); + +} diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp index af6797ef95a..b2bc4fce1aa 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_32.cpp @@ -208,13 +208,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ __ subptr(rsp, ymm_bytes); // Save upper half of YMM registers for (int n = 0; n < num_xmm_regs; n++) { - __ vextractf128h(Address(rsp, n*16), as_XMMRegister(n)); + __ vextractf128_high(Address(rsp, n*16), as_XMMRegister(n)); } if (UseAVX > 2) { __ subptr(rsp, zmm_bytes); // Save upper half of ZMM registers for (int n = 0; n < num_xmm_regs; n++) { - __ vextractf64x4h(Address(rsp, n*32), as_XMMRegister(n), 1); + __ vextractf64x4_high(Address(rsp, n*32), as_XMMRegister(n)); } } } @@ -304,13 +304,13 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve if (UseAVX > 2) { // Restore upper half of ZMM registers. for (int n = 0; n < num_xmm_regs; n++) { - __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, n*32), 1); + __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, n*32)); } __ addptr(rsp, zmm_bytes); } // Restore upper half of YMM registers. for (int n = 0; n < num_xmm_regs; n++) { - __ vinsertf128h(as_XMMRegister(n), Address(rsp, n*16)); + __ vinsertf128_high(as_XMMRegister(n), Address(rsp, n*16)); } __ addptr(rsp, ymm_bytes); } diff --git a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp index 686530b7e09..75f248fb1a3 100644 --- a/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/sharedRuntime_x86_64.cpp @@ -179,13 +179,13 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_ // Save upper half of YMM registers(0..15) int base_addr = XSAVE_AREA_YMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vextractf128h(Address(rsp, base_addr+n*16), as_XMMRegister(n)); + __ vextractf128_high(Address(rsp, base_addr+n*16), as_XMMRegister(n)); } if (VM_Version::supports_evex()) { // Save upper half of ZMM registers(0..15) base_addr = XSAVE_AREA_ZMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vextractf64x4h(Address(rsp, base_addr+n*32), as_XMMRegister(n), 1); + __ vextractf64x4_high(Address(rsp, base_addr+n*32), as_XMMRegister(n)); } // Save full ZMM registers(16..num_xmm_regs) base_addr = XSAVE_AREA_UPPERBANK; @@ -333,13 +333,13 @@ void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_ve // Restore upper half of YMM registers (0..15) int base_addr = XSAVE_AREA_YMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vinsertf128h(as_XMMRegister(n), Address(rsp, base_addr+n*16)); + __ vinsertf128_high(as_XMMRegister(n), Address(rsp, base_addr+n*16)); } if (VM_Version::supports_evex()) { // Restore upper half of ZMM registers (0..15) base_addr = XSAVE_AREA_ZMM_BEGIN; for (int n = 0; n < 16; n++) { - __ vinsertf64x4h(as_XMMRegister(n), Address(rsp, base_addr+n*32), 1); + __ vinsertf64x4_high(as_XMMRegister(n), Address(rsp, base_addr+n*32)); } // Restore full ZMM registers(16..num_xmm_regs) base_addr = XSAVE_AREA_UPPERBANK; diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp index 894e4cb3319..f5652df8b31 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_32.cpp @@ -3068,6 +3068,136 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_upper_word_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "upper_word_mask"); + address start = __ pc(); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0x00000000, relocInfo::none, 0); + __ emit_data(0xFFFFFFFF, relocInfo::none, 0); + return start; + } + + address generate_shuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "shuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data(0x0c0d0e0f, relocInfo::none, 0); + __ emit_data(0x08090a0b, relocInfo::none, 0); + __ emit_data(0x04050607, relocInfo::none, 0); + __ emit_data(0x00010203, relocInfo::none, 0); + return start; + } + + // ofs and limit are use for multi-block byte array. + // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha1_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = rax; + Register state = rdx; + Register ofs = rcx; + Register limit = rdi; + + const Address buf_param(rbp, 8 + 0); + const Address state_param(rbp, 8 + 4); + const Address ofs_param(rbp, 8 + 8); + const Address limit_param(rbp, 8 + 12); + + const XMMRegister abcd = xmm0; + const XMMRegister e0 = xmm1; + const XMMRegister e1 = xmm2; + const XMMRegister msg0 = xmm3; + + const XMMRegister msg1 = xmm4; + const XMMRegister msg2 = xmm5; + const XMMRegister msg3 = xmm6; + const XMMRegister shuf_mask = xmm7; + + __ enter(); + __ subptr(rsp, 8 * wordSize); + if (multi_block) { + __ push(limit); + } + __ movptr(buf, buf_param); + __ movptr(state, state_param); + if (multi_block) { + __ movptr(ofs, ofs_param); + __ movptr(limit, limit_param); + } + + __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask, + buf, state, ofs, limit, rsp, multi_block); + + if (multi_block) { + __ pop(limit); + } + __ addptr(rsp, 8 * wordSize); + __ leave(); + __ ret(0); + return start; + } + + address generate_pshuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "pshuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data(0x00010203, relocInfo::none, 0); + __ emit_data(0x04050607, relocInfo::none, 0); + __ emit_data(0x08090a0b, relocInfo::none, 0); + __ emit_data(0x0c0d0e0f, relocInfo::none, 0); + return start; + } + + // ofs and limit are use for multi-block byte array. + // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha256_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = rbx; + Register state = rsi; + Register ofs = rdx; + Register limit = rcx; + + const Address buf_param(rbp, 8 + 0); + const Address state_param(rbp, 8 + 4); + const Address ofs_param(rbp, 8 + 8); + const Address limit_param(rbp, 8 + 12); + + const XMMRegister msg = xmm0; + const XMMRegister state0 = xmm1; + const XMMRegister state1 = xmm2; + const XMMRegister msgtmp0 = xmm3; + + const XMMRegister msgtmp1 = xmm4; + const XMMRegister msgtmp2 = xmm5; + const XMMRegister msgtmp3 = xmm6; + const XMMRegister msgtmp4 = xmm7; + + __ enter(); + __ subptr(rsp, 8 * wordSize); + handleSOERegisters(true /*saving*/); + __ movptr(buf, buf_param); + __ movptr(state, state_param); + if (multi_block) { + __ movptr(ofs, ofs_param); + __ movptr(limit, limit_param); + } + + __ fast_sha256(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4, + buf, state, ofs, limit, rsp, multi_block); + + handleSOERegisters(false); + __ addptr(rsp, 8 * wordSize); + __ leave(); + __ ret(0); + return start; + } // byte swap x86 long address generate_ghash_long_swap_mask() { @@ -3772,6 +3902,19 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt_Parallel(); } + if (UseSHA1Intrinsics) { + StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask(); + StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask(); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress"); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); + } + if (UseSHA256Intrinsics) { + StubRoutines::x86::_k256_adr = (address)StubRoutines::x86::_k256; + StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask(); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress"); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB"); + } + // Generate GHASH intrinsics code if (UseGHASHIntrinsics) { StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask(); diff --git a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp index db518d804db..d1df1eac653 100644 --- a/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/stubGenerator_x86_64.cpp @@ -275,7 +275,7 @@ class StubGenerator: public StubCodeGenerator { } if (VM_Version::supports_evex()) { for (int i = xmm_save_first; i <= last_reg; i++) { - __ vextractf32x4h(xmm_save(i), as_XMMRegister(i), 0); + __ vextractf32x4(xmm_save(i), as_XMMRegister(i), 0); } } else { for (int i = xmm_save_first; i <= last_reg; i++) { @@ -393,7 +393,7 @@ class StubGenerator: public StubCodeGenerator { // emit the restores for xmm regs if (VM_Version::supports_evex()) { for (int i = xmm_save_first; i <= last_reg; i++) { - __ vinsertf32x4h(as_XMMRegister(i), xmm_save(i), 0); + __ vinsertf32x4(as_XMMRegister(i), as_XMMRegister(i), xmm_save(i), 0); } } else { for (int i = xmm_save_first; i <= last_reg; i++) { @@ -3695,6 +3695,133 @@ class StubGenerator: public StubCodeGenerator { return start; } + address generate_upper_word_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "upper_word_mask"); + address start = __ pc(); + __ emit_data64(0x0000000000000000, relocInfo::none); + __ emit_data64(0xFFFFFFFF00000000, relocInfo::none); + return start; + } + + address generate_shuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "shuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data64(0x08090a0b0c0d0e0f, relocInfo::none); + __ emit_data64(0x0001020304050607, relocInfo::none); + return start; + } + + // ofs and limit are use for multi-block byte array. + // int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha1_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = c_rarg0; + Register state = c_rarg1; + Register ofs = c_rarg2; + Register limit = c_rarg3; + + const XMMRegister abcd = xmm0; + const XMMRegister e0 = xmm1; + const XMMRegister e1 = xmm2; + const XMMRegister msg0 = xmm3; + + const XMMRegister msg1 = xmm4; + const XMMRegister msg2 = xmm5; + const XMMRegister msg3 = xmm6; + const XMMRegister shuf_mask = xmm7; + + __ enter(); + +#ifdef _WIN64 + // save the xmm registers which must be preserved 6-7 + __ subptr(rsp, 4 * wordSize); + __ movdqu(Address(rsp, 0), xmm6); + __ movdqu(Address(rsp, 2 * wordSize), xmm7); +#endif + + __ subptr(rsp, 4 * wordSize); + + __ fast_sha1(abcd, e0, e1, msg0, msg1, msg2, msg3, shuf_mask, + buf, state, ofs, limit, rsp, multi_block); + + __ addptr(rsp, 4 * wordSize); +#ifdef _WIN64 + // restore xmm regs belonging to calling function + __ movdqu(xmm6, Address(rsp, 0)); + __ movdqu(xmm7, Address(rsp, 2 * wordSize)); + __ addptr(rsp, 4 * wordSize); +#endif + + __ leave(); + __ ret(0); + return start; + } + + address generate_pshuffle_byte_flip_mask() { + __ align(64); + StubCodeMark mark(this, "StubRoutines", "pshuffle_byte_flip_mask"); + address start = __ pc(); + __ emit_data64(0x0405060700010203, relocInfo::none); + __ emit_data64(0x0c0d0e0f08090a0b, relocInfo::none); + return start; + } + +// ofs and limit are use for multi-block byte array. +// int com.sun.security.provider.DigestBase.implCompressMultiBlock(byte[] b, int ofs, int limit) + address generate_sha256_implCompress(bool multi_block, const char *name) { + __ align(CodeEntryAlignment); + StubCodeMark mark(this, "StubRoutines", name); + address start = __ pc(); + + Register buf = c_rarg0; + Register state = c_rarg1; + Register ofs = c_rarg2; + Register limit = c_rarg3; + + const XMMRegister msg = xmm0; + const XMMRegister state0 = xmm1; + const XMMRegister state1 = xmm2; + const XMMRegister msgtmp0 = xmm3; + + const XMMRegister msgtmp1 = xmm4; + const XMMRegister msgtmp2 = xmm5; + const XMMRegister msgtmp3 = xmm6; + const XMMRegister msgtmp4 = xmm7; + + const XMMRegister shuf_mask = xmm8; + + __ enter(); +#ifdef _WIN64 + // save the xmm registers which must be preserved 6-7 + __ subptr(rsp, 6 * wordSize); + __ movdqu(Address(rsp, 0), xmm6); + __ movdqu(Address(rsp, 2 * wordSize), xmm7); + __ movdqu(Address(rsp, 4 * wordSize), xmm8); +#endif + + __ subptr(rsp, 4 * wordSize); + + __ fast_sha256(msg, state0, state1, msgtmp0, msgtmp1, msgtmp2, msgtmp3, msgtmp4, + buf, state, ofs, limit, rsp, multi_block, shuf_mask); + + __ addptr(rsp, 4 * wordSize); +#ifdef _WIN64 + // restore xmm regs belonging to calling function + __ movdqu(xmm6, Address(rsp, 0)); + __ movdqu(xmm7, Address(rsp, 2 * wordSize)); + __ movdqu(xmm8, Address(rsp, 4 * wordSize)); + __ addptr(rsp, 6 * wordSize); +#endif + __ leave(); + __ ret(0); + return start; + } + // This is a version of CTR/AES crypt which does 6 blocks in a loop at a time // to hide instruction latency // @@ -4974,6 +5101,19 @@ class StubGenerator: public StubCodeGenerator { StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt_Parallel(); } + if (UseSHA1Intrinsics) { + StubRoutines::x86::_upper_word_mask_addr = generate_upper_word_mask(); + StubRoutines::x86::_shuffle_byte_flip_mask_addr = generate_shuffle_byte_flip_mask(); + StubRoutines::_sha1_implCompress = generate_sha1_implCompress(false, "sha1_implCompress"); + StubRoutines::_sha1_implCompressMB = generate_sha1_implCompress(true, "sha1_implCompressMB"); + } + if (UseSHA256Intrinsics) { + StubRoutines::x86::_k256_adr = (address)StubRoutines::x86::_k256; + StubRoutines::x86::_pshuffle_byte_flip_mask_addr = generate_pshuffle_byte_flip_mask(); + StubRoutines::_sha256_implCompress = generate_sha256_implCompress(false, "sha256_implCompress"); + StubRoutines::_sha256_implCompressMB = generate_sha256_implCompress(true, "sha256_implCompressMB"); + } + // Generate GHASH intrinsics code if (UseGHASHIntrinsics) { StubRoutines::x86::_ghash_long_swap_mask_addr = generate_ghash_long_swap_mask(); diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp index 3bc199b1db5..141fbf048eb 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.cpp @@ -29,6 +29,12 @@ #include "runtime/thread.inline.hpp" #include "crc32c.h" +#ifdef _MSC_VER +#define ALIGNED_(x) __declspec(align(x)) +#else +#define ALIGNED_(x) __attribute__ ((aligned(x))) +#endif + // Implementation of the platform-specific part of StubRoutines - for // a description of how to extend it, see the stubRoutines.hpp file. @@ -37,6 +43,10 @@ address StubRoutines::x86::_key_shuffle_mask_addr = NULL; address StubRoutines::x86::_counter_shuffle_mask_addr = NULL; address StubRoutines::x86::_ghash_long_swap_mask_addr = NULL; address StubRoutines::x86::_ghash_byte_swap_mask_addr = NULL; +address StubRoutines::x86::_upper_word_mask_addr = NULL; +address StubRoutines::x86::_shuffle_byte_flip_mask_addr = NULL; +address StubRoutines::x86::_k256_adr = NULL; +address StubRoutines::x86::_pshuffle_byte_flip_mask_addr = NULL; uint64_t StubRoutines::x86::_crc_by128_masks[] = { @@ -236,3 +246,23 @@ void StubRoutines::x86::generate_CRC32C_table(bool is_pclmulqdq_table_supported) _crc32c_table = (juint*)pclmulqdq_table; } } + +ALIGNED_(64) juint StubRoutines::x86::_k256[] = +{ + 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, + 0x3956c25bUL, 0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, + 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, + 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, + 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL, + 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, + 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, + 0xc6e00bf3UL, 0xd5a79147UL, 0x06ca6351UL, 0x14292967UL, + 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, + 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, + 0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, + 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, + 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, + 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL, 0x682e6ff3UL, + 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, + 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL +}; diff --git a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp index 5b2bf4bdf91..4c9ce0153fd 100644 --- a/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp +++ b/hotspot/src/cpu/x86/vm/stubRoutines_x86.hpp @@ -46,6 +46,17 @@ static address _ghash_long_swap_mask_addr; static address _ghash_byte_swap_mask_addr; + // upper word mask for sha1 + static address _upper_word_mask_addr; + // byte flip mask for sha1 + static address _shuffle_byte_flip_mask_addr; + + //k256 table for sha256 + static juint _k256[]; + static address _k256_adr; + // byte flip mask for sha256 + static address _pshuffle_byte_flip_mask_addr; + public: static address verify_mxcsr_entry() { return _verify_mxcsr_entry; } static address key_shuffle_mask_addr() { return _key_shuffle_mask_addr; } @@ -53,5 +64,9 @@ static address crc_by128_masks_addr() { return (address)_crc_by128_masks; } static address ghash_long_swap_mask_addr() { return _ghash_long_swap_mask_addr; } static address ghash_byte_swap_mask_addr() { return _ghash_byte_swap_mask_addr; } + static address upper_word_mask_addr() { return _upper_word_mask_addr; } + static address shuffle_byte_flip_mask_addr() { return _shuffle_byte_flip_mask_addr; } + static address k256_addr() { return _k256_adr; } + static address pshuffle_byte_flip_mask_addr() { return _pshuffle_byte_flip_mask_addr; } static void generate_CRC32C_table(bool is_pclmulqdq_supported); #endif // CPU_X86_VM_STUBROUTINES_X86_32_HPP diff --git a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp index 40e6e431882..713ee14472d 100644 --- a/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vmStructs_x86.hpp @@ -68,10 +68,11 @@ declare_constant(VM_Version::CPU_AVX512DQ) \ declare_constant(VM_Version::CPU_AVX512PF) \ declare_constant(VM_Version::CPU_AVX512ER) \ - declare_constant(VM_Version::CPU_AVX512CD) \ - declare_constant(VM_Version::CPU_AVX512BW) + declare_constant(VM_Version::CPU_AVX512CD) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ - declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) + declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ + declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ + declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) #endif // CPU_X86_VM_VMSTRUCTS_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp index 0bfd8e8f3e0..94c7e156d7e 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.cpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -385,7 +385,7 @@ class VM_Version_StubGenerator: public StubCodeGenerator { __ movdl(xmm0, rcx); __ pshufd(xmm0, xmm0, 0x00); - __ vinsertf128h(xmm0, xmm0, xmm0); + __ vinsertf128_high(xmm0, xmm0); __ vmovdqu(xmm7, xmm0); #ifdef _LP64 __ vmovdqu(xmm8, xmm0); @@ -577,7 +577,7 @@ void VM_Version::get_processor_features() { } char buf[256]; - jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + jio_snprintf(buf, sizeof(buf), "(%u cores per cpu, %u threads per core) family %d model %d stepping %d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cores_per_cpu(), threads_per_core(), cpu_family(), _model, _stepping, (supports_cmov() ? ", cmov" : ""), @@ -608,7 +608,8 @@ void VM_Version::get_processor_features() { (supports_bmi1() ? ", bmi1" : ""), (supports_bmi2() ? ", bmi2" : ""), (supports_adx() ? ", adx" : ""), - (supports_evex() ? ", evex" : "")); + (supports_evex() ? ", evex" : ""), + (supports_sha() ? ", sha" : "")); _features_string = os::strdup(buf); // UseSSE is set to the smaller of what hardware supports and what @@ -730,17 +731,29 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); } - if (UseSHA) { + if (supports_sha()) { + if (FLAG_IS_DEFAULT(UseSHA)) { + UseSHA = true; + } + } else if (UseSHA) { warning("SHA instructions are not available on this CPU"); FLAG_SET_DEFAULT(UseSHA, false); } - if (UseSHA1Intrinsics) { + if (UseSHA) { + if (FLAG_IS_DEFAULT(UseSHA1Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA1Intrinsics, true); + } + } else if (UseSHA1Intrinsics) { warning("Intrinsics for SHA-1 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA1Intrinsics, false); } - if (UseSHA256Intrinsics) { + if (UseSHA) { + if (FLAG_IS_DEFAULT(UseSHA256Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA256Intrinsics, true); + } + } else if (UseSHA256Intrinsics) { warning("Intrinsics for SHA-224 and SHA-256 crypto hash functions not available on this CPU."); FLAG_SET_DEFAULT(UseSHA256Intrinsics, false); } @@ -750,6 +763,10 @@ void VM_Version::get_processor_features() { FLAG_SET_DEFAULT(UseSHA512Intrinsics, false); } + if (!(UseSHA1Intrinsics || UseSHA256Intrinsics || UseSHA512Intrinsics)) { + FLAG_SET_DEFAULT(UseSHA, false); + } + if (UseAdler32Intrinsics) { warning("Adler32Intrinsics not available on this CPU."); FLAG_SET_DEFAULT(UseAdler32Intrinsics, false); diff --git a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp index 77550a96a4c..8dca27b546b 100644 --- a/hotspot/src/cpu/x86/vm/vm_version_x86.hpp +++ b/hotspot/src/cpu/x86/vm/vm_version_x86.hpp @@ -221,7 +221,7 @@ class VM_Version : public Abstract_VM_Version { avx512pf : 1, avx512er : 1, avx512cd : 1, - : 1, + sha : 1, avx512bw : 1, avx512vl : 1; } bits; @@ -282,11 +282,13 @@ protected: CPU_AVX512DQ = (1 << 27), CPU_AVX512PF = (1 << 28), CPU_AVX512ER = (1 << 29), - CPU_AVX512CD = (1 << 30), - CPU_AVX512BW = (1 << 31) + CPU_AVX512CD = (1 << 30) + // Keeping sign bit 31 unassigned. }; -#define CPU_AVX512VL UCONST64(0x100000000) // EVEX instructions with smaller vector length : enums are limited to 32bit +#define CPU_AVX512BW ((uint64_t)UCONST64(0x100000000)) // enums are limited to 31 bit +#define CPU_AVX512VL ((uint64_t)UCONST64(0x200000000)) // EVEX instructions with smaller vector length +#define CPU_SHA ((uint64_t)UCONST64(0x400000000)) // SHA instructions enum Extended_Family { // AMD @@ -516,6 +518,8 @@ protected: result |= CPU_ADX; if(_cpuid_info.sef_cpuid7_ebx.bits.bmi2 != 0) result |= CPU_BMI2; + if (_cpuid_info.sef_cpuid7_ebx.bits.sha != 0) + result |= CPU_SHA; if(_cpuid_info.ext_cpuid1_ecx.bits.lzcnt_intel != 0) result |= CPU_LZCNT; // for Intel, ecx.bits.misalignsse bit (bit 8) indicates support for prefetchw @@ -721,6 +725,7 @@ public: static bool supports_avx512nobw() { return (supports_evex() && !supports_avx512bw()); } static bool supports_avx256only() { return (supports_avx2() && !supports_evex()); } static bool supports_avxonly() { return ((supports_avx2() || supports_avx()) && !supports_evex()); } + static bool supports_sha() { return (_features & CPU_SHA) != 0; } // Intel features static bool is_intel_family_core() { return is_intel() && extended_cpu_family() == CPU_FAMILY_INTEL_CORE; } diff --git a/hotspot/src/cpu/x86/vm/x86.ad b/hotspot/src/cpu/x86/vm/x86.ad index a316b914a52..603e00beef4 100644 --- a/hotspot/src/cpu/x86/vm/x86.ad +++ b/hotspot/src/cpu/x86/vm/x86.ad @@ -3179,13 +3179,13 @@ instruct Repl32B(vecY dst, rRegI src) %{ "punpcklbw $dst,$dst\n\t" "pshuflw $dst,$dst,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate32B" %} + "vinserti128_high $dst,$dst\t! replicate32B" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ punpcklbw($dst$$XMMRegister, $dst$$XMMRegister); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3196,12 +3196,12 @@ instruct Repl32B_mem(vecY dst, memory mem) %{ format %{ "punpcklbw $dst,$mem\n\t" "pshuflw $dst,$dst,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate32B" %} + "vinserti128_high $dst,$dst\t! replicate32B" %} ins_encode %{ __ punpcklbw($dst$$XMMRegister, $mem$$Address); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3223,11 +3223,11 @@ instruct Repl32B_imm(vecY dst, immI con) %{ match(Set dst (ReplicateB con)); format %{ "movq $dst,[$constantaddress]\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! lreplicate32B($con)" %} + "vinserti128_high $dst,$dst\t! lreplicate32B($con)" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 1))); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3298,12 +3298,12 @@ instruct Repl16S(vecY dst, rRegI src) %{ format %{ "movd $dst,$src\n\t" "pshuflw $dst,$dst,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate16S" %} + "vinserti128_high $dst,$dst\t! replicate16S" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshuflw($dst$$XMMRegister, $dst$$XMMRegister, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3313,11 +3313,11 @@ instruct Repl16S_mem(vecY dst, memory mem) %{ match(Set dst (ReplicateS (LoadS mem))); format %{ "pshuflw $dst,$mem,0x00\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate16S" %} + "vinserti128_high $dst,$dst\t! replicate16S" %} ins_encode %{ __ pshuflw($dst$$XMMRegister, $mem$$Address, 0x00); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3327,11 +3327,11 @@ instruct Repl16S_imm(vecY dst, immI con) %{ match(Set dst (ReplicateS con)); format %{ "movq $dst,[$constantaddress]\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate16S($con)" %} + "vinserti128_high $dst,$dst\t! replicate16S($con)" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 2))); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3363,11 +3363,11 @@ instruct Repl8I(vecY dst, rRegI src) %{ match(Set dst (ReplicateI src)); format %{ "movd $dst,$src\n\t" "pshufd $dst,$dst,0x00\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate8I" %} + "vinserti128_high $dst,$dst\t! replicate8I" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ pshufd($dst$$XMMRegister, $dst$$XMMRegister, 0x00); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3376,10 +3376,10 @@ instruct Repl8I_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateI (LoadI mem))); format %{ "pshufd $dst,$mem,0x00\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate8I" %} + "vinserti128_high $dst,$dst\t! replicate8I" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3401,11 +3401,11 @@ instruct Repl8I_imm(vecY dst, immI con) %{ match(Set dst (ReplicateI con)); format %{ "movq $dst,[$constantaddress]\t! replicate8I($con)\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst" %} + "vinserti128_high $dst,$dst" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress(replicate8_imm($con$$constant, 4))); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3430,11 +3430,11 @@ instruct Repl4L(vecY dst, rRegL src) %{ match(Set dst (ReplicateL src)); format %{ "movdq $dst,$src\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L" %} + "vinserti128_high $dst,$dst\t! replicate4L" %} ins_encode %{ __ movdq($dst$$XMMRegister, $src$$Register); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3447,13 +3447,13 @@ instruct Repl4L(vecY dst, eRegL src, regD tmp) %{ "movdl $tmp,$src.hi\n\t" "punpckldq $dst,$tmp\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L" %} + "vinserti128_high $dst,$dst\t! replicate4L" %} ins_encode %{ __ movdl($dst$$XMMRegister, $src$$Register); __ movdl($tmp$$XMMRegister, HIGH_FROM_LOW($src$$Register)); __ punpckldq($dst$$XMMRegister, $tmp$$XMMRegister); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3464,11 +3464,11 @@ instruct Repl4L_imm(vecY dst, immL con) %{ match(Set dst (ReplicateL con)); format %{ "movq $dst,[$constantaddress]\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L($con)" %} + "vinserti128_high $dst,$dst\t! replicate4L($con)" %} ins_encode %{ __ movq($dst$$XMMRegister, $constantaddress($con)); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3478,11 +3478,11 @@ instruct Repl4L_mem(vecY dst, memory mem) %{ match(Set dst (ReplicateL (LoadL mem))); format %{ "movq $dst,$mem\n\t" "punpcklqdq $dst,$dst\n\t" - "vinserti128h $dst,$dst,$dst\t! replicate4L" %} + "vinserti128_high $dst,$dst\t! replicate4L" %} ins_encode %{ __ movq($dst$$XMMRegister, $mem$$Address); __ punpcklqdq($dst$$XMMRegister, $dst$$XMMRegister); - __ vinserti128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinserti128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3511,10 +3511,10 @@ instruct Repl8F(vecY dst, regF src) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF src)); format %{ "pshufd $dst,$src,0x00\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate8F" %} + "vinsertf128_high $dst,$dst\t! replicate8F" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x00); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3523,10 +3523,10 @@ instruct Repl8F_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 8 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateF (LoadF mem))); format %{ "pshufd $dst,$mem,0x00\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate8F" %} + "vinsertf128_high $dst,$dst\t! replicate8F" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $mem$$Address, 0x00); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3576,10 +3576,10 @@ instruct Repl4D(vecY dst, regD src) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD src)); format %{ "pshufd $dst,$src,0x44\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4D" %} + "vinsertf128_high $dst,$dst\t! replicate4D" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $src$$XMMRegister, 0x44); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -3588,10 +3588,10 @@ instruct Repl4D_mem(vecY dst, memory mem) %{ predicate(n->as_Vector()->length() == 4 && !VM_Version::supports_avx512vl()); match(Set dst (ReplicateD (LoadD mem))); format %{ "pshufd $dst,$mem,0x44\n\t" - "vinsertf128h $dst,$dst,$dst\t! replicate4D" %} + "vinsertf128_high $dst,$dst\t! replicate4D" %} ins_encode %{ __ pshufd($dst$$XMMRegister, $mem$$Address, 0x44); - __ vinsertf128h($dst$$XMMRegister, $dst$$XMMRegister, $dst$$XMMRegister); + __ vinsertf128_high($dst$$XMMRegister, $dst$$XMMRegister); %} ins_pipe( pipe_slow ); %} @@ -4791,7 +4791,7 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF effect(TEMP tmp, TEMP tmp2); format %{ "vphaddd $tmp,$src2,$src2\n\t" "vphaddd $tmp,$tmp,$tmp2\n\t" - "vextracti128 $tmp2,$tmp\n\t" + "vextracti128_high $tmp2,$tmp\n\t" "vpaddd $tmp,$tmp,$tmp2\n\t" "movd $tmp2,$src1\n\t" "vpaddd $tmp2,$tmp2,$tmp\n\t" @@ -4800,7 +4800,7 @@ instruct rvadd8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF int vector_len = 1; __ vphaddd($tmp$$XMMRegister, $src2$$XMMRegister, $src2$$XMMRegister, vector_len); __ vphaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len); - __ vextracti128h($tmp2$$XMMRegister, $tmp$$XMMRegister); + __ vextracti128_high($tmp2$$XMMRegister, $tmp$$XMMRegister); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0); __ movdl($tmp2$$XMMRegister, $src1$$Register); __ vpaddd($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -4813,7 +4813,7 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, regF tmp, predicate(UseAVX > 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpaddd $tmp,$tmp,$src2\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpaddd $tmp,$tmp,$tmp2\n\t" @@ -4824,7 +4824,7 @@ instruct rvadd8I_reduction_reg_evex(rRegI dst, rRegI src1, vecY src2, regF tmp, "movd $dst,$tmp2\t! add reduction8I" %} ins_encode %{ int vector_len = 0; - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, vector_len); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len); @@ -4841,9 +4841,9 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, vecZ src2, regF tmp, predicate(UseAVX > 2); match(Set dst (AddReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2, TEMP tmp3); - format %{ "vextracti64x4 $tmp3,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp3,$src2\n\t" "vpaddd $tmp3,$tmp3,$src2\n\t" - "vextracti128 $tmp,$tmp3\n\t" + "vextracti128_high $tmp,$tmp3\n\t" "vpaddd $tmp,$tmp,$tmp3\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpaddd $tmp,$tmp,$tmp2\n\t" @@ -4853,9 +4853,9 @@ instruct rvadd16I_reduction_reg_evex(rRegI dst, rRegI src1, vecZ src2, regF tmp, "vpaddd $tmp2,$tmp,$tmp2\n\t" "movd $dst,$tmp2\t! mul reduction16I" %} ins_encode %{ - __ vextracti64x4h($tmp3$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp3$$XMMRegister, $src2$$XMMRegister); __ vpaddd($tmp3$$XMMRegister, $tmp3$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp3$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp3$$XMMRegister); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp3$$XMMRegister, 0); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpaddd($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0); @@ -4892,7 +4892,7 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF predicate(UseAVX > 2); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpaddq $tmp2,$tmp,$src2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpaddq $tmp2,$tmp2,$tmp\n\t" @@ -4900,7 +4900,7 @@ instruct rvadd4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF "vpaddq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! add reduction4L" %} ins_encode %{ - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpaddq($tmp2$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -4915,9 +4915,9 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF predicate(UseAVX > 2); match(Set dst (AddReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti64x4 $tmp2,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp2,$src2\n\t" "vpaddq $tmp2,$tmp2,$src2\n\t" - "vextracti128 $tmp,$tmp2\n\t" + "vextracti128_high $tmp,$tmp2\n\t" "vpaddq $tmp2,$tmp2,$tmp\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpaddq $tmp2,$tmp2,$tmp\n\t" @@ -4925,9 +4925,9 @@ instruct rvadd8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF "vpaddq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! add reduction8L" %} ins_encode %{ - __ vextracti64x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp2$$XMMRegister); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpaddq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -5026,7 +5026,7 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf128 $tmp2,$src2\n\t" + "vextractf128_high $tmp2,$src2\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5042,7 +5042,7 @@ instruct radd8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister); + __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5065,7 +5065,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5073,7 +5073,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5081,7 +5081,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vaddss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vaddss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vaddss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vaddss $dst,$dst,$tmp\n\t" @@ -5097,7 +5097,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5105,7 +5105,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5113,7 +5113,7 @@ instruct radd16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vaddss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5162,7 +5162,7 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ format %{ "vaddsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4h $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\t! add reduction4D" %} @@ -5170,7 +5170,7 @@ instruct rvadd4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5185,15 +5185,15 @@ instruct rvadd8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ format %{ "vaddsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vaddsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vaddsd $dst,$dst,$tmp\t! add reduction8D" %} @@ -5201,15 +5201,15 @@ instruct rvadd8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vaddsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5307,7 +5307,7 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF predicate(UseAVX > 0); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpmulld $tmp,$tmp,$src2\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpmulld $tmp,$tmp,$tmp2\n\t" @@ -5318,7 +5318,7 @@ instruct rvmul8I_reduction_reg(rRegI dst, rRegI src1, vecY src2, regF tmp, regF "movd $dst,$tmp2\t! mul reduction8I" %} ins_encode %{ int vector_len = 0; - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, vector_len); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, vector_len); @@ -5335,9 +5335,9 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, vecZ src2, regF tmp, regF predicate(UseAVX > 2); match(Set dst (MulReductionVI src1 src2)); effect(TEMP tmp, TEMP tmp2, TEMP tmp3); - format %{ "vextracti64x4 $tmp3,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp3,$src2\n\t" "vpmulld $tmp3,$tmp3,$src2\n\t" - "vextracti128 $tmp,$tmp3\n\t" + "vextracti128_high $tmp,$tmp3\n\t" "vpmulld $tmp,$tmp,$src2\n\t" "pshufd $tmp2,$tmp,0xE\n\t" "vpmulld $tmp,$tmp,$tmp2\n\t" @@ -5347,9 +5347,9 @@ instruct rvmul16I_reduction_reg(rRegI dst, rRegI src1, vecZ src2, regF tmp, regF "vpmulld $tmp2,$tmp,$tmp2\n\t" "movd $dst,$tmp2\t! mul reduction16I" %} ins_encode %{ - __ vextracti64x4h($tmp3$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp3$$XMMRegister, $src2$$XMMRegister); __ vpmulld($tmp3$$XMMRegister, $tmp3$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp3$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp3$$XMMRegister); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp3$$XMMRegister, 0); __ pshufd($tmp2$$XMMRegister, $tmp$$XMMRegister, 0xE); __ vpmulld($tmp$$XMMRegister, $tmp$$XMMRegister, $tmp2$$XMMRegister, 0); @@ -5386,7 +5386,7 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti128 $tmp,$src2\n\t" + format %{ "vextracti128_high $tmp,$src2\n\t" "vpmullq $tmp2,$tmp,$src2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpmullq $tmp2,$tmp2,$tmp\n\t" @@ -5394,7 +5394,7 @@ instruct rvmul4L_reduction_reg(rRegL dst, rRegL src1, vecY src2, regF tmp, regF "vpmullq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! mul reduction4L" %} ins_encode %{ - __ vextracti128h($tmp$$XMMRegister, $src2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $src2$$XMMRegister); __ vpmullq($tmp2$$XMMRegister, $tmp$$XMMRegister, $src2$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -5409,9 +5409,9 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF predicate(UseAVX > 2 && VM_Version::supports_avx512dq()); match(Set dst (MulReductionVL src1 src2)); effect(TEMP tmp, TEMP tmp2); - format %{ "vextracti64x4 $tmp2,$src2,0x1\n\t" + format %{ "vextracti64x4_high $tmp2,$src2\n\t" "vpmullq $tmp2,$tmp2,$src2\n\t" - "vextracti128 $tmp,$tmp2\n\t" + "vextracti128_high $tmp,$tmp2\n\t" "vpmullq $tmp2,$tmp2,$tmp\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vpmullq $tmp2,$tmp2,$tmp\n\t" @@ -5419,9 +5419,9 @@ instruct rvmul8L_reduction_reg(rRegL dst, rRegL src1, vecZ src2, regF tmp, regF "vpmullq $tmp2,$tmp2,$tmp\n\t" "movdq $dst,$tmp2\t! mul reduction8L" %} ins_encode %{ - __ vextracti64x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 1); + __ vextracti64x4_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $src2$$XMMRegister, 1); - __ vextracti128h($tmp$$XMMRegister, $tmp2$$XMMRegister); + __ vextracti128_high($tmp$$XMMRegister, $tmp2$$XMMRegister); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vpmullq($tmp2$$XMMRegister, $tmp2$$XMMRegister, $tmp$$XMMRegister, 0); @@ -5520,7 +5520,7 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf128 $tmp2,$src2\n\t" + "vextractf128_high $tmp2,$src2\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5536,7 +5536,7 @@ instruct rvmul8F_reduction_reg(regF dst, vecY src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister); + __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5559,7 +5559,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$src2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5567,7 +5567,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5575,7 +5575,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ "vmulss $dst,$dst,$tmp\n\t" "pshufd $tmp,$tmp2,0x03\n\t" "vmulss $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vmulss $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0x01\n\t" "vmulss $dst,$dst,$tmp\n\t" @@ -5591,7 +5591,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5599,7 +5599,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5607,7 +5607,7 @@ instruct rvmul16F_reduction_reg(regF dst, vecZ src2, regF tmp, regF tmp2) %{ __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x03); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0x01); __ vmulss($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5656,7 +5656,7 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ format %{ "vmulsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf128 $tmp2,$src2\n\t" + "vextractf128_high $tmp2,$src2\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vmulsd $dst,$dst,$tmp\t! mul reduction4D" %} @@ -5664,7 +5664,7 @@ instruct rvmul4D_reduction_reg(regD dst, vecY src2, regD tmp, regD tmp2) %{ __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf128h($tmp2$$XMMRegister, $src2$$XMMRegister); + __ vextractf128_high($tmp2$$XMMRegister, $src2$$XMMRegister); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); @@ -5679,15 +5679,15 @@ instruct rvmul8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ format %{ "vmulsd $dst,$dst,$src2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x1\n\t" + "vextractf32x4 $tmp2,$src2,0x1\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$src2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x2\n\t" + "vextractf32x4 $tmp2,$src2,0x2\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vmulsd $dst,$dst,$tmp\n\t" - "vextractf32x4 $tmp2,$src2, 0x3\n\t" + "vextractf32x4 $tmp2,$src2,0x3\n\t" "vmulsd $dst,$dst,$tmp2\n\t" "pshufd $tmp,$tmp2,0xE\n\t" "vmulsd $dst,$dst,$tmp\t! mul reduction8D" %} @@ -5695,15 +5695,15 @@ instruct rvmul8D_reduction_reg(regD dst, vecZ src2, regD tmp, regD tmp2) %{ __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $src2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $src2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x1); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x2); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); - __ vextractf32x4h($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); + __ vextractf32x4($tmp2$$XMMRegister, $src2$$XMMRegister, 0x3); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp2$$XMMRegister); __ pshufd($tmp$$XMMRegister, $tmp2$$XMMRegister, 0xE); __ vmulsd($dst$$XMMRegister, $dst$$XMMRegister, $tmp$$XMMRegister); diff --git a/hotspot/src/cpu/x86/vm/x86_32.ad b/hotspot/src/cpu/x86/vm/x86_32.ad index b09ca8e36ab..c9583ba13e0 100644 --- a/hotspot/src/cpu/x86/vm/x86_32.ad +++ b/hotspot/src/cpu/x86/vm/x86_32.ad @@ -1420,9 +1420,6 @@ const bool Matcher::isSimpleConstant64(jlong value) { // The ecx parameter to rep stos for the ClearArray node is in dwords. const bool Matcher::init_array_count_is_in_bytes = false; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; - // Needs 2 CMOV's for longs. const int Matcher::long_cmove_cost() { return 1; } @@ -11369,27 +11366,54 @@ instruct MoveL2D_reg_reg_sse(regD dst, eRegL src, regD tmp) %{ // ======================================================================= // fast clearing of an array instruct rep_stos(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ - predicate(!UseFastStosb); + predicate(!((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "XOR EAX,EAX\t# ClearArray:\n\t" - "SHL ECX,1\t# Convert doublewords to words\n\t" - "REP STOS\t# store EAX into [EDI++] while ECX--" %} + + format %{ $$template + $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t" + $$emit$$"CMP InitArrayShortSize,rcx\n\t" + $$emit$$"JG LARGE\n\t" + $$emit$$"SHL ECX, 1\n\t" + $$emit$$"DEC ECX\n\t" + $$emit$$"JS DONE\t# Zero length\n\t" + $$emit$$"MOV EAX,(EDI,ECX,4)\t# LOOP\n\t" + $$emit$$"DEC ECX\n\t" + $$emit$$"JGE LOOP\n\t" + $$emit$$"JMP DONE\n\t" + $$emit$$"# LARGE:\n\t" + if (UseFastStosb) { + $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t" + $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t" + } else { + $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t" + $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t" + } + $$emit$$"# DONE" + %} ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, false); %} ins_pipe( pipe_slow ); %} -instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ - predicate(UseFastStosb); +instruct rep_stos_large(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy, eFlagsReg cr) %{ + predicate(((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "XOR EAX,EAX\t# ClearArray:\n\t" - "SHL ECX,3\t# Convert doublewords to bytes\n\t" - "REP STOSB\t# store EAX into [EDI++] while ECX--" %} + format %{ $$template + $$emit$$"XOR EAX,EAX\t# ClearArray:\n\t" + if (UseFastStosb) { + $$emit$$"SHL ECX,3\t# Convert doublewords to bytes\n\t" + $$emit$$"REP STOSB\t# store EAX into [EDI++] while ECX--\n\t" + } else { + $$emit$$"SHL ECX,1\t# Convert doublewords to words\n\t" + $$emit$$"REP STOS\t# store EAX into [EDI++] while ECX--\n\t" + } + $$emit$$"# DONE" + %} ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, true); %} ins_pipe( pipe_slow ); %} diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index 6f32ace2f18..9579436fb20 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -1637,9 +1637,6 @@ const bool Matcher::isSimpleConstant64(jlong value) { // The ecx parameter to rep stosq for the ClearArray node is in words. const bool Matcher::init_array_count_is_in_bytes = false; -// Threshold size for cleararray. -const int Matcher::init_array_short_size = 8 * BytesPerLong; - // No additional cost for CMOVL. const int Matcher::long_cmove_cost() { return 0; } @@ -10460,31 +10457,55 @@ instruct MoveL2D_reg_reg(regD dst, rRegL src) %{ instruct rep_stos(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, rFlagsReg cr) %{ - predicate(!UseFastStosb); + predicate(!((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "xorq rax, rax\t# ClearArray:\n\t" - "rep stosq\t# Store rax to *rdi++ while rcx--" %} + format %{ $$template + $$emit$$"xorq rax, rax\t# ClearArray:\n\t" + $$emit$$"cmp InitArrayShortSize,rcx\n\t" + $$emit$$"jg LARGE\n\t" + $$emit$$"dec rcx\n\t" + $$emit$$"js DONE\t# Zero length\n\t" + $$emit$$"mov rax,(rdi,rcx,8)\t# LOOP\n\t" + $$emit$$"dec rcx\n\t" + $$emit$$"jge LOOP\n\t" + $$emit$$"jmp DONE\n\t" + $$emit$$"# LARGE:\n\t" + if (UseFastStosb) { + $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t" + $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--\n\t" + } else { + $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--\n\t" + } + $$emit$$"# DONE" + %} ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, false); %} ins_pipe(pipe_slow); %} -instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, - rFlagsReg cr) +instruct rep_stos_large(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dummy, + rFlagsReg cr) %{ - predicate(UseFastStosb); + predicate(((ClearArrayNode*)n)->is_large()); match(Set dummy (ClearArray cnt base)); effect(USE_KILL cnt, USE_KILL base, KILL zero, KILL cr); - format %{ "xorq rax, rax\t# ClearArray:\n\t" - "shlq rcx,3\t# Convert doublewords to bytes\n\t" - "rep stosb\t# Store rax to *rdi++ while rcx--" %} - ins_encode %{ - __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register); + + format %{ $$template + $$emit$$"xorq rax, rax\t# ClearArray:\n\t" + if (UseFastStosb) { + $$emit$$"shlq rcx,3\t# Convert doublewords to bytes\n\t" + $$emit$$"rep stosb\t# Store rax to *rdi++ while rcx--" + } else { + $$emit$$"rep stosq\t# Store rax to *rdi++ while rcx--" + } %} - ins_pipe( pipe_slow ); + ins_encode %{ + __ clear_mem($base$$Register, $cnt$$Register, $zero$$Register, true); + %} + ins_pipe(pipe_slow); %} instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2, diff --git a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp index 387733de06d..4dc68335b6a 100644 --- a/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp +++ b/hotspot/src/cpu/zero/vm/cppInterpreter_zero.cpp @@ -773,7 +773,7 @@ InterpreterFrame *InterpreterFrame::build(int size, TRAPS) { } BasicType CppInterpreter::result_type_of(Method* method) { - BasicType t; + BasicType t = T_ILLEGAL; // silence compiler warnings switch (method->result_index()) { case 0 : t = T_BOOLEAN; break; case 1 : t = T_CHAR; break; diff --git a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp index 8fb45375262..2e2dc3cab60 100644 --- a/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp +++ b/hotspot/src/cpu/zero/vm/interpreterRT_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -62,7 +62,7 @@ void InterpreterRuntime::SignatureHandlerGeneratorBase::pass_object() { } void InterpreterRuntime::SignatureHandlerGeneratorBase::push(BasicType type) { - ffi_type *ftype; + ffi_type *ftype = NULL; switch (type) { case T_VOID: ftype = &ffi_type_void; diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/development/Server24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/development/Server24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/About24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/About24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Delete24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Delete24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Find16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Find16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Find16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Find16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Help24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Help24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/History24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/History24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Information24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Information24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/New24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/New24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Open24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Open24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Save24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Save24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Save24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Save24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/SaveAs24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/SaveAs24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Zoom16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Zoom16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/Zoom16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/Zoom16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/general/ZoomIn24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/general/ZoomIn24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Down16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Down16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Down16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Down16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Up16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Up16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/navigation/Up16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/navigation/Up16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignCenter24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignCenter24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignLeft24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignLeft24.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight16.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight16.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight16.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight16.gif diff --git a/hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight24.gif b/hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight24.gif similarity index 100% rename from hotspot/src/jdk.hotspot.agent/share/classes/images/toolbarButtonGraphics/text/AlignRight24.gif rename to hotspot/src/jdk.hotspot.agent/share/classes/toolbarButtonGraphics/text/AlignRight24.gif diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java index 37393ff08bc..3fb9046711b 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.amd64/src/jdk/vm/ci/amd64/AMD64.java @@ -22,6 +22,7 @@ */ package jdk.vm.ci.amd64; +import static jdk.vm.ci.code.MemoryBarriers.LOAD_LOAD; import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE; import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE; import static jdk.vm.ci.code.Register.SPECIAL; @@ -202,7 +203,8 @@ public class AMD64 extends Architecture { AVX512ER, AVX512CD, AVX512BW, - AVX512VL + AVX512VL, + SHA } private final EnumSet features; @@ -220,7 +222,7 @@ public class AMD64 extends Architecture { private final AMD64Kind largestKind; public AMD64(EnumSet features, EnumSet flags) { - super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8); + super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_LOAD | LOAD_STORE | STORE_STORE, 1, 8); this.features = features; this.flags = flags; assert features.contains(CPUFeature.SSE2) : "minimum config for x64"; diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java index 69a31604560..b2fec728519 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot.amd64/src/jdk/vm/ci/hotspot/amd64/AMD64HotSpotJVMCIBackendFactory.java @@ -122,6 +122,9 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto if ((config.vmVersionFeatures & config.amd64AVX512VL) != 0) { features.add(AMD64.CPUFeature.AVX512VL); } + if ((config.vmVersionFeatures & config.amd64SHA) != 0) { + features.add(AMD64.CPUFeature.SHA); + } return features; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java index 600ecc84ecc..c957b05e1d5 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotConstantReflectionProvider.java @@ -339,7 +339,7 @@ public class HotSpotConstantReflectionProvider implements ConstantReflectionProv public JavaConstant readStableFieldValue(ResolvedJavaField field, JavaConstant receiver, boolean isDefaultStable) { JavaConstant fieldValue = readNonStableFieldValue(field, receiver); - if (fieldValue.isNonNull()) { + if (fieldValue != null && fieldValue.isNonNull()) { JavaType declaredType = field.getType(); if (declaredType.getComponentType() != null) { int stableDimension = getArrayDimension(declaredType); diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java index b1b486721e8..b7b7f9ad347 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ package jdk.vm.ci.hotspot; import jdk.vm.ci.code.CompilationRequest; import jdk.vm.ci.code.CompilationRequestResult; import jdk.vm.ci.common.JVMCIError; +import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.Option; import jdk.vm.ci.runtime.JVMCICompiler; import jdk.vm.ci.runtime.JVMCICompilerFactory; import jdk.vm.ci.runtime.JVMCIRuntime; @@ -47,29 +48,33 @@ final class HotSpotJVMCICompilerConfig { } } + /** + * Factory of the selected system compiler. + */ private static JVMCICompilerFactory compilerFactory; /** - * Selects the system compiler. + * Gets the selected system compiler factory. * - * Called from VM. This method has an object return type to allow it to be called with a VM - * utility function used to call other static initialization methods. + * @return the selected system compiler factory */ - static Boolean selectCompiler(String compilerName) { - assert compilerFactory == null; - for (JVMCICompilerFactory factory : Services.load(JVMCICompilerFactory.class)) { - if (factory.getCompilerName().equals(compilerName)) { - compilerFactory = factory; - return Boolean.TRUE; - } - } - - throw new JVMCIError("JVMCI compiler '%s' not found", compilerName); - } - static JVMCICompilerFactory getCompilerFactory() { if (compilerFactory == null) { - compilerFactory = new DummyCompilerFactory(); + JVMCICompilerFactory factory = null; + String compilerName = Option.Compiler.getString(); + if (compilerName != null) { + for (JVMCICompilerFactory f : Services.load(JVMCICompilerFactory.class)) { + if (f.getCompilerName().equals(compilerName)) { + factory = f; + } + } + if (factory == null) { + throw new JVMCIError("JVMCI compiler '%s' not found", compilerName); + } + } else { + factory = new DummyCompilerFactory(); + } + compilerFactory = factory; } return compilerFactory; } diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index afdc02fe26f..802bc1ccef0 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -91,6 +91,7 @@ public final class HotSpotJVMCIRuntime implements HotSpotJVMCIRuntimeProvider, H * A list of all supported JVMCI options. */ public enum Option { + Compiler(String.class, null, "Selects the system compiler."), ImplicitStableValues(boolean.class, true, "Mark well-known stable fields as such."), // Note: The following one is not used (see InitTimer.ENABLED). InitTimer(boolean.class, false, "Specifies if initialization timing is enabled."), diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java index 5bd116cd57b..fd92a15bd96 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotMetaAccessProvider.java @@ -41,7 +41,6 @@ import jdk.vm.ci.meta.DeoptimizationAction; import jdk.vm.ci.meta.DeoptimizationReason; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; -import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -111,23 +110,26 @@ public class HotSpotMetaAccessProvider implements MetaAccessProvider, HotSpotPro } public ResolvedJavaField lookupJavaField(Field reflectionField) { - String name = reflectionField.getName(); Class fieldHolder = reflectionField.getDeclaringClass(); - Class fieldType = reflectionField.getType(); - // java.lang.reflect.Field's modifiers should be enough here since VM internal modifier bits - // are not used (yet). - final int modifiers = reflectionField.getModifiers(); - final long offset = Modifier.isStatic(modifiers) ? UNSAFE.staticFieldOffset(reflectionField) : UNSAFE.objectFieldOffset(reflectionField); HotSpotResolvedObjectType holder = fromObjectClass(fieldHolder); - JavaType type = runtime.fromClass(fieldType); - - if (offset != -1) { - HotSpotResolvedObjectType resolved = holder; - return resolved.createField(name, type, offset, modifiers); + if (Modifier.isStatic(reflectionField.getModifiers())) { + final long offset = UNSAFE.staticFieldOffset(reflectionField); + for (ResolvedJavaField field : holder.getStaticFields()) { + if (offset == ((HotSpotResolvedJavaField) field).offset()) { + return field; + } + } } else { - throw new JVMCIError("unresolved field %s", reflectionField); + final long offset = UNSAFE.objectFieldOffset(reflectionField); + for (ResolvedJavaField field : holder.getInstanceFields(false)) { + if (offset == ((HotSpotResolvedJavaField) field).offset()) { + return field; + } + } } + + throw new JVMCIError("unresolved field %s", reflectionField); } private static int intMaskRight(int n) { diff --git a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java index 3e90a4d73b0..744ec27c044 100644 --- a/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java +++ b/hotspot/src/jdk.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotVMConfig.java @@ -945,6 +945,7 @@ public class HotSpotVMConfig { @HotSpotVMConstant(name = "VM_Version::CPU_AVX512CD", archs = {"amd64"}) @Stable public long amd64AVX512CD; @HotSpotVMConstant(name = "VM_Version::CPU_AVX512BW", archs = {"amd64"}) @Stable public long amd64AVX512BW; @HotSpotVMConstant(name = "VM_Version::CPU_AVX512VL", archs = {"amd64"}) @Stable public long amd64AVX512VL; + @HotSpotVMConstant(name = "VM_Version::CPU_SHA", archs = {"amd64"}) @Stable public long amd64SHA; // SPARC specific values @HotSpotVMConstant(name = "VM_Version::vis3_instructions_m", archs = {"sparc"}) @Stable public int sparcVis3Instructions; @@ -1141,7 +1142,7 @@ public class HotSpotVMConfig { @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_sp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaSpOffset; @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_pc", type = "address", get = HotSpotVMField.Type.OFFSET) @Stable private int javaFrameAnchorLastJavaPcOffset; - @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset; + @HotSpotVMField(name = "JavaFrameAnchor::_last_Java_fp", type = "intptr_t*", get = HotSpotVMField.Type.OFFSET, archs = {"aarch64, amd64"}) @Stable private int javaFrameAnchorLastJavaFpOffset; @HotSpotVMField(name = "JavaFrameAnchor::_flags", type = "int", get = HotSpotVMField.Type.OFFSET, archs = {"sparc"}) @Stable private int javaFrameAnchorFlagsOffset; public int threadLastJavaSpOffset() { @@ -1152,11 +1153,8 @@ public class HotSpotVMConfig { return javaThreadAnchorOffset + javaFrameAnchorLastJavaPcOffset; } - /** - * This value is only valid on AMD64. - */ public int threadLastJavaFpOffset() { - // TODO add an assert for AMD64 + assert getHostArchitectureName().equals("aarch64") || getHostArchitectureName().equals("amd64"); return javaThreadAnchorOffset + javaFrameAnchorLastJavaFpOffset; } diff --git a/hotspot/src/os/aix/vm/attachListener_aix.cpp b/hotspot/src/os/aix/vm/attachListener_aix.cpp index cb56efc26f7..4e69822008a 100644 --- a/hotspot/src/os/aix/vm/attachListener_aix.cpp +++ b/hotspot/src/os/aix/vm/attachListener_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -225,7 +225,7 @@ int AixAttachListener::init() { // We must call bind with the actual socketaddr length. This is obligatory for AS400. int res = ::bind(listener, (struct sockaddr*)&addr, SUN_LEN(&addr)); if (res == -1) { - RESTARTABLE(::close(listener), res); + ::close(listener); return -1; } @@ -238,7 +238,7 @@ int AixAttachListener::init() { } } if (res == -1) { - RESTARTABLE(::close(listener), res); + ::close(listener); ::unlink(initial_path); return -1; } @@ -400,7 +400,7 @@ AixAttachOperation* AixAttachListener::dequeue() { AixAttachOperation* op = read_request(s); if (op == NULL) { int res; - RESTARTABLE(::close(s), res); + ::close(s); continue; } else { return op; @@ -452,7 +452,7 @@ void AixAttachOperation::complete(jint result, bufferedStream* st) { } // done - RESTARTABLE(::close(this->socket()), rc); + ::close(this->socket()); // were we externally suspended while we were waiting? thread->check_and_wait_while_suspended(); diff --git a/hotspot/src/os/aix/vm/os_aix.cpp b/hotspot/src/os/aix/vm/os_aix.cpp index f63a789b89c..2193a9611a3 100644 --- a/hotspot/src/os/aix/vm/os_aix.cpp +++ b/hotspot/src/os/aix/vm/os_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2015 SAP SE. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,7 @@ #include "compiler/compileBroker.hpp" #include "interpreter/interpreter.hpp" #include "jvm_aix.h" +#include "logging/log.hpp" #include "libo4.hpp" #include "libperfstat_aix.hpp" #include "libodm_aix.hpp" @@ -791,13 +792,8 @@ static void *java_start(Thread *thread) { const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - trcVerbose("newborn Thread : pthread-id %u, ktid " UINT64_FORMAT - ", stack %p ... %p, stacksize 0x%IX (%IB)", - pthread_id, kernel_thread_id, - thread->stack_end(), - thread->stack_base(), - thread->stack_size(), - thread->stack_size()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); // Normally, pthread stacks on AIX live in the data segment (are allocated with malloc() // by the pthread library). In rare cases, this may not be the case, e.g. when third-party @@ -805,7 +801,7 @@ static void *java_start(Thread *thread) { // guard pages on those stacks, because the stacks may reside in memory which is not // protectable (shmated). if (thread->stack_base() > ::sbrk(0)) { - trcVerbose("Thread " UINT64_FORMAT ": stack not in data segment.", (uint64_t) pthread_id); + log_warning(os, thread)("Thread stack not in data segment."); } // Try to randomize the cache line index of hot stack frames. @@ -839,8 +835,8 @@ static void *java_start(Thread *thread) { // Call one more level start routine. thread->run(); - trcVerbose("Thread finished : pthread-id %u, ktid " UINT64_FORMAT ".", - pthread_id, kernel_thread_id); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); return 0; } @@ -908,20 +904,19 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); - if (ret == 0) { - trcVerbose("Created New Thread : pthread-id %u", tid); - } else { - if (os::Aix::on_pase()) { - // QIBM_MULTI_THREADED=Y is needed when the launcher is started on iSeries - // using QSH. Otherwise pthread_create fails with errno=11. - trcVerbose("(Please make sure you set the environment variable " - "QIBM_MULTI_THREADED=Y before running this program.)"); - } - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } + if (ret != 0) { // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -958,13 +953,6 @@ bool os::create_attached_thread(JavaThread* thread) { const pthread_t pthread_id = ::pthread_self(); const tid_t kernel_thread_id = ::thread_self(); - trcVerbose("attaching Thread : pthread-id %u, ktid " UINT64_FORMAT ", stack %p ... %p, stacksize 0x%IX (%IB)", - pthread_id, kernel_thread_id, - thread->stack_end(), - thread->stack_base(), - thread->stack_size(), - thread->stack_size()); - // OSThread::thread_id is the pthread id. osthread->set_thread_id(pthread_id); @@ -990,6 +978,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Aix::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", kernel thread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) kernel_thread_id); + return true; } diff --git a/hotspot/src/os/aix/vm/perfMemory_aix.cpp b/hotspot/src/os/aix/vm/perfMemory_aix.cpp index 2604a03dae8..c2e7c0e4e90 100644 --- a/hotspot/src/os/aix/vm/perfMemory_aix.cpp +++ b/hotspot/src/os/aix/vm/perfMemory_aix.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2012, 2013 SAP SE. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016 SAP SE. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -121,7 +121,7 @@ static void save_memory_to_file(char* addr, size_t size) { addr += result; } - RESTARTABLE(::close(fd), result); + result = ::close(fd); if (PrintMiscellaneous && Verbose) { if (result == OS_ERR) { warning("Could not close %s: %s\n", destfile, strerror(errno)); @@ -299,10 +299,13 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u bool create; int error; int fd; + int result; create = false; - if (lstat(path, &orig_st) != 0) { + RESTARTABLE(::lstat(path, &orig_st), result); + + if (result == OS_ERR) { if (errno == ENOENT && (oflag & O_CREAT) != 0) { // File doesn't exist, but_we want to create it, add O_EXCL flag // to make sure no-one creates it (or a symlink) before us @@ -316,7 +319,7 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u return OS_ERR; } } else { - // Lstat success, check if existing file is a link. + // lstat success, check if existing file is a link. if ((orig_st.st_mode & S_IFMT) == S_IFLNK) { // File is a symlink. errno = ELOOP; @@ -325,9 +328,9 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u } if (use_mode == true) { - fd = open(path, oflag, mode); + RESTARTABLE(::open(path, oflag, mode), fd); } else { - fd = open(path, oflag); + RESTARTABLE(::open(path, oflag), fd); } if (fd == OS_ERR) { @@ -336,7 +339,8 @@ static int open_o_nofollow_impl(const char* path, int oflag, mode_t mode, bool u // Can't do inode checks on before/after if we created the file. if (create == false) { - if (fstat(fd, &new_st) != 0) { + RESTARTABLE(::fstat(fd, &new_st), result); + if (result == OS_ERR) { // Keep errno from fstat, in case close also fails. error = errno; ::close(fd); @@ -384,7 +388,7 @@ static DIR *open_directory_secure(const char* dirname) { RESTARTABLE(::open(dirname, O_RDONLY|O_NOFOLLOW), result); #else // workaround (jdk6 coding) - RESTARTABLE(::open_o_nofollow(dirname, O_RDONLY), result); + result = open_o_nofollow(dirname, O_RDONLY); #endif if (result == OS_ERR) { @@ -888,7 +892,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, RESTARTABLE(::open(filename, O_RDWR|O_CREAT|O_NOFOLLOW, S_IREAD|S_IWRITE), result); #else // workaround function (jdk6 code) - RESTARTABLE(::open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE), result); + result = open_o_nofollow(filename, O_RDWR|O_CREAT, S_IREAD|S_IWRITE); #endif if (result == OS_ERR) { @@ -931,7 +935,7 @@ static int create_sharedmem_resources(const char* dirname, const char* filename, if (PrintMiscellaneous && Verbose) { warning("could not set shared memory file size: %s\n", strerror(errno)); } - RESTARTABLE(::close(fd), result); + ::close(fd); return -1; } @@ -951,7 +955,7 @@ static int open_sharedmem_file(const char* filename, int oflags, TRAPS) { #ifdef O_NOFOLLOW RESTARTABLE(::open(filename, oflags), result); #else - RESTARTABLE(::open_o_nofollow(filename, oflags), result); + open_o_nofollow(filename, oflags); #endif if (result == OS_ERR) { @@ -1006,8 +1010,7 @@ static char* mmap_create_shared(size_t size) { char* dirname = get_user_tmp_dir(user_name); char* filename = get_sharedmem_filename(dirname, vmid); - - // Get the short filename. + // get the short filename. char* short_filename = strrchr(filename, '/'); if (short_filename == NULL) { short_filename = filename; @@ -1033,9 +1036,7 @@ static char* mmap_create_shared(size_t size) { mapAddress = (char*)::mmap((char*)0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); - // attempt to close the file - restart it if it was interrupted, - // but ignore other failures - RESTARTABLE(::close(fd), result); + result = ::close(fd); assert(result != OS_ERR, "could not close file"); if (mapAddress == MAP_FAILED) { @@ -1142,7 +1143,6 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor // constructs for the file and the shared memory mapping. if (mode == PerfMemory::PERF_MODE_RO) { mmap_prot = PROT_READ; - // No O_NOFOLLOW defined at buildtime, and it is not documented for open. #ifdef O_NOFOLLOW file_flags = O_RDONLY | O_NOFOLLOW; @@ -1205,21 +1205,28 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor FREE_C_HEAP_ARRAY(char, filename); // open the shared memory file for the give vmid - fd = open_sharedmem_file(rfilename, file_flags, CHECK); - assert(fd != OS_ERR, "unexpected value"); + fd = open_sharedmem_file(rfilename, file_flags, THREAD); + + if (fd == OS_ERR) { + return; + } + + if (HAS_PENDING_EXCEPTION) { + ::close(fd); + return; + } if (*sizep == 0) { size = sharedmem_filesize(fd, CHECK); - assert(size != 0, "unexpected size"); } else { size = *sizep; } + assert(size > 0, "unexpected size <= 0"); + mapAddress = (char*)::mmap((char*)0, size, mmap_prot, MAP_SHARED, fd, 0); - // attempt to close the file - restart if it gets interrupted, - // but ignore other failures - RESTARTABLE(::close(fd), result); + result = ::close(fd); assert(result != OS_ERR, "could not close file"); if (mapAddress == MAP_FAILED) { @@ -1230,7 +1237,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor "Could not map PerfMemory"); } - // It does not go through os api, the operation has to record from here. + // it does not go through os api, the operation has to record from here. MemTracker::record_virtual_memory_reserve((address)mapAddress, size, CURRENT_PC, mtInternal); *addr = mapAddress; @@ -1238,7 +1245,7 @@ static void mmap_attach_shared(const char* user, int vmid, PerfMemory::PerfMemor if (PerfTraceMemOps) { tty->print("mapped " SIZE_FORMAT " bytes for vmid %d at " - INTPTR_FORMAT "\n", size, vmid, (void*)mapAddress); + INTPTR_FORMAT "\n", size, vmid, p2i((void*)mapAddress)); } } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 8fdc6bc63b7..3d6f8fd6422 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_bsd.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_bsd.inline.hpp" @@ -681,6 +682,9 @@ static void *java_start(Thread *thread) { osthread->set_thread_id(os::Bsd::gettid()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + #ifdef __APPLE__ uint64_t unique_thread_id = locate_unique_thread_id(osthread->thread_id()); guarantee(unique_thread_id != 0, "unique thread id was not found"); @@ -716,6 +720,9 @@ static void *java_start(Thread *thread) { // call one more level start routine thread->run(); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return 0; } @@ -776,12 +783,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); if (ret != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -858,6 +871,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Bsd::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return true; } diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 3783351c345..f3896ed96a0 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -144,6 +144,7 @@ pthread_t os::Linux::_main_thread; int os::Linux::_page_size = -1; const int os::Linux::_vm_default_page_size = (8 * K); bool os::Linux::_supports_fast_thread_cpu_time = false; +uint32_t os::Linux::_os_version = 0; const char * os::Linux::_glibc_version = NULL; const char * os::Linux::_libpthread_version = NULL; pthread_condattr_t os::Linux::_condattr[1]; @@ -662,6 +663,9 @@ static void *java_start(Thread *thread) { osthread->set_thread_id(os::current_thread_id()); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { @@ -691,6 +695,9 @@ static void *java_start(Thread *thread) { // call one more level start routine thread->run(); + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return 0; } @@ -756,12 +763,18 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, pthread_t tid; int ret = pthread_create(&tid, &attr, (void* (*)(void*)) java_start, thread); + char buf[64]; + if (ret == 0) { + log_info(os, thread)("Thread started (pthread id: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } else { + log_warning(os, thread)("Failed to start thread - pthread_create failed (%s) for attributes: %s.", + strerror(ret), os::Posix::describe_pthread_attr(buf, sizeof(buf), &attr)); + } + pthread_attr_destroy(&attr); if (ret != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("pthread_create()"); - } // Need to clean up stuff we've allocated so far thread->set_osthread(NULL); delete osthread; @@ -858,6 +871,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Linux::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ", pthread id: " UINTX_FORMAT ").", + os::current_thread_id(), (uintx) pthread_self()); + return true; } @@ -4341,6 +4357,48 @@ jlong os::Linux::fast_thread_cpu_time(clockid_t clockid) { return (tp.tv_sec * NANOSECS_PER_SEC) + tp.tv_nsec; } +void os::Linux::initialize_os_info() { + assert(_os_version == 0, "OS info already initialized"); + + struct utsname _uname; + + uint32_t major; + uint32_t minor; + uint32_t fix; + + int rc; + + // Kernel version is unknown if + // verification below fails. + _os_version = 0x01000000; + + rc = uname(&_uname); + if (rc != -1) { + + rc = sscanf(_uname.release,"%d.%d.%d", &major, &minor, &fix); + if (rc == 3) { + + if (major < 256 && minor < 256 && fix < 256) { + // Kernel version format is as expected, + // set it overriding unknown state. + _os_version = (major << 16) | + (minor << 8 ) | + (fix << 0 ) ; + } + } + } +} + +uint32_t os::Linux::os_version() { + assert(_os_version != 0, "not initialized"); + return _os_version & 0x00FFFFFF; +} + +bool os::Linux::os_version_is_known() { + assert(_os_version != 0, "not initialized"); + return _os_version & 0x01000000 ? false : true; +} + ///// // glibc on Linux platform uses non-documented flag // to indicate, that some special sort of signal @@ -4563,6 +4621,8 @@ void os::init(void) { Linux::initialize_system_info(); + Linux::initialize_os_info(); + // main_thread points to the aboriginal thread Linux::_main_thread = pthread_self(); diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 1dcaafefd11..68e1968d2a1 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -56,6 +56,15 @@ class Linux { static GrowableArray* _cpu_to_node; + // 0x00000000 = uninitialized, + // 0x01000000 = kernel version unknown, + // otherwise a 32-bit number: + // Ox00AABBCC + // AA, Major Version + // BB, Minor Version + // CC, Fix Version + static uint32_t _os_version; + protected: static julong _physical_memory; @@ -198,6 +207,10 @@ class Linux { static jlong fast_thread_cpu_time(clockid_t clockid); + static void initialize_os_info(); + static bool os_version_is_known(); + static uint32_t os_version(); + // pthread_cond clock suppport private: static pthread_condattr_t _condattr[1]; diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index 68ab843bf44..85407bd3cad 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -238,14 +238,12 @@ void os::Posix::print_uname_info(outputStream* st) { st->cr(); } -#ifndef PRODUCT bool os::get_host_name(char* buf, size_t buflen) { struct utsname name; uname(&name); jio_snprintf(buf, buflen, "%s", name.nodename); return true; } -#endif // PRODUCT bool os::has_allocatable_memory_limit(julong* limit) { struct rlimit rlim; @@ -1073,6 +1071,19 @@ void os::Posix::ucontext_set_pc(ucontext_t* ctx, address pc) { #endif } +char* os::Posix::describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr) { + size_t stack_size = 0; + size_t guard_size = 0; + int detachstate = 0; + pthread_attr_getstacksize(attr, &stack_size); + pthread_attr_getguardsize(attr, &guard_size); + pthread_attr_getdetachstate(attr, &detachstate); + jio_snprintf(buf, buflen, "stacksize: " SIZE_FORMAT "k, guardsize: " SIZE_FORMAT "k, %s", + stack_size / 1024, guard_size / 1024, + (detachstate == PTHREAD_CREATE_DETACHED ? "detached" : "joinable")); + return buf; +} + os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { assert(Thread::current()->is_Watcher_thread(), "Must be WatcherThread"); diff --git a/hotspot/src/os/posix/vm/os_posix.hpp b/hotspot/src/os/posix/vm/os_posix.hpp index be464ea8fa1..0196e989456 100644 --- a/hotspot/src/os/posix/vm/os_posix.hpp +++ b/hotspot/src/os/posix/vm/os_posix.hpp @@ -76,6 +76,11 @@ public: static address ucontext_get_pc(const ucontext_t* ctx); // Set PC into context. Needed for continuation after signal. static void ucontext_set_pc(ucontext_t* ctx, address pc); + + // Helper function; describes pthread attributes as short string. String is written + // to buf with len buflen; buf is returned. + static char* describe_pthread_attr(char* buf, size_t buflen, const pthread_attr_t* attr); + }; /* diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index ae008b6dbe9..bc8138db6ff 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_solaris.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_solaris.inline.hpp" @@ -68,6 +69,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" // put OS-includes here @@ -736,6 +738,9 @@ extern "C" void* java_start(void* thread_addr) { osthr->set_lwp_id(_lwp_self()); // Store lwp in case we are bound thread->_schedctl = (void *) schedctl_init(); + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + if (UseNUMA) { int lgrp_id = os::numa_get_group_id(); if (lgrp_id != -1) { @@ -781,6 +786,8 @@ extern "C" void* java_start(void* thread_addr) { Atomic::dec(&os::Solaris::_os_thread_count); } + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id()); + if (UseDetachedThreads) { thr_exit(NULL); ShouldNotReachHere(); @@ -853,6 +860,9 @@ bool os::create_attached_thread(JavaThread* thread) { // and save the caller's signal mask os::Solaris::hotspot_sigmask(thread); + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + return true; } @@ -879,6 +889,24 @@ bool os::create_main_thread(JavaThread* thread) { return true; } +// Helper function to trace thread attributes, similar to os::Posix::describe_pthread_attr() +static char* describe_thr_create_attributes(char* buf, size_t buflen, + size_t stacksize, long flags) { + stringStream ss(buf, buflen); + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); + ss.print("flags: "); + #define PRINT_FLAG(f) if (flags & f) ss.print( #f " "); + #define ALL(X) \ + X(THR_SUSPENDED) \ + X(THR_DETACHED) \ + X(THR_BOUND) \ + X(THR_NEW_LWP) \ + X(THR_DAEMON) + ALL(PRINT_FLAG) + #undef ALL + #undef PRINT_FLAG + return buf; +} bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { @@ -974,10 +1002,17 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, osthread->set_thread_id(-1); status = thr_create(NULL, stack_size, java_start, thread, flags, &tid); + + char buf[64]; + if (status == 0) { + log_info(os, thread)("Thread started (tid: " UINTX_FORMAT ", attributes: %s). ", + (uintx) tid, describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + } else { + log_warning(os, thread)("Failed to start thread - thr_create failed (%s) for attributes: %s.", + strerror(status), describe_thr_create_attributes(buf, sizeof(buf), stack_size, flags)); + } + if (status != 0) { - if (PrintMiscellaneous && (Verbose || WizardMode)) { - perror("os::create_thread"); - } thread->set_osthread(NULL); // Need to clean up stuff we've allocated so far delete osthread; diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 1df102a7607..f8bc6081d8b 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -35,6 +35,7 @@ #include "compiler/disassembler.hpp" #include "interpreter/interpreter.hpp" #include "jvm_windows.h" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "mutex_windows.inline.hpp" @@ -71,6 +72,7 @@ #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" #include "utilities/growableArray.hpp" +#include "utilities/macros.hpp" #include "utilities/vmError.hpp" #ifdef _DEBUG @@ -436,6 +438,8 @@ static unsigned __stdcall java_start(Thread* thread) { res = 20115; // java thread } + log_info(os, thread)("Thread is alive (tid: " UINTX_FORMAT ").", os::current_thread_id()); + // Install a win32 structured exception handler around every thread created // by VM, so VM can generate error dump when an exception occurred in non- // Java thread (e.g. VM thread). @@ -446,6 +450,8 @@ static unsigned __stdcall java_start(Thread* thread) { // Nothing to do. } + log_info(os, thread)("Thread finished (tid: " UINTX_FORMAT ").", os::current_thread_id()); + // One less thread is executing // When the VMThread gets here, the main thread may have already exited // which frees the CodeHeap containing the Atomic::add code @@ -509,6 +515,10 @@ bool os::create_attached_thread(JavaThread* thread) { osthread->set_state(RUNNABLE); thread->set_osthread(osthread); + + log_info(os, thread)("Thread attached (tid: " UINTX_FORMAT ").", + os::current_thread_id()); + return true; } @@ -530,6 +540,27 @@ bool os::create_main_thread(JavaThread* thread) { return true; } +// Helper function to trace _beginthreadex attributes, +// similar to os::Posix::describe_pthread_attr() +static char* describe_beginthreadex_attributes(char* buf, size_t buflen, + size_t stacksize, unsigned initflag) { + stringStream ss(buf, buflen); + if (stacksize == 0) { + ss.print("stacksize: default, "); + } else { + ss.print("stacksize: " SIZE_FORMAT "k, ", stacksize / 1024); + } + ss.print("flags: "); + #define PRINT_FLAG(f) if (initflag & f) ss.print( #f " "); + #define ALL(X) \ + X(CREATE_SUSPENDED) \ + X(STACK_SIZE_PARAM_IS_A_RESERVATION) + ALL(PRINT_FLAG) + #undef ALL + #undef PRINT_FLAG + return buf; +} + // Allocate and initialize a new OSThread bool os::create_thread(Thread* thread, ThreadType thr_type, size_t stack_size) { @@ -596,14 +627,24 @@ bool os::create_thread(Thread* thread, ThreadType thr_type, // document because JVM uses C runtime library. The good news is that the // flag appears to work with _beginthredex() as well. + const unsigned initflag = CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION; HANDLE thread_handle = (HANDLE)_beginthreadex(NULL, (unsigned)stack_size, (unsigned (__stdcall *)(void*)) java_start, thread, - CREATE_SUSPENDED | STACK_SIZE_PARAM_IS_A_RESERVATION, + initflag, &thread_id); + char buf[64]; + if (thread_handle != NULL) { + log_info(os, thread)("Thread started (tid: %u, attributes: %s)", + thread_id, describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + } else { + log_warning(os, thread)("Failed to start thread - _beginthreadex failed (%s) for attributes: %s.", + strerror(errno), describe_beginthreadex_attributes(buf, sizeof(buf), stack_size, initflag)); + } + if (thread_handle == NULL) { // Need to clean up stuff we've allocated so far CloseHandle(osthread->interrupt_event()); @@ -1531,12 +1572,10 @@ int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *pa return result; } -#ifndef PRODUCT bool os::get_host_name(char* buf, size_t buflen) { DWORD size = (DWORD)buflen; return (GetComputerNameEx(ComputerNameDnsHostname, buf, &size) == TRUE); } -#endif // PRODUCT void os::get_summary_os_info(char* buf, size_t buflen) { stringStream sst(buf, buflen); @@ -1670,8 +1709,7 @@ void os::win32::print_windows_version(outputStream* st) { if (is_workstation) { st->print("10"); } else { - // The server version name of Windows 10 is not known at this time - st->print("%d.%d", major_version, minor_version); + st->print("Server 2016"); } break; diff --git a/hotspot/src/os/windows/vm/perfMemory_windows.cpp b/hotspot/src/os/windows/vm/perfMemory_windows.cpp index 8987ef1fb5b..7748b653c1d 100644 --- a/hotspot/src/os/windows/vm/perfMemory_windows.cpp +++ b/hotspot/src/os/windows/vm/perfMemory_windows.cpp @@ -628,6 +628,7 @@ static void cleanup_sharedmem_resources(const char* dirname) { if (!is_directory_secure(dirname)) { // the directory is not secure, don't attempt any cleanup + os::closedir(dirp); return; } @@ -1445,6 +1446,8 @@ static char* mapping_create_shared(size_t size) { // check that the file system is secure - i.e. it supports ACLs. if (!is_filesystem_secure(dirname)) { + FREE_C_HEAP_ARRAY(char, dirname); + FREE_C_HEAP_ARRAY(char, user); return NULL; } @@ -1624,6 +1627,7 @@ static void open_file_mapping(const char* user, int vmid, // if (!is_directory_secure(dirname)) { FREE_C_HEAP_ARRAY(char, dirname); + if (luser != user) FREE_C_HEAP_ARRAY(char, luser); THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), "Process not found"); } diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp index 5fc2dfd70d2..96575867dc2 100644 --- a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp +++ b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.inline.hpp @@ -26,44 +26,108 @@ #ifndef OS_CPU_LINUX_AARCH64_VM_COPY_LINUX_AARCH64_INLINE_HPP #define OS_CPU_LINUX_AARCH64_VM_COPY_LINUX_AARCH64_INLINE_HPP +#define COPY_SMALL(from, to, count) \ +{ \ + long tmp0, tmp1, tmp2, tmp3; \ + long tmp4, tmp5, tmp6, tmp7; \ + __asm volatile( \ +" adr %[t0], 0f;" \ +" add %[t0], %[t0], %[cnt], lsl #5;" \ +" br %[t0];" \ +" .align 5;" \ +"0:" \ +" b 1f;" \ +" .align 5;" \ +" ldr %[t0], [%[s], #0];" \ +" str %[t0], [%[d], #0];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldr %[t2], [%[s], #16];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" str %[t2], [%[d], #16];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" ldr %[t4], [%[s], #32];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" str %[t4], [%[d], #32];" \ +" b 1f;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" ldp %[t4], %[t5], [%[s], #32];" \ +"2:" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" stp %[t4], %[t5], [%[d], #32];" \ +" b 1f;" \ +" .align 5;" \ +" ldr %[t6], [%[s], #0];" \ +" ldp %[t0], %[t1], [%[s], #8];" \ +" ldp %[t2], %[t3], [%[s], #24];" \ +" ldp %[t4], %[t5], [%[s], #40];" \ +" str %[t6], [%[d]], #8;" \ +" b 2b;" \ +" .align 5;" \ +" ldp %[t0], %[t1], [%[s], #0];" \ +" ldp %[t2], %[t3], [%[s], #16];" \ +" ldp %[t4], %[t5], [%[s], #32];" \ +" ldp %[t6], %[t7], [%[s], #48];" \ +" stp %[t0], %[t1], [%[d], #0];" \ +" stp %[t2], %[t3], [%[d], #16];" \ +" stp %[t4], %[t5], [%[d], #32];" \ +" stp %[t6], %[t7], [%[d], #48];" \ +"1:" \ + \ + : [s]"+r"(from), [d]"+r"(to), [cnt]"+r"(count), \ + [t0]"=&r"(tmp0), [t1]"=&r"(tmp1), [t2]"=&r"(tmp2), [t3]"=&r"(tmp3), \ + [t4]"=&r"(tmp4), [t5]"=&r"(tmp5), [t6]"=&r"(tmp6), [t7]"=&r"(tmp7) \ + : \ + : "memory", "cc"); \ +} + static void pd_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { - (void)memmove(to, from, count * HeapWordSize); + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_conjoint_words(from, to, count); } static void pd_disjoint_words(HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - (void)memcpy(to, from, count * HeapWordSize); - break; + if (__builtin_constant_p(count)) { + memcpy(to, from, count * sizeof(HeapWord)); + return; } + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; + } + _Copy_disjoint_words(from, to, count); } static void pd_disjoint_words_atomic(HeapWord* from, HeapWord* to, size_t count) { - switch (count) { - case 8: to[7] = from[7]; - case 7: to[6] = from[6]; - case 6: to[5] = from[5]; - case 5: to[4] = from[4]; - case 4: to[3] = from[3]; - case 3: to[2] = from[2]; - case 2: to[1] = from[1]; - case 1: to[0] = from[0]; - case 0: break; - default: - while (count-- > 0) { - *to++ = *from++; - } - break; + __asm volatile( "prfm pldl1strm, [%[s], #0];" :: [s]"r"(from) : "memory"); + if (__builtin_expect(count <= 8, 1)) { + COPY_SMALL(from, to, count); + return; } + _Copy_disjoint_words(from, to, count); } static void pd_aligned_conjoint_words(HeapWord* from, HeapWord* to, size_t count) { diff --git a/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s new file mode 100644 index 00000000000..25e3b054f77 --- /dev/null +++ b/hotspot/src/os_cpu/linux_aarch64/vm/copy_linux_aarch64.s @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2016, Linaro Ltd. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + .global _Copy_conjoint_words + .global _Copy_disjoint_words + +s .req x0 +d .req x1 +count .req x2 +t0 .req x3 +t1 .req x4 +t2 .req x5 +t3 .req x6 +t4 .req x7 +t5 .req x8 +t6 .req x9 +t7 .req x10 + + .align 6 +_Copy_disjoint_words: + // Ensure 2 word aligned + tbz s, #3, fwd_copy_aligned + ldr t0, [s], #8 + str t0, [d], #8 + sub count, count, #1 + +fwd_copy_aligned: + // Bias s & d so we only pre index on the last copy + sub s, s, #16 + sub d, d, #16 + + ldp t0, t1, [s, #16] + ldp t2, t3, [s, #32] + ldp t4, t5, [s, #48] + ldp t6, t7, [s, #64]! + + subs count, count, #16 + blo fwd_copy_drain + +fwd_copy_again: + prfm pldl1keep, [s, #256] + stp t0, t1, [d, #16] + ldp t0, t1, [s, #16] + stp t2, t3, [d, #32] + ldp t2, t3, [s, #32] + stp t4, t5, [d, #48] + ldp t4, t5, [s, #48] + stp t6, t7, [d, #64]! + ldp t6, t7, [s, #64]! + subs count, count, #8 + bhs fwd_copy_again + +fwd_copy_drain: + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + stp t4, t5, [d, #48] + stp t6, t7, [d, #64]! + + // count is now -8..-1 for 0..7 words to copy + adr t0, 0f + add t0, t0, count, lsl #5 + br t0 + + .align 5 + ret // -8 == 0 words + .align 5 + ldr t0, [s, #16] // -7 == 1 word + str t0, [d, #16] + ret + .align 5 + ldp t0, t1, [s, #16] // -6 = 2 words + stp t0, t1, [d, #16] + ret + .align 5 + ldp t0, t1, [s, #16] // -5 = 3 words + ldr t2, [s, #32] + stp t0, t1, [d, #16] + str t2, [d, #32] + ret + .align 5 + ldp t0, t1, [s, #16] // -4 = 4 words + ldp t2, t3, [s, #32] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + ret + .align 5 + ldp t0, t1, [s, #16] // -3 = 5 words + ldp t2, t3, [s, #32] + ldr t4, [s, #48] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + str t4, [d, #48] + ret + .align 5 + ldp t0, t1, [s, #16] // -2 = 6 words + ldp t2, t3, [s, #32] + ldp t4, t5, [s, #48] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + stp t4, t5, [d, #48] + ret + .align 5 + ldp t0, t1, [s, #16] // -1 = 7 words + ldp t2, t3, [s, #32] + ldp t4, t5, [s, #48] + ldr t6, [s, #64] + stp t0, t1, [d, #16] + stp t2, t3, [d, #32] + stp t4, t5, [d, #48] + str t6, [d, #64] + // Is always aligned here, code for 7 words is one instruction + // too large so it just falls through. + .align 5 +0: + ret + + .align 6 +_Copy_conjoint_words: + sub t0, d, s + cmp t0, count, lsl #3 + bhs _Copy_disjoint_words + + add s, s, count, lsl #3 + add d, d, count, lsl #3 + + // Ensure 2 word aligned + tbz s, #3, bwd_copy_aligned + ldr t0, [s, #-8]! + str t0, [d, #-8]! + sub count, count, #1 + +bwd_copy_aligned: + ldp t0, t1, [s, #-16] + ldp t2, t3, [s, #-32] + ldp t4, t5, [s, #-48] + ldp t6, t7, [s, #-64]! + + subs count, count, #16 + blo bwd_copy_drain + +bwd_copy_again: + prfm pldl1keep, [s, #-256] + stp t0, t1, [d, #-16] + ldp t0, t1, [s, #-16] + stp t2, t3, [d, #-32] + ldp t2, t3, [s, #-32] + stp t4, t5, [d, #-48] + ldp t4, t5, [s, #-48] + stp t6, t7, [d, #-64]! + ldp t6, t7, [s, #-64]! + subs count, count, #8 + bhs bwd_copy_again + +bwd_copy_drain: + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + stp t4, t5, [d, #-48] + stp t6, t7, [d, #-64]! + + // count is now -8..-1 for 0..7 words to copy + adr t0, 0f + add t0, t0, count, lsl #5 + br t0 + + .align 5 + ret // -8 == 0 words + .align 5 + ldr t0, [s, #-8] // -7 == 1 word + str t0, [d, #-8] + ret + .align 5 + ldp t0, t1, [s, #-16] // -6 = 2 words + stp t0, t1, [d, #-16] + ret + .align 5 + ldp t0, t1, [s, #-16] // -5 = 3 words + ldr t2, [s, #-24] + stp t0, t1, [d, #-16] + str t2, [d, #-24] + ret + .align 5 + ldp t0, t1, [s, #-16] // -4 = 4 words + ldp t2, t3, [s, #-32] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + ret + .align 5 + ldp t0, t1, [s, #-16] // -3 = 5 words + ldp t2, t3, [s, #-32] + ldr t4, [s, #-40] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + str t4, [d, #-40] + ret + .align 5 + ldp t0, t1, [s, #-16] // -2 = 6 words + ldp t2, t3, [s, #-32] + ldp t4, t5, [s, #-48] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + stp t4, t5, [d, #-48] + ret + .align 5 + ldp t0, t1, [s, #-16] // -1 = 7 words + ldp t2, t3, [s, #-32] + ldp t4, t5, [s, #-48] + ldr t6, [s, #-56] + stp t0, t1, [d, #-16] + stp t2, t3, [d, #-32] + stp t4, t5, [d, #-48] + str t6, [d, #-56] + // Is always aligned here, code for 7 words is one instruction + // too large so it just falls through. + .align 5 +0: + ret diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index f57f89ad02f..b1e93a82dc8 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -65,6 +65,7 @@ address os::current_stack_pointer() { frame os::get_sender_for_C_frame(frame* fr) { ShouldNotCallThis(); + return frame(NULL, NULL); // silence compile warning. } frame os::current_frame() { @@ -102,6 +103,7 @@ void os::initialize_thread(Thread * thr){ address os::Linux::ucontext_get_pc(const ucontext_t* uc) { ShouldNotCallThis(); + return NULL; // silence compile warnings } void os::Linux::ucontext_set_pc(ucontext_t * uc, address pc) { @@ -112,10 +114,12 @@ ExtendedPC os::fetch_frame_from_context(const void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { ShouldNotCallThis(); + return NULL; // silence compile warnings } frame os::fetch_frame_from_context(const void* ucVoid) { ShouldNotCallThis(); + return frame(NULL, NULL); // silence compile warnings } extern "C" JNIEXPORT int @@ -262,11 +266,16 @@ JVM_handle_linux_signal(int sig, } #endif // !PRODUCT - const char *fmt = "caught unhandled signal %d"; char buf[64]; - sprintf(buf, fmt, sig); + sprintf(buf, "caught unhandled signal %d", sig); + +// Silence -Wformat-security warning for fatal() +PRAGMA_DIAG_PUSH +PRAGMA_FORMAT_NONLITERAL_IGNORED fatal(buf); +PRAGMA_DIAG_POP + return true; // silence compiler warnings } void os::Linux::init_thread_fpu_state(void) { @@ -275,6 +284,7 @@ void os::Linux::init_thread_fpu_state(void) { int os::Linux::get_fpu_control_word() { ShouldNotCallThis(); + return -1; // silence compile warnings } void os::Linux::set_fpu_control_word(int fpu) { @@ -419,6 +429,7 @@ void os::print_register_info(outputStream *st, const void *context) { extern "C" { int SpinPause() { + return -1; // silence compile warnings } diff --git a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp index 39f77f858d0..b9c73dc48c1 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp +++ b/hotspot/src/os_cpu/linux_zero/vm/thread_linux_zero.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * Copyright 2007, 2008, 2009, 2010 Red Hat, Inc. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -110,6 +110,7 @@ void* ucontext, bool isInJava) { ShouldNotCallThis(); + return false; // silence compile warning } // These routines are only used on cpu architectures that diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index 971fa84fc64..837607e6781 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -264,6 +264,7 @@ void PICL::close_library() { // We need to keep these here as long as we have to build on Solaris // versions before 10. + #ifndef SI_ARCHITECTURE_32 #define SI_ARCHITECTURE_32 516 /* basic 32-bit SI_ARCHITECTURE */ #endif @@ -272,36 +273,87 @@ void PICL::close_library() { #define SI_ARCHITECTURE_64 517 /* basic 64-bit SI_ARCHITECTURE */ #endif -static void do_sysinfo(int si, const char* string, int* features, int mask) { - char tmp; - size_t bufsize = sysinfo(si, &tmp, 1); +#ifndef SI_CPUBRAND +#define SI_CPUBRAND 523 /* return cpu brand string */ +#endif - // All SI defines used below must be supported. - guarantee(bufsize != -1, "must be supported"); +class Sysinfo { + char* _string; +public: + Sysinfo(int si) : _string(NULL) { + char tmp; + size_t bufsize = sysinfo(si, &tmp, 1); - char* buf = (char*) os::malloc(bufsize, mtInternal); - - if (buf == NULL) - return; - - if (sysinfo(si, buf, bufsize) == bufsize) { - // Compare the string. - if (strcmp(buf, string) == 0) { - *features |= mask; + if (bufsize != -1) { + char* buf = (char*) os::malloc(bufsize, mtInternal); + if (buf != NULL) { + if (sysinfo(si, buf, bufsize) == bufsize) { + _string = buf; + } else { + os::free(buf); + } + } } } - os::free(buf); -} + ~Sysinfo() { + if (_string != NULL) { + os::free(_string); + } + } + + const char* value() const { + return _string; + } + + bool valid() const { + return _string != NULL; + } + + bool match(const char* s) const { + return valid() ? strcmp(_string, s) == 0 : false; + } + + bool match_substring(const char* s) const { + return valid() ? strstr(_string, s) != NULL : false; + } +}; + +class Sysconf { + int _value; +public: + Sysconf(int sc) : _value(-1) { + _value = sysconf(sc); + } + bool valid() const { + return _value != -1; + } + int value() const { + return _value; + } +}; + + +#ifndef _SC_DCACHE_LINESZ +#define _SC_DCACHE_LINESZ 508 /* Data cache line size */ +#endif + +#ifndef _SC_L2CACHE_LINESZ +#define _SC_L2CACHE_LINESZ 527 /* Size of L2 cache line */ +#endif int VM_Version::platform_features(int features) { assert(os::Solaris::supports_getisax(), "getisax() must be available"); // Check 32-bit architecture. - do_sysinfo(SI_ARCHITECTURE_32, "sparc", &features, v8_instructions_m); + if (Sysinfo(SI_ARCHITECTURE_32).match("sparc")) { + features |= v8_instructions_m; + } // Check 64-bit architecture. - do_sysinfo(SI_ARCHITECTURE_64, "sparcv9", &features, generic_v9_m); + if (Sysinfo(SI_ARCHITECTURE_64).match("sparcv9")) { + features |= generic_v9_m; + } // Extract valid instruction set extensions. uint_t avs[2]; @@ -388,67 +440,63 @@ int VM_Version::platform_features(int features) { if (av & AV_SPARC_SHA512) features |= sha512_instruction_m; // Determine the machine type. - do_sysinfo(SI_MACHINE, "sun4v", &features, sun4v_m); + if (Sysinfo(SI_MACHINE).match("sun4v")) { + features |= sun4v_m; + } - { - // Using kstat to determine the machine type. + bool use_solaris_12_api = false; + Sysinfo impl(SI_CPUBRAND); + if (impl.valid()) { + // If SI_CPUBRAND works, that means Solaris 12 API to get the cache line sizes + // is available to us as well + use_solaris_12_api = true; + features |= parse_features(impl.value()); + } else { + // Otherwise use kstat to determine the machine type. kstat_ctl_t* kc = kstat_open(); kstat_t* ksp = kstat_lookup(kc, (char*)"cpu_info", -1, NULL); - const char* implementation = "UNKNOWN"; + const char* implementation; + bool has_implementation = false; if (ksp != NULL) { if (kstat_read(kc, ksp, NULL) != -1 && ksp->ks_data != NULL) { kstat_named_t* knm = (kstat_named_t *)ksp->ks_data; for (int i = 0; i < ksp->ks_ndata; i++) { if (strcmp((const char*)&(knm[i].name),"implementation") == 0) { implementation = KSTAT_NAMED_STR_PTR(&knm[i]); + has_implementation = true; #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("cpu_info.implementation: %s", implementation); } #endif - // Convert to UPPER case before compare. - char* impl = os::strdup_check_oom(implementation); - - for (int i = 0; impl[i] != 0; i++) - impl[i] = (char)toupper((uint)impl[i]); - - if (strstr(impl, "SPARC64") != NULL) { - features |= sparc64_family_m; - } else if (strstr(impl, "SPARC-M") != NULL) { - // M-series SPARC is based on T-series. - features |= (M_family_m | T_family_m); - } else if (strstr(impl, "SPARC-T") != NULL) { - features |= T_family_m; - if (strstr(impl, "SPARC-T1") != NULL) { - features |= T1_model_m; - } - } else { - if (strstr(impl, "SPARC") == NULL) { -#ifndef PRODUCT - // kstat on Solaris 8 virtual machines (branded zones) - // returns "(unsupported)" implementation. Solaris 8 is not - // supported anymore, but include this check to be on the - // safe side. - warning("kstat cpu_info implementation = '%s', assume generic SPARC", impl); -#endif - implementation = "SPARC"; - } - } - os::free((void*)impl); + features |= parse_features(implementation); break; } } // for( } } - assert(strcmp(implementation, "UNKNOWN") != 0, - "unknown cpu info (changed kstat interface?)"); + assert(has_implementation, "unknown cpu info (changed kstat interface?)"); kstat_close(kc); } - // Figure out cache line sizes using PICL - PICL picl((features & sparc64_family_m) != 0, (features & sun4v_m) != 0); - _L1_data_cache_line_size = picl.L1_data_cache_line_size(); - _L2_data_cache_line_size = picl.L2_data_cache_line_size(); + bool is_sun4v = (features & sun4v_m) != 0; + if (use_solaris_12_api && is_sun4v) { + // If Solaris 12 API is supported and it's sun4v use sysconf() to get the cache line sizes + Sysconf l1_dcache_line_size(_SC_DCACHE_LINESZ); + if (l1_dcache_line_size.valid()) { + _L1_data_cache_line_size = l1_dcache_line_size.value(); + } + Sysconf l2_dcache_line_size(_SC_L2CACHE_LINESZ); + if (l2_dcache_line_size.valid()) { + _L2_data_cache_line_size = l2_dcache_line_size.value(); + } + } else { + // Otherwise figure out the cache line sizes using PICL + bool is_fujitsu = (features & sparc64_family_m) != 0; + PICL picl(is_fujitsu, is_sun4v); + _L1_data_cache_line_size = picl.L1_data_cache_line_size(); + _L2_data_cache_line_size = picl.L2_data_cache_line_size(); + } return features; } diff --git a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp index 033beb0d25e..c4a084a4518 100644 --- a/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp +++ b/hotspot/src/share/vm/c1/c1_Canonicalizer.cpp @@ -257,7 +257,38 @@ void Canonicalizer::do_ArrayLength (ArrayLength* x) { } } -void Canonicalizer::do_LoadIndexed (LoadIndexed* x) {} +void Canonicalizer::do_LoadIndexed (LoadIndexed* x) { + StableArrayConstant* array = x->array()->type()->as_StableArrayConstant(); + IntConstant* index = x->index()->type()->as_IntConstant(); + + assert(array == NULL || FoldStableValues, "not enabled"); + + // Constant fold loads from stable arrays. + if (array != NULL && index != NULL) { + jint idx = index->value(); + if (idx < 0 || idx >= array->value()->length()) { + // Leave the load as is. The range check will handle it. + return; + } + + ciConstant field_val = array->value()->element_value(idx); + if (!field_val.is_null_or_zero()) { + jint dimension = array->dimension(); + assert(dimension <= array->value()->array_type()->dimension(), "inconsistent info"); + ValueType* value = NULL; + if (dimension > 1) { + // Preserve information about the dimension for the element. + assert(field_val.as_object()->is_array(), "not an array"); + value = new StableArrayConstant(field_val.as_object()->as_array(), dimension - 1); + } else { + assert(dimension == 1, "sanity"); + value = as_ValueType(field_val); + } + set_canonical(new Constant(value)); + } + } +} + void Canonicalizer::do_StoreIndexed (StoreIndexed* x) { // If a value is going to be stored into a field or array some of // the conversions emitted by javac are unneeded because the fields @@ -471,7 +502,7 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) { InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); if (c != NULL && !c->value()->is_null_object()) { // ciInstance::java_mirror_type() returns non-NULL only for Java mirrors - ciType* t = c->value()->as_instance()->java_mirror_type(); + ciType* t = c->value()->java_mirror_type(); if (t->is_klass()) { // substitute cls.isInstance(obj) of a constant Class into // an InstantOf instruction @@ -487,6 +518,17 @@ void Canonicalizer::do_Intrinsic (Intrinsic* x) { } break; } + case vmIntrinsics::_isPrimitive : { + assert(x->number_of_arguments() == 1, "wrong type"); + + // Class.isPrimitive is known on constant classes: + InstanceConstant* c = x->argument_at(0)->type()->as_InstanceConstant(); + if (c != NULL && !c->value()->is_null_object()) { + ciType* t = c->value()->java_mirror_type(); + set_constant(t->is_primitive_type()); + } + break; + } } } diff --git a/hotspot/src/share/vm/c1/c1_Compiler.cpp b/hotspot/src/share/vm/c1/c1_Compiler.cpp index 5dbe6c209f3..b7885a31cfc 100644 --- a/hotspot/src/share/vm/c1/c1_Compiler.cpp +++ b/hotspot/src/share/vm/c1/c1_Compiler.cpp @@ -148,6 +148,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_longBitsToDouble: case vmIntrinsics::_getClass: case vmIntrinsics::_isInstance: + case vmIntrinsics::_isPrimitive: case vmIntrinsics::_currentThread: case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: @@ -228,8 +229,6 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_getCharStringU: case vmIntrinsics::_putCharStringU: #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif break; diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index b2766898d71..c3483a5fe00 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1519,6 +1519,29 @@ void GraphBuilder::method_return(Value x) { append(new Return(x)); } +Value GraphBuilder::make_constant(ciConstant field_value, ciField* field) { + BasicType field_type = field_value.basic_type(); + ValueType* value = as_ValueType(field_value); + + // Attach dimension info to stable arrays. + if (FoldStableValues && + field->is_stable() && field_type == T_ARRAY && !field_value.is_null_or_zero()) { + ciArray* array = field_value.as_object()->as_array(); + jint dimension = field->type()->as_array_klass()->dimension(); + value = new StableArrayConstant(array, dimension); + } + + switch (field_type) { + case T_ARRAY: + case T_OBJECT: + if (field_value.as_object()->should_be_constant()) { + return new Constant(value); + } + return NULL; // Not a constant. + default: + return new Constant(value); + } +} void GraphBuilder::access_field(Bytecodes::Code code) { bool will_link; @@ -1563,22 +1586,13 @@ void GraphBuilder::access_field(Bytecodes::Code code) { switch (code) { case Bytecodes::_getstatic: { // check for compile-time constants, i.e., initialized static final fields - Instruction* constant = NULL; + Value constant = NULL; if (field->is_constant() && !PatchALot) { - ciConstant field_val = field->constant_value(); - BasicType field_type = field_val.basic_type(); - switch (field_type) { - case T_ARRAY: - case T_OBJECT: - if (field_val.as_object()->should_be_constant()) { - constant = new Constant(as_ValueType(field_val)); - } - break; - - default: - constant = new Constant(as_ValueType(field_val)); - } + ciConstant field_value = field->constant_value(); // Stable static fields are checked for non-default values in ciField::initialize_from(). + assert(!field->is_stable() || !field_value.is_null_or_zero(), + "stable static w/ default value shouldn't be a constant"); + constant = make_constant(field_value, field); } if (constant != NULL) { push(type, append(constant)); @@ -1591,38 +1605,29 @@ void GraphBuilder::access_field(Bytecodes::Code code) { } break; } - case Bytecodes::_putstatic: - { Value val = pop(type); - if (state_before == NULL) { - state_before = copy_state_for_exception(); - } - append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); + case Bytecodes::_putstatic: { + Value val = pop(type); + if (state_before == NULL) { + state_before = copy_state_for_exception(); } + append(new StoreField(append(obj), offset, field, val, true, state_before, needs_patching)); break; + } case Bytecodes::_getfield: { // Check for compile-time constants, i.e., trusted final non-static fields. - Instruction* constant = NULL; + Value constant = NULL; obj = apop(); ObjectType* obj_type = obj->type()->as_ObjectType(); if (obj_type->is_constant() && !PatchALot) { ciObject* const_oop = obj_type->constant_value(); if (!const_oop->is_null_object() && const_oop->is_loaded()) { if (field->is_constant()) { - ciConstant field_val = field->constant_value_of(const_oop); - BasicType field_type = field_val.basic_type(); - switch (field_type) { - case T_ARRAY: - case T_OBJECT: - if (field_val.as_object()->should_be_constant()) { - constant = new Constant(as_ValueType(field_val)); - } - break; - default: - constant = new Constant(as_ValueType(field_val)); - } - if (FoldStableValues && field->is_stable() && field_val.is_null_or_zero()) { + ciConstant field_value = field->constant_value_of(const_oop); + if (FoldStableValues && field->is_stable() && field_value.is_null_or_zero()) { // Stable field with default value can't be constant. constant = NULL; + } else { + constant = make_constant(field_value, field); } } else { // For CallSite objects treat the target field as a compile time constant. @@ -3942,7 +3947,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { - ValueStack* state_before = state()->copy_for_parsing(); + ValueStack* state_before = copy_state_before(); vmIntrinsics::ID iid = callee->intrinsic_id(); switch (iid) { case vmIntrinsics::_invokeBasic: @@ -4032,7 +4037,7 @@ bool GraphBuilder::try_method_handle_inline(ciMethod* callee) { fatal("unexpected intrinsic %d: %s", iid, vmIntrinsics::name_at(iid)); break; } - set_state(state_before); + set_state(state_before->copy_for_parsing()); return false; } diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp index 4fb1e184d6d..20bed2b164d 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp @@ -276,6 +276,7 @@ class GraphBuilder VALUE_OBJ_CLASS_SPEC { void iterate_all_blocks(bool start_in_current_block_for_inlining = false); Dependencies* dependency_recorder() const; // = compilation()->dependencies() bool direct_compare(ciKlass* k); + Value make_constant(ciConstant value, ciField* field); void kill_all(); diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp index 30ae8f86e9f..b8df66256b3 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.cpp @@ -43,6 +43,9 @@ #if INCLUDE_ALL_GCS #include "gc/g1/heapRegion.hpp" #endif // INCLUDE_ALL_GCS +#ifdef TRACE_HAVE_INTRINSICS +#include "trace/traceMacros.hpp" +#endif #ifdef ASSERT #define __ gen()->lir(__FILE__, __LINE__)-> @@ -1293,6 +1296,25 @@ void LIRGenerator::do_getClass(Intrinsic* x) { __ move_wide(new LIR_Address(temp, in_bytes(Klass::java_mirror_offset()), T_OBJECT), result); } +// java.lang.Class::isPrimitive() +void LIRGenerator::do_isPrimitive(Intrinsic* x) { + assert(x->number_of_arguments() == 1, "wrong type"); + + LIRItem rcvr(x->argument_at(0), this); + rcvr.load_item(); + LIR_Opr temp = new_register(T_METADATA); + LIR_Opr result = rlock_result(x); + + CodeEmitInfo* info = NULL; + if (x->needs_null_check()) { + info = state_for(x); + } + + __ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset_in_bytes(), T_ADDRESS), temp, info); + __ cmp(lir_cond_notEqual, temp, LIR_OprFact::intConst(0)); + __ cmove(lir_cond_notEqual, LIR_OprFact::intConst(0), LIR_OprFact::intConst(1), result, T_BOOLEAN); +} + // Example: Thread.currentThread() void LIRGenerator::do_currentThread(Intrinsic* x) { @@ -3067,42 +3089,7 @@ void LIRGenerator::do_RuntimeCall(address routine, Intrinsic* x) { __ move(reg, result); } -#ifdef TRACE_HAVE_INTRINSICS -void LIRGenerator::do_ThreadIDIntrinsic(Intrinsic* x) { - LIR_Opr thread = getThreadPointer(); - LIR_Opr osthread = new_pointer_register(); - __ move(new LIR_Address(thread, in_bytes(JavaThread::osthread_offset()), osthread->type()), osthread); - size_t thread_id_size = OSThread::thread_id_size(); - if (thread_id_size == (size_t) BytesPerLong) { - LIR_Opr id = new_register(T_LONG); - __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_LONG), id); - __ convert(Bytecodes::_l2i, id, rlock_result(x)); - } else if (thread_id_size == (size_t) BytesPerInt) { - __ move(new LIR_Address(osthread, in_bytes(OSThread::thread_id_offset()), T_INT), rlock_result(x)); - } else { - ShouldNotReachHere(); - } -} -void LIRGenerator::do_ClassIDIntrinsic(Intrinsic* x) { - CodeEmitInfo* info = state_for(x); - CodeEmitInfo* info2 = new CodeEmitInfo(info); // Clone for the second null check - BasicType klass_pointer_type = NOT_LP64(T_INT) LP64_ONLY(T_LONG); - assert(info != NULL, "must have info"); - LIRItem arg(x->argument_at(1), this); - arg.load_item(); - LIR_Opr klass = new_pointer_register(); - __ move(new LIR_Address(arg.result(), java_lang_Class::klass_offset_in_bytes(), klass_pointer_type), klass, info); - LIR_Opr id = new_register(T_LONG); - ByteSize offset = TRACE_ID_OFFSET; - LIR_Address* trace_id_addr = new LIR_Address(klass, in_bytes(offset), T_LONG); - __ move(trace_id_addr, id); - __ logical_or(id, LIR_OprFact::longConst(0x01l), id); - __ store(id, trace_id_addr); - __ logical_and(id, LIR_OprFact::longConst(~0x3l), id); - __ move(id, rlock_result(x)); -} -#endif void LIRGenerator::do_Intrinsic(Intrinsic* x) { switch (x->id()) { @@ -3115,8 +3102,6 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { } #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_threadID: do_ThreadIDIntrinsic(x); break; - case vmIntrinsics::_classID: do_ClassIDIntrinsic(x); break; case vmIntrinsics::_counterTime: do_RuntimeCall(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), x); break; @@ -3132,6 +3117,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_Object_init: do_RegisterFinalizer(x); break; case vmIntrinsics::_isInstance: do_isInstance(x); break; + case vmIntrinsics::_isPrimitive: do_isPrimitive(x); break; case vmIntrinsics::_getClass: do_getClass(x); break; case vmIntrinsics::_currentThread: do_currentThread(x); break; diff --git a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp index 9438d77288c..bf36d7dc10e 100644 --- a/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRGenerator.hpp @@ -246,6 +246,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_RegisterFinalizer(Intrinsic* x); void do_isInstance(Intrinsic* x); + void do_isPrimitive(Intrinsic* x); void do_getClass(Intrinsic* x); void do_currentThread(Intrinsic* x); void do_MathIntrinsic(Intrinsic* x); @@ -440,10 +441,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_SwitchRanges(SwitchRangeArray* x, LIR_Opr value, BlockBegin* default_sux); void do_RuntimeCall(address routine, Intrinsic* x); -#ifdef TRACE_HAVE_INTRINSICS - void do_ThreadIDIntrinsic(Intrinsic* x); - void do_ClassIDIntrinsic(Intrinsic* x); -#endif + ciKlass* profile_type(ciMethodData* md, int md_first_offset, int md_offset, intptr_t profiled_k, Value arg, LIR_Opr& mdp, bool not_null, ciKlass* signature_at_call_k, ciKlass* callee_signature_k); diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 92c721575d0..70c4fc3304f 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -335,6 +335,7 @@ JRT_ENTRY(void, Runtime1::new_instance(JavaThread* thread, Klass* klass)) NOT_PRODUCT(_new_instance_slowcase_cnt++;) assert(klass->is_klass(), "not a class"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive instanceKlassHandle h(thread, klass); h->check_valid_for_instantiation(true, CHECK); // make sure klass is initialized @@ -370,6 +371,7 @@ JRT_ENTRY(void, Runtime1::new_object_array(JavaThread* thread, Klass* array_klas // anymore after new_objArray() and no GC can happen before. // (This may have to change if this code changes!) assert(array_klass->is_klass(), "not a class"); + Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); objArrayOop obj = oopFactory::new_objArray(elem_klass, length, CHECK); thread->set_vm_result(obj); @@ -386,6 +388,7 @@ JRT_ENTRY(void, Runtime1::new_multi_array(JavaThread* thread, Klass* klass, int assert(klass->is_klass(), "not a class"); assert(rank >= 1, "rank must be nonzero"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); thread->set_vm_result(obj); JRT_END diff --git a/hotspot/src/share/vm/c1/c1_ValueType.hpp b/hotspot/src/share/vm/c1/c1_ValueType.hpp index 291dd2386d3..a5e901523ef 100644 --- a/hotspot/src/share/vm/c1/c1_ValueType.hpp +++ b/hotspot/src/share/vm/c1/c1_ValueType.hpp @@ -45,6 +45,7 @@ class ObjectType; class ObjectConstant; class ArrayType; class ArrayConstant; +class StableArrayConstant; class InstanceType; class InstanceConstant; class MetadataType; @@ -168,6 +169,7 @@ class ValueType: public CompilationResourceObj { virtual MethodConstant* as_MethodConstant() { return NULL; } virtual MethodDataConstant* as_MethodDataConstant() { return NULL; } virtual ArrayConstant* as_ArrayConstant() { return NULL; } + virtual StableArrayConstant* as_StableArrayConstant() { return NULL; } virtual AddressConstant* as_AddressConstant() { return NULL; } // type operations @@ -355,6 +357,20 @@ class ArrayConstant: public ArrayType { virtual ciType* exact_type() const; }; +class StableArrayConstant: public ArrayConstant { + private: + jint _dimension; + + public: + StableArrayConstant(ciArray* value, jint dimension) : ArrayConstant(value) { + assert(dimension > 0, "not a stable array"); + _dimension = dimension; + } + + jint dimension() const { return _dimension; } + + virtual StableArrayConstant* as_StableArrayConstant() { return this; } +}; class InstanceType: public ObjectType { public: diff --git a/hotspot/src/share/vm/ci/ciArray.cpp b/hotspot/src/share/vm/ci/ciArray.cpp index f527d3ed538..04a6db8df3f 100644 --- a/hotspot/src/share/vm/ci/ciArray.cpp +++ b/hotspot/src/share/vm/ci/ciArray.cpp @@ -107,8 +107,9 @@ ciConstant ciArray::element_value_by_offset(intptr_t element_offset) { intptr_t header = arrayOopDesc::base_offset_in_bytes(elembt); intptr_t index = (element_offset - header) >> shift; intptr_t offset = header + ((intptr_t)index << shift); - if (offset != element_offset || index != (jint)index) + if (offset != element_offset || index != (jint)index || index < 0 || index >= length()) { return ciConstant(); + } return element_value((jint) index); } diff --git a/hotspot/src/share/vm/ci/ciMethodData.cpp b/hotspot/src/share/vm/ci/ciMethodData.cpp index 7aaf9bdf2c4..0ede3dfc31e 100644 --- a/hotspot/src/share/vm/ci/ciMethodData.cpp +++ b/hotspot/src/share/vm/ci/ciMethodData.cpp @@ -81,7 +81,7 @@ ciMethodData::ciMethodData() : ciMetadata(NULL) { void ciMethodData::load_extra_data() { MethodData* mdo = get_MethodData(); - MutexLocker(mdo->extra_data_lock()); + MutexLocker ml(mdo->extra_data_lock()); // speculative trap entries also hold a pointer to a Method so need to be translated DataLayout* dp_src = mdo->extra_data_base(); @@ -103,16 +103,13 @@ void ciMethodData::load_extra_data() { switch(tag) { case DataLayout::speculative_trap_data_tag: { - ciSpeculativeTrapData* data_dst = new ciSpeculativeTrapData(dp_dst); - SpeculativeTrapData* data_src = new SpeculativeTrapData(dp_src); - - data_dst->translate_from(data_src); - -#ifdef ASSERT - SpeculativeTrapData* data_src2 = new SpeculativeTrapData(dp_src); - assert(data_src2->method() == data_src->method() && data_src2->bci() == data_src->bci(), "entries changed while translating"); -#endif + ciSpeculativeTrapData data_dst(dp_dst); + SpeculativeTrapData data_src(dp_src); + { // During translation a safepoint can happen or VM lock can be taken (e.g., Compile_lock). + MutexUnlocker ml(mdo->extra_data_lock()); + data_dst.translate_from(&data_src); + } break; } case DataLayout::bit_data_tag: @@ -120,9 +117,11 @@ void ciMethodData::load_extra_data() { case DataLayout::no_tag: case DataLayout::arg_info_data_tag: // An empty slot or ArgInfoData entry marks the end of the trap data - return; + { + return; // Need a block to avoid SS compiler bug + } default: - fatal("bad tag = %d", dp_dst->tag()); + fatal("bad tag = %d", tag); } } } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index a75504d2025..97d6bdfcd56 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -5380,7 +5380,7 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, TRAPS) { } } - TRACE_INIT_ID(ik); + TRACE_INIT_KLASS_ID(ik); // If we reach here, all is well. // Now remove the InstanceKlass* from the _klass_to_deallocate field diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 14feb9876cf..0a1e20df3f0 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -37,6 +37,7 @@ #include "gc/shared/generation.hpp" #include "interpreter/bytecodeStream.hpp" #include "interpreter/oopMapCache.hpp" +#include "logging/logTag.hpp" #include "memory/allocation.inline.hpp" #include "memory/filemap.hpp" #include "memory/oopFactory.hpp" @@ -417,34 +418,30 @@ bool ClassPathImageEntry::is_jrt() { #if INCLUDE_CDS void ClassLoader::exit_with_path_failure(const char* error, const char* message) { assert(DumpSharedSpaces, "only called at dump time"); - tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure"); + tty->print_cr("Hint: enable -Xlog:classpath=info to diagnose the failure"); vm_exit_during_initialization(error, message); } #endif -void ClassLoader::trace_class_path(outputStream* out, const char* msg, const char* name) { - if (!TraceClassPaths) { - return; - } - - if (msg) { - out->print("%s", msg); - } - if (name) { - if (strlen(name) < 256) { - out->print("%s", name); - } else { - // For very long paths, we need to print each character separately, - // as print_cr() has a length limit - while (name[0] != '\0') { - out->print("%c", name[0]); - name++; +void ClassLoader::trace_class_path(const char* msg, const char* name) { + if (log_is_enabled(Info, classpath)) { + ResourceMark rm; + outputStream* out = LogHandle(classpath)::info_stream(); + if (msg) { + out->print("%s", msg); + } + if (name) { + if (strlen(name) < 256) { + out->print("%s", name); + } else { + // For very long paths, we need to print each character separately, + // as print_cr() has a length limit + while (name[0] != '\0') { + out->print("%c", name[0]); + name++; + } } } - } - if (msg && msg[0] == '[') { - out->print_cr("]"); - } else { out->cr(); } } @@ -470,11 +467,13 @@ void ClassLoader::check_shared_classpath(const char *path) { void ClassLoader::setup_bootstrap_search_path() { assert(_first_entry == NULL, "should not setup bootstrap class search path twice"); const char* sys_class_path = Arguments::get_sysclasspath(); + const char* java_class_path = Arguments::get_appclasspath(); if (PrintSharedArchiveAndExit) { // Don't print sys_class_path - this is the bootcp of this current VM process, not necessarily // the same as the bootcp of the shared archive. } else { - trace_class_path(tty, "[Bootstrap loader class path=", sys_class_path); + trace_class_path("bootstrap loader class path=", sys_class_path); + trace_class_path("classpath: ", java_class_path); } #if INCLUDE_CDS if (DumpSharedSpaces) { @@ -578,9 +577,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str } } } - if (TraceClassPaths) { - tty->print_cr("[Opened %s]", path); - } + log_info(classpath)("opened: %s", path); log_info(classload)("opened: %s", path); } else { // Directory diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 92ee90f2675..c2a68c04b09 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -331,7 +331,7 @@ class ClassLoader: AllStatic { static void exit_with_path_failure(const char* error, const char* message); #endif - static void trace_class_path(outputStream* out, const char* msg, const char* name = NULL); + static void trace_class_path(const char* msg, const char* name = NULL); // VM monitoring and management support static jlong classloader_time_ms(); diff --git a/hotspot/src/share/vm/classfile/dictionary.cpp b/hotspot/src/share/vm/classfile/dictionary.cpp index 6f70ef9b47e..61c3bad0f8e 100644 --- a/hotspot/src/share/vm/classfile/dictionary.cpp +++ b/hotspot/src/share/vm/classfile/dictionary.cpp @@ -135,8 +135,10 @@ void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_dom // via a store to _pd_set. OrderAccess::release_store_ptr(&_pd_set, new_head); } - if (TraceProtectionDomainVerification && WizardMode) { - print(); + if (log_is_enabled(Trace, protectiondomain)) { + ResourceMark rm; + outputStream* log = LogHandle(protectiondomain)::trace_stream(); + print_count(log); } } diff --git a/hotspot/src/share/vm/classfile/dictionary.hpp b/hotspot/src/share/vm/classfile/dictionary.hpp index a77f33717f3..a873fdd3e47 100644 --- a/hotspot/src/share/vm/classfile/dictionary.hpp +++ b/hotspot/src/share/vm/classfile/dictionary.hpp @@ -29,6 +29,7 @@ #include "oops/instanceKlass.hpp" #include "oops/oop.hpp" #include "utilities/hashtable.hpp" +#include "utilities/ostream.hpp" class DictionaryEntry; class PSPromotionManager; @@ -323,14 +324,14 @@ class DictionaryEntry : public HashtableEntry { return (klass->name() == class_name && _loader_data == loader_data); } - void print() { + void print_count(outputStream *st) { int count = 0; for (ProtectionDomainEntry* current = _pd_set; current != NULL; current = current->_next) { count++; } - tty->print_cr("pd set = #%d", count); + st->print_cr("pd set count = #%d", count); } }; diff --git a/hotspot/src/share/vm/classfile/klassFactory.cpp b/hotspot/src/share/vm/classfile/klassFactory.cpp index 14af5574021..033d9bfb660 100644 --- a/hotspot/src/share/vm/classfile/klassFactory.cpp +++ b/hotspot/src/share/vm/classfile/klassFactory.cpp @@ -1,5 +1,5 @@ /* -* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +* Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include "classfile/klassFactory.hpp" #include "memory/resourceArea.hpp" #include "prims/jvmtiEnvBase.hpp" +#include "trace/traceMacros.hpp" static ClassFileStream* prologue(ClassFileStream* stream, Symbol* name, @@ -136,5 +137,7 @@ instanceKlassHandle KlassFactory::create_from_stream(ClassFileStream* stream, result->set_cached_class_file(cached_class_file); } + TRACE_KLASS_CREATION(result, parser, THREAD); + return result; } diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp index 9233e3243ad..40843700bd6 100644 --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,15 +26,15 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/sharedPathsMiscInfo.hpp" +#include "logging/log.hpp" #include "memory/allocation.inline.hpp" #include "memory/metaspaceShared.hpp" #include "runtime/arguments.hpp" +#include "utilities/ostream.hpp" void SharedPathsMiscInfo::add_path(const char* path, int type) { - if (TraceClassPaths) { - tty->print("[type=%s] ", type_name(type)); - trace_class_path("[Add misc shared path ", path); - } + log_info(classpath)("type=%s ", type_name(type)); + ClassLoader::trace_class_path("add misc shared path ", path); write(path, strlen(path) + 1); write_jint(jint(type)); } @@ -67,11 +67,29 @@ bool SharedPathsMiscInfo::read(void* ptr, size_t size) { } bool SharedPathsMiscInfo::fail(const char* msg, const char* name) { - ClassLoader::trace_class_path(tty, msg, name); + ClassLoader::trace_class_path(msg, name); MetaspaceShared::set_archive_loading_failed(); return false; } +void SharedPathsMiscInfo::print_path(int type, const char* path) { + ResourceMark rm; + outputStream* out = LogHandle(classpath)::info_stream(); + switch (type) { + case BOOT: + out->print("Expecting -Dsun.boot.class.path=%s", path); + break; + case NON_EXIST: + out->print("Expecting that %s does not exist", path); + break; + case REQUIRED: + out->print("Expecting that file %s must exist and is not altered", path); + break; + default: + ShouldNotReachHere(); + } +} + bool SharedPathsMiscInfo::check() { // The whole buffer must be 0 terminated so that we can use strlen and strcmp // without fear. @@ -90,17 +108,14 @@ bool SharedPathsMiscInfo::check() { if (!read_jint(&type)) { return fail("Corrupted archive file header"); } - if (TraceClassPaths) { - tty->print("[type=%s ", type_name(type)); - print_path(tty, type, path); - tty->print_cr("]"); - } + log_info(classpath)("type=%s ", type_name(type)); + print_path(type, path); if (!check(type, path)) { if (!PrintSharedArchiveAndExit) { return false; } } else { - trace_class_path("[ok"); + ClassLoader::trace_class_path("ok"); } } diff --git a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp index 652d20c883a..435630febac 100644 --- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp +++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp @@ -64,9 +64,6 @@ protected: void write(const void* ptr, size_t size); bool read(void* ptr, size_t size); - static void trace_class_path(const char* msg, const char* name = NULL) { - ClassLoader::trace_class_path(tty, msg, name); - } protected: static bool fail(const char* msg, const char* name = NULL); virtual bool check(jint type, const char* path); @@ -144,21 +141,7 @@ public: } } - virtual void print_path(outputStream* out, int type, const char* path) { - switch (type) { - case BOOT: - out->print("Expecting -Dsun.boot.class.path=%s", path); - break; - case NON_EXIST: - out->print("Expecting that %s does not exist", path); - break; - case REQUIRED: - out->print("Expecting that file %s must exist and is not altered", path); - break; - default: - ShouldNotReachHere(); - } - } + virtual void print_path(int type, const char* path); bool check(); bool read_jint(jint *ptr) { diff --git a/hotspot/src/share/vm/classfile/stringTable.cpp b/hotspot/src/share/vm/classfile/stringTable.cpp index ee303426f3c..167ec28449c 100644 --- a/hotspot/src/share/vm/classfile/stringTable.cpp +++ b/hotspot/src/share/vm/classfile/stringTable.cpp @@ -200,7 +200,6 @@ oop StringTable::lookup(jchar* name, int len) { return string; } - oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { oop found_string = lookup_shared(name, len); @@ -214,7 +213,9 @@ oop StringTable::intern(Handle string_or_null, jchar* name, // Found if (found_string != NULL) { - ensure_string_alive(found_string); + if (found_string != string_or_null()) { + ensure_string_alive(found_string); + } return found_string; } @@ -249,7 +250,9 @@ oop StringTable::intern(Handle string_or_null, jchar* name, hashValue, CHECK_NULL); } - ensure_string_alive(added_or_found); + if (added_or_found != string()) { + ensure_string_alive(added_or_found); + } return added_or_found; } diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 2a61613e910..549182e82cf 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -430,12 +430,15 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, // Now we have to call back to java to check if the initating class has access JavaValue result(T_VOID); - if (TraceProtectionDomainVerification) { + if (log_is_enabled(Debug, protectiondomain)) { + ResourceMark rm; // Print out trace information - tty->print_cr("Checking package access"); - tty->print(" - class loader: "); class_loader()->print_value_on(tty); tty->cr(); - tty->print(" - protection domain: "); protection_domain()->print_value_on(tty); tty->cr(); - tty->print(" - loading: "); klass()->print_value_on(tty); tty->cr(); + outputStream* log = LogHandle(protectiondomain)::debug_stream(); + log->print_cr("Checking package access"); + log->print("class loader: "); class_loader()->print_value_on(log); + log->print(" protection domain: "); protection_domain()->print_value_on(log); + log->print(" loading: "); klass()->print_value_on(log); + log->cr(); } KlassHandle system_loader(THREAD, SystemDictionary::ClassLoader_klass()); @@ -448,13 +451,10 @@ void SystemDictionary::validate_protection_domain(instanceKlassHandle klass, protection_domain, THREAD); - if (TraceProtectionDomainVerification) { - if (HAS_PENDING_EXCEPTION) { - tty->print_cr(" -> DENIED !!!!!!!!!!!!!!!!!!!!!"); - } else { - tty->print_cr(" -> granted"); - } - tty->cr(); + if (HAS_PENDING_EXCEPTION) { + log_debug(protectiondomain)("DENIED !!!!!!!!!!!!!!!!!!!!!"); + } else { + log_debug(protectiondomain)("granted"); } if (HAS_PENDING_EXCEPTION) return; diff --git a/hotspot/src/share/vm/classfile/vmSymbols.cpp b/hotspot/src/share/vm/classfile/vmSymbols.cpp index 1a5fe2a05fd..73324bc9ec6 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.cpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.cpp @@ -328,8 +328,6 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { assert(id != vmIntrinsics::_none, "must be a VM intrinsic"); switch(id) { #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_currentTimeMillis: diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 4cce6873268..3610618800c 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -123,7 +123,7 @@ template(sun_misc_Launcher_ExtClassLoader, "sun/misc/Launcher$ExtClassLoader") \ \ /* Java runtime version access */ \ - template(sun_misc_Version, "sun/misc/Version") \ + template(java_lang_VersionProps, "java/lang/VersionProps") \ template(java_runtime_name_name, "java_runtime_name") \ template(java_runtime_version_name, "java_runtime_version") \ \ @@ -1035,14 +1035,15 @@ do_name( updateByteBuffer_A_name, "updateByteBuffer") \ \ /* support for Unsafe */ \ - do_class(sun_misc_Unsafe, "sun/misc/Unsafe") \ do_class(jdk_internal_misc_Unsafe, "jdk/internal/misc/Unsafe") \ \ do_intrinsic(_allocateInstance, jdk_internal_misc_Unsafe, allocateInstance_name, allocateInstance_signature, F_RN) \ do_name( allocateInstance_name, "allocateInstance") \ do_signature(allocateInstance_signature, "(Ljava/lang/Class;)Ljava/lang/Object;") \ + do_intrinsic(_allocateUninitializedArray, jdk_internal_misc_Unsafe, allocateUninitializedArray_name, newArray_signature, F_R) \ + do_name( allocateUninitializedArray_name, "allocateUninitializedArray0") \ do_intrinsic(_copyMemory, jdk_internal_misc_Unsafe, copyMemory_name, copyMemory_signature, F_RN) \ - do_name( copyMemory_name, "copyMemory") \ + do_name( copyMemory_name, "copyMemory0") \ do_signature(copyMemory_signature, "(Ljava/lang/Object;JLjava/lang/Object;JJ)V") \ do_intrinsic(_loadFence, jdk_internal_misc_Unsafe, loadFence_name, loadFence_signature, F_RN) \ do_name( loadFence_name, "loadFence") \ diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index 36c35a92f55..b026e5a645b 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -369,7 +369,6 @@ void DebugInformationRecorder::describe_scope(int pc_offset, assert(method == NULL || (method->is_native() && bci == 0) || (!method->is_native() && 0 <= bci && bci < method->code_size()) || - (method->is_compiled_lambda_form() && bci == -99) || // this might happen in C1 bci == -1, "illegal bci"); // serialize the locals/expressions/monitors diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 8689088455c..672fed6f7f4 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -838,12 +838,8 @@ void CompileBroker::compile_method_base(const methodHandle& method, const methodHandle& hot_method, int hot_count, const char* comment, + bool blocking, Thread* thread) { - // do nothing if compiler thread(s) is not available - if (!_initialized) { - return; - } - guarantee(!method->is_abstract(), "cannot compile abstract methods"); assert(method->method_holder()->is_instance_klass(), "sanity check"); @@ -916,7 +912,6 @@ void CompileBroker::compile_method_base(const methodHandle& method, // Outputs from the following MutexLocker block: CompileTask* task = NULL; - bool blocking = false; CompileQueue* queue = compile_queue(comp_level); // Acquire our lock. @@ -946,9 +941,6 @@ void CompileBroker::compile_method_base(const methodHandle& method, return; } - // Should this thread wait for completion of the compile? - blocking = is_compile_blocking(); - #if INCLUDE_JVMCI if (UseJVMCICompiler) { if (blocking) { @@ -1034,11 +1026,28 @@ void CompileBroker::compile_method_base(const methodHandle& method, } } - nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, int comp_level, const methodHandle& hot_method, int hot_count, const char* comment, Thread* THREAD) { + // do nothing if compilebroker is not available + if (!_initialized) { + return NULL; + } + AbstractCompiler *comp = CompileBroker::compiler(comp_level); + assert(comp != NULL, "Ensure we don't compile before compilebroker init"); + DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); + nmethod* nm = CompileBroker::compile_method(method, osr_bci, comp_level, hot_method, hot_count, comment, directive, THREAD); + DirectivesStack::release(directive); + return nm; +} + +nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, + int comp_level, + const methodHandle& hot_method, int hot_count, + const char* comment, DirectiveSet* directive, + Thread* THREAD) { + // make sure arguments make sense assert(method->method_holder()->is_instance_klass(), "not an instance method"); assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range"); @@ -1051,8 +1060,8 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, // lock, make sure that the compilation // isn't prohibited in a straightforward way. AbstractCompiler *comp = CompileBroker::compiler(comp_level); - if (comp == NULL || !comp->can_compile_method(method) || - compilation_is_prohibited(method, osr_bci, comp_level)) { + if (!comp->can_compile_method(method) || + compilation_is_prohibited(method, osr_bci, comp_level, directive->ExcludeOption)) { return NULL; } @@ -1160,7 +1169,7 @@ nmethod* CompileBroker::compile_method(const methodHandle& method, int osr_bci, CompilationPolicy::policy()->delay_compilation(method()); return NULL; } - compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, THREAD); + compile_method_base(method, osr_bci, comp_level, hot_method, hot_count, comment, !directive->BackgroundCompilationOption, THREAD); } // return requested nmethod @@ -1217,7 +1226,7 @@ bool CompileBroker::compilation_is_in_queue(const methodHandle& method) { // CompileBroker::compilation_is_prohibited // // See if this compilation is not allowed. -bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level) { +bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded) { bool is_native = method->is_native(); // Some compilers may not support the compilation of natives. AbstractCompiler *comp = compiler(comp_level); @@ -1235,11 +1244,6 @@ bool CompileBroker::compilation_is_prohibited(const methodHandle& method, int os return true; } - // Breaking the abstraction - directives are only used inside a compilation otherwise. - DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp); - bool excluded = directive->ExcludeOption; - DirectivesStack::release(directive); - // The method may be explicitly excluded by the user. double scale; if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) { @@ -1304,16 +1308,6 @@ uint CompileBroker::assign_compile_id_unlocked(Thread* thread, const methodHandl return assign_compile_id(method, osr_bci); } -/** - * Should the current thread block until this compilation request - * has been fulfilled? - */ -bool CompileBroker::is_compile_blocking() { - assert(!InstanceRefKlass::owns_pending_list_lock(JavaThread::current()), "possible deadlock"); - return !BackgroundCompilation; -} - - // ------------------------------------------------------------------ // CompileBroker::preload_classes void CompileBroker::preload_classes(const methodHandle& method, TRAPS) { diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index ba4db7d0cdd..01a85b59dd0 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -222,8 +222,7 @@ class CompileBroker: AllStatic { static JavaThread* make_thread(const char* name, CompileQueue* queue, CompilerCounters* counters, AbstractCompiler* comp, bool compiler_thread, TRAPS); static void init_compiler_sweeper_threads(int c1_compiler_count, int c2_compiler_count); static bool compilation_is_complete (const methodHandle& method, int osr_bci, int comp_level); - static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level); - static bool is_compile_blocking(); + static bool compilation_is_prohibited(const methodHandle& method, int osr_bci, int comp_level, bool excluded); static void preload_classes (const methodHandle& method, TRAPS); static CompileTask* create_compile_task(CompileQueue* queue, @@ -253,6 +252,7 @@ class CompileBroker: AllStatic { const methodHandle& hot_method, int hot_count, const char* comment, + bool blocking, Thread* thread); static CompileQueue* compile_queue(int comp_level); @@ -291,6 +291,15 @@ public: int hot_count, const char* comment, Thread* thread); + static nmethod* compile_method(const methodHandle& method, + int osr_bci, + int comp_level, + const methodHandle& hot_method, + int hot_count, + const char* comment, + DirectiveSet* directive, + Thread* thread); + // Acquire any needed locks and assign a compile id static uint assign_compile_id_unlocked(Thread* thread, const methodHandle& method, int osr_bci); diff --git a/hotspot/src/share/vm/compiler/compilerDirectives.cpp b/hotspot/src/share/vm/compiler/compilerDirectives.cpp index 28b09f6cb61..22ba721e7f2 100644 --- a/hotspot/src/share/vm/compiler/compilerDirectives.cpp +++ b/hotspot/src/share/vm/compiler/compilerDirectives.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -472,9 +472,12 @@ void DirectivesStack::push(CompilerDirectives* directive) { _depth++; } -void DirectivesStack::pop() { +void DirectivesStack::pop(int count) { MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag); - pop_inner(); + assert(count > -1, "No negative values"); + for (int i = 0; i < count; i++) { + pop_inner(); + } } void DirectivesStack::pop_inner() { diff --git a/hotspot/src/share/vm/compiler/compilerDirectives.hpp b/hotspot/src/share/vm/compiler/compilerDirectives.hpp index a754c8bad83..0432d87068f 100644 --- a/hotspot/src/share/vm/compiler/compilerDirectives.hpp +++ b/hotspot/src/share/vm/compiler/compilerDirectives.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \ cflags(PrintInlining, bool, PrintInlining, PrintInlining) \ cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \ + cflags(BackgroundCompilation, bool, BackgroundCompilation, BackgroundCompilation) \ cflags(ReplayInline, bool, false, ReplayInline) \ cflags(DumpReplay, bool, false, DumpReplay) \ cflags(DumpInline, bool, false, DumpInline) \ @@ -87,7 +88,7 @@ public: static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp); static DirectiveSet* getDefaultDirective(AbstractCompiler* comp); static void push(CompilerDirectives* directive); - static void pop(); + static void pop(int count); static bool check_capacity(int request_size, outputStream* st); static void clear(); static void print(outputStream* st); diff --git a/hotspot/src/share/vm/compiler/directivesParser.cpp b/hotspot/src/share/vm/compiler/directivesParser.cpp index 4847e228160..9c6d6a0201f 100644 --- a/hotspot/src/share/vm/compiler/directivesParser.cpp +++ b/hotspot/src/share/vm/compiler/directivesParser.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,7 @@ void DirectivesParser::clean_tmp() { assert(_tmp_depth == 0, "Consistency"); } -bool DirectivesParser::parse_string(const char* text, outputStream* st) { +int DirectivesParser::parse_string(const char* text, outputStream* st) { DirectivesParser cd(text, st); if (cd.valid()) { return cd.install_directives(); @@ -63,7 +63,7 @@ bool DirectivesParser::parse_string(const char* text, outputStream* st) { cd.clean_tmp(); st->flush(); st->print_cr("Parsing of compiler directives failed"); - return false; + return -1; } } @@ -97,17 +97,17 @@ bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* buffer[num_read] = '\0'; // close file os::close(file_handle); - return parse_string(buffer, stream); + return parse_string(buffer, stream) > 0; } } return false; } -bool DirectivesParser::install_directives() { +int DirectivesParser::install_directives() { // Check limit if (!DirectivesStack::check_capacity(_tmp_depth, _st)) { clean_tmp(); - return false; + return 0; } // Pop from internal temporary stack and push to compileBroker. @@ -120,14 +120,14 @@ bool DirectivesParser::install_directives() { } if (i == 0) { _st->print_cr("No directives in file"); - return false; + return 0; } else { _st->print_cr("%i compiler directives added", i); if (CompilerDirectivesPrint) { // Print entire directives stack after new has been pushed. DirectivesStack::print(_st); } - return true; + return i; } } diff --git a/hotspot/src/share/vm/compiler/directivesParser.hpp b/hotspot/src/share/vm/compiler/directivesParser.hpp index f62630f7d56..e7c404b5b3d 100644 --- a/hotspot/src/share/vm/compiler/directivesParser.hpp +++ b/hotspot/src/share/vm/compiler/directivesParser.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,8 +51,8 @@ public: static bool has_file(); static bool parse_from_flag(); static bool parse_from_file(const char* filename, outputStream* st); - static bool parse_string(const char* string, outputStream* st); - bool install_directives(); + static int parse_string(const char* string, outputStream* st); + int install_directives(); private: DirectivesParser(const char* text, outputStream* st); diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp index 0f2f019e9d8..366bf4671b3 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.cpp @@ -39,6 +39,7 @@ #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/generation.hpp" #include "gc/shared/plab.inline.hpp" +#include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/space.hpp" #include "gc/shared/spaceDecorator.hpp" @@ -64,6 +65,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_, int thread_num_, ObjToScanQueueSet* work_queue_set_, Stack* overflow_stacks_, + PreservedMarks* preserved_marks_, size_t desired_plab_sz_, ParallelTaskTerminator& term_) : _to_space(to_space_), @@ -73,6 +75,7 @@ ParScanThreadState::ParScanThreadState(Space* to_space_, _work_queue(work_queue_set_->queue(thread_num_)), _to_space_full(false), _overflow_stack(overflow_stacks_ ? overflow_stacks_ + thread_num_ : NULL), + _preserved_marks(preserved_marks_), _ageTable(false), // false ==> not the global age table, no perf data. _to_space_alloc_buffer(desired_plab_sz_), _to_space_closure(young_gen_, this), @@ -286,6 +289,7 @@ public: Generation& old_gen, ObjToScanQueueSet& queue_set, Stack* overflow_stacks_, + PreservedMarksSet& preserved_marks_set, size_t desired_plab_sz, ParallelTaskTerminator& term); @@ -322,6 +326,7 @@ ParScanThreadStateSet::ParScanThreadStateSet(int num_threads, Generation& old_gen, ObjToScanQueueSet& queue_set, Stack* overflow_stacks, + PreservedMarksSet& preserved_marks_set, size_t desired_plab_sz, ParallelTaskTerminator& term) : ResourceArray(sizeof(ParScanThreadState), num_threads), @@ -336,7 +341,8 @@ ParScanThreadStateSet::ParScanThreadStateSet(int num_threads, for (int i = 0; i < num_threads; ++i) { new ((ParScanThreadState*)_data + i) ParScanThreadState(&to_space, &young_gen, &old_gen, i, &queue_set, - overflow_stacks, desired_plab_sz, term); + overflow_stacks, preserved_marks_set.get(i), + desired_plab_sz, term); } } @@ -609,7 +615,7 @@ ParNewGeneration::ParNewGeneration(ReservedSpace rs, size_t initial_byte_size) : DefNewGeneration(rs, initial_byte_size, "PCopy"), _overflow_list(NULL), _is_alive_closure(this), - _plab_stats(YoungPLABSize, PLABWeight) + _plab_stats("Young", YoungPLABSize, PLABWeight) { NOT_PRODUCT(_overflow_counter = ParGCWorkQueueOverflowInterval;) NOT_PRODUCT(_num_par_pushes = 0;) @@ -905,12 +911,16 @@ void ParNewGeneration::collect(bool full, // Set the correct parallelism (number of queues) in the reference processor ref_processor()->set_active_mt_degree(active_workers); + // Need to initialize the preserved marks before the ThreadStateSet c'tor. + _preserved_marks_set.init(active_workers); + // Always set the terminator for the active number of workers // because only those workers go through the termination protocol. ParallelTaskTerminator _term(active_workers, task_queues()); ParScanThreadStateSet thread_state_set(active_workers, *to(), *this, *_old_gen, *task_queues(), - _overflow_stacks, desired_plab_sz(), _term); + _overflow_stacks, _preserved_marks_set, + desired_plab_sz(), _term); thread_state_set.reset(active_workers, promotion_failed()); @@ -993,13 +1003,12 @@ void ParNewGeneration::collect(bool full, } else { handle_promotion_failed(gch, thread_state_set); } + _preserved_marks_set.reclaim(); // set new iteration safe limit for the survivor spaces from()->set_concurrent_iteration_safe_limit(from()->top()); to()->set_concurrent_iteration_safe_limit(to()->top()); - if (ResizePLAB) { - plab_stats()->adjust_desired_plab_sz(); - } + plab_stats()->adjust_desired_plab_sz(); TASKQUEUE_STATS_ONLY(thread_state_set.print_termination_stats()); TASKQUEUE_STATS_ONLY(thread_state_set.print_taskqueue_stats()); @@ -1070,15 +1079,6 @@ oop ParNewGeneration::real_forwardee_slow(oop obj) { return forward_ptr; } -void ParNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { - if (m->must_be_preserved_for_promotion_failure(obj)) { - // We should really have separate per-worker stacks, rather - // than use locking of a common pair of stacks. - MutexLocker ml(ParGCRareEvent_lock); - preserve_mark(obj, m); - } -} - // Multiple GC threads may try to promote an object. If the object // is successfully promoted, a forwarding pointer will be installed in // the object in the young generation. This method claims the right @@ -1136,7 +1136,7 @@ oop ParNewGeneration::copy_to_survivor_space(ParScanThreadState* par_scan_state, _promotion_failed = true; new_obj = old; - preserve_mark_if_necessary(old, m); + par_scan_state->preserved_marks()->push_if_necessary(old, m); par_scan_state->register_promotion_failure(sz); } diff --git a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp index 765ea72962e..94ec916357c 100644 --- a/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp +++ b/hotspot/src/share/vm/gc/cms/parNewGeneration.hpp @@ -30,6 +30,7 @@ #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/gcTrace.hpp" #include "gc/shared/plab.hpp" +#include "gc/shared/preservedMarks.hpp" #include "gc/shared/taskqueue.hpp" #include "memory/padded.hpp" @@ -65,6 +66,7 @@ class ParScanThreadState { private: ObjToScanQueue *_work_queue; Stack* const _overflow_stack; + PreservedMarks* const _preserved_marks; PLAB _to_space_alloc_buffer; @@ -128,6 +130,7 @@ class ParScanThreadState { Generation* old_gen_, int thread_num_, ObjToScanQueueSet* work_queue_set_, Stack* overflow_stacks_, + PreservedMarks* preserved_marks_, size_t desired_plab_sz_, ParallelTaskTerminator& term_); @@ -136,6 +139,8 @@ class ParScanThreadState { ObjToScanQueue* work_queue() { return _work_queue; } + PreservedMarks* preserved_marks() const { return _preserved_marks; } + PLAB* to_space_alloc_buffer() { return &_to_space_alloc_buffer; } @@ -331,10 +336,6 @@ class ParNewGeneration: public DefNewGeneration { static oop real_forwardee_slow(oop obj); static void waste_some_time(); - // Preserve the mark of "obj", if necessary, in preparation for its mark - // word being overwritten with a self-forwarding-pointer. - void preserve_mark_if_necessary(oop obj, markOop m); - void handle_promotion_failed(GenCollectedHeap* gch, ParScanThreadStateSet& thread_state_set); protected: diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp index 0e2f4dd4bb3..5edec2775ed 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,19 +36,19 @@ ConcurrentG1Refine::ConcurrentG1Refine(G1CollectedHeap* g1h) : { // Ergonomically select initial concurrent refinement parameters if (FLAG_IS_DEFAULT(G1ConcRefinementGreenZone)) { - FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, (intx)ParallelGCThreads); + FLAG_SET_DEFAULT(G1ConcRefinementGreenZone, ParallelGCThreads); } set_green_zone(G1ConcRefinementGreenZone); if (FLAG_IS_DEFAULT(G1ConcRefinementYellowZone)) { FLAG_SET_DEFAULT(G1ConcRefinementYellowZone, green_zone() * 3); } - set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); + set_yellow_zone(MAX2(G1ConcRefinementYellowZone, green_zone())); if (FLAG_IS_DEFAULT(G1ConcRefinementRedZone)) { FLAG_SET_DEFAULT(G1ConcRefinementRedZone, yellow_zone() * 2); } - set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); + set_red_zone(MAX2(G1ConcRefinementRedZone, yellow_zone())); } ConcurrentG1Refine* ConcurrentG1Refine::create(G1CollectedHeap* g1h, CardTableEntryClosure* refine_closure, jint* ecode) { diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp index 0e5525f73c2..2333fea311f 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1Refine.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,11 +61,11 @@ class ConcurrentG1Refine: public CHeapObj { * 2) green = 0. Means no caching. Can be a good way to minimize the * amount of time spent updating rsets during a collection. */ - int _green_zone; - int _yellow_zone; - int _red_zone; + size_t _green_zone; + size_t _yellow_zone; + size_t _red_zone; - int _thread_threshold_step; + size_t _thread_threshold_step; // We delay the refinement of 'hot' cards using the hot card cache. G1HotCardCache _hot_card_cache; @@ -100,17 +100,17 @@ class ConcurrentG1Refine: public CHeapObj { void print_worker_threads_on(outputStream* st) const; - void set_green_zone(int x) { _green_zone = x; } - void set_yellow_zone(int x) { _yellow_zone = x; } - void set_red_zone(int x) { _red_zone = x; } + void set_green_zone(size_t x) { _green_zone = x; } + void set_yellow_zone(size_t x) { _yellow_zone = x; } + void set_red_zone(size_t x) { _red_zone = x; } - int green_zone() const { return _green_zone; } - int yellow_zone() const { return _yellow_zone; } - int red_zone() const { return _red_zone; } + size_t green_zone() const { return _green_zone; } + size_t yellow_zone() const { return _yellow_zone; } + size_t red_zone() const { return _red_zone; } uint worker_thread_num() const { return _n_worker_threads; } - int thread_threshold_step() const { return _thread_threshold_step; } + size_t thread_threshold_step() const { return _thread_threshold_step; } G1HotCardCache* hot_card_cache() { return &_hot_card_cache; } diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp index dc1b5ea1352..778b37f058e 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.cpp @@ -67,10 +67,12 @@ ConcurrentG1RefineThread(ConcurrentG1Refine* cg1r, ConcurrentG1RefineThread *nex void ConcurrentG1RefineThread::initialize() { // Current thread activation threshold - _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), - cg1r()->yellow_zone()); + _threshold = MIN2(cg1r()->thread_threshold_step() * (_worker_id + 1) + cg1r()->green_zone(), + cg1r()->yellow_zone()); // A thread deactivates once the number of buffer reached a deactivation threshold - _deactivation_threshold = MAX2(_threshold - cg1r()->thread_threshold_step(), cg1r()->green_zone()); + _deactivation_threshold = + MAX2(_threshold - MIN2(_threshold, cg1r()->thread_threshold_step()), + cg1r()->green_zone()); } void ConcurrentG1RefineThread::wait_for_completed_buffers() { @@ -89,8 +91,6 @@ bool ConcurrentG1RefineThread::is_active() { void ConcurrentG1RefineThread::activate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); if (!is_primary()) { - log_debug(gc, refine)("G1-Refine-activated worker %d, on threshold %d, current %d", - _worker_id, _threshold, JavaThread::dirty_card_queue_set().completed_buffers_num()); set_active(true); } else { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); @@ -102,8 +102,6 @@ void ConcurrentG1RefineThread::activate() { void ConcurrentG1RefineThread::deactivate() { MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); if (!is_primary()) { - log_debug(gc, refine)("G1-Refine-deactivated worker %d, off threshold %d, current %d", - _worker_id, _deactivation_threshold, JavaThread::dirty_card_queue_set().completed_buffers_num()); set_active(false); } else { DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); @@ -130,36 +128,34 @@ void ConcurrentG1RefineThread::run_service() { break; } + DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); + log_debug(gc, refine)("Activated %d, on threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, + _worker_id, _threshold, dcqs.completed_buffers_num()); + { SuspendibleThreadSetJoiner sts_join; - DirtyCardQueueSet& dcqs = JavaThread::dirty_card_queue_set(); do { - int curr_buffer_num = (int)dcqs.completed_buffers_num(); + size_t curr_buffer_num = dcqs.completed_buffers_num(); // If the number of the buffers falls down into the yellow zone, // that means that the transition period after the evacuation pause has ended. if (dcqs.completed_queue_padding() > 0 && curr_buffer_num <= cg1r()->yellow_zone()) { dcqs.set_completed_queue_padding(0); } - if (!is_primary() && curr_buffer_num <= _deactivation_threshold) { - // If the number of the buffer has fallen below our threshold - // we should deactivate. The predecessor will reactivate this - // thread should the number of the buffers cross the threshold again. - deactivate(); - break; - } - // Check if we need to activate the next thread. if (_next != NULL && !_next->is_active() && curr_buffer_num > _next->_threshold) { _next->activate(); } - } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, _worker_id + _worker_id_offset, cg1r()->green_zone())); + } while (dcqs.apply_closure_to_completed_buffer(_refine_closure, + _worker_id + _worker_id_offset, + _deactivation_threshold, + false /* during_pause */)); - // We can exit the loop above while being active if there was a yield request. - if (is_active()) { - deactivate(); - } + deactivate(); + log_debug(gc, refine)("Deactivated %d, off threshold: " SIZE_FORMAT ", current: " SIZE_FORMAT, + _worker_id, _deactivation_threshold, + dcqs.completed_buffers_num()); } if (os::supports_vtime()) { @@ -169,7 +165,7 @@ void ConcurrentG1RefineThread::run_service() { } } - log_debug(gc, refine)("G1-Refine-stop"); + log_debug(gc, refine)("Stopping %d", _worker_id); } void ConcurrentG1RefineThread::stop() { diff --git a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp index 5b6d3ed79d5..40071766d6f 100644 --- a/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp +++ b/hotspot/src/share/vm/gc/g1/concurrentG1RefineThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,11 +53,11 @@ class ConcurrentG1RefineThread: public ConcurrentGCThread { // The closure applied to completed log buffers. CardTableEntryClosure* _refine_closure; - int _thread_threshold_step; + size_t _thread_threshold_step; // This thread activation threshold - int _threshold; + size_t _threshold; // This thread deactivation threshold - int _deactivation_threshold; + size_t _deactivation_threshold; void wait_for_completed_buffers(); diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp index 155faa0be5a..d79ac8066b9 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -207,58 +207,53 @@ bool DirtyCardQueueSet::mut_process_buffer(void** buf) { } -BufferNode* DirtyCardQueueSet::get_completed_buffer(int stop_at) { +BufferNode* DirtyCardQueueSet::get_completed_buffer(size_t stop_at) { BufferNode* nd = NULL; MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - if ((int)_n_completed_buffers <= stop_at) { + if (_n_completed_buffers <= stop_at) { _process_completed = false; return NULL; } if (_completed_buffers_head != NULL) { nd = _completed_buffers_head; + assert(_n_completed_buffers > 0, "Invariant"); _completed_buffers_head = nd->next(); - if (_completed_buffers_head == NULL) - _completed_buffers_tail = NULL; _n_completed_buffers--; - assert(_n_completed_buffers >= 0, "Invariant"); + if (_completed_buffers_head == NULL) { + assert(_n_completed_buffers == 0, "Invariant"); + _completed_buffers_tail = NULL; + } } DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); return nd; } -bool DirtyCardQueueSet::apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - uint worker_i, - BufferNode* nd) { - if (nd != NULL) { - void **buf = BufferNode::make_buffer_from_node(nd); - size_t index = nd->index(); - bool b = - DirtyCardQueue::apply_closure_to_buffer(cl, buf, - index, _sz, - true, worker_i); - if (b) { - deallocate_buffer(buf); - return true; // In normal case, go on to next buffer. - } else { - enqueue_complete_buffer(buf, index); - return false; - } - } else { - return false; - } -} - bool DirtyCardQueueSet::apply_closure_to_completed_buffer(CardTableEntryClosure* cl, uint worker_i, - int stop_at, + size_t stop_at, bool during_pause) { assert(!during_pause || stop_at == 0, "Should not leave any completed buffers during a pause"); BufferNode* nd = get_completed_buffer(stop_at); - bool res = apply_closure_to_completed_buffer_helper(cl, worker_i, nd); - if (res) Atomic::inc(&_processed_buffers_rs_thread); - return res; + if (nd == NULL) { + return false; + } else { + void** buf = BufferNode::make_buffer_from_node(nd); + size_t index = nd->index(); + if (DirtyCardQueue::apply_closure_to_buffer(cl, + buf, index, _sz, + true, worker_i)) { + // Done with fully processed buffer. + deallocate_buffer(buf); + Atomic::inc(&_processed_buffers_rs_thread); + return true; + } else { + // Return partially processed buffer to the queue. + enqueue_complete_buffer(buf, index); + return false; + } + } } void DirtyCardQueueSet::apply_closure_to_all_completed_buffers(CardTableEntryClosure* cl) { diff --git a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp index 9fa3c3da069..96865a5784b 100644 --- a/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/dirtyCardQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,16 +133,11 @@ public: // partially completed buffer (with its processed elements set to NULL) // is returned to the completed buffer set, and this call returns false. bool apply_closure_to_completed_buffer(CardTableEntryClosure* cl, - uint worker_i = 0, - int stop_at = 0, - bool during_pause = false); + uint worker_i, + size_t stop_at, + bool during_pause); - // Helper routine for the above. - bool apply_closure_to_completed_buffer_helper(CardTableEntryClosure* cl, - uint worker_i, - BufferNode* nd); - - BufferNode* get_completed_buffer(int stop_at); + BufferNode* get_completed_buffer(size_t stop_at); // Applies the current closure to all completed buffers, // non-consumptively. diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp index f62e2d5973c..743bdd598f7 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp @@ -1400,7 +1400,6 @@ bool G1CollectedHeap::do_full_collection(bool explicit_gc, JavaThread::dirty_card_queue_set().abandon_logs(); assert(dirty_card_queue_set().completed_buffers_num() == 0, "DCQS should be empty"); - _young_list->reset_sampled_info(); // At this point there should be no regions in the // entire heap tagged as young. assert(check_young_list_empty(true /* check_heap */), @@ -1761,8 +1760,8 @@ G1CollectedHeap::G1CollectedHeap(G1CollectorPolicy* policy_) : _young_list(new YoungList(this)), _gc_time_stamp(0), _summary_bytes_used(0), - _survivor_evac_stats(YoungPLABSize, PLABWeight), - _old_evac_stats(OldPLABSize, PLABWeight), + _survivor_evac_stats("Young", YoungPLABSize, PLABWeight), + _old_evac_stats("Old", OldPLABSize, PLABWeight), _expand_heap_after_alloc_failure(true), _old_marking_cycles_started(0), _old_marking_cycles_completed(0), @@ -1985,8 +1984,8 @@ jint G1CollectedHeap::initialize() { JavaThread::dirty_card_queue_set().initialize(_refine_cte_cl, DirtyCardQ_CBL_mon, DirtyCardQ_FL_lock, - concurrent_g1_refine()->yellow_zone(), - concurrent_g1_refine()->red_zone(), + (int)concurrent_g1_refine()->yellow_zone(), + (int)concurrent_g1_refine()->red_zone(), Shared_DirtyCardQ_lock, NULL, // fl_owner true); // init_free_ids @@ -2777,12 +2776,6 @@ void G1CollectedHeap::gc_threads_do(ThreadClosure* tc) const { } void G1CollectedHeap::print_tracing_info() const { - // We'll overload this to mean "trace GC pause statistics." - if (TraceYoungGenTime || TraceOldGenTime) { - // The "G1CollectorPolicy" is keeping track of these stats, so delegate - // to that. - g1_policy()->print_tracing_info(); - } g1_rem_set()->print_summary_info(); concurrent_mark()->print_summary_info(); g1_policy()->print_yg_surv_rate_info(); @@ -2908,7 +2901,6 @@ HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size, bool* succeeded, GCCause::Cause gc_cause) { assert_heap_not_locked_and_not_at_safepoint(); - g1_policy()->record_stop_world_start(); VM_G1IncCollectionPause op(gc_count_before, word_size, false, /* should_initiate_conc_mark */ @@ -3242,10 +3234,6 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { GCTraceCPUTime tcpu; - uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), - workers()->active_workers(), - Threads::number_of_non_daemon_threads()); - workers()->set_active_workers(active_workers); FormatBuffer<> gc_string("Pause "); if (collector_state()->during_initial_mark_pause()) { gc_string.append("Initial Mark"); @@ -3256,6 +3244,11 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { } GCTraceTime(Info, gc) tm(gc_string, NULL, gc_cause(), true); + uint active_workers = AdaptiveSizePolicy::calc_active_workers(workers()->total_workers(), + workers()->active_workers(), + Threads::number_of_non_daemon_threads()); + workers()->set_active_workers(active_workers); + g1_policy()->note_gc_start(active_workers); TraceCollectorStats tcs(g1mm()->incremental_collection_counters()); @@ -3391,13 +3384,15 @@ G1CollectedHeap::do_collection_pause_at_safepoint(double target_pause_time_ms) { g1_policy()->clear_collection_set(); + record_obj_copy_mem_stats(); + _survivor_evac_stats.adjust_desired_plab_sz(); + _old_evac_stats.adjust_desired_plab_sz(); + // Start a new incremental collection set for the next pause. g1_policy()->start_incremental_cset_building(); clear_cset_fast_test(); - _young_list->reset_sampled_info(); - // Don't check the whole heap at this point as the // GC alloc regions from this pause have been tagged // as survivors and moved on to the survivor list. @@ -4404,6 +4399,8 @@ public: { } void work(uint worker_id) { + G1GCParPhaseTimesTracker x(_g1h->g1_policy()->phase_times(), G1GCPhaseTimes::PreserveCMReferents, worker_id); + ResourceMark rm; HandleMark hm; @@ -4467,13 +4464,8 @@ void G1CollectedHeap::process_weak_jni_handles() { g1_policy()->phase_times()->record_ref_proc_time(ref_proc_time * 1000.0); } -// Weak Reference processing during an evacuation pause (part 1). -void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { - double ref_proc_start = os::elapsedTime(); - - ReferenceProcessor* rp = _ref_processor_stw; - assert(rp->discovery_enabled(), "should have been enabled"); - +void G1CollectedHeap::preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states) { + double preserve_cm_referents_start = os::elapsedTime(); // Any reference objects, in the collection set, that were 'discovered' // by the CM ref processor should have already been copied (either by // applying the external root copy closure to the discovered lists, or @@ -4501,9 +4493,18 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per per_thread_states, no_of_gc_workers, _task_queues); - workers()->run_task(&keep_cm_referents); + g1_policy()->phase_times()->record_preserve_cm_referents_time_ms((os::elapsedTime() - preserve_cm_referents_start) * 1000.0); +} + +// Weak Reference processing during an evacuation pause (part 1). +void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per_thread_states) { + double ref_proc_start = os::elapsedTime(); + + ReferenceProcessor* rp = _ref_processor_stw; + assert(rp->discovery_enabled(), "should have been enabled"); + // Closure to test whether a referent is alive. G1STWIsAliveClosure is_alive(this); @@ -4535,6 +4536,8 @@ void G1CollectedHeap::process_discovered_references(G1ParScanThreadStateSet* per NULL, _gc_timer_stw); } else { + uint no_of_gc_workers = workers()->active_workers(); + // Parallel reference processing assert(rp->num_q() == no_of_gc_workers, "sanity"); assert(no_of_gc_workers <= rp->max_num_q(), "sanity"); @@ -4592,6 +4595,12 @@ void G1CollectedHeap::enqueue_discovered_references(G1ParScanThreadStateSet* per g1_policy()->phase_times()->record_ref_enq_time(ref_enq_time * 1000.0); } +void G1CollectedHeap::merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states) { + double merge_pss_time_start = os::elapsedTime(); + per_thread_states->flush(); + g1_policy()->phase_times()->record_merge_pss_time_ms((os::elapsedTime() - merge_pss_time_start) * 1000.0); +} + void G1CollectedHeap::pre_evacuate_collection_set() { _expand_heap_after_alloc_failure = true; _evacuation_failed = false; @@ -4650,6 +4659,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in // objects (and their reachable sub-graphs) that were // not copied during the pause. if (g1_policy()->should_process_references()) { + preserve_cm_referents(per_thread_states); process_discovered_references(per_thread_states); } else { ref_processor_stw()->verify_no_references_recorded(); @@ -4693,12 +4703,7 @@ void G1CollectedHeap::post_evacuate_collection_set(EvacuationInfo& evacuation_in _allocator->release_gc_alloc_regions(evacuation_info); - per_thread_states->flush(); - - record_obj_copy_mem_stats(); - - _survivor_evac_stats.adjust_desired_plab_sz(); - _old_evac_stats.adjust_desired_plab_sz(); + merge_per_thread_state_info(per_thread_states); // Reset and re-enable the hot card cache. // Note the counts for the cards in the regions in the @@ -5194,8 +5199,8 @@ public: bool success() { return _success; } }; -bool G1CollectedHeap::check_young_list_empty(bool check_heap, bool check_sample) { - bool ret = _young_list->check_list_empty(check_sample); +bool G1CollectedHeap::check_young_list_empty(bool check_heap) { + bool ret = _young_list->check_list_empty(); if (check_heap) { NoYoungRegionsClosure closure; diff --git a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp index 3d8badc27bb..adbf7a20ef8 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.hpp @@ -511,6 +511,9 @@ protected: // allocated block, or else "NULL". HeapWord* expand_and_allocate(size_t word_size, AllocationContext_t context); + // Preserve any referents discovered by concurrent marking that have not yet been + // copied by the STW pause. + void preserve_cm_referents(G1ParScanThreadStateSet* per_thread_states); // Process any reference objects discovered during // an incremental evacuation pause. void process_discovered_references(G1ParScanThreadStateSet* per_thread_states); @@ -519,6 +522,9 @@ protected: // after processing. void enqueue_discovered_references(G1ParScanThreadStateSet* per_thread_states); + // Merges the information gathered on a per-thread basis for all worker threads + // during GC into global variables. + void merge_per_thread_state_info(G1ParScanThreadStateSet* per_thread_states); public: WorkGang* workers() const { return _workers; } @@ -1333,8 +1339,7 @@ public: return _young_list->check_list_well_formed(); } - bool check_young_list_empty(bool check_heap, - bool check_sample = true); + bool check_young_list_empty(bool check_heap); // *** Stuff related to concurrent marking. It's not clear to me that so // many of these need to be public. diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp index 566dfcc28ff..eda5e18e1a8 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.cpp @@ -81,10 +81,8 @@ static double non_young_other_cost_per_region_ms_defaults[] = { G1CollectorPolicy::G1CollectorPolicy() : _predictor(G1ConfidencePercent / 100.0), - _parallel_gc_threads(ParallelGCThreads), _recent_gc_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), - _stop_world_start(0.0), _concurrent_mark_remark_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), _concurrent_mark_cleanup_times_ms(new TruncatedSeq(NumPrevPausesForHeuristics)), @@ -129,7 +127,6 @@ G1CollectorPolicy::G1CollectorPolicy() : _inc_cset_head(NULL), _inc_cset_tail(NULL), _inc_cset_bytes_used_before(0), - _inc_cset_max_finger(NULL), _inc_cset_recorded_rs_lengths(0), _inc_cset_recorded_rs_lengths_diffs(0), _inc_cset_predicted_elapsed_time_ms(0.0), @@ -172,9 +169,9 @@ G1CollectorPolicy::G1CollectorPolicy() : _prev_collection_pause_end_ms = os::elapsedTime() * 1000.0; clear_ratio_check_data(); - _phase_times = new G1GCPhaseTimes(_parallel_gc_threads); + _phase_times = new G1GCPhaseTimes(ParallelGCThreads); - int index = MIN2(_parallel_gc_threads - 1, 7); + int index = MIN2(ParallelGCThreads - 1, 7u); _rs_length_diff_seq->add(rs_length_diff_defaults[index]); _cost_per_card_ms_seq->add(cost_per_card_ms_defaults[index]); @@ -790,10 +787,9 @@ double G1CollectorPolicy::predict_survivor_regions_evac_time() const { return survivor_regions_evac_time; } -void G1CollectorPolicy::revise_young_list_target_length_if_necessary() { +void G1CollectorPolicy::revise_young_list_target_length_if_necessary(size_t rs_lengths) { guarantee( adaptive_young_list_length(), "should not call this otherwise" ); - size_t rs_lengths = _g1->young_list()->sampled_rs_lengths(); if (rs_lengths > _rs_lengths_prediction) { // add 10% to avoid having to recalculate often size_t rs_lengths_prediction = rs_lengths * 1100 / 1000; @@ -872,8 +868,6 @@ void G1CollectorPolicy::record_full_collection_end() { double full_gc_time_sec = end_sec - _full_collection_start_sec; double full_gc_time_ms = full_gc_time_sec * 1000.0; - _trace_old_gen_time_data.record_full_collection(full_gc_time_ms); - update_recent_gc_times(end_sec, full_gc_time_ms); collector_state()->set_full_collection(false); @@ -904,10 +898,6 @@ void G1CollectorPolicy::record_full_collection_end() { record_pause(FullGC, _full_collection_start_sec, end_sec); } -void G1CollectorPolicy::record_stop_world_start() { - _stop_world_start = os::elapsedTime(); -} - void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) { // We only need to do this here as the policy will only be applied // to the GC we're about to start. so, no point is calculating this @@ -918,10 +908,6 @@ void G1CollectorPolicy::record_collection_pause_start(double start_time_sec) { "sanity, used: " SIZE_FORMAT " recalculate_used: " SIZE_FORMAT, _g1->used(), _g1->recalculate_used()); - double s_w_t_ms = (start_time_sec - _stop_world_start) * 1000.0; - _trace_young_gen_time_data.record_start_collection(s_w_t_ms); - _stop_world_start = 0.0; - phase_times()->record_cur_collection_start_sec(start_time_sec); _pending_cards = _g1->pending_card_num(); @@ -973,13 +959,6 @@ void G1CollectorPolicy::record_concurrent_mark_cleanup_completed() { collector_state()->set_in_marking_window(false); } -void G1CollectorPolicy::record_concurrent_pause() { - if (_stop_world_start > 0.0) { - double yield_ms = (os::elapsedTime() - _stop_world_start) * 1000.0; - _trace_young_gen_time_data.record_yield_time(yield_ms); - } -} - double G1CollectorPolicy::average_time_ms(G1GCPhaseTimes::GCParPhases phase) const { return phase_times()->average_time_ms(phase); } @@ -1064,7 +1043,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t } if (update_stats) { - _trace_young_gen_time_data.record_end_collection(pause_time_ms, phase_times()); // We maintain the invariant that all objects allocated by mutator // threads will be allocated out of eden regions. So, we can use // the eden region number allocated since the previous GC to @@ -1139,14 +1117,15 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t _short_lived_surv_rate_group->start_adding_regions(); // Do that for any other surv rate groups + double scan_hcc_time_ms = ConcurrentG1Refine::hot_card_cache_enabled() ? average_time_ms(G1GCPhaseTimes::ScanHCC) : 0.0; + if (update_stats) { double cost_per_card_ms = 0.0; - double cost_scan_hcc = average_time_ms(G1GCPhaseTimes::ScanHCC); if (_pending_cards > 0) { - cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - cost_scan_hcc) / (double) _pending_cards; + cost_per_card_ms = (average_time_ms(G1GCPhaseTimes::UpdateRS) - scan_hcc_time_ms) / (double) _pending_cards; _cost_per_card_ms_seq->add(cost_per_card_ms); } - _cost_scan_hcc_seq->add(cost_scan_hcc); + _cost_scan_hcc_seq->add(scan_hcc_time_ms); double cost_per_entry_ms = 0.0; if (cards_scanned > 10) { @@ -1236,8 +1215,6 @@ void G1CollectorPolicy::record_collection_pause_end(double pause_time_ms, size_t // Note that _mmu_tracker->max_gc_time() returns the time in seconds. double update_rs_time_goal_ms = _mmu_tracker->max_gc_time() * MILLIUNITS * G1RSetUpdatingPauseTimePercent / 100.0; - double scan_hcc_time_ms = average_time_ms(G1GCPhaseTimes::ScanHCC); - if (update_rs_time_goal_ms < scan_hcc_time_ms) { log_debug(gc, ergo, refine)("Adjust concurrent refinement thresholds (scanning the HCC expected to take longer than Update RS time goal)." "Update RS time goal: %1.2fms Scan HCC time: %1.2fms", @@ -1323,12 +1300,12 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, const int k_gy = 3, k_gr = 6; const double inc_k = 1.1, dec_k = 0.9; - int g = cg1r->green_zone(); + size_t g = cg1r->green_zone(); if (update_rs_time > goal_ms) { - g = (int)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. + g = (size_t)(g * dec_k); // Can become 0, that's OK. That would mean a mutator-only processing. } else { if (update_rs_time < goal_ms && update_rs_processed_buffers > g) { - g = (int)MAX2(g * inc_k, g + 1.0); + g = (size_t)MAX2(g * inc_k, g + 1.0); } } // Change the refinement threads params @@ -1337,15 +1314,15 @@ void G1CollectorPolicy::adjust_concurrent_refinement(double update_rs_time, cg1r->set_red_zone(g * k_gr); cg1r->reinitialize_threads(); - int processing_threshold_delta = MAX2((int)(cg1r->green_zone() * _predictor.sigma()), 1); - int processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, + size_t processing_threshold_delta = MAX2(cg1r->green_zone() * _predictor.sigma(), 1); + size_t processing_threshold = MIN2(cg1r->green_zone() + processing_threshold_delta, cg1r->yellow_zone()); // Change the barrier params - dcqs.set_process_completed_threshold(processing_threshold); - dcqs.set_max_completed_queue(cg1r->red_zone()); + dcqs.set_process_completed_threshold((int)processing_threshold); + dcqs.set_max_completed_queue((int)cg1r->red_zone()); } - int curr_queue_size = dcqs.completed_buffers_num(); + size_t curr_queue_size = dcqs.completed_buffers_num(); if (curr_queue_size >= cg1r->yellow_zone()) { dcqs.set_completed_queue_padding(curr_queue_size); } else { @@ -1654,11 +1631,6 @@ size_t G1CollectorPolicy::expansion_amount() { return expand_bytes; } -void G1CollectorPolicy::print_tracing_info() const { - _trace_young_gen_time_data.print(); - _trace_old_gen_time_data.print(); -} - void G1CollectorPolicy::print_yg_surv_rate_info() const { #ifndef PRODUCT _short_lived_surv_rate_group->print_surv_rate_summary(); @@ -1869,7 +1841,6 @@ void G1CollectorPolicy::start_incremental_cset_building() { _inc_cset_tail = NULL; _inc_cset_bytes_used_before = 0; - _inc_cset_max_finger = 0; _inc_cset_recorded_rs_lengths = 0; _inc_cset_recorded_rs_lengths_diffs = 0; _inc_cset_predicted_elapsed_time_ms = 0.0; @@ -1981,9 +1952,6 @@ void G1CollectorPolicy::add_region_to_incremental_cset_common(HeapRegion* hr) { size_t rs_length = hr->rem_set()->occupied(); add_to_incremental_cset_info(hr, rs_length); - HeapWord* hr_end = hr->end(); - _inc_cset_max_finger = MAX2(_inc_cset_max_finger, hr_end); - assert(!hr->in_collection_set(), "invariant"); _g1->register_young_region_with_cset(hr); assert(hr->next_in_collection_set() == NULL, "invariant"); @@ -2190,12 +2158,6 @@ double G1CollectorPolicy::finalize_young_cset_part(double target_pause_time_ms) collector_state()->set_last_gc_was_young(collector_state()->gcs_are_young()); - if (collector_state()->last_gc_was_young()) { - _trace_young_gen_time_data.increment_young_collection_count(); - } else { - _trace_young_gen_time_data.increment_mixed_collection_count(); - } - // The young list is laid with the survivor regions from the previous // pause are appended to the RHS of the young list, i.e. // [Newly Young Regions ++ Survivors from last pause]. @@ -2335,127 +2297,3 @@ void G1CollectorPolicy::finalize_old_cset_part(double time_remaining_ms) { double non_young_end_time_sec = os::elapsedTime(); phase_times()->record_non_young_cset_choice_time_ms((non_young_end_time_sec - non_young_start_time_sec) * 1000.0); } - -void TraceYoungGenTimeData::record_start_collection(double time_to_stop_the_world_ms) { - if(TraceYoungGenTime) { - _all_stop_world_times_ms.add(time_to_stop_the_world_ms); - } -} - -void TraceYoungGenTimeData::record_yield_time(double yield_time_ms) { - if(TraceYoungGenTime) { - _all_yield_times_ms.add(yield_time_ms); - } -} - -void TraceYoungGenTimeData::record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times) { - if(TraceYoungGenTime) { - _total.add(pause_time_ms); - _other.add(pause_time_ms - phase_times->accounted_time_ms()); - _root_region_scan_wait.add(phase_times->root_region_scan_wait_time_ms()); - _parallel.add(phase_times->cur_collection_par_time_ms()); - _ext_root_scan.add(phase_times->average_time_ms(G1GCPhaseTimes::ExtRootScan)); - _satb_filtering.add(phase_times->average_time_ms(G1GCPhaseTimes::SATBFiltering)); - _update_rs.add(phase_times->average_time_ms(G1GCPhaseTimes::UpdateRS)); - _scan_rs.add(phase_times->average_time_ms(G1GCPhaseTimes::ScanRS)); - _obj_copy.add(phase_times->average_time_ms(G1GCPhaseTimes::ObjCopy)); - _termination.add(phase_times->average_time_ms(G1GCPhaseTimes::Termination)); - - double parallel_known_time = phase_times->average_time_ms(G1GCPhaseTimes::ExtRootScan) + - phase_times->average_time_ms(G1GCPhaseTimes::SATBFiltering) + - phase_times->average_time_ms(G1GCPhaseTimes::UpdateRS) + - phase_times->average_time_ms(G1GCPhaseTimes::ScanRS) + - phase_times->average_time_ms(G1GCPhaseTimes::ObjCopy) + - phase_times->average_time_ms(G1GCPhaseTimes::Termination); - - double parallel_other_time = phase_times->cur_collection_par_time_ms() - parallel_known_time; - _parallel_other.add(parallel_other_time); - _clear_ct.add(phase_times->cur_clear_ct_time_ms()); - } -} - -void TraceYoungGenTimeData::increment_young_collection_count() { - if(TraceYoungGenTime) { - ++_young_pause_num; - } -} - -void TraceYoungGenTimeData::increment_mixed_collection_count() { - if(TraceYoungGenTime) { - ++_mixed_pause_num; - } -} - -void TraceYoungGenTimeData::print_summary(const char* str, - const NumberSeq* seq) const { - double sum = seq->sum(); - tty->print_cr("%-27s = %8.2lf s (avg = %8.2lf ms)", - str, sum / 1000.0, seq->avg()); -} - -void TraceYoungGenTimeData::print_summary_sd(const char* str, - const NumberSeq* seq) const { - print_summary(str, seq); - tty->print_cr("%45s = %5d, std dev = %8.2lf ms, max = %8.2lf ms)", - "(num", seq->num(), seq->sd(), seq->maximum()); -} - -void TraceYoungGenTimeData::print() const { - if (!TraceYoungGenTime) { - return; - } - - tty->print_cr("ALL PAUSES"); - print_summary_sd(" Total", &_total); - tty->cr(); - tty->cr(); - tty->print_cr(" Young GC Pauses: %8d", _young_pause_num); - tty->print_cr(" Mixed GC Pauses: %8d", _mixed_pause_num); - tty->cr(); - - tty->print_cr("EVACUATION PAUSES"); - - if (_young_pause_num == 0 && _mixed_pause_num == 0) { - tty->print_cr("none"); - } else { - print_summary_sd(" Evacuation Pauses", &_total); - print_summary(" Root Region Scan Wait", &_root_region_scan_wait); - print_summary(" Parallel Time", &_parallel); - print_summary(" Ext Root Scanning", &_ext_root_scan); - print_summary(" SATB Filtering", &_satb_filtering); - print_summary(" Update RS", &_update_rs); - print_summary(" Scan RS", &_scan_rs); - print_summary(" Object Copy", &_obj_copy); - print_summary(" Termination", &_termination); - print_summary(" Parallel Other", &_parallel_other); - print_summary(" Clear CT", &_clear_ct); - print_summary(" Other", &_other); - } - tty->cr(); - - tty->print_cr("MISC"); - print_summary_sd(" Stop World", &_all_stop_world_times_ms); - print_summary_sd(" Yields", &_all_yield_times_ms); -} - -void TraceOldGenTimeData::record_full_collection(double full_gc_time_ms) { - if (TraceOldGenTime) { - _all_full_gc_times.add(full_gc_time_ms); - } -} - -void TraceOldGenTimeData::print() const { - if (!TraceOldGenTime) { - return; - } - - if (_all_full_gc_times.num() > 0) { - tty->print("\n%4d full_gcs: total time = %8.2f s", - _all_full_gc_times.num(), - _all_full_gc_times.sum() / 1000.0); - tty->print_cr(" (avg = %8.2fms).", _all_full_gc_times.avg()); - tty->print_cr(" [std. dev = %8.2f ms, max = %8.2f ms]", - _all_full_gc_times.sd(), - _all_full_gc_times.maximum()); - } -} diff --git a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp index 81ba9f7b4c5..6db53e64119 100644 --- a/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp +++ b/hotspot/src/share/vm/gc/g1/g1CollectorPolicy.hpp @@ -45,52 +45,6 @@ class CollectionSetChooser; class G1IHOPControl; class G1YoungGenSizer; -// TraceYoungGenTime collects data on _both_ young and mixed evacuation pauses -// (the latter may contain non-young regions - i.e. regions that are -// technically in old) while TraceOldGenTime collects data about full GCs. -class TraceYoungGenTimeData : public CHeapObj { - private: - unsigned _young_pause_num; - unsigned _mixed_pause_num; - - NumberSeq _all_stop_world_times_ms; - NumberSeq _all_yield_times_ms; - - NumberSeq _total; - NumberSeq _other; - NumberSeq _root_region_scan_wait; - NumberSeq _parallel; - NumberSeq _ext_root_scan; - NumberSeq _satb_filtering; - NumberSeq _update_rs; - NumberSeq _scan_rs; - NumberSeq _obj_copy; - NumberSeq _termination; - NumberSeq _parallel_other; - NumberSeq _clear_ct; - - void print_summary(const char* str, const NumberSeq* seq) const; - void print_summary_sd(const char* str, const NumberSeq* seq) const; - -public: - TraceYoungGenTimeData() : _young_pause_num(0), _mixed_pause_num(0) {}; - void record_start_collection(double time_to_stop_the_world_ms); - void record_yield_time(double yield_time_ms); - void record_end_collection(double pause_time_ms, G1GCPhaseTimes* phase_times); - void increment_young_collection_count(); - void increment_mixed_collection_count(); - void print() const; -}; - -class TraceOldGenTimeData : public CHeapObj { - private: - NumberSeq _all_full_gc_times; - - public: - void record_full_collection(double full_gc_time_ms); - void print() const; -}; - class G1CollectorPolicy: public CollectorPolicy { private: G1IHOPControl* _ihop_control; @@ -107,13 +61,6 @@ class G1CollectorPolicy: public CollectorPolicy { double get_new_prediction(TruncatedSeq const* seq) const; size_t get_new_size_prediction(TruncatedSeq const* seq) const; - // either equal to the number of parallel threads, if ParallelGCThreads - // has been set, or 1 otherwise - int _parallel_gc_threads; - - // The number of GC threads currently active. - uintx _no_of_gc_threads; - G1MMUTracker* _mmu_tracker; void initialize_alignments(); @@ -134,11 +81,6 @@ class G1CollectorPolicy: public CollectorPolicy { double _ratio_over_threshold_sum; uint _pauses_since_start; - TraceYoungGenTimeData _trace_young_gen_time_data; - TraceOldGenTimeData _trace_old_gen_time_data; - - double _stop_world_start; - uint _young_list_target_length; uint _young_list_fixed_length; @@ -212,9 +154,6 @@ class G1CollectorPolicy: public CollectorPolicy { double update_rs_processed_buffers, double goal_ms); - uintx no_of_gc_threads() { return _no_of_gc_threads; } - void set_no_of_gc_threads(uintx v) { _no_of_gc_threads = v; } - double _pause_time_target_ms; size_t _pending_cards; @@ -389,9 +328,6 @@ private: // an evacuation pause. size_t _inc_cset_bytes_used_before; - // Used to record the highest end of heap region in collection set - HeapWord* _inc_cset_max_finger; - // The RSet lengths recorded for regions in the CSet. It is updated // by the thread that adds a new region to the CSet. We assume that // only one thread can be allocating a new CSet region (currently, @@ -535,7 +471,7 @@ public: // Check the current value of the young list RSet lengths and // compare it against the last prediction. If the current value is // higher, recalculate the young list target length prediction. - void revise_young_list_target_length_if_necessary(); + void revise_young_list_target_length_if_necessary(size_t rs_lengths); // This should be called after the heap is resized. void record_new_heap_size(uint new_number_of_regions); @@ -573,9 +509,6 @@ public: virtual void print_phases(); - void record_stop_world_start(); - void record_concurrent_pause(); - // Record how much space we copied during a GC. This is typically // called when a GC alloc region is being retired. void record_bytes_copied_during_gc(size_t bytes) { @@ -685,9 +618,6 @@ public: // Clear ratio tracking data used by expansion_amount(). void clear_ratio_check_data(); - // Print tracing information. - void print_tracing_info() const; - // Print stats on young survival ratio void print_yg_surv_rate_info() const; diff --git a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp index a6a1d056bd3..33e001122ae 100644 --- a/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ConcurrentMark.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1097,7 +1097,7 @@ void G1ConcurrentMark::checkpointRootsFinal(bool clear_all_soft_refs) { reset_marking_state(); } else { { - GCTraceTime(Debug, gc) trace("GC Aggregate Data", g1h->gc_timer_cm()); + GCTraceTime(Debug, gc) trace("Aggregate Data", g1h->gc_timer_cm()); // Aggregate the per-task counting data that we have accumulated // while marking. @@ -2018,7 +2018,7 @@ void G1ConcurrentMark::weakRefsWork(bool clear_all_soft_refs) { // Inner scope to exclude the cleaning of the string and symbol // tables from the displayed time. { - GCTraceTime(Debug, gc) trace("GC Ref Proc", g1h->gc_timer_cm()); + GCTraceTime(Debug, gc) trace("Reference Processing", g1h->gc_timer_cm()); ReferenceProcessor* rp = g1h->ref_processor_cm(); @@ -2271,7 +2271,7 @@ void G1ConcurrentMark::checkpointRootsFinalWork() { SATBMarkQueueSet& satb_mq_set = JavaThread::satb_mark_queue_set(); guarantee(has_overflown() || satb_mq_set.completed_buffers_num() == 0, - "Invariant: has_overflown = %s, num buffers = %d", + "Invariant: has_overflown = %s, num buffers = " SIZE_FORMAT, BOOL_TO_STR(has_overflown()), satb_mq_set.completed_buffers_num()); @@ -2662,9 +2662,6 @@ void G1ConcurrentMark::print_on_error(outputStream* st) const { // We take a break if someone is trying to stop the world. bool G1ConcurrentMark::do_yield_check(uint worker_id) { if (SuspendibleThreadSet::should_yield()) { - if (worker_id == 0) { - _g1h->g1_policy()->record_concurrent_pause(); - } SuspendibleThreadSet::yield(); return true; } else { @@ -2705,11 +2702,8 @@ public: }; static ReferenceProcessor* get_cm_oop_closure_ref_processor(G1CollectedHeap* g1h) { - ReferenceProcessor* result = NULL; - if (G1UseConcMarkReferenceProcessing) { - result = g1h->ref_processor_cm(); - assert(result != NULL, "should not be NULL"); - } + ReferenceProcessor* result = g1h->ref_processor_cm(); + assert(result != NULL, "CM reference processor should not be NULL"); return result; } diff --git a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp index ca7643f59a8..eff37e8ae44 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacFailure.hpp @@ -27,25 +27,12 @@ #include "gc/g1/g1OopClosures.hpp" #include "gc/g1/heapRegionManager.hpp" + #include "gc/shared/preservedMarks.hpp" #include "gc/shared/workgroup.hpp" #include "utilities/globalDefinitions.hpp" class G1CollectedHeap; -class OopAndMarkOop { - oop _o; - markOop _m; - public: - OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) { - } - - void set_mark() { - _o->set_mark(_m); - } -}; - -typedef Stack OopAndMarkOopStack; - // Task to fixup self-forwarding pointers // installed as a result of an evacuation failure. class G1ParRemoveSelfForwardPtrsTask: public AbstractGangTask { diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp index a000a1e40ce..1cb7384ed46 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,15 +29,26 @@ #include "logging/log.hpp" #include "trace/tracing.hpp" +void G1EvacStats::log_plab_allocation() { + PLABStats::log_plab_allocation(); + log_debug(gc, plab)("%s other allocation: " + "region end waste: " SIZE_FORMAT "B, " + "regions filled: %u, " + "direct allocated: " SIZE_FORMAT "B, " + "failure used: " SIZE_FORMAT "B, " + "failure wasted: " SIZE_FORMAT "B", + _description, + _region_end_waste * HeapWordSize, + _regions_filled, + _direct_allocated * HeapWordSize, + _failure_used * HeapWordSize, + _failure_waste * HeapWordSize); +} + void G1EvacStats::adjust_desired_plab_sz() { + log_plab_allocation(); + if (!ResizePLAB) { - log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " - "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " - "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " - "regions filled = %u direct_allocated = " SIZE_FORMAT " " - "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") ", - _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, - _regions_filled, _direct_allocated, _failure_used, _failure_waste); // Clear accumulators for next round. reset(); return; @@ -107,18 +118,19 @@ void G1EvacStats::adjust_desired_plab_sz() { // Latch the result _desired_net_plab_sz = plab_sz; - log_debug(gc, plab)(" (allocated = " SIZE_FORMAT " wasted = " SIZE_FORMAT " " - "unused = " SIZE_FORMAT " used = " SIZE_FORMAT " " - "undo_waste = " SIZE_FORMAT " region_end_waste = " SIZE_FORMAT " " - "regions filled = %u direct_allocated = " SIZE_FORMAT " " - "failure_used = " SIZE_FORMAT " failure_waste = " SIZE_FORMAT ") " - " (plab_sz = " SIZE_FORMAT " desired_plab_sz = " SIZE_FORMAT ")", - _allocated, _wasted, _unused, used(), _undo_wasted, _region_end_waste, - _regions_filled, _direct_allocated, _failure_used, _failure_waste, - cur_plab_sz, plab_sz); - + log_sizing(cur_plab_sz, plab_sz); // Clear accumulators for next round. reset(); } +G1EvacStats::G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt) : + PLABStats(description, desired_plab_sz_, wt), + _region_end_waste(0), + _regions_filled(0), + _direct_allocated(0), + _failure_used(0), + _failure_waste(0) { +} + + G1EvacStats::~G1EvacStats() { } diff --git a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp index 1d0a53f5453..b322593e7ea 100644 --- a/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp +++ b/hotspot/src/share/vm/gc/g1/g1EvacStats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,20 +51,15 @@ class G1EvacStats : public PLABStats { _failure_waste = 0; } + virtual void log_plab_allocation(); + public: - G1EvacStats(size_t desired_plab_sz_, unsigned wt) : PLABStats(desired_plab_sz_, wt), - _region_end_waste(0), _regions_filled(0), _direct_allocated(0), - _failure_used(0), _failure_waste(0) { - } + G1EvacStats(const char* description, size_t desired_plab_sz_, unsigned wt); + + ~G1EvacStats(); virtual void adjust_desired_plab_sz(); - size_t allocated() const { return _allocated; } - size_t wasted() const { return _wasted; } - size_t unused() const { return _unused; } - size_t used() const { return allocated() - (wasted() + unused()); } - size_t undo_wasted() const { return _undo_wasted; } - uint regions_filled() const { return _regions_filled; } size_t region_end_waste() const { return _region_end_waste; } size_t direct_allocated() const { return _direct_allocated; } @@ -77,8 +72,6 @@ class G1EvacStats : public PLABStats { inline void add_direct_allocated(size_t value); inline void add_region_end_waste(size_t value); inline void add_failure_used_and_waste(size_t used, size_t waste); - - ~G1EvacStats(); }; #endif // SHARE_VM_GC_G1_G1EVACSTATS_HPP diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp index 706495fdbc7..9ab25e6a73f 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,107 +28,70 @@ #include "gc/g1/g1GCPhaseTimes.hpp" #include "gc/g1/g1StringDedup.hpp" #include "gc/g1/workerDataArray.inline.hpp" -#include "memory/allocation.hpp" +#include "memory/resourceArea.hpp" #include "logging/log.hpp" #include "runtime/timer.hpp" #include "runtime/os.hpp" -// Helper class for avoiding interleaved logging -class LineBuffer: public StackObj { - -private: - static const int BUFFER_LEN = 1024; - static const int INDENT_CHARS = 3; - char _buffer[BUFFER_LEN]; - int _indent_level; - int _cur; - - void vappend(const char* format, va_list ap) ATTRIBUTE_PRINTF(2, 0) { - int res = vsnprintf(&_buffer[_cur], BUFFER_LEN - _cur, format, ap); - if (res != -1) { - _cur += res; - } else { - DEBUG_ONLY(warning("buffer too small in LineBuffer");) - _buffer[BUFFER_LEN -1] = 0; - _cur = BUFFER_LEN; // vsnprintf above should not add to _buffer if we are called again - } - } - -public: - explicit LineBuffer(int indent_level): _indent_level(indent_level), _cur(0) { - for (; (_cur < BUFFER_LEN && _cur < (_indent_level * INDENT_CHARS)); _cur++) { - _buffer[_cur] = ' '; - } - } - -#ifndef PRODUCT - ~LineBuffer() { - assert(_cur == _indent_level * INDENT_CHARS, "pending data in buffer - append_and_print_cr() not called?"); - } -#endif - - void append(const char* format, ...) ATTRIBUTE_PRINTF(2, 3) { - va_list ap; - va_start(ap, format); - vappend(format, ap); - va_end(ap); - } - - const char* to_string() { - _cur = _indent_level * INDENT_CHARS; - return _buffer; - } -}; - -static const char* Indents[4] = {"", " ", " ", " "}; +static const char* Indents[5] = {"", " ", " ", " ", " "}; G1GCPhaseTimes::G1GCPhaseTimes(uint max_gc_threads) : _max_gc_threads(max_gc_threads) { assert(max_gc_threads > 0, "Must have some GC threads"); - _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start:", false, 2); - _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning:", true, 2); + _gc_par_phases[GCWorkerStart] = new WorkerDataArray(max_gc_threads, "GC Worker Start (ms):"); + _gc_par_phases[ExtRootScan] = new WorkerDataArray(max_gc_threads, "Ext Root Scanning (ms):"); // Root scanning phases - _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots:", true, 3); - _gc_par_phases[StringTableRoots] = new WorkerDataArray(max_gc_threads, "StringTable Roots:", true, 3); - _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots:", true, 3); - _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots:", true, 3); - _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots:", true, 3); - _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray(max_gc_threads, "FlatProfiler Roots:", true, 3); - _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots:", true, 3); - _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots:", true, 3); - _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots:", true, 3); - _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots:", true, 3); - _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots:", true, 3); - _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD:", true, 3); - _gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots:", true, 3); - _gc_par_phases[SATBFiltering] = new WorkerDataArray(max_gc_threads, "SATB Filtering:", true, 3); + _gc_par_phases[ThreadRoots] = new WorkerDataArray(max_gc_threads, "Thread Roots (ms):"); + _gc_par_phases[StringTableRoots] = new WorkerDataArray(max_gc_threads, "StringTable Roots (ms):"); + _gc_par_phases[UniverseRoots] = new WorkerDataArray(max_gc_threads, "Universe Roots (ms):"); + _gc_par_phases[JNIRoots] = new WorkerDataArray(max_gc_threads, "JNI Handles Roots (ms):"); + _gc_par_phases[ObjectSynchronizerRoots] = new WorkerDataArray(max_gc_threads, "ObjectSynchronizer Roots (ms):"); + _gc_par_phases[FlatProfilerRoots] = new WorkerDataArray(max_gc_threads, "FlatProfiler Roots (ms):"); + _gc_par_phases[ManagementRoots] = new WorkerDataArray(max_gc_threads, "Management Roots (ms):"); + _gc_par_phases[SystemDictionaryRoots] = new WorkerDataArray(max_gc_threads, "SystemDictionary Roots (ms):"); + _gc_par_phases[CLDGRoots] = new WorkerDataArray(max_gc_threads, "CLDG Roots (ms):"); + _gc_par_phases[JVMTIRoots] = new WorkerDataArray(max_gc_threads, "JVMTI Roots (ms):"); + _gc_par_phases[CMRefRoots] = new WorkerDataArray(max_gc_threads, "CM RefProcessor Roots (ms):"); + _gc_par_phases[WaitForStrongCLD] = new WorkerDataArray(max_gc_threads, "Wait For Strong CLD (ms):"); + _gc_par_phases[WeakCLDRoots] = new WorkerDataArray(max_gc_threads, "Weak CLD Roots (ms):"); + _gc_par_phases[SATBFiltering] = new WorkerDataArray(max_gc_threads, "SATB Filtering (ms):"); - _gc_par_phases[UpdateRS] = new WorkerDataArray(max_gc_threads, "Update RS:", true, 2); - _gc_par_phases[ScanHCC] = new WorkerDataArray(max_gc_threads, "Scan HCC:", true, 3); - _gc_par_phases[ScanHCC]->set_enabled(ConcurrentG1Refine::hot_card_cache_enabled()); - _gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS:", true, 2); - _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning:", true, 2); - _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy:", true, 2); - _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination:", true, 2); - _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total:", true, 2); - _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End:", false, 2); - _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other:", true, 2); + _gc_par_phases[UpdateRS] = new WorkerDataArray(max_gc_threads, "Update RS (ms):"); + if (ConcurrentG1Refine::hot_card_cache_enabled()) { + _gc_par_phases[ScanHCC] = new WorkerDataArray(max_gc_threads, "Scan HCC (ms):"); + } else { + _gc_par_phases[ScanHCC] = NULL; + } + _gc_par_phases[ScanRS] = new WorkerDataArray(max_gc_threads, "Scan RS (ms):"); + _gc_par_phases[CodeRoots] = new WorkerDataArray(max_gc_threads, "Code Root Scanning (ms):"); + _gc_par_phases[ObjCopy] = new WorkerDataArray(max_gc_threads, "Object Copy (ms):"); + _gc_par_phases[Termination] = new WorkerDataArray(max_gc_threads, "Termination (ms):"); + _gc_par_phases[GCWorkerTotal] = new WorkerDataArray(max_gc_threads, "GC Worker Total (ms):"); + _gc_par_phases[GCWorkerEnd] = new WorkerDataArray(max_gc_threads, "GC Worker End (ms):"); + _gc_par_phases[Other] = new WorkerDataArray(max_gc_threads, "GC Worker Other (ms):"); - _update_rs_processed_buffers = new WorkerDataArray(max_gc_threads, "Processed Buffers:", true, 3); + _update_rs_processed_buffers = new WorkerDataArray(max_gc_threads, "Processed Buffers:"); _gc_par_phases[UpdateRS]->link_thread_work_items(_update_rs_processed_buffers); - _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:", true, 3); + _termination_attempts = new WorkerDataArray(max_gc_threads, "Termination Attempts:"); _gc_par_phases[Termination]->link_thread_work_items(_termination_attempts); - _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup:", true, 2); - _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup:", true, 2); + if (UseStringDeduplication) { + _gc_par_phases[StringDedupQueueFixup] = new WorkerDataArray(max_gc_threads, "Queue Fixup (ms):"); + _gc_par_phases[StringDedupTableFixup] = new WorkerDataArray(max_gc_threads, "Table Fixup (ms):"); + } else { + _gc_par_phases[StringDedupQueueFixup] = NULL; + _gc_par_phases[StringDedupTableFixup] = NULL; + } - _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty:", true, 3); - _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:", true, 3); + _gc_par_phases[RedirtyCards] = new WorkerDataArray(max_gc_threads, "Parallel Redirty (ms):"); + _redirtied_cards = new WorkerDataArray(max_gc_threads, "Redirtied Cards:"); _gc_par_phases[RedirtyCards]->link_thread_work_items(_redirtied_cards); + + _gc_par_phases[PreserveCMReferents] = new WorkerDataArray(max_gc_threads, "Parallel Preserve CM Refs (ms):"); } void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { @@ -140,11 +103,10 @@ void G1GCPhaseTimes::note_gc_start(uint active_gc_threads) { _external_accounted_time_ms = 0.0; for (int i = 0; i < GCParPhasesSentinel; i++) { - _gc_par_phases[i]->reset(); + if (_gc_par_phases[i] != NULL) { + _gc_par_phases[i]->reset(); + } } - - _gc_par_phases[StringDedupQueueFixup]->set_enabled(G1StringDedup::is_enabled()); - _gc_par_phases[StringDedupTableFixup]->set_enabled(G1StringDedup::is_enabled()); } void G1GCPhaseTimes::note_gc_end() { @@ -166,43 +128,10 @@ void G1GCPhaseTimes::note_gc_end() { } for (int i = 0; i < GCParPhasesSentinel; i++) { - _gc_par_phases[i]->verify(_active_gc_threads); - } -} - -void G1GCPhaseTimes::print_stats(const char* indent, const char* str, double value) { - log_debug(gc, phases)("%s%s: %.1lf ms", indent, str, value); -} - -double G1GCPhaseTimes::accounted_time_ms() { - // First subtract any externally accounted time - double misc_time_ms = _external_accounted_time_ms; - - // Subtract the root region scanning wait time. It's initialized to - // zero at the start of the pause. - misc_time_ms += _root_region_scan_wait_time_ms; - - misc_time_ms += _cur_collection_par_time_ms; - - // Now subtract the time taken to fix up roots in generated code - misc_time_ms += _cur_collection_code_root_fixup_time_ms; - - // Strong code root purge time - misc_time_ms += _cur_strong_code_root_purge_time_ms; - - if (G1StringDedup::is_enabled()) { - // String dedup fixup time - misc_time_ms += _cur_string_dedup_fixup_time_ms; + if (_gc_par_phases[i] != NULL) { + _gc_par_phases[i]->verify(_active_gc_threads); } - - // Subtract the time taken to clean the card table from the - // current value of "other time" - misc_time_ms += _cur_clear_ct_time_ms; - - // Remove expand heap time from "other time" - misc_time_ms += _cur_expand_heap_time_ms; - - return misc_time_ms; + } } // record the time a phase took in seconds @@ -224,193 +153,144 @@ double G1GCPhaseTimes::average_time_ms(GCParPhases phase) { return _gc_par_phases[phase]->average(_active_gc_threads) * 1000.0; } -double G1GCPhaseTimes::get_time_ms(GCParPhases phase, uint worker_i) { - return _gc_par_phases[phase]->get(worker_i) * 1000.0; -} - -double G1GCPhaseTimes::sum_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->sum(_active_gc_threads) * 1000.0; -} - -double G1GCPhaseTimes::min_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->minimum(_active_gc_threads) * 1000.0; -} - -double G1GCPhaseTimes::max_time_ms(GCParPhases phase) { - return _gc_par_phases[phase]->maximum(_active_gc_threads) * 1000.0; -} - -size_t G1GCPhaseTimes::get_thread_work_item(GCParPhases phase, uint worker_i) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->get(worker_i); -} - size_t G1GCPhaseTimes::sum_thread_work_items(GCParPhases phase) { assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); return _gc_par_phases[phase]->thread_work_items()->sum(_active_gc_threads); } -double G1GCPhaseTimes::average_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->average(_active_gc_threads); +template +void G1GCPhaseTimes::details(T* phase, const char* indent) { + LogHandle(gc, phases, task) log; + if (log.is_level(LogLevel::Trace)) { + outputStream* trace_out = log.trace_stream(); + trace_out->print("%s", indent); + phase->print_details_on(trace_out, _active_gc_threads); + } } -size_t G1GCPhaseTimes::min_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->minimum(_active_gc_threads); +void G1GCPhaseTimes::log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum) { + out->print("%s", Indents[indent]); + phase->print_summary_on(out, _active_gc_threads, print_sum); + details(phase, Indents[indent]); + + WorkerDataArray* work_items = phase->thread_work_items(); + if (work_items != NULL) { + out->print("%s", Indents[indent + 1]); + work_items->print_summary_on(out, _active_gc_threads, true); + details(work_items, Indents[indent + 1]); + } } -size_t G1GCPhaseTimes::max_thread_work_items(GCParPhases phase) { - assert(_gc_par_phases[phase]->thread_work_items() != NULL, "No sub count"); - return _gc_par_phases[phase]->thread_work_items()->maximum(_active_gc_threads); +void G1GCPhaseTimes::debug_phase(WorkerDataArray* phase) { + LogHandle(gc, phases) log; + if (log.is_level(LogLevel::Debug)) { + ResourceMark rm; + log_phase(phase, 2, log.debug_stream(), true); + } } -class G1GCParPhasePrinter : public StackObj { - G1GCPhaseTimes* _phase_times; - public: - G1GCParPhasePrinter(G1GCPhaseTimes* phase_times) : _phase_times(phase_times) {} - - void print(G1GCPhaseTimes::GCParPhases phase_id) { - WorkerDataArray* phase = _phase_times->_gc_par_phases[phase_id]; - - if (phase->_length == 1) { - print_single_length(phase_id, phase); - } else { - print_multi_length(phase_id, phase); - } +void G1GCPhaseTimes::trace_phase(WorkerDataArray* phase, bool print_sum) { + LogHandle(gc, phases) log; + if (log.is_level(LogLevel::Trace)) { + ResourceMark rm; + log_phase(phase, 3, log.trace_stream(), print_sum); } +} +#define PHASE_DOUBLE_FORMAT "%s%s: %.1lfms" +#define PHASE_SIZE_FORMAT "%s%s: " SIZE_FORMAT - private: - void print_single_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* phase) { - // No need for min, max, average and sum for only one worker - log_debug(gc, phases)("%s%s: %.1lf", Indents[phase->_indent_level], phase->_title, _phase_times->get_time_ms(phase_id, 0)); +#define info_line(str, value) \ + log_info(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[1], str, value); - WorkerDataArray* work_items = phase->_thread_work_items; - if (work_items != NULL) { - log_debug(gc, phases)("%s%s: " SIZE_FORMAT, Indents[work_items->_indent_level], work_items->_title, _phase_times->sum_thread_work_items(phase_id)); - } - } +#define debug_line(str, value) \ + log_debug(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[2], str, value); - void print_time_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id) { - if (log_is_enabled(Trace, gc)) { - LineBuffer buf(0); - uint active_length = _phase_times->_active_gc_threads; - for (uint i = 0; i < active_length; ++i) { - buf.append(" %4.1lf", _phase_times->get_time_ms(phase_id, i)); - } - const char* line = buf.to_string(); - log_trace(gc, phases)("%s%-25s%s", indent, "", line); - } - } +#define trace_line(str, value) \ + log_trace(gc, phases)(PHASE_DOUBLE_FORMAT, Indents[3], str, value); - void print_count_values(const char* indent, G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* thread_work_items) { - if (log_is_enabled(Trace, gc)) { - LineBuffer buf(0); - uint active_length = _phase_times->_active_gc_threads; - for (uint i = 0; i < active_length; ++i) { - buf.append(" " SIZE_FORMAT, _phase_times->get_thread_work_item(phase_id, i)); - } - const char* line = buf.to_string(); - log_trace(gc, phases)("%s%-25s%s", indent, "", line); - } - } +#define trace_line_sz(str, value) \ + log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); - void print_thread_work_items(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* thread_work_items) { - const char* indent = Indents[thread_work_items->_indent_level]; +#define trace_line_ms(str, value) \ + log_trace(gc, phases)(PHASE_SIZE_FORMAT, Indents[3], str, value); - assert(thread_work_items->_print_sum, "%s does not have print sum true even though it is a count", thread_work_items->_title); - - log_debug(gc, phases)("%s%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT ", Sum: " SIZE_FORMAT, - indent, thread_work_items->_title, - _phase_times->min_thread_work_items(phase_id), _phase_times->average_thread_work_items(phase_id), _phase_times->max_thread_work_items(phase_id), - _phase_times->max_thread_work_items(phase_id) - _phase_times->min_thread_work_items(phase_id), _phase_times->sum_thread_work_items(phase_id)); - - print_count_values(indent, phase_id, thread_work_items); - } - - void print_multi_length(G1GCPhaseTimes::GCParPhases phase_id, WorkerDataArray* phase) { - const char* indent = Indents[phase->_indent_level]; - - if (phase->_print_sum) { - log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf, Sum: %4.1lf", - indent, phase->_title, - _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), - _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id), _phase_times->sum_time_ms(phase_id)); - } else { - log_debug(gc, phases)("%s%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", - indent, phase->_title, - _phase_times->min_time_ms(phase_id), _phase_times->average_time_ms(phase_id), _phase_times->max_time_ms(phase_id), - _phase_times->max_time_ms(phase_id) - _phase_times->min_time_ms(phase_id)); - } - - print_time_values(indent, phase_id); - - if (phase->_thread_work_items != NULL) { - print_thread_work_items(phase_id, phase->_thread_work_items); - } - } -}; +#define info_line_and_account(str, value) \ + info_line(str, value); \ + accounted_time_ms += value; void G1GCPhaseTimes::print() { note_gc_end(); - G1GCParPhasePrinter par_phase_printer(this); - + double accounted_time_ms = _external_accounted_time_ms; if (_root_region_scan_wait_time_ms > 0.0) { - print_stats(Indents[1], "Root Region Scan Waiting", _root_region_scan_wait_time_ms); + info_line_and_account("Root Region Scan Waiting", _root_region_scan_wait_time_ms); } - print_stats(Indents[1], "Parallel Time", _cur_collection_par_time_ms); - for (int i = 0; i <= GCMainParPhasesLast; i++) { - par_phase_printer.print((GCParPhases) i); + info_line_and_account("Evacuate Collection Set", _cur_collection_par_time_ms); + trace_phase(_gc_par_phases[GCWorkerStart], false); + debug_phase(_gc_par_phases[ExtRootScan]); + for (int i = ThreadRoots; i <= SATBFiltering; i++) { + trace_phase(_gc_par_phases[i]); } + debug_phase(_gc_par_phases[UpdateRS]); + if (ConcurrentG1Refine::hot_card_cache_enabled()) { + trace_phase(_gc_par_phases[ScanHCC]); + } + debug_phase(_gc_par_phases[ScanRS]); + debug_phase(_gc_par_phases[CodeRoots]); + debug_phase(_gc_par_phases[ObjCopy]); + debug_phase(_gc_par_phases[Termination]); + debug_phase(_gc_par_phases[Other]); + debug_phase(_gc_par_phases[GCWorkerTotal]); + trace_phase(_gc_par_phases[GCWorkerEnd], false); + + info_line_and_account("Code Roots", _cur_collection_code_root_fixup_time_ms + _cur_strong_code_root_purge_time_ms); + debug_line("Code Roots Fixup", _cur_collection_code_root_fixup_time_ms); + debug_line("Code Roots Purge", _cur_strong_code_root_purge_time_ms); - print_stats(Indents[1], "Code Root Fixup", _cur_collection_code_root_fixup_time_ms); - print_stats(Indents[1], "Code Root Purge", _cur_strong_code_root_purge_time_ms); if (G1StringDedup::is_enabled()) { - print_stats(Indents[1], "String Dedup Fixup", _cur_string_dedup_fixup_time_ms); - for (int i = StringDedupPhasesFirst; i <= StringDedupPhasesLast; i++) { - par_phase_printer.print((GCParPhases) i); - } + info_line_and_account("String Dedup Fixup", _cur_string_dedup_fixup_time_ms); + debug_phase(_gc_par_phases[StringDedupQueueFixup]); + debug_phase(_gc_par_phases[StringDedupTableFixup]); } - print_stats(Indents[1], "Clear CT", _cur_clear_ct_time_ms); - print_stats(Indents[1], "Expand Heap After Collection", _cur_expand_heap_time_ms); - double misc_time_ms = _gc_pause_time_ms - accounted_time_ms(); - print_stats(Indents[1], "Other", misc_time_ms); + info_line_and_account("Clear Card Table", _cur_clear_ct_time_ms); + info_line_and_account("Expand Heap After Collection", _cur_expand_heap_time_ms); + + double free_cset_time = _recorded_young_free_cset_time_ms + _recorded_non_young_free_cset_time_ms; + info_line_and_account("Free Collection Set", free_cset_time); + debug_line("Young Free Collection Set", _recorded_young_free_cset_time_ms); + debug_line("Non-Young Free Collection Set", _recorded_non_young_free_cset_time_ms); + info_line_and_account("Merge Per-Thread State", _recorded_merge_pss_time_ms); + + info_line("Other", _gc_pause_time_ms - accounted_time_ms); if (_cur_verify_before_time_ms > 0.0) { - print_stats(Indents[2], "Verify Before", _cur_verify_before_time_ms); + debug_line("Verify Before", _cur_verify_before_time_ms); } if (G1CollectedHeap::heap()->evacuation_failed()) { double evac_fail_handling = _cur_evac_fail_recalc_used + _cur_evac_fail_remove_self_forwards + _cur_evac_fail_restore_remsets; - print_stats(Indents[2], "Evacuation Failure", evac_fail_handling); - log_trace(gc, phases)("%sRecalculate Used: %.1lf ms", Indents[3], _cur_evac_fail_recalc_used); - log_trace(gc, phases)("%sRemove Self Forwards: %.1lf ms", Indents[3], _cur_evac_fail_remove_self_forwards); - log_trace(gc, phases)("%sRestore RemSet: %.1lf ms", Indents[3], _cur_evac_fail_restore_remsets); + debug_line("Evacuation Failure", evac_fail_handling); + trace_line("Recalculate Used", _cur_evac_fail_recalc_used); + trace_line("Remove Self Forwards",_cur_evac_fail_remove_self_forwards); + trace_line("Restore RemSet", _cur_evac_fail_restore_remsets); } - print_stats(Indents[2], "Choose CSet", - (_recorded_young_cset_choice_time_ms + - _recorded_non_young_cset_choice_time_ms)); - print_stats(Indents[2], "Ref Proc", _cur_ref_proc_time_ms); - print_stats(Indents[2], "Ref Enq", _cur_ref_enq_time_ms); - print_stats(Indents[2], "Redirty Cards", _recorded_redirty_logged_cards_time_ms); - par_phase_printer.print(RedirtyCards); + debug_line("Choose CSet", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); + debug_line("Preserve CM Refs", _recorded_preserve_cm_referents_time_ms); + debug_line("Reference Processing", _cur_ref_proc_time_ms); + debug_line("Reference Enqueuing", _cur_ref_enq_time_ms); + debug_line("Redirty Cards", _recorded_redirty_logged_cards_time_ms); + trace_phase(_gc_par_phases[RedirtyCards]); + trace_phase(_gc_par_phases[PreserveCMReferents]); if (G1EagerReclaimHumongousObjects) { - print_stats(Indents[2], "Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); - - log_trace(gc, phases)("%sHumongous Total: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_total); - log_trace(gc, phases)("%sHumongous Candidate: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_candidates); - print_stats(Indents[2], "Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); - log_trace(gc, phases)("%sHumongous Reclaimed: " SIZE_FORMAT, Indents[3], _cur_fast_reclaim_humongous_reclaimed); + debug_line("Humongous Register", _cur_fast_reclaim_humongous_register_time_ms); + trace_line_sz("Humongous Total", _cur_fast_reclaim_humongous_total); + trace_line_sz("Humongous Candidate", _cur_fast_reclaim_humongous_candidates); + debug_line("Humongous Reclaim", _cur_fast_reclaim_humongous_time_ms); + trace_line_sz("Humongous Reclaimed", _cur_fast_reclaim_humongous_reclaimed); } - print_stats(Indents[2], "Free CSet", - (_recorded_young_free_cset_time_ms + - _recorded_non_young_free_cset_time_ms)); - log_trace(gc, phases)("%sYoung Free CSet: %.1lf ms", Indents[3], _recorded_young_free_cset_time_ms); - log_trace(gc, phases)("%sNon-Young Free CSet: %.1lf ms", Indents[3], _recorded_non_young_free_cset_time_ms); if (_cur_verify_after_time_ms > 0.0) { - print_stats(Indents[2], "Verify After", _cur_verify_after_time_ms); + debug_line("Verify After", _cur_verify_after_time_ms); } } diff --git a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp index 5607c3f4ea0..e87075b5e93 100644 --- a/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp +++ b/hotspot/src/share/vm/gc/g1/g1GCPhaseTimes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,8 +32,6 @@ class LineBuffer; template class WorkerDataArray; class G1GCPhaseTimes : public CHeapObj { - friend class G1GCParPhasePrinter; - uint _active_gc_threads; uint _max_gc_threads; jlong _gc_start_counter; @@ -69,6 +67,7 @@ class G1GCPhaseTimes : public CHeapObj { StringDedupQueueFixup, StringDedupTableFixup, RedirtyCards, + PreserveCMReferents, GCParPhasesSentinel }; @@ -108,6 +107,10 @@ class G1GCPhaseTimes : public CHeapObj { double _recorded_redirty_logged_cards_time_ms; + double _recorded_preserve_cm_referents_time_ms; + + double _recorded_merge_pss_time_ms; + double _recorded_young_free_cset_time_ms; double _recorded_non_young_free_cset_time_ms; @@ -120,11 +123,14 @@ class G1GCPhaseTimes : public CHeapObj { double _cur_verify_before_time_ms; double _cur_verify_after_time_ms; - // Helper methods for detailed logging - void print_stats(const char*, const char* str, double value); - void note_gc_end(); + template + void details(T* phase, const char* indent); + void log_phase(WorkerDataArray* phase, uint indent, outputStream* out, bool print_sum); + void debug_phase(WorkerDataArray* phase); + void trace_phase(WorkerDataArray* phase, bool print_sum = true); + public: G1GCPhaseTimes(uint max_gc_threads); void note_gc_start(uint active_gc_threads); @@ -143,16 +149,6 @@ class G1GCPhaseTimes : public CHeapObj { size_t sum_thread_work_items(GCParPhases phase); - private: - double get_time_ms(GCParPhases phase, uint worker_i); - double sum_time_ms(GCParPhases phase); - double min_time_ms(GCParPhases phase); - double max_time_ms(GCParPhases phase); - size_t get_thread_work_item(GCParPhases phase, uint worker_i); - double average_thread_work_items(GCParPhases phase); - size_t min_thread_work_items(GCParPhases phase); - size_t max_thread_work_items(GCParPhases phase); - public: void record_clear_ct_time(double ms) { @@ -234,6 +230,14 @@ class G1GCPhaseTimes : public CHeapObj { _recorded_redirty_logged_cards_time_ms = time_ms; } + void record_preserve_cm_referents_time_ms(double time_ms) { + _recorded_preserve_cm_referents_time_ms = time_ms; + } + + void record_merge_pss_time_ms(double time_ms) { + _recorded_merge_pss_time_ms = time_ms; + } + void record_cur_collection_start_sec(double time_ms) { _cur_collection_start_sec = time_ms; } @@ -250,8 +254,6 @@ class G1GCPhaseTimes : public CHeapObj { _external_accounted_time_ms += time_ms; } - double accounted_time_ms(); - double cur_collection_start_sec() { return _cur_collection_start_sec; } diff --git a/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp index b7c176d632b..013be1a12f8 100644 --- a/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp +++ b/hotspot/src/share/vm/gc/g1/g1HotCardCache.cpp @@ -81,10 +81,7 @@ jbyte* G1HotCardCache::insert(jbyte* card_ptr) { } void G1HotCardCache::drain(CardTableEntryClosure* cl, uint worker_i) { - if (!default_use_cache()) { - assert(_hot_cache == NULL, "Logic"); - return; - } + assert(default_use_cache(), "Drain only necessary if we use the hot card cache."); assert(_hot_cache != NULL, "Logic"); assert(!use_cache(), "cache should be disabled"); diff --git a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp index 0cf5dab9448..5759ed0c68f 100644 --- a/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp +++ b/hotspot/src/share/vm/gc/g1/g1IHOPControl.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,14 +47,16 @@ void G1IHOPControl::update_allocation_info(double allocation_time_s, size_t allo void G1IHOPControl::print() { size_t cur_conc_mark_start_threshold = get_conc_mark_start_threshold(); - log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B," - " recent old gen allocation rate: %1.2f, recent marking phase length: %1.2f", + log_debug(gc, ihop)("Basic information (value update), threshold: " SIZE_FORMAT "B (%1.2f), target occupancy: " SIZE_FORMAT "B, current occupancy: " SIZE_FORMAT "B, " + "recent allocation size: " SIZE_FORMAT "B, recent allocation duration: %1.2fms, recent old gen allocation rate: %1.2fB/s, recent marking phase length: %1.2fms", cur_conc_mark_start_threshold, cur_conc_mark_start_threshold * 100.0 / _target_occupancy, _target_occupancy, G1CollectedHeap::heap()->used(), + _last_allocated_bytes, + _last_allocation_time_s * 1000.0, _last_allocation_time_s > 0.0 ? _last_allocated_bytes / _last_allocation_time_s : 0.0, - last_marking_length_s()); + last_marking_length_s() * 1000.0); } void G1IHOPControl::send_trace_event(G1NewTracer* tracer) { @@ -191,13 +193,16 @@ void G1AdaptiveIHOPControl::update_marking_length(double marking_length_s) { void G1AdaptiveIHOPControl::print() { G1IHOPControl::print(); size_t actual_target = actual_target_threshold(); - log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: " SIZE_FORMAT "B (%1.2f), internal target occupancy: " SIZE_FORMAT "B," - " predicted old gen allocation rate: %1.2f, predicted marking phase length: %1.2f, prediction active: %s", + log_debug(gc, ihop)("Adaptive IHOP information (value update), threshold: " SIZE_FORMAT "B (%1.2f), internal target occupancy: " SIZE_FORMAT "B, " + "occupancy: " SIZE_FORMAT "B, additional buffer size: " SIZE_FORMAT "B, predicted old gen allocation rate: %1.2fB/s, " + "predicted marking phase length: %1.2fms, prediction active: %s", get_conc_mark_start_threshold(), percent_of(get_conc_mark_start_threshold(), actual_target), actual_target, + G1CollectedHeap::heap()->used(), + _last_unrestrained_young_size, _predictor->get_new_prediction(&_allocation_rate_s), - _predictor->get_new_prediction(&_marking_times_s), + _predictor->get_new_prediction(&_marking_times_s) * 1000.0, have_enough_data_for_prediction() ? "true" : "false"); } diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp index f22c6e2195c..b59fc203c6c 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,6 +327,9 @@ oop G1ParScanThreadState::copy_to_survivor_space(InCSetState const state, G1ParScanThreadState* G1ParScanThreadStateSet::state_for_worker(uint worker_id) { assert(worker_id < _n_workers, "out of bounds access"); + if (_states[worker_id] == NULL) { + _states[worker_id] = new_par_scan_state(worker_id, _young_cset_length); + } return _states[worker_id]; } @@ -352,6 +355,10 @@ void G1ParScanThreadStateSet::flush() { for (uint worker_index = 0; worker_index < _n_workers; ++worker_index) { G1ParScanThreadState* pss = _states[worker_index]; + if (pss == NULL) { + continue; + } + _total_cards_scanned += _cards_scanned[worker_index]; pss->flush(_surviving_young_words_total); diff --git a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp index 47c5328d2b9..6accb48c1de 100644 --- a/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp +++ b/hotspot/src/share/vm/gc/g1/g1ParScanThreadState.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -200,6 +200,7 @@ class G1ParScanThreadStateSet : public StackObj { size_t* _surviving_young_words_total; size_t* _cards_scanned; size_t _total_cards_scanned; + size_t _young_cset_length; uint _n_workers; bool _flushed; @@ -210,10 +211,11 @@ class G1ParScanThreadStateSet : public StackObj { _surviving_young_words_total(NEW_C_HEAP_ARRAY(size_t, young_cset_length, mtGC)), _cards_scanned(NEW_C_HEAP_ARRAY(size_t, n_workers, mtGC)), _total_cards_scanned(0), + _young_cset_length(young_cset_length), _n_workers(n_workers), _flushed(false) { for (uint i = 0; i < n_workers; ++i) { - _states[i] = new_par_scan_state(i, young_cset_length); + _states[i] = NULL; } memset(_surviving_young_words_total, 0, young_cset_length * sizeof(size_t)); memset(_cards_scanned, 0, n_workers * sizeof(size_t)); diff --git a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp index 40e3959c886..8c31430e185 100644 --- a/hotspot/src/share/vm/gc/g1/g1RemSet.cpp +++ b/hotspot/src/share/vm/gc/g1/g1RemSet.cpp @@ -238,7 +238,7 @@ void G1RemSet::updateRS(DirtyCardQueue* into_cset_dcq, uint worker_i) { RefineRecordRefsIntoCSCardTableEntryClosure into_cset_update_rs_cl(_g1, into_cset_dcq); G1GCParPhaseTimesTracker x(_g1p->phase_times(), G1GCPhaseTimes::UpdateRS, worker_i); - { + if (ConcurrentG1Refine::hot_card_cache_enabled()) { // Apply the closure to the entries of the hot card cache. G1GCParPhaseTimesTracker y(_g1p->phase_times(), G1GCPhaseTimes::ScanHCC, worker_i); _g1->iterate_hcc_closure(&into_cset_update_rs_cl, worker_i); @@ -291,7 +291,6 @@ void G1RemSet::cleanup_after_oops_into_collection_set_do() { _g1->cleanUpCardTable(); DirtyCardQueueSet& into_cset_dcqs = _into_cset_dirty_card_queue_set; - int into_cset_n_buffers = into_cset_dcqs.completed_buffers_num(); if (_g1->evacuation_failed()) { double restore_remembered_set_start = os::elapsedTime(); diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp index b511b04617f..8df01b58511 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.cpp @@ -26,6 +26,8 @@ #include "gc/g1/g1CollectedHeap.inline.hpp" #include "gc/g1/g1CollectorPolicy.hpp" #include "gc/g1/g1YoungRemSetSamplingThread.hpp" +#include "gc/g1/heapRegion.inline.hpp" +#include "gc/g1/heapRegionRemSet.hpp" #include "gc/g1/suspendibleThreadSet.hpp" #include "runtime/mutexLocker.hpp" @@ -55,21 +57,21 @@ void G1YoungRemSetSamplingThread::stop() { } } -G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : ConcurrentGCThread() { - _monitor = new Monitor(Mutex::nonleaf, - "G1YoungRemSetSamplingThread monitor", - true, - Monitor::_safepoint_check_never); - +G1YoungRemSetSamplingThread::G1YoungRemSetSamplingThread() : + ConcurrentGCThread(), + _monitor(Mutex::nonleaf, + "G1YoungRemSetSamplingThread monitor", + true, + Monitor::_safepoint_check_never) { set_name("G1 Young RemSet Sampling"); create_and_start(); } void G1YoungRemSetSamplingThread::sleep_before_next_cycle() { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); + MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); if (!_should_terminate) { - intx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? - _monitor->wait(Mutex::_no_safepoint_check_flag, waitms); + uintx waitms = G1ConcRefinementServiceIntervalMillis; // 300, really should be? + _monitor.wait(Mutex::_no_safepoint_check_flag, waitms); } } @@ -90,8 +92,8 @@ void G1YoungRemSetSamplingThread::run_service() { } void G1YoungRemSetSamplingThread::stop_service() { - MutexLockerEx x(_monitor, Mutex::_no_safepoint_check_flag); - _monitor->notify(); + MutexLockerEx x(&_monitor, Mutex::_no_safepoint_check_flag); + _monitor.notify(); } void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() { @@ -100,22 +102,35 @@ void G1YoungRemSetSamplingThread::sample_young_list_rs_lengths() { G1CollectorPolicy* g1p = g1h->g1_policy(); if (g1p->adaptive_young_list_length()) { int regions_visited = 0; - g1h->young_list()->rs_length_sampling_init(); - while (g1h->young_list()->rs_length_sampling_more()) { - g1h->young_list()->rs_length_sampling_next(); + HeapRegion* hr = g1h->young_list()->first_region(); + size_t sampled_rs_lengths = 0; + + while (hr != NULL) { + size_t rs_length = hr->rem_set()->occupied(); + sampled_rs_lengths += rs_length; + + // The current region may not yet have been added to the + // incremental collection set (it gets added when it is + // retired as the current allocation region). + if (hr->in_collection_set()) { + // Update the collection set policy information for this region + g1p->update_incremental_cset_info(hr, rs_length); + } + ++regions_visited; // we try to yield every time we visit 10 regions if (regions_visited == 10) { if (sts.should_yield()) { sts.yield(); - // we just abandon the iteration - break; + // A gc may have occurred and our sampling data is stale and further + // traversal of the young list is unsafe + return; } regions_visited = 0; } + hr = hr->get_next_young_region(); } - - g1p->revise_young_list_target_length_if_necessary(); + g1p->revise_young_list_target_length_if_necessary(sampled_rs_lengths); } } diff --git a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp index d5837e42aee..78e82e7e352 100644 --- a/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp +++ b/hotspot/src/share/vm/gc/g1/g1YoungRemSetSamplingThread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,7 +41,7 @@ // increase the young gen size to keep pause time length goal. class G1YoungRemSetSamplingThread: public ConcurrentGCThread { private: - Monitor* _monitor; + Monitor _monitor; void sample_young_list_rs_lengths(); diff --git a/hotspot/src/share/vm/gc/g1/g1_globals.hpp b/hotspot/src/share/vm/gc/g1/g1_globals.hpp index 086e27bd589..7bc980e0fee 100644 --- a/hotspot/src/share/vm/gc/g1/g1_globals.hpp +++ b/hotspot/src/share/vm/gc/g1/g1_globals.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,10 +71,6 @@ "draining concurrent marking work queues.") \ range(1, max_intx) \ \ - experimental(bool, G1UseConcMarkReferenceProcessing, true, \ - "If true, enable reference discovery during concurrent " \ - "marking and reference processing at the end of remark.") \ - \ experimental(double, G1LastPLABAverageOccupancy, 50.0, \ "The expected average occupancy of the last PLAB in " \ "percent.") \ @@ -107,35 +103,35 @@ "Size of an update buffer") \ range(1, NOT_LP64(32*M) LP64_ONLY(1*G)) \ \ - product(intx, G1ConcRefinementYellowZone, 0, \ + product(size_t, G1ConcRefinementYellowZone, 0, \ "Number of enqueued update buffers that will " \ "trigger concurrent processing. Will be selected ergonomically " \ "by default.") \ range(0, max_intx) \ \ - product(intx, G1ConcRefinementRedZone, 0, \ + product(size_t, G1ConcRefinementRedZone, 0, \ "Maximum number of enqueued update buffers before mutator " \ "threads start processing new ones instead of enqueueing them. " \ "Will be selected ergonomically by default. Zero will disable " \ "concurrent processing.") \ range(0, max_intx) \ \ - product(intx, G1ConcRefinementGreenZone, 0, \ + product(size_t, G1ConcRefinementGreenZone, 0, \ "The number of update buffers that are left in the queue by the " \ "concurrent processing threads. Will be selected ergonomically " \ "by default.") \ range(0, max_intx) \ \ - product(intx, G1ConcRefinementServiceIntervalMillis, 300, \ + product(uintx, G1ConcRefinementServiceIntervalMillis, 300, \ "The last concurrent refinement thread wakes up every " \ "specified number of milliseconds to do miscellaneous work.") \ range(0, max_jint) \ \ - product(intx, G1ConcRefinementThresholdStep, 0, \ + product(size_t, G1ConcRefinementThresholdStep, 0, \ "Each time the rset update queue increases by this amount " \ "activate the next refinement thread if available. " \ "Will be selected ergonomically by default.") \ - range(0, max_jint) \ + range(0, SIZE_MAX) \ \ product(intx, G1RSetUpdatingPauseTimePercent, 10, \ "A target percentage of time that is allowed to be spend on " \ diff --git a/hotspot/src/share/vm/gc/g1/heapRegion.cpp b/hotspot/src/share/vm/gc/g1/heapRegion.cpp index 1c332adcdf1..42cb7d5928a 100644 --- a/hotspot/src/share/vm/gc/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc/g1/heapRegion.cpp @@ -781,7 +781,9 @@ public: ResourceMark rm; _containing_obj->print_on(log.error_stream()); log.error("points to obj " PTR_FORMAT " in region " HR_FORMAT, p2i(obj), HR_FORMAT_PARAMS(to)); - obj->print_on(log.error_stream()); + if (obj->is_oop()) { + obj->print_on(log.error_stream()); + } log.error("Obj head CTE = %d, field CTE = %d.", cv_obj, cv_field); log.error("----------"); _failures = true; diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp index 756b9599fb8..d6cf5c50e6a 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.cpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ #include "runtime/mutexLocker.hpp" #include "runtime/thread.inline.hpp" +#include + PtrQueue::PtrQueue(PtrQueueSet* qset, bool permanent, bool active) : _qset(qset), _buf(NULL), _index(0), _sz(0), _active(active), _permanent(permanent), _lock(NULL) @@ -87,6 +89,19 @@ void PtrQueue::locking_enqueue_completed_buffer(void** buf) { } +BufferNode* BufferNode::allocate(size_t byte_size) { + assert(byte_size > 0, "precondition"); + assert(is_size_aligned(byte_size, sizeof(void**)), + "Invalid buffer size " SIZE_FORMAT, byte_size); + void* data = NEW_C_HEAP_ARRAY(char, buffer_offset() + byte_size, mtGC); + return new (data) BufferNode; +} + +void BufferNode::deallocate(BufferNode* node) { + node->~BufferNode(); + FREE_C_HEAP_ARRAY(char, node); +} + PtrQueueSet::PtrQueueSet(bool notify_when_complete) : _max_completed_queue(0), _cbl_mon(NULL), _fl_lock(NULL), @@ -123,17 +138,23 @@ void PtrQueueSet::initialize(Monitor* cbl_mon, void** PtrQueueSet::allocate_buffer() { assert(_sz > 0, "Didn't set a buffer size."); - MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); - if (_fl_owner->_buf_free_list != NULL) { - void** res = BufferNode::make_buffer_from_node(_fl_owner->_buf_free_list); - _fl_owner->_buf_free_list = _fl_owner->_buf_free_list->next(); - _fl_owner->_buf_free_list_sz--; - return res; - } else { - // Allocate space for the BufferNode in front of the buffer. - char *b = NEW_C_HEAP_ARRAY(char, _sz + BufferNode::aligned_size(), mtGC); - return BufferNode::make_buffer_from_block(b); + BufferNode* node = NULL; + { + MutexLockerEx x(_fl_owner->_fl_lock, Mutex::_no_safepoint_check_flag); + node = _fl_owner->_buf_free_list; + if (node != NULL) { + _fl_owner->_buf_free_list = node->next(); + _fl_owner->_buf_free_list_sz--; + } } + if (node == NULL) { + node = BufferNode::allocate(_sz); + } else { + // Reinitialize buffer obtained from free list. + node->set_index(0); + node->set_next(NULL); + } + return BufferNode::make_buffer_from_node(node); } void PtrQueueSet::deallocate_buffer(void** buf) { @@ -150,13 +171,13 @@ void PtrQueueSet::reduce_free_list() { // For now we'll adopt the strategy of deleting half. MutexLockerEx x(_fl_lock, Mutex::_no_safepoint_check_flag); size_t n = _buf_free_list_sz / 2; - while (n > 0) { - assert(_buf_free_list != NULL, "_buf_free_list_sz must be wrong."); - void* b = BufferNode::make_block_from_node(_buf_free_list); - _buf_free_list = _buf_free_list->next(); - FREE_C_HEAP_ARRAY(char, b); - _buf_free_list_sz --; - n--; + for (size_t i = 0; i < n; ++i) { + assert(_buf_free_list != NULL, + "_buf_free_list_sz is wrong: " SIZE_FORMAT, _buf_free_list_sz); + BufferNode* node = _buf_free_list; + _buf_free_list = node->next(); + _buf_free_list_sz--; + BufferNode::deallocate(node); } } @@ -236,8 +257,9 @@ bool PtrQueueSet::process_or_enqueue_complete_buffer(void** buf) { void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - BufferNode* cbn = BufferNode::new_from_buffer(buf); + BufferNode* cbn = BufferNode::make_node_from_buffer(buf); cbn->set_index(index); + cbn->set_next(NULL); if (_completed_buffers_tail == NULL) { assert(_completed_buffers_head == NULL, "Well-formedness"); _completed_buffers_head = cbn; @@ -249,16 +271,17 @@ void PtrQueueSet::enqueue_complete_buffer(void** buf, size_t index) { _n_completed_buffers++; if (!_process_completed && _process_completed_threshold >= 0 && - _n_completed_buffers >= _process_completed_threshold) { + _n_completed_buffers >= (size_t)_process_completed_threshold) { _process_completed = true; - if (_notify_when_complete) + if (_notify_when_complete) { _cbl_mon->notify(); + } } DEBUG_ONLY(assert_completed_buffer_list_len_correct_locked()); } -int PtrQueueSet::completed_buffers_list_length() { - int n = 0; +size_t PtrQueueSet::completed_buffers_list_length() { + size_t n = 0; BufferNode* cbn = _completed_buffers_head; while (cbn != NULL) { n++; @@ -312,7 +335,8 @@ void PtrQueueSet::merge_bufferlists(PtrQueueSet *src) { void PtrQueueSet::notify_if_necessary() { MutexLockerEx x(_cbl_mon, Mutex::_no_safepoint_check_flag); - if (_n_completed_buffers >= _process_completed_threshold || _max_completed_queue == 0) { + assert(_process_completed_threshold >= 0, "_process_completed is negative"); + if (_n_completed_buffers >= (size_t)_process_completed_threshold || _max_completed_queue == 0) { _process_completed = true; if (_notify_when_complete) _cbl_mon->notify(); diff --git a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp index 707d591c0c0..4d5c5e6c28a 100644 --- a/hotspot/src/share/vm/gc/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc/g1/ptrQueue.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,9 +33,6 @@ // the addresses of modified old-generation objects. This type supports // this operation. -// The definition of placement operator new(size_t, void*) in the . -#include - class PtrQueueSet; class PtrQueue VALUE_OBJ_CLASS_SPEC { friend class VMStructs; @@ -168,42 +165,38 @@ protected: class BufferNode { size_t _index; BufferNode* _next; -public: + void* _buffer[1]; // Pseudo flexible array member. + BufferNode() : _index(0), _next(NULL) { } + ~BufferNode() { } + + static size_t buffer_offset() { + return offset_of(BufferNode, _buffer); + } + +public: BufferNode* next() const { return _next; } void set_next(BufferNode* n) { _next = n; } size_t index() const { return _index; } void set_index(size_t i) { _index = i; } - // Align the size of the structure to the size of the pointer - static size_t aligned_size() { - static const size_t alignment = round_to(sizeof(BufferNode), sizeof(void*)); - return alignment; + // Allocate a new BufferNode with the "buffer" having size bytes. + static BufferNode* allocate(size_t byte_size); + + // Free a BufferNode. + static void deallocate(BufferNode* node); + + // Return the BufferNode containing the buffer. + static BufferNode* make_node_from_buffer(void** buffer) { + return reinterpret_cast( + reinterpret_cast(buffer) - buffer_offset()); } - // BufferNode is allocated before the buffer. - // The chunk of memory that holds both of them is a block. - - // Produce a new BufferNode given a buffer. - static BufferNode* new_from_buffer(void** buf) { - return new (make_block_from_buffer(buf)) BufferNode; - } - - // The following are the required conversion routines: - static BufferNode* make_node_from_buffer(void** buf) { - return (BufferNode*)make_block_from_buffer(buf); - } + // Return the buffer for node. static void** make_buffer_from_node(BufferNode *node) { - return make_buffer_from_block(node); - } - static void* make_block_from_node(BufferNode *node) { - return (void*)node; - } - static void** make_buffer_from_block(void* p) { - return (void**)((char*)p + aligned_size()); - } - static void* make_block_from_buffer(void** p) { - return (void*)((char*)p - aligned_size()); + // &_buffer[0] might lead to index out of bounds warnings. + return reinterpret_cast( + reinterpret_cast(node) + buffer_offset()); } }; @@ -216,7 +209,7 @@ protected: Monitor* _cbl_mon; // Protects the fields below. BufferNode* _completed_buffers_head; BufferNode* _completed_buffers_tail; - int _n_completed_buffers; + size_t _n_completed_buffers; int _process_completed_threshold; volatile bool _process_completed; @@ -240,9 +233,9 @@ protected: // Maximum number of elements allowed on completed queue: after that, // enqueuer does the work itself. Zero indicates no maximum. int _max_completed_queue; - int _completed_queue_padding; + size_t _completed_queue_padding; - int completed_buffers_list_length(); + size_t completed_buffers_list_length(); void assert_completed_buffer_list_len_correct_locked(); void assert_completed_buffer_list_len_correct(); @@ -306,15 +299,15 @@ public: // list size may be reduced, if that is deemed desirable. void reduce_free_list(); - int completed_buffers_num() { return _n_completed_buffers; } + size_t completed_buffers_num() { return _n_completed_buffers; } void merge_bufferlists(PtrQueueSet* src); void set_max_completed_queue(int m) { _max_completed_queue = m; } int max_completed_queue() { return _max_completed_queue; } - void set_completed_queue_padding(int padding) { _completed_queue_padding = padding; } - int completed_queue_padding() { return _completed_queue_padding; } + void set_completed_queue_padding(size_t padding) { _completed_queue_padding = padding; } + size_t completed_queue_padding() { return _completed_queue_padding; } // Notify the consumer if the number of buffers crossed the threshold void notify_if_necessary(); diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp index 0e3305d5c2a..62b66559a53 100644 --- a/hotspot/src/share/vm/gc/g1/workerDataArray.cpp +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.cpp @@ -24,18 +24,53 @@ #include "precompiled.hpp" #include "gc/g1/workerDataArray.inline.hpp" +#include "utilities/ostream.hpp" + +template <> +void WorkerDataArray::WDAPrinter::summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum) { + out->print("%-25s Min: %4.1lf, Avg: %4.1lf, Max: %4.1lf, Diff: %4.1lf", title, min * MILLIUNITS, avg * MILLIUNITS, max * MILLIUNITS, diff* MILLIUNITS); + if (print_sum) { + out->print_cr(", Sum: %4.1lf", sum * MILLIUNITS); + } else { + out->cr(); + } +} + +template <> +void WorkerDataArray::WDAPrinter::summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum) { + out->print("%-25s Min: " SIZE_FORMAT ", Avg: %4.1lf, Max: " SIZE_FORMAT ", Diff: " SIZE_FORMAT, title, min, avg, max, diff); + if (print_sum) { + out->print_cr(", Sum: " SIZE_FORMAT, sum); + } else { + out->cr(); + } +} + +template <> +void WorkerDataArray::WDAPrinter::details(const WorkerDataArray* phase, outputStream* out, uint active_threads) { + out->print("%-25s", ""); + for (uint i = 0; i < active_threads; ++i) { + out->print(" %4.1lf", phase->get(i) * 1000.0); + } + out->cr(); +} + +template <> +void WorkerDataArray::WDAPrinter::details(const WorkerDataArray* phase, outputStream* out, uint active_threads) { + out->print("%-25s", ""); + for (uint i = 0; i < active_threads; ++i) { + out->print(" " SIZE_FORMAT, phase->get(i)); + } + out->cr(); +} #ifndef PRODUCT void WorkerDataArray_test() { const uint length = 3; const char* title = "Test array"; - const bool print_sum = false; - const uint indent_level = 2; - WorkerDataArray array(length, title, print_sum, indent_level); + WorkerDataArray array(length, title); assert(strncmp(array.title(), title, strlen(title)) == 0 , "Expected titles to match"); - assert(array.should_print_sum() == print_sum, "Expected should_print_sum to match print_sum"); - assert(array.indentation() == indent_level, "Expected indentation to match"); const size_t expected[length] = {5, 3, 7}; for (uint i = 0; i < length; i++) { @@ -46,10 +81,7 @@ void WorkerDataArray_test() { } assert(array.sum(length) == (5 + 3 + 7), "Expected sums to match"); - assert(array.minimum(length) == 3, "Expected mininum to match"); - assert(array.maximum(length) == 7, "Expected maximum to match"); - assert(array.diff(length) == (7 - 3), "Expected diffs to match"); - assert(array.average(length) == 5, "Expected averages to match"); + assert(array.average(length) == 5.0, "Expected averages to match"); for (uint i = 0; i < length; i++) { array.add(i, 1); diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp index 09f0b61a5f7..e1e972327ea 100644 --- a/hotspot/src/share/vm/gc/g1/workerDataArray.hpp +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.hpp @@ -22,18 +22,19 @@ * */ +#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_HPP +#define SHARE_VM_GC_G1_WORKERDATAARRAY_HPP + #include "memory/allocation.hpp" #include "utilities/debug.hpp" +class outputStream; + template class WorkerDataArray : public CHeapObj { - friend class G1GCParPhasePrinter; T* _data; uint _length; const char* _title; - bool _print_sum; - uint _indent_level; - bool _enabled; WorkerDataArray* _thread_work_items; @@ -42,11 +43,7 @@ class WorkerDataArray : public CHeapObj { void set_all(T value); public: - WorkerDataArray(uint length, - const char* title, - bool print_sum, - uint indent_level); - + WorkerDataArray(uint length, const char* title); ~WorkerDataArray(); void link_thread_work_items(WorkerDataArray* thread_work_items); @@ -62,27 +59,30 @@ class WorkerDataArray : public CHeapObj { double average(uint active_threads) const; T sum(uint active_threads) const; - T minimum(uint active_threads) const; - T maximum(uint active_threads) const; - T diff(uint active_threads) const; - - uint indentation() const { - return _indent_level; - } const char* title() const { return _title; } - bool should_print_sum() const { - return _print_sum; - } - void clear(); - void set_enabled(bool enabled) { - _enabled = enabled; - } void reset() PRODUCT_RETURN; void verify(uint active_threads) const PRODUCT_RETURN; + + + private: + class WDAPrinter { + public: + static void summary(outputStream* out, const char* title, double min, double avg, double max, double diff, double sum, bool print_sum); + static void summary(outputStream* out, const char* title, size_t min, double avg, size_t max, size_t diff, size_t sum, bool print_sum); + + static void details(const WorkerDataArray* phase, outputStream* out, uint active_threads); + static void details(const WorkerDataArray* phase, outputStream* out, uint active_threads); + }; + + public: + void print_summary_on(outputStream* out, uint active_threads, bool print_sum = true) const; + void print_details_on(outputStream* out, uint active_threads) const; }; + +#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_HPP diff --git a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp index 713eb125cff..7b4df8628b8 100644 --- a/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp +++ b/hotspot/src/share/vm/gc/g1/workerDataArray.inline.hpp @@ -22,20 +22,18 @@ * */ +#ifndef SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP +#define SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP + #include "gc/g1/workerDataArray.hpp" #include "memory/allocation.inline.hpp" +#include "utilities/ostream.hpp" template -WorkerDataArray::WorkerDataArray(uint length, - const char* title, - bool print_sum, - uint indent_level) : +WorkerDataArray::WorkerDataArray(uint length, const char* title) : _title(title), _length(0), - _print_sum(print_sum), - _indent_level(indent_level), - _thread_work_items(NULL), - _enabled(true) { + _thread_work_items(NULL) { assert(length > 0, "Must have some workers to store data for"); _length = length; _data = NEW_C_HEAP_ARRAY(T, _length, mtGC); @@ -93,29 +91,6 @@ T WorkerDataArray::sum(uint active_threads) const { return s; } -template -T WorkerDataArray::minimum(uint active_threads) const { - T min = get(0); - for (uint i = 1; i < active_threads; ++i) { - min = MIN2(min, get(i)); - } - return min; -} - -template -T WorkerDataArray::maximum(uint active_threads) const { - T max = get(0); - for (uint i = 1; i < active_threads; ++i) { - max = MAX2(max, get(i)); - } - return max; -} - -template -T WorkerDataArray::diff(uint active_threads) const { - return maximum(active_threads) - minimum(active_threads); -} - template void WorkerDataArray::clear() { set_all(0); @@ -128,6 +103,27 @@ void WorkerDataArray::set_all(T value) { } } +template +void WorkerDataArray::print_summary_on(outputStream* out, uint active_threads, bool print_sum) const { + T max = get(0); + T min = max; + T sum = 0; + for (uint i = 1; i < active_threads; ++i) { + T value = get(i); + max = MAX2(max, value); + min = MIN2(min, value); + sum += value; + } + T diff = max - min; + double avg = sum / (double) active_threads; + WDAPrinter::summary(out, title(), min, avg, max, diff, sum, print_sum); +} + +template +void WorkerDataArray::print_details_on(outputStream* out, uint active_threads) const { + WDAPrinter::details(this, out, active_threads); +} + #ifndef PRODUCT template void WorkerDataArray::reset() { @@ -139,10 +135,6 @@ void WorkerDataArray::reset() { template void WorkerDataArray::verify(uint active_threads) const { - if (!_enabled) { - return; - } - assert(active_threads <= _length, "Wrong number of active threads"); for (uint i = 0; i < active_threads; i++) { assert(_data[i] != uninitialized(), @@ -163,3 +155,5 @@ inline double WorkerDataArray::uninitialized() const { return -1.0; } #endif + +#endif // SHARE_VM_GC_G1_WORKERDATAARRAY_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/g1/youngList.cpp b/hotspot/src/share/vm/gc/g1/youngList.cpp index 3d95e8ff93a..25b9d21d4fa 100644 --- a/hotspot/src/share/vm/gc/g1/youngList.cpp +++ b/hotspot/src/share/vm/gc/g1/youngList.cpp @@ -33,9 +33,9 @@ #include "utilities/ostream.hpp" YoungList::YoungList(G1CollectedHeap* g1h) : - _g1h(g1h), _head(NULL), _length(0), _last_sampled_rs_lengths(0), + _g1h(g1h), _head(NULL), _length(0), _survivor_head(NULL), _survivor_tail(NULL), _survivor_length(0) { - guarantee(check_list_empty(false), "just making sure..."); + guarantee(check_list_empty(), "just making sure..."); } void YoungList::push_region(HeapRegion *hr) { @@ -86,9 +86,7 @@ void YoungList::empty_list() { _survivor_tail = NULL; _survivor_length = 0; - _last_sampled_rs_lengths = 0; - - assert(check_list_empty(false), "just making sure..."); + assert(check_list_empty(), "just making sure..."); } bool YoungList::check_list_well_formed() { @@ -119,17 +117,13 @@ bool YoungList::check_list_well_formed() { return ret; } -bool YoungList::check_list_empty(bool check_sample) { +bool YoungList::check_list_empty() { bool ret = true; if (_length != 0) { log_error(gc, verify)("### YOUNG LIST should have 0 length, not %u", _length); ret = false; } - if (check_sample && _last_sampled_rs_lengths != 0) { - log_error(gc, verify)("### YOUNG LIST has non-zero last sampled RS lengths"); - ret = false; - } if (_head != NULL) { log_error(gc, verify)("### YOUNG LIST does not have a NULL head"); ret = false; @@ -141,38 +135,6 @@ bool YoungList::check_list_empty(bool check_sample) { return ret; } -void -YoungList::rs_length_sampling_init() { - _sampled_rs_lengths = 0; - _curr = _head; -} - -bool -YoungList::rs_length_sampling_more() { - return _curr != NULL; -} - -void -YoungList::rs_length_sampling_next() { - assert( _curr != NULL, "invariant" ); - size_t rs_length = _curr->rem_set()->occupied(); - - _sampled_rs_lengths += rs_length; - - // The current region may not yet have been added to the - // incremental collection set (it gets added when it is - // retired as the current allocation region). - if (_curr->in_collection_set()) { - // Update the collection set policy information for this region - _g1h->g1_policy()->update_incremental_cset_info(_curr, rs_length); - } - - _curr = _curr->get_next_young_region(); - if (_curr == NULL) { - _last_sampled_rs_lengths = _sampled_rs_lengths; - } -} - void YoungList::reset_auxilary_lists() { guarantee( is_empty(), "young list should be empty" ); diff --git a/hotspot/src/share/vm/gc/g1/youngList.hpp b/hotspot/src/share/vm/gc/g1/youngList.hpp index 36108b807db..1030b3f9c1c 100644 --- a/hotspot/src/share/vm/gc/g1/youngList.hpp +++ b/hotspot/src/share/vm/gc/g1/youngList.hpp @@ -37,14 +37,9 @@ private: HeapRegion* _survivor_head; HeapRegion* _survivor_tail; - HeapRegion* _curr; - uint _length; uint _survivor_length; - size_t _last_sampled_rs_lengths; - size_t _sampled_rs_lengths; - void empty_list(HeapRegion* list); public: @@ -72,15 +67,6 @@ public: return (size_t) survivor_length() * HeapRegion::GrainBytes; } - void rs_length_sampling_init(); - bool rs_length_sampling_more(); - void rs_length_sampling_next(); - - void reset_sampled_info() { - _last_sampled_rs_lengths = 0; - } - size_t sampled_rs_lengths() { return _last_sampled_rs_lengths; } - // for development purposes void reset_auxilary_lists(); void clear() { _head = NULL; _length = 0; } @@ -97,7 +83,7 @@ public: // debugging bool check_list_well_formed(); - bool check_list_empty(bool check_sample = true); + bool check_list_empty(); void print(); }; diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp index 9c00cd90383..08a21b2634f 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp @@ -36,6 +36,7 @@ #include "gc/shared/genCollectedHeap.hpp" #include "gc/shared/genOopClosures.inline.hpp" #include "gc/shared/generationSpec.hpp" +#include "gc/shared/preservedMarks.inline.hpp" #include "gc/shared/referencePolicy.hpp" #include "gc/shared/space.inline.hpp" #include "gc/shared/spaceDecorator.hpp" @@ -184,6 +185,7 @@ DefNewGeneration::DefNewGeneration(ReservedSpace rs, size_t initial_size, const char* policy) : Generation(rs, initial_size), + _preserved_marks_set(false /* in_c_heap */), _promo_failure_drain_in_progress(false), _should_allocate_from_space(false) { @@ -602,6 +604,8 @@ void DefNewGeneration::collect(bool full, age_table()->clear(); to()->clear(SpaceDecorator::Mangle); + // The preserved marks should be empty at the start of the GC. + _preserved_marks_set.init(1); gch->rem_set()->prepare_for_younger_refs_iterate(false); @@ -704,6 +708,8 @@ void DefNewGeneration::collect(bool full, // Reset the PromotionFailureALot counters. NOT_PRODUCT(gch->reset_promotion_should_fail();) } + // We should have processed and cleared all the preserved marks. + _preserved_marks_set.reclaim(); // set new iteration safe limit for the survivor spaces from()->set_concurrent_iteration_safe_limit(from()->top()); to()->set_concurrent_iteration_safe_limit(to()->top()); @@ -721,13 +727,6 @@ void DefNewGeneration::collect(bool full, gc_tracer.report_gc_end(_gc_timer->gc_end(), _gc_timer->time_partitions()); } -class RemoveForwardPointerClosure: public ObjectClosure { -public: - void do_object(oop obj) { - obj->init_mark(); - } -}; - void DefNewGeneration::init_assuming_no_promotion_failure() { _promotion_failed = false; _promotion_failed_info.reset(); @@ -735,33 +734,12 @@ void DefNewGeneration::init_assuming_no_promotion_failure() { } void DefNewGeneration::remove_forwarding_pointers() { - RemoveForwardPointerClosure rspc; + RemoveForwardedPointerClosure rspc; eden()->object_iterate(&rspc); from()->object_iterate(&rspc); // Now restore saved marks, if any. - assert(_objs_with_preserved_marks.size() == _preserved_marks_of_objs.size(), - "should be the same"); - while (!_objs_with_preserved_marks.is_empty()) { - oop obj = _objs_with_preserved_marks.pop(); - markOop m = _preserved_marks_of_objs.pop(); - obj->set_mark(m); - } - _objs_with_preserved_marks.clear(true); - _preserved_marks_of_objs.clear(true); -} - -void DefNewGeneration::preserve_mark(oop obj, markOop m) { - assert(_promotion_failed && m->must_be_preserved_for_promotion_failure(obj), - "Oversaving!"); - _objs_with_preserved_marks.push(obj); - _preserved_marks_of_objs.push(m); -} - -void DefNewGeneration::preserve_mark_if_necessary(oop obj, markOop m) { - if (m->must_be_preserved_for_promotion_failure(obj)) { - preserve_mark(obj, m); - } + _preserved_marks_set.restore(); } void DefNewGeneration::handle_promotion_failure(oop old) { @@ -769,7 +747,7 @@ void DefNewGeneration::handle_promotion_failure(oop old) { _promotion_failed = true; _promotion_failed_info.register_copy_failure(old->size()); - preserve_mark_if_necessary(old, old->mark()); + _preserved_marks_set.get()->push_if_necessary(old, old->mark()); // forward to self old->forward_to(old); diff --git a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp index 484a6b6aa52..f258491ae32 100644 --- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp +++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp @@ -30,6 +30,7 @@ #include "gc/shared/copyFailedInfo.hpp" #include "gc/shared/generation.hpp" #include "gc/shared/generationCounters.hpp" +#include "gc/shared/preservedMarks.hpp" #include "utilities/stack.hpp" class ContiguousSpace; @@ -87,15 +88,8 @@ protected: // therefore we must remove their forwarding pointers. void remove_forwarding_pointers(); - // Preserve the mark of "obj", if necessary, in preparation for its mark - // word being overwritten with a self-forwarding-pointer. - void preserve_mark_if_necessary(oop obj, markOop m); - void preserve_mark(oop obj, markOop m); // work routine used by the above - - // Together, these keep pairs. - // They should always contain the same number of elements. - Stack _objs_with_preserved_marks; - Stack _preserved_marks_of_objs; + // Preserved marks + PreservedMarksSet _preserved_marks_set; // Promotion failure handling ExtendedOopClosure *_promo_failure_scan_stack_closure; diff --git a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp index 9bba8daf55e..f132d75e860 100644 --- a/hotspot/src/share/vm/gc/shared/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc/shared/collectedHeap.cpp @@ -405,7 +405,9 @@ size_t CollectedHeap::max_tlab_size() const { oop CollectedHeap::new_store_pre_barrier(JavaThread* thread, oop new_obj) { // If a previous card-mark was deferred, flush it now. flush_deferred_store_barrier(thread); - if (can_elide_initializing_store_barrier(new_obj)) { + if (can_elide_initializing_store_barrier(new_obj) || + new_obj->is_typeArray()) { + // Arrays of non-references don't need a pre-barrier. // The deferred_card_mark region should be empty // following the flush above. assert(thread->deferred_card_mark().is_empty(), "Error"); diff --git a/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp b/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp index 6a6a64e31eb..b7e0bbe98b0 100644 --- a/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp +++ b/hotspot/src/share/vm/gc/shared/copyFailedInfo.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ #define SHARE_VM_GC_SHARED_COPYFAILEDINFO_HPP #include "runtime/thread.hpp" +#include "trace/traceMacros.hpp" #include "utilities/globalDefinitions.hpp" class CopyFailedInfo : public CHeapObj { @@ -63,26 +64,28 @@ class CopyFailedInfo : public CHeapObj { }; class PromotionFailedInfo : public CopyFailedInfo { - OSThread* _thread; + traceid _thread_trace_id; public: - PromotionFailedInfo() : CopyFailedInfo(), _thread(NULL) {} + PromotionFailedInfo() : CopyFailedInfo(), _thread_trace_id(0) {} void register_copy_failure(size_t size) { CopyFailedInfo::register_copy_failure(size); - if (_thread == NULL) { - _thread = Thread::current()->osthread(); + if (_thread_trace_id == 0) { + _thread_trace_id = THREAD_TRACE_ID(Thread::current()); } else { - assert(_thread == Thread::current()->osthread(), "The PromotionFailedInfo should be thread local."); + assert(THREAD_TRACE_ID(Thread::current()) == _thread_trace_id, + "The PromotionFailedInfo should be thread local."); } } void reset() { CopyFailedInfo::reset(); - _thread = NULL; + _thread_trace_id = 0; } - OSThread* thread() const { return _thread; } + traceid thread_trace_id() const { return _thread_trace_id; } + }; class EvacuationFailedInfo : public CopyFailedInfo {}; diff --git a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp index 0bd6fef7471..db538eb4f41 100644 --- a/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp +++ b/hotspot/src/share/vm/gc/shared/gcTraceSend.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -174,7 +174,7 @@ void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_in if (e.should_commit()) { e.set_gcId(GCId::current()); e.set_data(to_trace_struct(pf_info)); - e.set_thread(pf_info.thread()->thread_id()); + e.set_thread(pf_info.thread_trace_id()); e.commit(); } } diff --git a/hotspot/src/share/vm/gc/shared/plab.cpp b/hotspot/src/share/vm/gc/shared/plab.cpp index d8566523e7c..1743bffb089 100644 --- a/hotspot/src/share/vm/gc/shared/plab.cpp +++ b/hotspot/src/share/vm/gc/shared/plab.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,6 +110,30 @@ void PLAB::undo_allocation(HeapWord* obj, size_t word_sz) { } } +void PLABStats::log_plab_allocation() { + log_debug(gc, plab)("%s PLAB allocation: " + "allocated: " SIZE_FORMAT "B, " + "wasted: " SIZE_FORMAT "B, " + "unused: " SIZE_FORMAT "B, " + "used: " SIZE_FORMAT "B, " + "undo waste: " SIZE_FORMAT "B, ", + _description, + _allocated * HeapWordSize, + _wasted * HeapWordSize, + _unused * HeapWordSize, + used() * HeapWordSize, + _undo_wasted * HeapWordSize); +} + +void PLABStats::log_sizing(size_t calculated_words, size_t net_desired_words) { + log_debug(gc, plab)("%s sizing: " + "calculated: " SIZE_FORMAT "B, " + "actual: " SIZE_FORMAT "B", + _description, + calculated_words * HeapWordSize, + net_desired_words * HeapWordSize); +} + // Calculates plab size for current number of gc worker threads. size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) { return MAX2(min_size(), (size_t)align_object_size(_desired_net_plab_sz / no_of_gc_workers)); @@ -119,7 +143,13 @@ size_t PLABStats::desired_plab_sz(uint no_of_gc_workers) { // use. This should be called once at the end of parallel // scavenge; it clears the sensor accumulators. void PLABStats::adjust_desired_plab_sz() { - assert(ResizePLAB, "Not set"); + log_plab_allocation(); + + if (!ResizePLAB) { + // Clear accumulators for next round. + reset(); + return; + } assert(is_object_aligned(max_size()) && min_size() <= max_size(), "PLAB clipping computation may be incorrect"); @@ -150,8 +180,9 @@ void PLABStats::adjust_desired_plab_sz() { new_plab_sz = MIN2(max_size(), new_plab_sz); new_plab_sz = align_object_size(new_plab_sz); // Latch the result - log_trace(gc, plab)("plab_size = " SIZE_FORMAT " desired_net_plab_sz = " SIZE_FORMAT ") ", recent_plab_sz, new_plab_sz); _desired_net_plab_sz = new_plab_sz; + log_sizing(recent_plab_sz, new_plab_sz); + reset(); } diff --git a/hotspot/src/share/vm/gc/shared/plab.hpp b/hotspot/src/share/vm/gc/shared/plab.hpp index b684769ed61..e73562b301f 100644 --- a/hotspot/src/share/vm/gc/shared/plab.hpp +++ b/hotspot/src/share/vm/gc/shared/plab.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -146,6 +146,8 @@ public: // PLAB book-keeping. class PLABStats : public CHeapObj { protected: + const char* _description; // Identifying string. + size_t _allocated; // Total allocated size_t _wasted; // of which wasted (internal fragmentation) size_t _undo_wasted; // of which wasted on undo (is not used for calculation of PLAB size) @@ -160,8 +162,12 @@ class PLABStats : public CHeapObj { _undo_wasted = 0; _unused = 0; } + + virtual void log_plab_allocation(); + virtual void log_sizing(size_t calculated, size_t net_desired); public: - PLABStats(size_t desired_net_plab_sz_, unsigned wt) : + PLABStats(const char* description, size_t desired_net_plab_sz_, unsigned wt) : + _description(description), _allocated(0), _wasted(0), _undo_wasted(0), @@ -172,6 +178,12 @@ class PLABStats : public CHeapObj { virtual ~PLABStats() { } + size_t allocated() const { return _allocated; } + size_t wasted() const { return _wasted; } + size_t unused() const { return _unused; } + size_t used() const { return allocated() - (wasted() + unused()); } + size_t undo_wasted() const { return _undo_wasted; } + static const size_t min_size() { return PLAB::min_size(); } diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.cpp b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp new file mode 100644 index 00000000000..a82c8dd7bd4 --- /dev/null +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.cpp @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc/shared/preservedMarks.inline.hpp" +#include "memory/allocation.inline.hpp" +#include "oops/oop.inline.hpp" + +void PreservedMarks::restore() { + // First, iterate over the stack and restore all marks. + StackIterator iter(_stack); + while (!iter.is_empty()) { + OopAndMarkOop elem = iter.next(); + elem.set_mark(); + } + + // Second, reclaim all the stack memory + _stack.clear(true /* clear_cache */); +} + +void RemoveForwardedPointerClosure::do_object(oop obj) { + if (obj->is_forwarded()) { + obj->init_mark(); + } +} + +void PreservedMarksSet::init(uint num) { + assert(_stacks == NULL && _num == 0, "do not re-initialize"); + assert(num > 0, "pre-condition"); + if (_in_c_heap) { + _stacks = NEW_C_HEAP_ARRAY(Padded, num, mtGC); + } else { + _stacks = NEW_RESOURCE_ARRAY(Padded, num); + } + for (uint i = 0; i < num; i += 1) { + ::new (_stacks + i) PreservedMarks(); + } + _num = num; + + assert_empty(); +} + +void PreservedMarksSet::restore() { + for (uint i = 0; i < _num; i += 1) { + get(i)->restore(); + } +} + +void PreservedMarksSet::reclaim() { + assert_empty(); + + for (uint i = 0; i < _num; i += 1) { + _stacks[i].~Padded(); + } + + if (_in_c_heap) { + FREE_C_HEAP_ARRAY(Padded, _stacks); + } else { + // the array was resource-allocated, so nothing to do + } + _stacks = NULL; + _num = 0; +} + +#ifndef PRODUCT +void PreservedMarksSet::assert_empty() { + assert(_stacks != NULL && _num > 0, "should have been initialized"); + for (uint i = 0; i < _num; i += 1) { + assert(get(i)->is_empty(), "stack should be empty"); + } +} +#endif // ndef PRODUCT diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp new file mode 100644 index 00000000000..42576d18f38 --- /dev/null +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.hpp @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP +#define SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP + +#include "memory/allocation.hpp" +#include "memory/padded.hpp" +#include "oops/oop.hpp" +#include "utilities/stack.hpp" + +class OopAndMarkOop { +private: + oop _o; + markOop _m; + +public: + OopAndMarkOop(oop obj, markOop m) : _o(obj), _m(m) { } + + void set_mark() const { + _o->set_mark(_m); + } +}; +typedef Stack OopAndMarkOopStack; + +class PreservedMarks VALUE_OBJ_CLASS_SPEC { +private: + OopAndMarkOopStack _stack; + + inline bool should_preserve_mark(oop obj, markOop m) const; + inline void push(oop obj, markOop m); + +public: + bool is_empty() const { return _stack.is_empty(); } + inline void push_if_necessary(oop obj, markOop m); + // Iterate over the stack, restore the preserved marks, then reclaim + // the memory taken up by stack chunks. + void restore(); + ~PreservedMarks() { assert(is_empty(), "should have been cleared"); } +}; + +class RemoveForwardedPointerClosure: public ObjectClosure { +public: + virtual void do_object(oop obj); +}; + +class PreservedMarksSet VALUE_OBJ_CLASS_SPEC { +private: + // true -> _stacks will be allocated in the C heap + // false -> _stacks will be allocated in the resource arena + const bool _in_c_heap; + + // Number of stacks we have allocated (typically, one stack per GC worker). + // This should be >= 1 if the stacks have been initialized, + // or == 0 if they have not. + uint _num; + + // Stack array (typically, one stack per GC worker) of length _num. + // This should be != NULL if the stacks have been initialized, + // or == NULL if they have not. + Padded* _stacks; + +public: + // Return the i'th stack. + PreservedMarks* get(uint i = 0) const { + assert(_num > 0 && _stacks != NULL, "stacks should have been initialized"); + assert(i < _num, "pre-condition"); + return (_stacks + i); + } + + // Allocate stack array. + void init(uint num); + // Iterate over all stacks, restore all preserved marks, then + // reclaim the memory taken up by stack chunks. + void restore(); + // Reclaim stack array. + void reclaim(); + + // Assert all the stacks are empty. + void assert_empty() PRODUCT_RETURN; + + PreservedMarksSet(bool in_c_heap) + : _in_c_heap(in_c_heap), _num(0), _stacks(NULL) { } + + ~PreservedMarksSet() { + assert(_stacks == NULL && _num == 0, "stacks should have been reclaimed"); + } +}; + +#endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_HPP diff --git a/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp new file mode 100644 index 00000000000..32c83115a69 --- /dev/null +++ b/hotspot/src/share/vm/gc/shared/preservedMarks.inline.hpp @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "gc/shared/preservedMarks.hpp" +#include "oops/markOop.inline.hpp" +#include "utilities/stack.inline.hpp" + +#ifndef SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP +#define SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP + +inline bool PreservedMarks::should_preserve_mark(oop obj, markOop m) const { + return m->must_be_preserved_for_promotion_failure(obj); +} + +inline void PreservedMarks::push(oop obj, markOop m) { + assert(should_preserve_mark(obj, m), "pre-condition"); + OopAndMarkOop elem(obj, m); + _stack.push(elem); +} + +inline void PreservedMarks::push_if_necessary(oop obj, markOop m) { + if (should_preserve_mark(obj, m)) { + push(obj, m); + } +} + +#endif // SHARE_VM_GC_SHARED_PRESERVEDMARKS_INLINE_HPP diff --git a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp index 544cf81001d..7b3616ff168 100644 --- a/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp +++ b/hotspot/src/share/vm/gc/shared/referenceProcessor.cpp @@ -339,7 +339,7 @@ void ReferenceProcessor::enqueue_discovered_reflist(DiscoveredList& refs_list, // all linked Reference objects. Note that it is important to not dirty any // cards during reference processing since this will cause card table // verification to fail for G1. - log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(refs_list.head())); + log_develop_trace(gc, ref)("ReferenceProcessor::enqueue_discovered_reflist list " INTPTR_FORMAT, p2i(&refs_list)); oop obj = NULL; oop next_d = refs_list.head(); @@ -502,7 +502,7 @@ ReferenceProcessor::process_phase1(DiscoveredList& refs_list, // Close the reachable set complete_gc->do_void(); log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " dead Refs out of " SIZE_FORMAT " discovered Refs by policy, from list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } // Traverse the list and remove any Refs that are not active, or @@ -536,7 +536,7 @@ ReferenceProcessor::pp2_work(DiscoveredList& refs_list, if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } ) } @@ -575,7 +575,7 @@ ReferenceProcessor::pp2_work_concurrent_discovery(DiscoveredList& refs_list, if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " active Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } ) } @@ -1198,7 +1198,7 @@ ReferenceProcessor::preclean_discovered_reflist(DiscoveredList& refs_list, NOT_PRODUCT( if (iter.processed() > 0) { log_develop_trace(gc, ref)(" Dropped " SIZE_FORMAT " Refs out of " SIZE_FORMAT " Refs in discovered list " INTPTR_FORMAT, - iter.removed(), iter.processed(), p2i(refs_list.head())); + iter.removed(), iter.processed(), p2i(&refs_list)); } ) } diff --git a/hotspot/src/share/vm/gc/shared/workgroup.hpp b/hotspot/src/share/vm/gc/shared/workgroup.hpp index b2a48647cab..c28579ef471 100644 --- a/hotspot/src/share/vm/gc/shared/workgroup.hpp +++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp @@ -29,6 +29,7 @@ #include "runtime/globals.hpp" #include "runtime/thread.hpp" #include "gc/shared/gcId.hpp" +#include "logging/log.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" @@ -151,6 +152,7 @@ class AbstractWorkGang : public CHeapObj { _active_workers = MAX2(1U, _active_workers); assert(UseDynamicNumberOfGCThreads || _active_workers == _total_workers, "Unless dynamic should use total workers"); + log_info(gc, task)("GC Workers: %d", _active_workers); } // Return the Ith worker. diff --git a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp index cbcfccbd759..2dcef77ef53 100644 --- a/hotspot/src/share/vm/interpreter/cppInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/cppInterpreter.cpp @@ -27,6 +27,7 @@ #include "interpreter/cppInterpreterGenerator.hpp" #include "interpreter/interpreter.hpp" #include "interpreter/interpreterRuntime.hpp" +#include "runtime/logTimer.hpp" #ifdef CC_INTERP @@ -42,7 +43,7 @@ void CppInterpreter::initialize() { // generate interpreter { ResourceMark rm; - TraceTime timer("Interpreter generation", TraceStartupTime); + TraceStartupTime timer("Interpreter generation"); int code_size = InterpreterCodeSize; NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space _code = new StubQueue(new InterpreterCodeletInterface, code_size, NULL, diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 166390d8d6b..839eec62153 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -762,14 +762,6 @@ void InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes::Code byte ConstantPoolCacheEntry* cp_cache_entry = cache_entry(thread); if (cp_cache_entry->is_resolved(bytecode)) return; - if (bytecode == Bytecodes::_invokeinterface) { - if (log_develop_is_enabled(Trace, itables)) { - ResourceMark rm(thread); - log_develop_trace(itables)("Resolving: klass: %s to method: %s", - info.resolved_klass()->name()->as_C_string(), - info.resolved_method()->name()->as_C_string()); - } - } #ifdef ASSERT if (bytecode == Bytecodes::_invokeinterface) { if (info.resolved_method()->method_holder() == diff --git a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp index c68f6858da6..8c2363be0d8 100644 --- a/hotspot/src/share/vm/interpreter/templateInterpreter.cpp +++ b/hotspot/src/share/vm/interpreter/templateInterpreter.cpp @@ -31,6 +31,7 @@ #include "interpreter/templateInterpreterGenerator.hpp" #include "interpreter/templateTable.hpp" #include "memory/resourceArea.hpp" +#include "runtime/logTimer.hpp" #ifndef CC_INTERP @@ -48,7 +49,7 @@ void TemplateInterpreter::initialize() { // generate interpreter { ResourceMark rm; - TraceTime timer("Interpreter generation", TraceStartupTime); + TraceStartupTime timer("Interpreter generation"); int code_size = InterpreterCodeSize; NOT_PRODUCT(code_size *= 4;) // debug uses extra interpreter code space #if INCLUDE_JVMTI diff --git a/hotspot/src/share/vm/interpreter/templateTable.cpp b/hotspot/src/share/vm/interpreter/templateTable.cpp index ddd7fc6470c..c71ebd28263 100644 --- a/hotspot/src/share/vm/interpreter/templateTable.cpp +++ b/hotspot/src/share/vm/interpreter/templateTable.cpp @@ -26,8 +26,7 @@ #include "gc/shared/collectedHeap.hpp" #include "interpreter/interp_masm.hpp" #include "interpreter/templateTable.hpp" -#include "runtime/timer.hpp" - +#include "runtime/logTimer.hpp" #ifdef CC_INTERP @@ -246,7 +245,7 @@ void TemplateTable::initialize() { if (_is_initialized) return; // Initialize table - TraceTime timer("TemplateTable initialization", TraceStartupTime); + TraceStartupTime timer("TemplateTable initialization"); _bs = Universe::heap()->barrier_set(); diff --git a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp index cb06c34d4b6..2043b59d5e1 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCodeInstaller.cpp @@ -551,6 +551,14 @@ JVMCIEnv::CodeInstallResult CodeInstaller::install(JVMCICompiler* compiler, Hand compiler, _debug_recorder, _dependencies, env, id, has_unsafe_access, _has_wide_vector, installed_code, compiled_code, speculation_log); cb = nm; + if (nm != NULL && env == NULL) { + DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, compiler); + bool printnmethods = directive->PrintAssemblyOption || directive->PrintNMethodsOption; + if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) { + nm->print_nmethod(printnmethods); + } + DirectivesStack::release(directive); + } } if (cb != NULL) { diff --git a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp index 429ccabbe6c..e84d4b319c5 100644 --- a/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciCompiler.cpp @@ -162,6 +162,9 @@ void JVMCICompiler::compile_method(const methodHandle& method, int entry_bci, JV CLEAR_PENDING_EXCEPTION; java_lang_Throwable::java_printStackTrace(exception, THREAD); + if (HAS_PENDING_EXCEPTION) { + CLEAR_PENDING_EXCEPTION; + } env->set_failure("exception throw", false); } else { diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp index 716f73c06b1..367afbf36e1 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.cpp @@ -51,7 +51,6 @@ jobject JVMCIRuntime::_HotSpotJVMCIRuntime_instance = NULL; bool JVMCIRuntime::_HotSpotJVMCIRuntime_initialized = false; bool JVMCIRuntime::_well_known_classes_initialized = false; -const char* JVMCIRuntime::_compiler = NULL; int JVMCIRuntime::_trivial_prefixes_count = 0; char** JVMCIRuntime::_trivial_prefixes = NULL; bool JVMCIRuntime::_shutdown_called = false; @@ -104,6 +103,7 @@ static void deopt_caller() { JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_instance(JavaThread* thread, Klass* klass)) JRT_BLOCK; assert(klass->is_klass(), "not a class"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive instanceKlassHandle h(thread, klass); h->check_valid_for_instantiation(true, CHECK); // make sure klass is initialized @@ -129,6 +129,7 @@ JRT_BLOCK_ENTRY(void, JVMCIRuntime::new_array(JavaThread* thread, Klass* array_k BasicType elt_type = TypeArrayKlass::cast(array_klass)->element_type(); obj = oopFactory::new_typeArray(elt_type, length, CHECK); } else { + Handle holder(THREAD, array_klass->klass_holder()); // keep the klass alive Klass* elem_klass = ObjArrayKlass::cast(array_klass)->element_klass(); obj = oopFactory::new_objArray(elem_klass, length, CHECK); } @@ -172,6 +173,7 @@ void JVMCIRuntime::new_store_pre_barrier(JavaThread* thread) { JRT_ENTRY(void, JVMCIRuntime::new_multi_array(JavaThread* thread, Klass* klass, int rank, jint* dims)) assert(klass->is_klass(), "not a class"); assert(rank >= 1, "rank must be nonzero"); + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(klass)->multi_allocate(rank, dims, CHECK); thread->set_vm_result(obj); JRT_END @@ -293,13 +295,11 @@ JRT_ENTRY_NO_ASYNC(static address, exception_handler_for_pc_helper(JavaThread* t // tracing if (log_is_enabled(Info, exceptions)) { ResourceMark rm; - log_info(exceptions)("Exception <%s> (" INTPTR_FORMAT ") thrown in" - " compiled method <%s> at PC " INTPTR_FORMAT - " for thread " INTPTR_FORMAT, - exception->print_value_string(), - p2i((address)exception()), - nm->method()->print_value_string(), p2i(pc), - p2i(thread)); + stringStream tempst; + tempst.print("compiled method <%s>\n" + " at PC" INTPTR_FORMAT " for thread " INTPTR_FORMAT, + nm->method()->print_value_string(), p2i(pc), p2i(thread)); + Exceptions::log_exception(exception, tempst); } // for AbortVMOnException flag NOT_PRODUCT(Exceptions::debug_check_abort(exception)); @@ -644,15 +644,6 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(TRAPS) { "HotSpotJVMCIRuntime initialization should only be triggered through JVMCI initialization"); #endif - if (_compiler != NULL) { - JavaCallArguments args; - oop compiler = java_lang_String::create_oop_from_str(_compiler, CHECK); - args.push_oop(compiler); - callStatic("jdk/vm/ci/hotspot/HotSpotJVMCICompilerConfig", - "selectCompiler", - "(Ljava/lang/String;)Ljava/lang/Boolean;", &args, CHECK); - } - Handle result = callStatic("jdk/vm/ci/hotspot/HotSpotJVMCIRuntime", "runtime", "()Ljdk/vm/ci/hotspot/HotSpotJVMCIRuntime;", NULL, CHECK); @@ -785,66 +776,6 @@ JVM_ENTRY(void, JVM_RegisterJVMCINatives(JNIEnv *env, jclass c2vmClass)) } JVM_END -/** - * Closure for parsing a line from a *.properties file in jre/lib/jvmci/properties. - * The line must match the regular expression "[^=]+=.*". That is one or more - * characters other than '=' followed by '=' followed by zero or more characters. - * Everything before the '=' is the property name and everything after '=' is the value. - * Lines that start with '#' are treated as comments and ignored. - * No special processing of whitespace or any escape characters is performed. - * The last definition of a property "wins" (i.e., it overrides all earlier - * definitions of the property). - */ -class JVMCIPropertiesFileClosure : public ParseClosure { - SystemProperty** _plist; -public: - JVMCIPropertiesFileClosure(SystemProperty** plist) : _plist(plist) {} - void do_line(char* line) { - if (line[0] == '#') { - // skip comment - return; - } - size_t len = strlen(line); - char* sep = strchr(line, '='); - if (sep == NULL) { - warn_and_abort("invalid format: could not find '=' character"); - return; - } - if (sep == line) { - warn_and_abort("invalid format: name cannot be empty"); - return; - } - *sep = '\0'; - const char* name = line; - char* value = sep + 1; - Arguments::PropertyList_unique_add(_plist, name, value); - } -}; - -void JVMCIRuntime::init_system_properties(SystemProperty** plist) { - char jvmciDir[JVM_MAXPATHLEN]; - const char* fileSep = os::file_separator(); - jio_snprintf(jvmciDir, sizeof(jvmciDir), "%s%slib%sjvmci", - Arguments::get_java_home(), fileSep, fileSep, fileSep); - DIR* dir = os::opendir(jvmciDir); - if (dir != NULL) { - struct dirent *entry; - char *dbuf = NEW_C_HEAP_ARRAY(char, os::readdir_buf_size(jvmciDir), mtInternal); - JVMCIPropertiesFileClosure closure(plist); - const unsigned suffix_len = (unsigned)strlen(".properties"); - while ((entry = os::readdir(dir, (dirent *) dbuf)) != NULL && !closure.is_aborted()) { - const char* name = entry->d_name; - if (strlen(name) > suffix_len && strcmp(name + strlen(name) - suffix_len, ".properties") == 0) { - char propertiesFilePath[JVM_MAXPATHLEN]; - jio_snprintf(propertiesFilePath, sizeof(propertiesFilePath), "%s%s%s",jvmciDir, fileSep, name); - JVMCIRuntime::parse_lines(propertiesFilePath, &closure, false); - } - } - FREE_C_HEAP_ARRAY(char, dbuf); - os::closedir(dir); - } -} - #define CHECK_WARN_ABORT_(message) THREAD); \ if (HAS_PENDING_EXCEPTION) { \ warning(message); \ @@ -855,12 +786,6 @@ void JVMCIRuntime::init_system_properties(SystemProperty** plist) { } \ (void)(0 -void JVMCIRuntime::save_compiler(const char* compiler) { - assert(compiler != NULL, "npe"); - assert(_compiler == NULL, "cannot reassign JVMCI compiler"); - _compiler = compiler; -} - void JVMCIRuntime::shutdown(TRAPS) { if (_HotSpotJVMCIRuntime_instance != NULL) { _shutdown_called = true; @@ -886,69 +811,3 @@ bool JVMCIRuntime::treat_as_trivial(Method* method) { } return false; } - -void JVMCIRuntime::parse_lines(char* path, ParseClosure* closure, bool warnStatFailure) { - struct stat st; - if (::stat(path, &st) == 0 && (st.st_mode & S_IFREG) == S_IFREG) { // exists & is regular file - int file_handle = ::open(path, os::default_file_open_flags(), 0); - if (file_handle != -1) { - char* buffer = NEW_C_HEAP_ARRAY(char, st.st_size + 1, mtInternal); - int num_read; - num_read = (int) ::read(file_handle, (char*) buffer, st.st_size); - if (num_read == -1) { - warning("Error reading file %s due to %s", path, strerror(errno)); - } else if (num_read != st.st_size) { - warning("Only read %d of " SIZE_FORMAT " bytes from %s", num_read, (size_t) st.st_size, path); - } - ::close(file_handle); - closure->set_filename(path); - if (num_read == st.st_size) { - buffer[num_read] = '\0'; - - char* line = buffer; - while (line - buffer < num_read && !closure->is_aborted()) { - // find line end (\r, \n or \r\n) - char* nextline = NULL; - char* cr = strchr(line, '\r'); - char* lf = strchr(line, '\n'); - if (cr != NULL && lf != NULL) { - char* min = MIN2(cr, lf); - *min = '\0'; - if (lf == cr + 1) { - nextline = lf + 1; - } else { - nextline = min + 1; - } - } else if (cr != NULL) { - *cr = '\0'; - nextline = cr + 1; - } else if (lf != NULL) { - *lf = '\0'; - nextline = lf + 1; - } - // trim left - while (*line == ' ' || *line == '\t') line++; - char* end = line + strlen(line); - // trim right - while (end > line && (*(end -1) == ' ' || *(end -1) == '\t')) end--; - *end = '\0'; - // skip comments and empty lines - if (*line != '#' && strlen(line) > 0) { - closure->parse_line(line); - } - if (nextline != NULL) { - line = nextline; - } else { - // File without newline at the end - break; - } - } - } - FREE_C_HEAP_ARRAY(char, buffer); - } else { - warning("Error opening file %s due to %s", path, strerror(errno)); - } - } else if (warnStatFailure) { - warning("Could not stat file %s due to %s", path, strerror(errno)); - } -} diff --git a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp index 17476d65af9..4c37817537d 100644 --- a/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp +++ b/hotspot/src/share/vm/jvmci/jvmciRuntime.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -70,7 +70,6 @@ class JVMCIRuntime: public AllStatic { static jobject _HotSpotJVMCIRuntime_instance; static bool _HotSpotJVMCIRuntime_initialized; static bool _well_known_classes_initialized; - static const char* _compiler; static int _trivial_prefixes_count; static char** _trivial_prefixes; @@ -85,19 +84,9 @@ class JVMCIRuntime: public AllStatic { static Handle create_Service(const char* name, TRAPS); public: - - /** - * Parses *.properties files in jre/lib/jvmci/ and adds the properties to plist. - */ - static void init_system_properties(SystemProperty** plist); - - /** - * Saves the value of the "jvmci.compiler" system property for processing - * when JVMCI is initialized. - */ - static void save_compiler(const char* compiler); - - static bool is_HotSpotJVMCIRuntime_initialized() { return _HotSpotJVMCIRuntime_initialized; } + static bool is_HotSpotJVMCIRuntime_initialized() { + return _HotSpotJVMCIRuntime_initialized; + } /** * Gets the singleton HotSpotJVMCIRuntime instance, initializing it if necessary @@ -136,7 +125,6 @@ class JVMCIRuntime: public AllStatic { } static bool treat_as_trivial(Method* method); - static void parse_lines(char* path, ParseClosure* closure, bool warnStatFailure); static BasicType kindToBasicType(Handle kind, TRAPS); diff --git a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp index 9456f34a0eb..9c754133a40 100644 --- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp +++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp @@ -592,6 +592,14 @@ #endif // TARGET_OS_FAMILY_bsd +#ifdef TARGET_ARCH_aarch64 + +#define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ + volatile_nonstatic_field(JavaFrameAnchor, _last_Java_fp, intptr_t*) + +#endif // TARGET_ARCH_aarch64 + + #ifdef TARGET_ARCH_x86 #define VM_STRUCTS_CPU(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field, nonproduct_nonstatic_field, c2_nonstatic_field, unchecked_c1_static_field, unchecked_c2_static_field) \ @@ -631,11 +639,12 @@ declare_constant(VM_Version::CPU_AVX512DQ) \ declare_constant(VM_Version::CPU_AVX512PF) \ declare_constant(VM_Version::CPU_AVX512ER) \ - declare_constant(VM_Version::CPU_AVX512CD) \ - declare_constant(VM_Version::CPU_AVX512BW) + declare_constant(VM_Version::CPU_AVX512CD) #define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \ - declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) + declare_preprocessor_constant("VM_Version::CPU_AVX512BW", CPU_AVX512BW) \ + declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL) \ + declare_preprocessor_constant("VM_Version::CPU_SHA", CPU_SHA) #endif // TARGET_ARCH_x86 diff --git a/hotspot/src/share/vm/logging/logConfiguration.cpp b/hotspot/src/share/vm/logging/logConfiguration.cpp index 2ff86004cce..2bdd8682f93 100644 --- a/hotspot/src/share/vm/logging/logConfiguration.cpp +++ b/hotspot/src/share/vm/logging/logConfiguration.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -82,8 +82,7 @@ void LogConfiguration::post_initialize() { void LogConfiguration::initialize(jlong vm_start_time) { LogFileOutput::set_file_name_parameters(vm_start_time); - LogDecorations::set_vm_start_time_millis(vm_start_time); - + LogDecorations::initialize(vm_start_time); assert(_outputs == NULL, "Should not initialize _outputs before this function, initialize called twice?"); _outputs = NEW_C_HEAP_ARRAY(LogOutput*, 2, mtLogging); _outputs[0] = LogOutput::Stdout; diff --git a/hotspot/src/share/vm/logging/logDecorations.cpp b/hotspot/src/share/vm/logging/logDecorations.cpp index 3438b8ad734..210ab31313a 100644 --- a/hotspot/src/share/vm/logging/logDecorations.cpp +++ b/hotspot/src/share/vm/logging/logDecorations.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,21 @@ #include "services/management.hpp" jlong LogDecorations::_vm_start_time_millis = 0; +const char* LogDecorations::_host_name = ""; LogDecorations::LogDecorations(LogLevelType level, const LogTagSet &tagset, const LogDecorators &decorators) : _level(level), _tagset(tagset), _millis(-1) { create_decorations(decorators); } +void LogDecorations::initialize(jlong vm_start_time) { + char buffer[1024]; + if (os::get_host_name(buffer, sizeof(buffer))){ + _host_name = os::strdup_check_oom(buffer); + } + _vm_start_time_millis = vm_start_time; +} + void LogDecorations::create_decorations(const LogDecorators &decorators) { char* position = _decorations_buffer; #define DECORATOR(full_name, abbr) \ @@ -109,3 +118,9 @@ char* LogDecorations::create_tags_decoration(char* pos) { int written = _tagset.label(pos, DecorationsBufferSize - (pos - _decorations_buffer)); ASSERT_AND_RETURN(written, pos) } + +char* LogDecorations::create_hostname_decoration(char* pos) { + int written = jio_snprintf(pos, DecorationsBufferSize - (pos - _decorations_buffer), "%s", _host_name); + ASSERT_AND_RETURN(written, pos) +} + diff --git a/hotspot/src/share/vm/logging/logDecorations.hpp b/hotspot/src/share/vm/logging/logDecorations.hpp index 08a675f225b..fcc166147e8 100644 --- a/hotspot/src/share/vm/logging/logDecorations.hpp +++ b/hotspot/src/share/vm/logging/logDecorations.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ class LogDecorations VALUE_OBJ_CLASS_SPEC { LogTagSet _tagset; jlong _millis; static jlong _vm_start_time_millis; + static const char* _host_name; jlong java_millis(); void create_decorations(const LogDecorators& decorators); @@ -48,15 +49,13 @@ class LogDecorations VALUE_OBJ_CLASS_SPEC { #undef DECORATOR public: + static void initialize(jlong vm_start_time); + LogDecorations(LogLevelType level, const LogTagSet& tagset, const LogDecorators& decorators); const char* decoration(LogDecorators::Decorator decorator) const { return _decoration_offset[decorator]; } - - static void set_vm_start_time_millis(jlong start_time) { - _vm_start_time_millis = start_time; - } }; #endif // SHARE_VM_LOGGING_LOGDECORATIONS_HPP diff --git a/hotspot/src/share/vm/logging/logDecorators.hpp b/hotspot/src/share/vm/logging/logDecorators.hpp index 56a4778b034..1e52124060f 100644 --- a/hotspot/src/share/vm/logging/logDecorators.hpp +++ b/hotspot/src/share/vm/logging/logDecorators.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ // uptimemillis - Milliseconds since the JVM started // timenanos - The same value as generated by System.nanoTime() // uptimenanos - Nanoseconds since the JVM started +// hostname - The hostname // pid - The process identifier // tid - The thread identifier // level - The level associated with the log message @@ -45,6 +46,7 @@ DECORATOR(uptimemillis, um) \ DECORATOR(timenanos, tn) \ DECORATOR(uptimenanos, un) \ + DECORATOR(hostname, hn) \ DECORATOR(pid, p) \ DECORATOR(tid, ti) \ DECORATOR(level, l) \ diff --git a/hotspot/src/share/vm/logging/logPrefix.hpp b/hotspot/src/share/vm/logging/logPrefix.hpp index 039e5f44416..213fa7c2806 100644 --- a/hotspot/src/share/vm/logging/logPrefix.hpp +++ b/hotspot/src/share/vm/logging/logPrefix.hpp @@ -58,6 +58,7 @@ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, metaspace)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, start)) \ + LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, phases, task)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, plab)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, region)) \ LOG_PREFIX(GCId::print_prefix, LOG_TAGS(gc, remset)) \ diff --git a/hotspot/src/share/vm/logging/logTag.hpp b/hotspot/src/share/vm/logging/logTag.hpp index d4ff40bd0dd..d292c8339e9 100644 --- a/hotspot/src/share/vm/logging/logTag.hpp +++ b/hotspot/src/share/vm/logging/logTag.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ LOG_TAG(alloc) \ LOG_TAG(age) \ LOG_TAG(barrier) \ + LOG_TAG(biasedlocking) \ LOG_TAG(bot) \ LOG_TAG(census) \ LOG_TAG(classhisto) \ @@ -42,6 +43,7 @@ LOG_TAG(classload) /* Trace all classes loaded */ \ LOG_TAG(classloaderdata) /* class loader loader_data lifetime */ \ LOG_TAG(classunload) /* Trace unloading of classes */ \ + LOG_TAG(classpath) \ LOG_TAG(compaction) \ LOG_TAG(cpu) \ LOG_TAG(cset) \ @@ -65,6 +67,7 @@ LOG_TAG(phases) \ LOG_TAG(plab) \ LOG_TAG(promotion) \ + LOG_TAG(protectiondomain) /* "Trace protection domain verification" */ \ LOG_TAG(ref) \ LOG_TAG(refine) \ LOG_TAG(region) \ @@ -73,12 +76,14 @@ LOG_TAG(scavenge) \ LOG_TAG(scrub) \ LOG_TAG(start) \ + LOG_TAG(startuptime) \ LOG_TAG(state) \ LOG_TAG(stats) \ LOG_TAG(stringdedup) \ LOG_TAG(survivor) \ LOG_TAG(sweep) \ LOG_TAG(task) \ + LOG_TAG(thread) \ LOG_TAG(tlab) \ LOG_TAG(time) \ LOG_TAG(verify) \ diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index 2a82e60c063..1b21736315c 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -208,9 +208,7 @@ void FileMapInfo::allocate_classpath_entry_table() { count ++; bytes += (int)entry_size; bytes += name_bytes; - if (TraceClassPaths) { - tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name); - } + log_info(classpath)("add main shared path (%s) %s", (cpe->is_jar_file() ? "jar" : "dir"), name); } else { SharedClassPathEntry* ent = shared_classpath(cur_entry); if (cpe->is_jar_file()) { @@ -275,9 +273,7 @@ bool FileMapInfo::validate_classpath_entry_table() { struct stat st; const char* name = ent->_name; bool ok = true; - if (TraceClassPaths) { - tty->print_cr("[Checking shared classpath entry: %s]", name); - } + log_info(classpath)("checking shared classpath entry: %s", name); if (os::stat(name, &st) != 0) { fail_continue("Required classpath entry does not exist: %s", name); ok = false; @@ -301,9 +297,7 @@ bool FileMapInfo::validate_classpath_entry_table() { } } if (ok) { - if (TraceClassPaths) { - tty->print_cr("[ok]"); - } + log_info(classpath)("ok"); } else if (!PrintSharedArchiveAndExit) { _validating_classpath_entry_table = false; return false; @@ -888,10 +882,8 @@ bool FileMapInfo::FileMapHeader::validate() { char header_version[JVM_IDENT_MAX]; get_header_version(header_version); if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) { - if (TraceClassPaths) { - tty->print_cr("Expected: %s", header_version); - tty->print_cr("Actual: %s", _jvm_ident); - } + log_info(classpath)("expected: %s", header_version); + log_info(classpath)("actual: %s", _jvm_ident); FileMapInfo::fail_continue("The shared archive file was created by a different" " version or build of HotSpot"); return false; @@ -919,7 +911,7 @@ bool FileMapInfo::validate_header() { if (status) { if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) { if (!PrintSharedArchiveAndExit) { - fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)"); + fail_continue("shared class paths mismatch (hint: enable -Xlog:classpath=info to diagnose the failure)"); status = false; } } diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index 72ec52da3d1..199702e083e 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -791,7 +791,6 @@ Mutex* const SpaceManager::_expand_lock = void VirtualSpaceNode::inc_container_count() { assert_lock_strong(SpaceManager::expand_lock()); _container_count++; - DEBUG_ONLY(verify_container_count();) } void VirtualSpaceNode::dec_container_count() { @@ -1073,6 +1072,7 @@ void VirtualSpaceList::purge(ChunkManager* chunk_manager) { VirtualSpaceNode* next_vsl = prev_vsl; while (next_vsl != NULL) { VirtualSpaceNode* vsl = next_vsl; + DEBUG_ONLY(vsl->verify_container_count();) next_vsl = vsl->next(); // Don't free the current virtual space since it will likely // be needed soon. @@ -1137,19 +1137,19 @@ void VirtualSpaceList::retire_current_virtual_space() { } void VirtualSpaceNode::retire(ChunkManager* chunk_manager) { + DEBUG_ONLY(verify_container_count();) for (int i = (int)MediumIndex; i >= (int)ZeroIndex; --i) { ChunkIndex index = (ChunkIndex)i; size_t chunk_size = chunk_manager->free_chunks(index)->size(); while (free_words_in_vs() >= chunk_size) { - DEBUG_ONLY(verify_container_count();) Metachunk* chunk = get_chunk_vs(chunk_size); assert(chunk != NULL, "allocation should have been successful"); chunk_manager->return_chunks(index, chunk); chunk_manager->inc_free_chunks_total(chunk_size); - DEBUG_ONLY(verify_container_count();) } + DEBUG_ONLY(verify_container_count();) } assert(free_words_in_vs() == 0, "should be empty now"); } diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index d71f9292511..3f10488bf7f 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "memory/metaspaceShared.hpp" #include "oops/objArrayOop.hpp" #include "oops/oop.inline.hpp" +#include "runtime/logTimer.hpp" #include "runtime/os.hpp" #include "runtime/signature.hpp" #include "runtime/vmThread.hpp" @@ -771,88 +772,89 @@ void MetaspaceShared::prepare_for_dumping() { // Preload classes from a list, populate the shared spaces and dump to a // file. void MetaspaceShared::preload_and_dump(TRAPS) { - TraceTime timer("Dump Shared Spaces", TraceStartupTime); - ResourceMark rm; - char class_list_path_str[JVM_MAXPATHLEN]; + { TraceStartupTime timer("Dump Shared Spaces"); + ResourceMark rm; + char class_list_path_str[JVM_MAXPATHLEN]; - tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT, - MetaspaceShared::shared_rs()->size(), - p2i(MetaspaceShared::shared_rs()->base())); + tty->print_cr("Allocated shared space: " SIZE_FORMAT " bytes at " PTR_FORMAT, + MetaspaceShared::shared_rs()->size(), + p2i(MetaspaceShared::shared_rs()->base())); - // Preload classes to be shared. - // Should use some os:: method rather than fopen() here. aB. - const char* class_list_path; - if (SharedClassListFile == NULL) { - // Construct the path to the class list (in jre/lib) - // Walk up two directories from the location of the VM and - // optionally tack on "lib" (depending on platform) - os::jvm_path(class_list_path_str, sizeof(class_list_path_str)); - for (int i = 0; i < 3; i++) { - char *end = strrchr(class_list_path_str, *os::file_separator()); - if (end != NULL) *end = '\0'; - } - int class_list_path_len = (int)strlen(class_list_path_str); - if (class_list_path_len >= 3) { - if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) { - if (class_list_path_len < JVM_MAXPATHLEN - 4) { - jio_snprintf(class_list_path_str + class_list_path_len, - sizeof(class_list_path_str) - class_list_path_len, - "%slib", os::file_separator()); - class_list_path_len += 4; + // Preload classes to be shared. + // Should use some os:: method rather than fopen() here. aB. + const char* class_list_path; + if (SharedClassListFile == NULL) { + // Construct the path to the class list (in jre/lib) + // Walk up two directories from the location of the VM and + // optionally tack on "lib" (depending on platform) + os::jvm_path(class_list_path_str, sizeof(class_list_path_str)); + for (int i = 0; i < 3; i++) { + char *end = strrchr(class_list_path_str, *os::file_separator()); + if (end != NULL) *end = '\0'; + } + int class_list_path_len = (int)strlen(class_list_path_str); + if (class_list_path_len >= 3) { + if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) { + if (class_list_path_len < JVM_MAXPATHLEN - 4) { + jio_snprintf(class_list_path_str + class_list_path_len, + sizeof(class_list_path_str) - class_list_path_len, + "%slib", os::file_separator()); + class_list_path_len += 4; + } } } + if (class_list_path_len < JVM_MAXPATHLEN - 10) { + jio_snprintf(class_list_path_str + class_list_path_len, + sizeof(class_list_path_str) - class_list_path_len, + "%sclasslist", os::file_separator()); + } + class_list_path = class_list_path_str; + } else { + class_list_path = SharedClassListFile; } - if (class_list_path_len < JVM_MAXPATHLEN - 10) { - jio_snprintf(class_list_path_str + class_list_path_len, - sizeof(class_list_path_str) - class_list_path_len, - "%sclasslist", os::file_separator()); - } - class_list_path = class_list_path_str; - } else { - class_list_path = SharedClassListFile; - } - int class_count = 0; - GrowableArray* class_promote_order = new GrowableArray(); + int class_count = 0; + GrowableArray* class_promote_order = new GrowableArray(); - // sun.io.Converters - static const char obj_array_sig[] = "[[Ljava/lang/Object;"; - SymbolTable::new_permanent_symbol(obj_array_sig, THREAD); + // sun.io.Converters + static const char obj_array_sig[] = "[[Ljava/lang/Object;"; + SymbolTable::new_permanent_symbol(obj_array_sig, THREAD); - // java.util.HashMap - static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; - SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); + // java.util.HashMap + static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;"; + SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD); - // Need to allocate the op here: - // op.misc_data_space_alloc() will be called during preload_and_dump(). - ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); - VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); + // Need to allocate the op here: + // op.misc_data_space_alloc() will be called during preload_and_dump(). + ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data(); + VM_PopulateDumpSharedSpace op(loader_data, class_promote_order); - tty->print_cr("Loading classes to share ..."); - _has_error_classes = false; - class_count += preload_and_dump(class_list_path, class_promote_order, - THREAD); - if (ExtraSharedClassListFile) { - class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order, + tty->print_cr("Loading classes to share ..."); + _has_error_classes = false; + class_count += preload_and_dump(class_list_path, class_promote_order, THREAD); + if (ExtraSharedClassListFile) { + class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order, + THREAD); + } + tty->print_cr("Loading classes to share: done."); + + if (PrintSharedSpaces) { + tty->print_cr("Shared spaces: preloaded %d classes", class_count); + } + + // Rewrite and link classes + tty->print_cr("Rewriting and linking classes ..."); + + // Link any classes which got missed. This would happen if we have loaded classes that + // were not explicitly specified in the classlist. E.g., if an interface implemented by class K + // fails verification, all other interfaces that were not specified in the classlist but + // are implemented by K are not verified. + link_and_cleanup_shared_classes(CATCH); + tty->print_cr("Rewriting and linking classes: done"); + + VMThread::execute(&op); } - tty->print_cr("Loading classes to share: done."); - - if (PrintSharedSpaces) { - tty->print_cr("Shared spaces: preloaded %d classes", class_count); - } - - // Rewrite and link classes - tty->print_cr("Rewriting and linking classes ..."); - - // Link any classes which got missed. This would happen if we have loaded classes that - // were not explicitly specified in the classlist. E.g., if an interface implemented by class K - // fails verification, all other interfaces that were not specified in the classlist but - // are implemented by K are not verified. - link_and_cleanup_shared_classes(CATCH); - tty->print_cr("Rewriting and linking classes: done"); - - VMThread::execute(&op); // Since various initialization steps have been undone by this process, // it is not reasonable to continue running a java process. exit(0); diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index ac36a988d97..3a7945768e8 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -64,6 +64,7 @@ #include "runtime/init.hpp" #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/logTimer.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.inline.hpp" @@ -626,7 +627,9 @@ jint universe_init() { guarantee(sizeof(oop) >= sizeof(HeapWord), "HeapWord larger than oop?"); guarantee(sizeof(oop) % sizeof(HeapWord) == 0, "oop size is not not a multiple of HeapWord size"); - TraceTime timer("Genesis", TraceStartupTime); + + TraceStartupTime timer("Genesis"); + JavaClasses::compute_hard_coded_offsets(); jint status = Universe::initialize_heap(); diff --git a/hotspot/src/share/vm/oops/arrayKlass.cpp b/hotspot/src/share/vm/oops/arrayKlass.cpp index e92df43076f..2278ce92471 100644 --- a/hotspot/src/share/vm/oops/arrayKlass.cpp +++ b/hotspot/src/share/vm/oops/arrayKlass.cpp @@ -89,7 +89,7 @@ ArrayKlass::ArrayKlass(Symbol* name) : set_super(Universe::is_bootstrapping() ? (Klass*)NULL : SystemDictionary::Object_klass()); set_layout_helper(Klass::_lh_neutral_value); set_is_cloneable(); // All arrays are considered to be cloneable (See JLS 20.1.5) - TRACE_INIT_ID(this); + TRACE_INIT_KLASS_ID(this); } diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index aa3604f8997..47924e5d03b 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -839,7 +839,7 @@ public: // support for stub routines static ByteSize init_state_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_state)); } - TRACE_DEFINE_OFFSET; + TRACE_DEFINE_KLASS_TRACE_ID_OFFSET; static ByteSize init_thread_offset() { return in_ByteSize(offset_of(InstanceKlass, _init_thread)); } // subclass/subinterface checks diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index b391f222d6a..3cedd3470f0 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -494,7 +494,7 @@ void Klass::remove_unshareable_info() { } void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) { - TRACE_INIT_ID(this); + TRACE_INIT_KLASS_ID(this); // If an exception happened during CDS restore, some of these fields may already be // set. We leave the class on the CLD list, even if incomplete so that we don't // modify the CLD list outside a safepoint. diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 00fe28d614b..cff1d74d6ef 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -132,7 +132,7 @@ class Klass : public Metadata { jint _modifier_flags; // Processed access flags, for use by Class.getModifiers. AccessFlags _access_flags; // Access flags. The class/interface distinction is stored here. - TRACE_DEFINE_KLASS_TRACE_ID; + TRACE_DEFINE_TRACE_ID_FIELD; // Biased locking implementation and statistics // (the 64-bit chunk goes first, to avoid some fragmentation) @@ -569,7 +569,7 @@ protected: 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; } - TRACE_DEFINE_KLASS_METHODS; + TRACE_DEFINE_TRACE_ID_METHODS; // garbage collection support void oops_do(OopClosure* cl); diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 7620ea9f985..8c6029e6fef 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1338,73 +1338,6 @@ vmSymbols::SID Method::klass_id_for_intrinsics(const Klass* holder) { return vmSymbols::find_sid(klass_name); } -static bool is_unsafe_alias(vmSymbols::SID name_id) { - // All 70 intrinsic candidate methods from sun.misc.Unsafe in 1.8. - // Some have the same method name but different signature, e.g. - // getByte(long), getByte(Object,long) - switch (name_id) { - case vmSymbols::VM_SYMBOL_ENUM_NAME(allocateInstance_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(copyMemory_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(loadFence_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(storeFence_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(fullFence_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getBoolean_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getByte_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getShort_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getChar_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloat_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getDouble_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putBoolean_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putByte_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putShort_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putChar_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloat_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putDouble_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getObjectVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getBooleanVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getByteVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getShortVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getCharVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getIntVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getLongVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getFloatVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getDoubleVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putObjectVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putBooleanVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putByteVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putShortVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putCharVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putIntVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putLongVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putFloatVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putDoubleVolatile_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAddress_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putAddress_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(compareAndSwapInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(putOrderedInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndAddLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetInt_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetLong_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(getAndSetObject_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(park_name): - case vmSymbols::VM_SYMBOL_ENUM_NAME(unpark_name): - return true; - } - - return false; -} - void Method::init_intrinsic_id() { assert(_intrinsic_id == vmIntrinsics::_none, "do this just once"); const uintptr_t max_id_uint = right_n_bits((int)(sizeof(_intrinsic_id) * BitsPerByte)); @@ -1457,14 +1390,6 @@ void Method::init_intrinsic_id() { if (is_static() != MethodHandles::is_signature_polymorphic_static(id)) id = vmIntrinsics::_none; break; - - case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Unsafe): - // Map sun.misc.Unsafe to jdk.internal.misc.Unsafe - if (!is_unsafe_alias(name_id)) break; - // pretend it is the corresponding method in the internal Unsafe class: - klass_id = vmSymbols::VM_SYMBOL_ENUM_NAME(jdk_internal_misc_Unsafe); - id = vmIntrinsics::find_id(klass_id, name_id, sig_id, flags); - break; } if (id != vmIntrinsics::_none) { diff --git a/hotspot/src/share/vm/oops/typeArrayOop.hpp b/hotspot/src/share/vm/oops/typeArrayOop.hpp index e4670a8949b..8ab2f4d1f74 100644 --- a/hotspot/src/share/vm/oops/typeArrayOop.hpp +++ b/hotspot/src/share/vm/oops/typeArrayOop.hpp @@ -129,7 +129,7 @@ class typeArrayOopDesc : public arrayOopDesc { Metadata* metadata_at(int which) const { return (Metadata*)*long_at_addr(which); } void metadata_at_put(int which, Metadata* contents) { - *long_at_addr(which) = (long)contents; + *long_at_addr(which) = (jlong)contents; } #else Metadata* metadata_at(int which) const { diff --git a/hotspot/src/share/vm/opto/c2compiler.cpp b/hotspot/src/share/vm/opto/c2compiler.cpp index aeea26748fe..33c5918a95a 100644 --- a/hotspot/src/share/vm/opto/c2compiler.cpp +++ b/hotspot/src/share/vm/opto/c2compiler.cpp @@ -493,13 +493,12 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_currentThread: case vmIntrinsics::_isInterrupted: #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: - case vmIntrinsics::_threadID: case vmIntrinsics::_counterTime: #endif case vmIntrinsics::_currentTimeMillis: case vmIntrinsics::_nanoTime: case vmIntrinsics::_allocateInstance: + case vmIntrinsics::_allocateUninitializedArray: case vmIntrinsics::_newArray: case vmIntrinsics::_getLength: case vmIntrinsics::_copyOf: diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index ffe97dc68ab..6a43b33cde4 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -1243,13 +1243,13 @@ void SafePointNode::pop_monitor() { Node *SafePointNode::peek_monitor_box() const { int mon = jvms()->nof_monitors() - 1; - assert(mon >= 0, "most have a monitor"); + assert(mon >= 0, "must have a monitor"); return monitor_box(jvms(), mon); } Node *SafePointNode::peek_monitor_obj() const { int mon = jvms()->nof_monitors() - 1; - assert(mon >= 0, "most have a monitor"); + assert(mon >= 0, "must have a monitor"); return monitor_obj(jvms(), mon); } diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index 12aa7c7d6b4..c0bad767d0c 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -1665,7 +1665,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { bool uncasted = false; Node* uin = unique_input(phase, false); - if (uin == NULL) { + if (uin == NULL && can_reshape) { uncasted = true; uin = unique_input(phase, true); } @@ -1702,6 +1702,8 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { } if (uncasted) { + // Wait until after parsing for the type information to propagate from the casts + assert(can_reshape, "Invalid during parsing"); const Type* phi_type = bottom_type(); assert(phi_type->isa_int() || phi_type->isa_ptr(), "bad phi type"); int opcode; @@ -1720,8 +1722,9 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node* cast = ConstraintCastNode::make_cast(opcode, r, uin, phi_type, true); cast = phase->transform(cast); // set all inputs to the new cast so the Phi is removed by Identity + PhaseIterGVN* igvn = phase->is_IterGVN(); for (uint i = 1; i < req(); i++) { - set_req(i, cast); + set_req_X(i, cast, igvn); } uin = cast; } diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 40724fbd6b7..343574e68f3 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -1118,7 +1118,11 @@ class Compile : public Phase { bool in_scratch_emit_size() const { return _in_scratch_emit_size; } enum ScratchBufferBlob { +#if defined(PPC64) + MAX_inst_size = 2048, +#else MAX_inst_size = 1024, +#endif MAX_locs_size = 128, // number of relocInfo elements MAX_const_size = 128, MAX_stubs_size = 128 diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index a47897db8c1..73f7c3e1254 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1179,8 +1179,10 @@ Node* GraphKit::load_array_length(Node* array) { // Helper function to do a NULL pointer check. Returned value is // the incoming address with NULL casted away. You are allowed to use the // not-null value only if you are control dependent on the test. +#ifndef PRODUCT extern int explicit_null_checks_inserted, explicit_null_checks_elided; +#endif Node* GraphKit::null_check_common(Node* value, BasicType type, // optional arguments for variations: bool assert_null, @@ -1193,7 +1195,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, value = cast_not_null(value); // Make it appear to be non-null (4962416). return value; } - explicit_null_checks_inserted++; + NOT_PRODUCT(explicit_null_checks_inserted++); // Construct NULL check Node *chk = NULL; @@ -1233,7 +1235,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // See if the type is contained in NULL_PTR. // If so, then the value is already null. if (t->higher_equal(TypePtr::NULL_PTR)) { - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return value; // Elided null assert quickly! } } else { @@ -1242,7 +1244,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, // type. In other words, "value" was not-null. if (t->meet(TypePtr::NULL_PTR) != t->remove_speculative()) { // same as: if (!TypePtr::NULL_PTR->higher_equal(t)) ... - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return value; // Elided null check quickly! } } @@ -1282,7 +1284,7 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, set_control(cfg); Node *res = cast_not_null(value); set_control(oldcontrol); - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); return res; } cfg = IfNode::up_one_dom(cfg, /*linear_only=*/ true); @@ -1326,15 +1328,18 @@ Node* GraphKit::null_check_common(Node* value, BasicType type, IfNode* iff = create_and_map_if(control(), tst, ok_prob, COUNT_UNKNOWN); Node* null_true = _gvn.transform( new IfFalseNode(iff)); set_control( _gvn.transform( new IfTrueNode(iff))); - if (null_true == top()) +#ifndef PRODUCT + if (null_true == top()) { explicit_null_checks_elided++; + } +#endif (*null_control) = null_true; } else { BuildCutout unless(this, tst, ok_prob); // Check for optimizer eliding test at parse time if (stopped()) { // Failure not possible; do not bother making uncommon trap. - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); } else if (assert_null) { uncommon_trap(reason, Deoptimization::Action_make_not_entrant, diff --git a/hotspot/src/share/vm/opto/ifnode.cpp b/hotspot/src/share/vm/opto/ifnode.cpp index a2cea88273f..9e315739008 100644 --- a/hotspot/src/share/vm/opto/ifnode.cpp +++ b/hotspot/src/share/vm/opto/ifnode.cpp @@ -40,7 +40,9 @@ // Optimization - Graph Style +#ifndef PRODUCT extern int explicit_null_checks_elided; +#endif //============================================================================= //------------------------------Value------------------------------------------ @@ -1504,24 +1506,28 @@ Node* IfNode::search_identical(int dist) { Node* prev_dom = this; int op = Opcode(); // Search up the dominator tree for an If with an identical test - while( dom->Opcode() != op || // Not same opcode? + while (dom->Opcode() != op || // Not same opcode? dom->in(1) != in(1) || // Not same input 1? (req() == 3 && dom->in(2) != in(2)) || // Not same input 2? - prev_dom->in(0) != dom ) { // One path of test does not dominate? - if( dist < 0 ) return NULL; + prev_dom->in(0) != dom) { // One path of test does not dominate? + if (dist < 0) return NULL; dist--; prev_dom = dom; - dom = up_one_dom( dom ); - if( !dom ) return NULL; + dom = up_one_dom(dom); + if (!dom) return NULL; } // Check that we did not follow a loop back to ourselves - if( this == dom ) + if (this == dom) { return NULL; + } - if( dist > 2 ) // Add to count of NULL checks elided +#ifndef PRODUCT + if (dist > 2) { // Add to count of NULL checks elided explicit_null_checks_elided++; + } +#endif return prev_dom; } diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 3edfc5e0ef0..431bba14c7e 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -348,8 +348,10 @@ void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allo } // ---- Found an implicit null check +#ifndef PRODUCT extern int implicit_null_checks; implicit_null_checks++; +#endif if( is_decoden ) { // Check if we need to hoist decodeHeapOop_not_null first. diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index de751bc1a97..3ce6cc3a4c4 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -48,8 +48,11 @@ #include "opto/runtime.hpp" #include "opto/subnode.hpp" #include "prims/nativeLookup.hpp" +#include "prims/unsafe.hpp" #include "runtime/sharedRuntime.hpp" +#ifdef TRACE_HAVE_INTRINSICS #include "trace/traceMacros.hpp" +#endif class LibraryIntrinsic : public InlineCallGenerator { // Extend the set of intrinsics known to the runtime: @@ -246,18 +249,14 @@ class LibraryCallKit : public GraphKit { bool inline_unsafe_access(bool is_native_ptr, bool is_store, BasicType type, AccessKind kind, bool is_unaligned); static bool klass_needs_init_guard(Node* kls); bool inline_unsafe_allocate(); + bool inline_unsafe_newArray(bool uninitialized); bool inline_unsafe_copyMemory(); bool inline_native_currentThread(); -#ifdef TRACE_HAVE_INTRINSICS - bool inline_native_classID(); - bool inline_native_threadID(); -#endif + bool inline_native_time_funcs(address method, const char* funcName); bool inline_native_isInterrupted(); bool inline_native_Class_query(vmIntrinsics::ID id); bool inline_native_subtype_check(); - - bool inline_native_newArray(); bool inline_native_getLength(); bool inline_array_copyOf(bool is_copyOfRange); bool inline_array_equals(StrIntrinsicNode::ArgEnc ae); @@ -706,15 +705,12 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_isInterrupted: return inline_native_isInterrupted(); #ifdef TRACE_HAVE_INTRINSICS - case vmIntrinsics::_classID: return inline_native_classID(); - case vmIntrinsics::_threadID: return inline_native_threadID(); case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, TRACE_TIME_METHOD), "counterTime"); #endif case vmIntrinsics::_currentTimeMillis: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeMillis), "currentTimeMillis"); case vmIntrinsics::_nanoTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, os::javaTimeNanos), "nanoTime"); case vmIntrinsics::_allocateInstance: return inline_unsafe_allocate(); case vmIntrinsics::_copyMemory: return inline_unsafe_copyMemory(); - case vmIntrinsics::_newArray: return inline_native_newArray(); case vmIntrinsics::_getLength: return inline_native_getLength(); case vmIntrinsics::_copyOf: return inline_array_copyOf(false); case vmIntrinsics::_copyOfRange: return inline_array_copyOf(true); @@ -723,6 +719,9 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_Objects_checkIndex: return inline_objects_checkIndex(); case vmIntrinsics::_clone: return inline_native_clone(intrinsic()->is_virtual()); + case vmIntrinsics::_allocateUninitializedArray: return inline_unsafe_newArray(true); + case vmIntrinsics::_newArray: return inline_unsafe_newArray(false); + case vmIntrinsics::_isAssignableFrom: return inline_native_subtype_check(); case vmIntrinsics::_isInstance: @@ -2306,9 +2305,6 @@ void LibraryCallKit::insert_pre_barrier(Node* base_oop, Node* offset, } -// Interpret Unsafe.fieldOffset cookies correctly: -extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); - const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_type, const TypePtr *adr_type, bool is_native_ptr) { // Attempt to infer a sharper value type from the offset and base type. ciKlass* sharpened_klass = NULL; @@ -2541,10 +2537,12 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor if (alias_type->element() != NULL || alias_type->field() != NULL) { BasicType bt; if (alias_type->element() != NULL) { - const Type* element = alias_type->element(); + // Use address type to get the element type. Alias type doesn't provide + // enough information (e.g., doesn't differentiate between byte[] and boolean[]). + const Type* element = adr_type->is_aryptr()->elem(); bt = element->isa_narrowoop() ? T_OBJECT : element->array_element_basic_type(); } else { - bt = alias_type->field()->type()->basic_type(); + bt = alias_type->field()->layout_type(); } if (bt == T_ARRAY) { // accessing an array field with getObject is not a mismatch @@ -2561,7 +2559,7 @@ bool LibraryCallKit::inline_unsafe_access(const bool is_native_ptr, bool is_stor // Try to constant fold a load from a constant field ciField* field = alias_type->field(); if (heap_base_oop != top() && - field != NULL && field->is_constant() && field->layout_type() == type) { + field != NULL && field->is_constant() && !mismatched) { // final or stable field const Type* con_type = Type::make_constant(alias_type->field(), heap_base_oop); if (con_type != NULL) { @@ -3182,52 +3180,6 @@ bool LibraryCallKit::inline_unsafe_allocate() { return true; } -#ifdef TRACE_HAVE_INTRINSICS -/* - * oop -> myklass - * myklass->trace_id |= USED - * return myklass->trace_id & ~0x3 - */ -bool LibraryCallKit::inline_native_classID() { - null_check_receiver(); // null-check, then ignore - Node* cls = null_check(argument(1), T_OBJECT); - Node* kls = load_klass_from_mirror(cls, false, NULL, 0); - kls = null_check(kls, T_OBJECT); - ByteSize offset = TRACE_ID_OFFSET; - Node* insp = basic_plus_adr(kls, in_bytes(offset)); - Node* tvalue = make_load(NULL, insp, TypeLong::LONG, T_LONG, MemNode::unordered); - Node* bits = longcon(~0x03l); // ignore bit 0 & 1 - Node* andl = _gvn.transform(new AndLNode(tvalue, bits)); - Node* clsused = longcon(0x01l); // set the class bit - Node* orl = _gvn.transform(new OrLNode(tvalue, clsused)); - - const TypePtr *adr_type = _gvn.type(insp)->isa_ptr(); - store_to_memory(control(), insp, orl, T_LONG, adr_type, MemNode::unordered); - set_result(andl); - return true; -} - -bool LibraryCallKit::inline_native_threadID() { - Node* tls_ptr = NULL; - Node* cur_thr = generate_current_thread(tls_ptr); - Node* p = basic_plus_adr(top()/*!oop*/, tls_ptr, in_bytes(JavaThread::osthread_offset())); - Node* osthread = make_load(NULL, p, TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered); - p = basic_plus_adr(top()/*!oop*/, osthread, in_bytes(OSThread::thread_id_offset())); - - Node* threadid = NULL; - size_t thread_id_size = OSThread::thread_id_size(); - if (thread_id_size == (size_t) BytesPerLong) { - threadid = ConvL2I(make_load(control(), p, TypeLong::LONG, T_LONG, MemNode::unordered)); - } else if (thread_id_size == (size_t) BytesPerInt) { - threadid = make_load(control(), p, TypeInt::INT, T_INT, MemNode::unordered); - } else { - ShouldNotReachHere(); - } - set_result(threadid); - return true; -} -#endif - //------------------------inline_native_time_funcs-------------- // inline code for System.currentTimeMillis() and System.nanoTime() // these have the same type and signature @@ -3829,9 +3781,17 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, //-----------------------inline_native_newArray-------------------------- // private static native Object java.lang.reflect.newArray(Class componentType, int length); -bool LibraryCallKit::inline_native_newArray() { - Node* mirror = argument(0); - Node* count_val = argument(1); +// private native Object Unsafe.allocateUninitializedArray0(Class cls, int size); +bool LibraryCallKit::inline_unsafe_newArray(bool uninitialized) { + Node* mirror; + Node* count_val; + if (uninitialized) { + mirror = argument(1); + count_val = argument(2); + } else { + mirror = argument(0); + count_val = argument(1); + } mirror = null_check(mirror); // If mirror or obj is dead, only null-path is taken. @@ -3876,6 +3836,12 @@ bool LibraryCallKit::inline_native_newArray() { result_val->init_req(_normal_path, obj); result_io ->init_req(_normal_path, i_o()); result_mem->init_req(_normal_path, reset_memory()); + + if (uninitialized) { + // Mark the allocation so that zeroing is skipped + AllocateArrayNode* alloc = AllocateArrayNode::Ideal_array_allocation(obj, &_gvn); + alloc->maybe_set_complete(&_gvn); + } } // Return the combined state. @@ -4464,7 +4430,7 @@ bool LibraryCallKit::inline_fp_conversions(vmIntrinsics::ID id) { } //----------------------inline_unsafe_copyMemory------------------------- -// public native void Unsafe.copyMemory(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); +// public native void Unsafe.copyMemory0(Object srcBase, long srcOffset, Object destBase, long destOffset, long bytes); bool LibraryCallKit::inline_unsafe_copyMemory() { if (callee()->is_static()) return false; // caller must have the capability! null_check_receiver(); // null-check receiver diff --git a/hotspot/src/share/vm/opto/macroArrayCopy.cpp b/hotspot/src/share/vm/opto/macroArrayCopy.cpp index 82816b2462b..17065895bff 100644 --- a/hotspot/src/share/vm/opto/macroArrayCopy.cpp +++ b/hotspot/src/share/vm/opto/macroArrayCopy.cpp @@ -880,8 +880,14 @@ bool PhaseMacroExpand::generate_block_arraycopy(Node** ctrl, MergeMemNode** mem, Node* sptr = basic_plus_adr(src, src_off); Node* dptr = basic_plus_adr(dest, dest_off); uint alias_idx = C->get_alias_index(adr_type); - Node* sval = transform_later(LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, TypeInt::INT, T_INT, MemNode::unordered)); - Node* st = transform_later(StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, sval, T_INT, MemNode::unordered)); + bool is_mismatched = (basic_elem_type != T_INT); + Node* sval = transform_later( + LoadNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), sptr, adr_type, + TypeInt::INT, T_INT, MemNode::unordered, LoadNode::DependsOnlyOnTest, + false /*unaligned*/, is_mismatched)); + Node* st = transform_later( + StoreNode::make(_igvn, *ctrl, (*mem)->memory_at(alias_idx), dptr, adr_type, + sval, T_INT, MemNode::unordered)); (*mem)->set_memory_at(alias_idx, st); src_off += BytesPerInt; dest_off += BytesPerInt; diff --git a/hotspot/src/share/vm/opto/matcher.cpp b/hotspot/src/share/vm/opto/matcher.cpp index edb69afb43d..1df9f7ca1c0 100644 --- a/hotspot/src/share/vm/opto/matcher.cpp +++ b/hotspot/src/share/vm/opto/matcher.cpp @@ -2415,8 +2415,10 @@ void Matcher::collect_null_checks( Node *proj, Node *orig_proj ) { bool push_it = false; if( proj->Opcode() == Op_IfTrue ) { +#ifndef PRODUCT extern int all_null_checks_found; all_null_checks_found++; +#endif if( b->_test._test == BoolTest::ne ) { push_it = true; } diff --git a/hotspot/src/share/vm/opto/matcher.hpp b/hotspot/src/share/vm/opto/matcher.hpp index 64cc48c65ec..dad3854e3f2 100644 --- a/hotspot/src/share/vm/opto/matcher.hpp +++ b/hotspot/src/share/vm/opto/matcher.hpp @@ -399,10 +399,6 @@ public: // Optional scaling for the parameter to the ClearArray/CopyArray node. static const bool init_array_count_is_in_bytes; - // Threshold small size (in bytes) for a ClearArray/CopyArray node. - // Anything this size or smaller may get converted to discrete scalar stores. - static const int init_array_short_size; - // Some hardware needs 2 CMOV's for longs. static const int long_cmove_cost(); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index 75a699349f8..a09caf81bb7 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -1582,6 +1582,21 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls, return NULL; } +static bool is_mismatched_access(ciConstant con, BasicType loadbt) { + BasicType conbt = con.basic_type(); + switch (conbt) { + case T_BOOLEAN: conbt = T_BYTE; break; + case T_ARRAY: conbt = T_OBJECT; break; + } + switch (loadbt) { + case T_BOOLEAN: loadbt = T_BYTE; break; + case T_NARROWOOP: loadbt = T_OBJECT; break; + case T_ARRAY: loadbt = T_OBJECT; break; + case T_ADDRESS: loadbt = T_OBJECT; break; + } + return (conbt != loadbt); +} + // Try to constant-fold a stable array element. static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { assert(ary->const_oop(), "array should be constant"); @@ -1590,10 +1605,12 @@ static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicTyp // Decode the results of GraphKit::array_element_address. ciArray* aobj = ary->const_oop()->as_array(); ciConstant con = aobj->element_value_by_offset(off); - if (con.basic_type() != T_ILLEGAL && !con.is_null_or_zero()) { + bool is_mismatched = is_mismatched_access(con, loadbt); + assert(!is_mismatched, "conbt=%s; loadbt=%s", type2name(con.basic_type()), type2name(loadbt)); const Type* con_type = Type::make_from_constant(con); - if (con_type != NULL) { + // Guard against erroneous constant folding. + if (!is_mismatched && con_type != NULL) { if (con_type->isa_aryptr()) { // Join with the array element type, in case it is also stable. int dim = ary->stable_dimension(); @@ -1642,7 +1659,7 @@ const Type* LoadNode::Value(PhaseGVN* phase) const { const bool off_beyond_header = ((uint)off >= (uint)min_base_off); // Try to constant-fold a stable array element. - if (FoldStableValues && ary->is_stable() && ary->const_oop() != NULL) { + if (FoldStableValues && !is_mismatched_access() && ary->is_stable() && ary->const_oop() != NULL) { // Make sure the reference is not into the header and the offset is constant if (off_beyond_header && adr->is_AddP() && off != Type::OffsetBot) { const Type* con_type = fold_stable_ary_elem(ary, off, memory_type()); @@ -2724,6 +2741,9 @@ Node* ClearArrayNode::Identity(PhaseGVN* phase) { //------------------------------Idealize--------------------------------------- // Clearing a short array is faster with stores Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){ + // Already know this is a large node, do not try to ideal it + if (_is_large) return NULL; + const int unit = BytesPerLong; const TypeX* t = phase->type(in(2))->isa_intptr_t(); if (!t) return NULL; @@ -2736,8 +2756,11 @@ Node *ClearArrayNode::Ideal(PhaseGVN *phase, bool can_reshape){ // (see jck test stmt114.stmt11402.val). if (size <= 0 || size % unit != 0) return NULL; intptr_t count = size / unit; - // Length too long; use fast hardware clear - if (size > Matcher::init_array_short_size) return NULL; + // Length too long; communicate this to matchers and assemblers. + // Assemblers are responsible to produce fast hardware clears for it. + if (size > InitArrayShortSize) { + return new ClearArrayNode(in(0), in(1), in(2), in(3), true); + } Node *mem = in(1); if( phase->type(mem)==Type::TOP ) return NULL; Node *adr = in(3); @@ -2835,7 +2858,7 @@ Node* ClearArrayNode::clear_memory(Node* ctl, Node* mem, Node* dest, // Bulk clear double-words Node* zsize = phase->transform(new SubXNode(zend, zbase) ); Node* adr = phase->transform(new AddPNode(dest, dest, start_offset) ); - mem = new ClearArrayNode(ctl, mem, zsize, adr); + mem = new ClearArrayNode(ctl, mem, zsize, adr, false); return phase->transform(mem); } @@ -3884,7 +3907,7 @@ Node* InitializeNode::complete_stores(Node* rawctl, Node* rawmem, Node* rawptr, zeroes_done, zeroes_needed, phase); zeroes_done = zeroes_needed; - if (zsize > Matcher::init_array_short_size && ++big_init_gaps > 2) + if (zsize > InitArrayShortSize && ++big_init_gaps > 2) do_zeroing = false; // leave the hole, next time } } diff --git a/hotspot/src/share/vm/opto/memnode.hpp b/hotspot/src/share/vm/opto/memnode.hpp index 8d9cd71bc0a..c1477bb2e4c 100644 --- a/hotspot/src/share/vm/opto/memnode.hpp +++ b/hotspot/src/share/vm/opto/memnode.hpp @@ -1013,9 +1013,11 @@ public: //------------------------------ClearArray------------------------------------- class ClearArrayNode: public Node { +private: + bool _is_large; public: - ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base ) - : Node(ctrl,arymem,word_cnt,base) { + ClearArrayNode( Node *ctrl, Node *arymem, Node *word_cnt, Node *base, bool is_large) + : Node(ctrl,arymem,word_cnt,base), _is_large(is_large) { init_class_id(Class_ClearArray); } virtual int Opcode() const; @@ -1026,6 +1028,7 @@ public: virtual Node* Identity(PhaseGVN* phase); virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual uint match_edge(uint idx) const; + bool is_large() const { return _is_large; } // Clear the given area of an object or array. // The start offset must always be aligned mod BytesPerInt. diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index 42ca23d212a..78dcacc550b 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -576,17 +576,11 @@ void Node::setup_is_top() { //------------------------------~Node------------------------------------------ // Fancy destructor; eagerly attempt to reclaim Node numberings and storage -extern int reclaim_idx ; -extern int reclaim_in ; -extern int reclaim_node; void Node::destruct() { // Eagerly reclaim unique Node numberings Compile* compile = Compile::current(); if ((uint)_idx+1 == compile->unique()) { compile->set_unique(compile->unique()-1); -#ifdef ASSERT - reclaim_idx++; -#endif } // Clear debug info: Node_Notes* nn = compile->node_notes_at(_idx); @@ -604,43 +598,25 @@ void Node::destruct() { int out_edge_size = _outmax*sizeof(void*); char *edge_end = ((char*)_in) + edge_size; char *out_array = (char*)(_out == NO_OUT_ARRAY? NULL: _out); - char *out_edge_end = out_array + out_edge_size; int node_size = size_of(); // Free the output edge array if (out_edge_size > 0) { -#ifdef ASSERT - if( out_edge_end == compile->node_arena()->hwm() ) - reclaim_in += out_edge_size; // count reclaimed out edges with in edges -#endif compile->node_arena()->Afree(out_array, out_edge_size); } // Free the input edge array and the node itself if( edge_end == (char*)this ) { -#ifdef ASSERT - if( edge_end+node_size == compile->node_arena()->hwm() ) { - reclaim_in += edge_size; - reclaim_node+= node_size; - } -#else // It was; free the input array and object all in one hit +#ifndef ASSERT compile->node_arena()->Afree(_in,edge_size+node_size); #endif } else { - // Free just the input array -#ifdef ASSERT - if( edge_end == compile->node_arena()->hwm() ) - reclaim_in += edge_size; -#endif compile->node_arena()->Afree(_in,edge_size); // Free just the object -#ifdef ASSERT - if( ((char*)this) + node_size == compile->node_arena()->hwm() ) - reclaim_node+= node_size; -#else +#ifndef ASSERT compile->node_arena()->Afree(this,node_size); #endif } diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index c8a35c9ba53..b26a59f8497 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -104,13 +104,6 @@ public: // For temporary (stack-allocated, stateless) ilts: InlineTree(Compile* c, ciMethod* callee_method, JVMState* caller_jvms, float site_invoke_ratio, int max_inline_level); - // InlineTree enum - enum InlineStyle { - Inline_do_not_inline = 0, // - Inline_cha_is_monomorphic = 1, // - Inline_type_profile_monomorphic = 2 // - }; - // See if it is OK to inline. // The receiver is the inline tree for the caller. // @@ -349,9 +342,6 @@ class Parse : public GraphKit { Block* _block; // block currently getting parsed ciBytecodeStream _iter; // stream of this method's bytecodes - int _blocks_merged; // Progress meter: state merges from BB preds - int _blocks_parsed; // Progress meter: BBs actually parsed - const FastLockNode* _synch_lock; // FastLockNode for synchronized method #ifndef PRODUCT diff --git a/hotspot/src/share/vm/opto/parse1.cpp b/hotspot/src/share/vm/opto/parse1.cpp index e051b5e1e5c..503f3c7f400 100644 --- a/hotspot/src/share/vm/opto/parse1.cpp +++ b/hotspot/src/share/vm/opto/parse1.cpp @@ -45,6 +45,7 @@ // the most. Some of the non-static variables are needed in bytecodeInfo.cpp // and eventually should be encapsulated in a proper class (gri 8/18/98). +#ifndef PRODUCT int nodes_created = 0; int methods_parsed = 0; int methods_seen = 0; @@ -53,42 +54,42 @@ int blocks_seen = 0; int explicit_null_checks_inserted = 0; int explicit_null_checks_elided = 0; -int all_null_checks_found = 0, implicit_null_checks = 0; -int implicit_null_throws = 0; +int all_null_checks_found = 0; +int implicit_null_checks = 0; -int reclaim_idx = 0; -int reclaim_in = 0; -int reclaim_node = 0; - -#ifndef PRODUCT bool Parse::BytecodeParseHistogram::_initialized = false; uint Parse::BytecodeParseHistogram::_bytecodes_parsed [Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_nodes_constructed[Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_nodes_transformed[Bytecodes::number_of_codes]; uint Parse::BytecodeParseHistogram::_new_values [Bytecodes::number_of_codes]; -#endif //------------------------------print_statistics------------------------------- -#ifndef PRODUCT void Parse::print_statistics() { tty->print_cr("--- Compiler Statistics ---"); tty->print("Methods seen: %d Methods parsed: %d", methods_seen, methods_parsed); tty->print(" Nodes created: %d", nodes_created); tty->cr(); - if (methods_seen != methods_parsed) + if (methods_seen != methods_parsed) { tty->print_cr("Reasons for parse failures (NOT cumulative):"); + } tty->print_cr("Blocks parsed: %d Blocks seen: %d", blocks_parsed, blocks_seen); - if( explicit_null_checks_inserted ) - tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", explicit_null_checks_inserted, explicit_null_checks_elided, (100*explicit_null_checks_elided)/explicit_null_checks_inserted, all_null_checks_found); - if( all_null_checks_found ) + if (explicit_null_checks_inserted) { + tty->print_cr("%d original NULL checks - %d elided (%2d%%); optimizer leaves %d,", + explicit_null_checks_inserted, explicit_null_checks_elided, + (100*explicit_null_checks_elided)/explicit_null_checks_inserted, + all_null_checks_found); + } + if (all_null_checks_found) { tty->print_cr("%d made implicit (%2d%%)", implicit_null_checks, (100*implicit_null_checks)/all_null_checks_found); - if( implicit_null_throws ) + } + if (SharedRuntime::_implicit_null_throws) { tty->print_cr("%d implicit null exceptions at runtime", - implicit_null_throws); + SharedRuntime::_implicit_null_throws); + } - if( PrintParseStatistics && BytecodeParseHistogram::initialized() ) { + if (PrintParseStatistics && BytecodeParseHistogram::initialized()) { BytecodeParseHistogram::print(); } } @@ -495,7 +496,7 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) C->dependencies()->assert_evol_method(method()); } - methods_seen++; + NOT_PRODUCT(methods_seen++); // Do some special top-level things. if (depth() == 1 && C->is_osr_compilation()) { @@ -530,8 +531,8 @@ Parse::Parse(JVMState* caller, ciMethod* parse_method, float expected_uses) } #endif - methods_parsed++; #ifndef PRODUCT + methods_parsed++; // add method size here to guarantee that inlined methods are added too if (CITime) _total_bytes_compiled += method()->code_size(); @@ -652,7 +653,7 @@ void Parse::do_all_blocks() { continue; } - blocks_parsed++; + NOT_PRODUCT(blocks_parsed++); progress = true; if (block->is_loop_head() || block->is_handler() || has_irreducible && !block->is_ready()) { @@ -712,9 +713,9 @@ void Parse::do_all_blocks() { } } +#ifndef PRODUCT blocks_seen += block_count(); -#ifndef PRODUCT // Make sure there are no half-processed blocks remaining. // Every remaining unprocessed block is dead and may be ignored now. for (int rpo = 0; rpo < block_count(); rpo++) { @@ -1446,7 +1447,6 @@ void Parse::do_one_block() { assert(block()->is_merged(), "must be merged before being parsed"); block()->mark_parsed(); - ++_blocks_parsed; // Set iterator to start of block. iter().reset_to_bci(block()->start()); @@ -1596,9 +1596,6 @@ void Parse::merge_common(Parse::Block* target, int pnum) { return; } - // Record that a new block has been merged. - ++_blocks_merged; - // Make a region if we know there are multiple or unpredictable inputs. // (Also, if this is a plain fall-through, we might see another region, // which must not be allowed into this block's map.) diff --git a/hotspot/src/share/vm/opto/parse2.cpp b/hotspot/src/share/vm/opto/parse2.cpp index e03abd4f931..8004ef246e5 100644 --- a/hotspot/src/share/vm/opto/parse2.cpp +++ b/hotspot/src/share/vm/opto/parse2.cpp @@ -44,8 +44,10 @@ #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" +#ifndef PRODUCT extern int explicit_null_checks_inserted, explicit_null_checks_elided; +#endif //---------------------------------array_load---------------------------------- void Parse::array_load(BasicType elem_type) { @@ -997,7 +999,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { return; } - explicit_null_checks_inserted++; + NOT_PRODUCT(explicit_null_checks_inserted++); // Generate real control flow Node *tst = _gvn.transform( new BoolNode( c, btest ) ); @@ -1013,7 +1015,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { set_control(iftrue); if (stopped()) { // Path is dead? - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); if (C->eliminate_boxing()) { // Mark the successor block as parsed branch_block->next_path_num(); @@ -1033,7 +1035,7 @@ void Parse::do_ifnull(BoolTest::mask btest, Node *c) { set_control(iffalse); if (stopped()) { // Path is dead? - explicit_null_checks_elided++; + NOT_PRODUCT(explicit_null_checks_elided++); if (C->eliminate_boxing()) { // Mark the successor block as parsed next_block->next_path_num(); diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index 5e14b9d5abc..781a53cc00b 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -287,7 +287,7 @@ uint PhaseChaitin::split_USE(MachSpillCopyNode::SpillType spill_type, Node *def, Node* clone_node(Node* def, Block *b, Compile* C) { if (def->needs_anti_dependence_check()) { #ifdef ASSERT - if (Verbose) { + if (PrintOpto && WizardMode) { tty->print_cr("RA attempts to clone node with anti_dependence:"); def->dump(-1); tty->cr(); tty->print_cr("into block:"); diff --git a/hotspot/src/share/vm/opto/runtime.cpp b/hotspot/src/share/vm/opto/runtime.cpp index 1d6bdfb6230..dff0da6161b 100644 --- a/hotspot/src/share/vm/opto/runtime.cpp +++ b/hotspot/src/share/vm/opto/runtime.cpp @@ -220,22 +220,17 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_instance_C(Klass* klass, JavaThread* thre // These checks are cheap to make and support reflective allocation. int lh = klass->layout_helper(); - if (Klass::layout_helper_needs_slow_path(lh) - || !InstanceKlass::cast(klass)->is_initialized()) { - KlassHandle kh(THREAD, klass); - kh->check_valid_for_instantiation(false, THREAD); + if (Klass::layout_helper_needs_slow_path(lh) || !InstanceKlass::cast(klass)->is_initialized()) { + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive + klass->check_valid_for_instantiation(false, THREAD); if (!HAS_PENDING_EXCEPTION) { - InstanceKlass::cast(kh())->initialize(THREAD); - } - if (!HAS_PENDING_EXCEPTION) { - klass = kh(); - } else { - klass = NULL; + InstanceKlass::cast(klass)->initialize(THREAD); } } - if (klass != NULL) { + if (!HAS_PENDING_EXCEPTION) { // Scavenge and allocate an instance. + Handle holder(THREAD, klass->klass_holder()); // keep the klass alive oop result = InstanceKlass::cast(klass)->allocate_instance(THREAD); thread->set_vm_result(result); @@ -275,6 +270,7 @@ JRT_BLOCK_ENTRY(void, OptoRuntime::new_array_C(Klass* array_type, int len, JavaT // Although the oopFactory likes to work with the elem_type, // the compiler prefers the array_type, since it must already have // that latter value in hand for the fast path. + Handle holder(THREAD, array_type->klass_holder()); // keep the array klass alive Klass* elem_type = ObjArrayKlass::cast(array_type)->element_klass(); result = oopFactory::new_objArray(elem_type, len, THREAD); } @@ -353,6 +349,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray2_C(Klass* elem_type, int len1, int l jint dims[2]; dims[0] = len1; dims[1] = len2; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(2, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -369,6 +366,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray3_C(Klass* elem_type, int len1, int l dims[0] = len1; dims[1] = len2; dims[2] = len3; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(3, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -386,6 +384,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray4_C(Klass* elem_type, int len1, int l dims[1] = len2; dims[2] = len3; dims[3] = len4; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(4, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -404,6 +403,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarray5_C(Klass* elem_type, int len1, int l dims[2] = len3; dims[3] = len4; dims[4] = len5; + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(5, dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); @@ -421,6 +421,7 @@ JRT_ENTRY(void, OptoRuntime::multianewarrayN_C(Klass* elem_type, arrayOopDesc* d jint *c_dims = NEW_RESOURCE_ARRAY(jint, len); Copy::conjoint_jints_atomic(j_dims, c_dims, len); + Handle holder(THREAD, elem_type->klass_holder()); // keep the klass alive oop obj = ArrayKlass::cast(elem_type)->multi_allocate(len, c_dims, THREAD); deoptimize_caller_frame(thread, HAS_PENDING_EXCEPTION); thread->set_vm_result(obj); diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index d4808682944..40e3c92668a 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -73,6 +73,7 @@ #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" #include "services/runtimeService.hpp" +#include "trace/traceMacros.hpp" #include "trace/tracing.hpp" #include "utilities/defaultStream.hpp" #include "utilities/dtrace.hpp" @@ -88,7 +89,7 @@ #include "jvmci/jvmciRuntime.hpp" #endif -static jint CurrentVersion = JNI_VERSION_1_8; +static jint CurrentVersion = JNI_VERSION_9; #ifdef _WIN32 extern LONG WINAPI topLevelExceptionFilter(_EXCEPTION_POINTERS* ); @@ -930,13 +931,7 @@ class JNI_ArgumentPusherVaArg : public JNI_ArgumentPusher { _arguments->push_oop(Handle((oop *)l, false)); } inline void set_ap(va_list rap) { -#ifdef va_copy va_copy(_ap, rap); -#elif defined (__va_copy) - __va_copy(_ap, rap); -#else - _ap = rap; -#endif } public: @@ -3935,7 +3930,7 @@ static jint JNI_CreateJavaVM_inner(JavaVM **vm, void **penv, void *args) { EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } @@ -4155,7 +4150,7 @@ static jint attach_current_thread(JavaVM *vm, void **penv, void *_args, bool dae EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } diff --git a/hotspot/src/share/vm/prims/jni.h b/hotspot/src/share/vm/prims/jni.h index 582f2c97024..564499f83da 100644 --- a/hotspot/src/share/vm/prims/jni.h +++ b/hotspot/src/share/vm/prims/jni.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1952,6 +1952,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved); #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 #ifdef __cplusplus } /* extern "C" */ diff --git a/hotspot/src/share/vm/prims/jvmtiExport.cpp b/hotspot/src/share/vm/prims/jvmtiExport.cpp index 2c352044f02..7ad054138c6 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.cpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.cpp @@ -2200,6 +2200,16 @@ extern "C" { } jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { + // get agent name and options + const char* agent = op->arg(0); + const char* absParam = op->arg(1); + const char* options = op->arg(2); + + return load_agent_library(agent, absParam, options, st); +} + +jint JvmtiExport::load_agent_library(const char *agent, const char *absParam, + const char *options, outputStream* st) { char ebuf[1024]; char buffer[JVM_MAXPATHLEN]; void* library = NULL; @@ -2207,11 +2217,6 @@ jint JvmtiExport::load_agent_library(AttachOperation* op, outputStream* st) { const char *on_attach_symbols[] = AGENT_ONATTACH_SYMBOLS; size_t num_symbol_entries = ARRAY_SIZE(on_attach_symbols); - // get agent name and options - const char* agent = op->arg(0); - const char* absParam = op->arg(1); - const char* options = op->arg(2); - // The abs paramter should be "true" or "false" bool is_absolute_path = (absParam != NULL) && (strcmp(absParam,"true")==0); diff --git a/hotspot/src/share/vm/prims/jvmtiExport.hpp b/hotspot/src/share/vm/prims/jvmtiExport.hpp index 4b1ff34cf61..8b06d62104b 100644 --- a/hotspot/src/share/vm/prims/jvmtiExport.hpp +++ b/hotspot/src/share/vm/prims/jvmtiExport.hpp @@ -372,6 +372,7 @@ class JvmtiExport : public AllStatic { static void transition_pending_onload_raw_monitors() NOT_JVMTI_RETURN; // attach support + static jint load_agent_library(const char *agent, const char *absParam, const char *options, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR); static jint load_agent_library(AttachOperation* op, outputStream* out) NOT_JVMTI_RETURN_(JNI_ERR); // SetNativeMethodPrefix support diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 8823e6670a6..6b176ec1f70 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -3940,6 +3940,10 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, scratch_class->set_methods(_old_methods); // To prevent potential GCing of the old methods, // and to be able to undo operation easily. + Array* old_ordering = the_class->method_ordering(); + the_class->set_method_ordering(scratch_class->method_ordering()); + scratch_class->set_method_ordering(old_ordering); + ConstantPool* old_constants = the_class->constants(); the_class->set_constants(scratch_class->constants()); scratch_class->set_constants(old_constants); // See the previous comment. diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index b1909cdfaa0..38b68a40422 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,7 @@ #include "prims/jvmtiRedefineClassesTrace.hpp" #include "runtime/compilationPolicy.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/logTimer.hpp" #include "runtime/reflection.hpp" #include "runtime/signature.hpp" #include "runtime/stubRoutines.hpp" @@ -72,7 +73,7 @@ void MethodHandles::generate_adapters() { assert(_adapter_code == NULL, "generate only once"); ResourceMark rm; - TraceTime timer("MethodHandles adapters generation", TraceStartupTime); + TraceStartupTime timer("MethodHandles adapters generation"); _adapter_code = MethodHandlesAdapterBlob::create(adapter_code_size); CodeBuffer code(_adapter_code); MethodHandlesAdapterGenerator g(&code); diff --git a/hotspot/src/share/vm/prims/nativeLookup.cpp b/hotspot/src/share/vm/prims/nativeLookup.cpp index c89e4f10c32..51525c26f2d 100644 --- a/hotspot/src/share/vm/prims/nativeLookup.cpp +++ b/hotspot/src/share/vm/prims/nativeLookup.cpp @@ -35,6 +35,7 @@ #include "oops/symbol.hpp" #include "prims/jvm_misc.hpp" #include "prims/nativeLookup.hpp" +#include "prims/unsafe.hpp" #include "runtime/arguments.hpp" #include "runtime/handles.inline.hpp" #include "runtime/javaCalls.hpp" @@ -107,8 +108,6 @@ char* NativeLookup::long_jni_name(const methodHandle& method) { } extern "C" { - void JNICALL JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafecls); - void JNICALL JVM_RegisterSunMiscUnsafeMethods(JNIEnv *env, jclass unsafecls); void JNICALL JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass unsafecls); void JNICALL JVM_RegisterPerfMethods(JNIEnv *env, jclass perfclass); void JNICALL JVM_RegisterWhiteBoxMethods(JNIEnv *env, jclass wbclass); @@ -123,7 +122,6 @@ extern "C" { static JNINativeMethod lookup_special_native_methods[] = { { CC"Java_jdk_internal_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterJDKInternalMiscUnsafeMethods) }, - { CC"Java_sun_misc_Unsafe_registerNatives", NULL, FN_PTR(JVM_RegisterSunMiscUnsafeMethods) }, { CC"Java_java_lang_invoke_MethodHandleNatives_registerNatives", NULL, FN_PTR(JVM_RegisterMethodHandleMethods) }, { CC"Java_jdk_internal_perf_Perf_registerNatives", NULL, FN_PTR(JVM_RegisterPerfMethods) }, { CC"Java_sun_hotspot_WhiteBox_registerNatives", NULL, FN_PTR(JVM_RegisterWhiteBoxMethods) }, diff --git a/hotspot/src/share/vm/prims/unsafe.cpp b/hotspot/src/share/vm/prims/unsafe.cpp index cdd4334e229..dc60ebfd208 100644 --- a/hotspot/src/share/vm/prims/unsafe.cpp +++ b/hotspot/src/share/vm/prims/unsafe.cpp @@ -30,6 +30,7 @@ #include "oops/oop.inline.hpp" #include "prims/jni.h" #include "prims/jvm.h" +#include "prims/unsafe.hpp" #include "runtime/atomic.inline.hpp" #include "runtime/globals.hpp" #include "runtime/interfaceSupport.hpp" @@ -45,8 +46,8 @@ #include "gc/g1/g1SATBCardTableModRefBS.hpp" #endif // INCLUDE_ALL_GCS -/* - * Implementation of class Unsafe +/** + * Implementation of the jdk.internal.misc.Unsafe class */ @@ -56,25 +57,15 @@ #define UNSAFE_ENTRY(result_type, header) \ - JVM_ENTRY(result_type, header) + JVM_ENTRY(static result_type, header) -// Can't use UNSAFE_LEAF because it has the signature of a straight -// call into the runtime (just like JVM_LEAF, funny that) but it's -// called like a Java Native and thus the wrapper built for it passes -// arguments like a JNI call. It expects those arguments to be popped -// from the stack on Intel like all good JNI args are, and adjusts the -// stack according. Since the JVM_LEAF call expects no extra -// arguments the stack isn't popped in the C code, is pushed by the -// wrapper and we get sick. -//#define UNSAFE_LEAF(result_type, header) \ -// JVM_LEAF(result_type, header) +#define UNSAFE_LEAF(result_type, header) \ + JVM_LEAF(static result_type, header) #define UNSAFE_END JVM_END -#define UnsafeWrapper(arg) /*nothing, for the present*/ - -inline void* addr_from_java(jlong addr) { +static inline void* addr_from_java(jlong addr) { // This assert fails in a variety of ways on 32-bit systems. // It is impossible to predict whether native code that converts // pointers to longs will sign-extend or zero-extend the addresses. @@ -82,7 +73,7 @@ inline void* addr_from_java(jlong addr) { return (void*)(uintptr_t)addr; } -inline jlong addr_to_java(void* p) { +static inline jlong addr_to_java(void* p) { assert(p == (void*)(uintptr_t)p, "must not be odd high bits"); return (uintptr_t)p; } @@ -98,24 +89,17 @@ inline jlong addr_to_java(void* p) { // through conversion functions when going between the VM and the Unsafe API. // The conversion functions just happen to be no-ops at present. -inline jlong field_offset_to_byte_offset(jlong field_offset) { +static inline jlong field_offset_to_byte_offset(jlong field_offset) { return field_offset; } -inline jlong field_offset_from_byte_offset(jlong byte_offset) { +static inline jlong field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } -inline jint invocation_key_from_method_slot(jint slot) { - return slot; -} - -inline jint invocation_key_to_method_slot(jint key) { - return key; -} - -inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { +static inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { jlong byte_offset = field_offset_to_byte_offset(field_offset); + #ifdef ASSERT if (p != NULL) { assert(byte_offset >= 0 && byte_offset <= (jlong)MAX_OBJECT_SIZE, "sane offset"); @@ -128,10 +112,12 @@ inline void* index_oop_from_field_offset_long(oop p, jlong field_offset) { assert(byte_offset < p_size, "Unsafe access: offset " INT64_FORMAT " > object's size " INT64_FORMAT, byte_offset, p_size); } #endif - if (sizeof(char*) == sizeof(jint)) // (this constant folds!) + + if (sizeof(char*) == sizeof(jint)) { // (this constant folds!) return (address)p + (jint) byte_offset; - else + } else { return (address)p + byte_offset; + } } // Externally callable versions: @@ -142,12 +128,6 @@ jlong Unsafe_field_offset_to_byte_offset(jlong field_offset) { jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset) { return byte_offset; } -jint Unsafe_invocation_key_from_method_slot(jint slot) { - return invocation_key_from_method_slot(slot); -} -jint Unsafe_invocation_key_to_method_slot(jint key) { - return invocation_key_to_method_slot(key); -} ///// Data in the Java heap. @@ -177,17 +157,19 @@ jint Unsafe_invocation_key_to_method_slot(jint key) { // These functions allow a null base pointer with an arbitrary address. // But if the base pointer is non-null, the offset should make some sense. // That is, it should be in the range [0, MAX_OBJECT_SIZE]. -UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) - UnsafeWrapper("Unsafe_GetObject"); +UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); oop v; + if (UseCompressedOops) { narrowOop n = *(narrowOop*)index_oop_from_field_offset_long(p, offset); v = oopDesc::decode_heap_oop(n); } else { v = *(oop*)index_oop_from_field_offset_long(p, offset); } + jobject ret = JNIHandles::make_local(env, v); + #if INCLUDE_ALL_GCS // We could be accessing the referent field in a reference // object. If G1 is enabled then we need to register non-null @@ -212,67 +194,71 @@ UNSAFE_ENTRY(jobject, Unsafe_GetObject(JNIEnv *env, jobject unsafe, jobject obj, } } #endif // INCLUDE_ALL_GCS - return ret; -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) - UnsafeWrapper("Unsafe_SetObject"); + return ret; +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); + if (UseCompressedOops) { oop_store((narrowOop*)index_oop_from_field_offset_long(p, offset), x); } else { oop_store((oop*)index_oop_from_field_offset_long(p, offset), x); } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) - UnsafeWrapper("Unsafe_GetObjectVolatile"); +UNSAFE_ENTRY(jobject, Unsafe_GetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); + volatile oop v; + if (UseCompressedOops) { volatile narrowOop n = *(volatile narrowOop*) addr; (void)const_cast(v = oopDesc::decode_heap_oop(n)); } else { (void)const_cast(v = *(volatile oop*) addr); } + OrderAccess::acquire(); return JNIHandles::make_local(env, v); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) - UnsafeWrapper("Unsafe_SetObjectVolatile"); +UNSAFE_ENTRY(void, Unsafe_SetObjectVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); OrderAccess::release(); + if (UseCompressedOops) { oop_store((narrowOop*)addr, x); } else { oop_store((oop*)addr, x); } + OrderAccess::fence(); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_GetUncompressedObject"); +UNSAFE_ENTRY(jobject, Unsafe_GetUncompressedObject(JNIEnv *env, jobject unsafe, jlong addr)) { oop v = *(oop*) (address) addr; + return JNIHandles::make_local(env, v); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass)) - UnsafeWrapper("Unsafe_GetJavaMirror"); +UNSAFE_ENTRY(jclass, Unsafe_GetJavaMirror(JNIEnv *env, jobject unsafe, jlong metaspace_klass)) { Klass* klass = (Klass*) (address) metaspace_klass; - return (jclass) JNIHandles::make_local(klass->java_mirror()); -UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj)) - UnsafeWrapper("Unsafe_GetKlassPointer"); + return (jclass) JNIHandles::make_local(klass->java_mirror()); +} UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_GetKlassPointer(JNIEnv *env, jobject unsafe, jobject obj)) { oop o = JNIHandles::resolve(obj); jlong klass = (jlong) (address) o->klass(); + return klass; -UNSAFE_END +} UNSAFE_END #ifndef SUPPORTS_NATIVE_CX8 @@ -303,83 +289,54 @@ UNSAFE_END // the address of the field _after_ we have acquired the lock, else the object may have // been moved by the GC -UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) - UnsafeWrapper("Unsafe_GetLongVolatile"); - { - if (VM_Version::supports_cx8()) { - GET_FIELD_VOLATILE(obj, offset, jlong, v); - return v; - } - else { - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - jlong value = Atomic::load(addr); - return value; - } +UNSAFE_ENTRY(jlong, Unsafe_GetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { + if (VM_Version::supports_cx8()) { + GET_FIELD_VOLATILE(obj, offset, jlong, v); + return v; + } else { + Handle p (THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong value = Atomic::load(addr); + return value; } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) - UnsafeWrapper("Unsafe_SetLongVolatile"); - { - if (VM_Version::supports_cx8()) { - SET_FIELD_VOLATILE(obj, offset, jlong, x); - } - else { - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - Atomic::store(x, addr); - } +UNSAFE_ENTRY(void, Unsafe_SetLongVolatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) { + if (VM_Version::supports_cx8()) { + SET_FIELD_VOLATILE(obj, offset, jlong, x); + } else { + Handle p (THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } -UNSAFE_END +} UNSAFE_END #endif // not SUPPORTS_NATIVE_CX8 -UNSAFE_ENTRY(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_IsBigEndian0"); - { +UNSAFE_LEAF(jboolean, Unsafe_isBigEndian0(JNIEnv *env, jobject unsafe)) { #ifdef VM_LITTLE_ENDIAN - return false; + return false; #else - return true; + return true; #endif - } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_UnalignedAccess0"); - { - return UseUnalignedAccesses; - } -UNSAFE_END +UNSAFE_LEAF(jint, Unsafe_unalignedAccess0(JNIEnv *env, jobject unsafe)) { + return UseUnalignedAccesses; +} UNSAFE_END -#define DEFINE_GETSETOOP(jboolean, Boolean) \ +#define DEFINE_GETSETOOP(java_type, Type) \ \ -UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset)) \ - UnsafeWrapper("Unsafe_Get"#Boolean); \ - if (obj == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); \ - GET_FIELD(obj, offset, jboolean, v); \ +UNSAFE_ENTRY(java_type, Unsafe_Get##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ + GET_FIELD(obj, offset, java_type, v); \ return v; \ -UNSAFE_END \ +} UNSAFE_END \ \ -UNSAFE_ENTRY(void, Unsafe_Set##Boolean##140(JNIEnv *env, jobject unsafe, jobject obj, jint offset, jboolean x)) \ - UnsafeWrapper("Unsafe_Set"#Boolean); \ - if (obj == NULL) THROW(vmSymbols::java_lang_NullPointerException()); \ - SET_FIELD(obj, offset, jboolean, x); \ -UNSAFE_END \ - \ -UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \ - UnsafeWrapper("Unsafe_Get"#Boolean); \ - GET_FIELD(obj, offset, jboolean, v); \ - return v; \ -UNSAFE_END \ - \ -UNSAFE_ENTRY(void, Unsafe_Set##Boolean(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \ - UnsafeWrapper("Unsafe_Set"#Boolean); \ - SET_FIELD(obj, offset, jboolean, x); \ -UNSAFE_END \ +UNSAFE_ENTRY(void, Unsafe_Set##Type(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ + SET_FIELD(obj, offset, java_type, x); \ +} UNSAFE_END \ \ // END DEFINE_GETSETOOP. @@ -394,18 +351,16 @@ DEFINE_GETSETOOP(jdouble, Double); #undef DEFINE_GETSETOOP -#define DEFINE_GETSETOOP_VOLATILE(jboolean, Boolean) \ +#define DEFINE_GETSETOOP_VOLATILE(java_type, Type) \ \ -UNSAFE_ENTRY(jboolean, Unsafe_Get##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) \ - UnsafeWrapper("Unsafe_Get"#Boolean); \ - GET_FIELD_VOLATILE(obj, offset, jboolean, v); \ +UNSAFE_ENTRY(java_type, Unsafe_Get##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset)) { \ + GET_FIELD_VOLATILE(obj, offset, java_type, v); \ return v; \ -UNSAFE_END \ +} UNSAFE_END \ \ -UNSAFE_ENTRY(void, Unsafe_Set##Boolean##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jboolean x)) \ - UnsafeWrapper("Unsafe_Set"#Boolean); \ - SET_FIELD_VOLATILE(obj, offset, jboolean, x); \ -UNSAFE_END \ +UNSAFE_ENTRY(void, Unsafe_Set##Type##Volatile(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, java_type x)) { \ + SET_FIELD_VOLATILE(obj, offset, java_type, x); \ +} UNSAFE_END \ \ // END DEFINE_GETSETOOP_VOLATILE. @@ -425,59 +380,53 @@ DEFINE_GETSETOOP_VOLATILE(jlong, Long); // The non-intrinsified versions of setOrdered just use setVolatile -UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) - UnsafeWrapper("Unsafe_SetOrderedInt"); +UNSAFE_ENTRY(void, Unsafe_SetOrderedInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint x)) { SET_FIELD_VOLATILE(obj, offset, jint, x); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) - UnsafeWrapper("Unsafe_SetOrderedObject"); +UNSAFE_ENTRY(void, Unsafe_SetOrderedObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop p = JNIHandles::resolve(obj); void* addr = index_oop_from_field_offset_long(p, offset); OrderAccess::release(); + if (UseCompressedOops) { oop_store((narrowOop*)addr, x); } else { oop_store((oop*)addr, x); } - OrderAccess::fence(); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) - UnsafeWrapper("Unsafe_SetOrderedLong"); + OrderAccess::fence(); +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetOrderedLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong x)) { #ifdef SUPPORTS_NATIVE_CX8 SET_FIELD_VOLATILE(obj, offset, jlong, x); #else + // Keep old code for platforms which may not have atomic long (8 bytes) instructions - { - if (VM_Version::supports_cx8()) { - SET_FIELD_VOLATILE(obj, offset, jlong, x); - } - else { - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); - MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); - Atomic::store(x, addr); - } + if (VM_Version::supports_cx8()) { + SET_FIELD_VOLATILE(obj, offset, jlong, x); + } else { + Handle p(THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + Atomic::store(x, addr); } #endif -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_LoadFence"); +UNSAFE_LEAF(void, Unsafe_LoadFence(JNIEnv *env, jobject unsafe)) { OrderAccess::acquire(); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_StoreFence"); +UNSAFE_LEAF(void, Unsafe_StoreFence(JNIEnv *env, jobject unsafe)) { OrderAccess::release(); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_FullFence"); +UNSAFE_LEAF(void, Unsafe_FullFence(JNIEnv *env, jobject unsafe)) { OrderAccess::fence(); -UNSAFE_END +} UNSAFE_END ////// Data in the C heap. @@ -486,24 +435,22 @@ UNSAFE_END // #define DEFINE_GETSETNATIVE(java_type, Type, native_type) \ \ -UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) \ - UnsafeWrapper("Unsafe_GetNative"#Type); \ +UNSAFE_ENTRY(java_type, Unsafe_GetNative##Type(JNIEnv *env, jobject unsafe, jlong addr)) { \ void* p = addr_from_java(addr); \ JavaThread* t = JavaThread::current(); \ t->set_doing_unsafe_access(true); \ java_type x = *(volatile native_type*)p; \ t->set_doing_unsafe_access(false); \ return x; \ -UNSAFE_END \ +} UNSAFE_END \ \ -UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) \ - UnsafeWrapper("Unsafe_SetNative"#Type); \ +UNSAFE_ENTRY(void, Unsafe_SetNative##Type(JNIEnv *env, jobject unsafe, jlong addr, java_type x)) { \ JavaThread* t = JavaThread::current(); \ t->set_doing_unsafe_access(true); \ void* p = addr_from_java(addr); \ *(volatile native_type*)p = x; \ t->set_doing_unsafe_access(false); \ -UNSAFE_END \ +} UNSAFE_END \ \ // END DEFINE_GETSETNATIVE. @@ -517,8 +464,7 @@ DEFINE_GETSETNATIVE(jdouble, Double, double); #undef DEFINE_GETSETNATIVE -UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_GetNativeLong"); +UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr)) { JavaThread* t = JavaThread::current(); // We do it this way to avoid problems with access to heap using 64 // bit loads, as jlong in heap could be not 64-bit aligned, and on @@ -526,7 +472,8 @@ UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr t->set_doing_unsafe_access(true); void* p = addr_from_java(addr); jlong x; - if (((intptr_t)p & 7) == 0) { + + if (is_ptr_aligned(p, sizeof(jlong)) == 0) { // jlong is aligned, do a volatile access x = *(volatile jlong*)p; } else { @@ -535,17 +482,19 @@ UNSAFE_ENTRY(jlong, Unsafe_GetNativeLong(JNIEnv *env, jobject unsafe, jlong addr acc.words[1] = ((volatile jint*)p)[1]; x = acc.long_value; } - t->set_doing_unsafe_access(false); - return x; -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) - UnsafeWrapper("Unsafe_SetNativeLong"); + t->set_doing_unsafe_access(false); + + return x; +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) { JavaThread* t = JavaThread::current(); // see comment for Unsafe_GetNativeLong t->set_doing_unsafe_access(true); void* p = addr_from_java(addr); - if (((intptr_t)p & 7) == 0) { + + if (is_ptr_aligned(p, sizeof(jlong))) { // jlong is aligned, do a volatile access *(volatile jlong*)p = x; } else { @@ -554,119 +503,81 @@ UNSAFE_ENTRY(void, Unsafe_SetNativeLong(JNIEnv *env, jobject unsafe, jlong addr, ((volatile jint*)p)[0] = acc.words[0]; ((volatile jint*)p)[1] = acc.words[1]; } + t->set_doing_unsafe_access(false); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_GetNativeAddress"); +UNSAFE_LEAF(jlong, Unsafe_GetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr)) { void* p = addr_from_java(addr); - return addr_to_java(*(void**)p); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) - UnsafeWrapper("Unsafe_SetNativeAddress"); + return addr_to_java(*(void**)p); +} UNSAFE_END + +UNSAFE_LEAF(void, Unsafe_SetNativeAddress(JNIEnv *env, jobject unsafe, jlong addr, jlong x)) { void* p = addr_from_java(addr); *(void**)p = addr_from_java(x); -UNSAFE_END +} UNSAFE_END ////// Allocation requests -UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) - UnsafeWrapper("Unsafe_AllocateInstance"); - { - ThreadToNativeFromVM ttnfv(thread); - return env->AllocObject(cls); - } -UNSAFE_END +UNSAFE_ENTRY(jobject, Unsafe_AllocateInstance(JNIEnv *env, jobject unsafe, jclass cls)) { + ThreadToNativeFromVM ttnfv(thread); + return env->AllocObject(cls); +} UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory(JNIEnv *env, jobject unsafe, jlong size)) - UnsafeWrapper("Unsafe_AllocateMemory"); +UNSAFE_ENTRY(jlong, Unsafe_AllocateMemory0(JNIEnv *env, jobject unsafe, jlong size)) { size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); - } - if (sz == 0) { - return 0; - } + sz = round_to(sz, HeapWordSize); void* x = os::malloc(sz, mtInternal); - if (x == NULL) { - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); - } - //Copy::fill_to_words((HeapWord*)x, sz / HeapWordSize); - return addr_to_java(x); -UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) - UnsafeWrapper("Unsafe_ReallocateMemory"); + return addr_to_java(x); +} UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_ReallocateMemory0(JNIEnv *env, jobject unsafe, jlong addr, jlong size)) { void* p = addr_from_java(addr); size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); - } - if (sz == 0) { - os::free(p); - return 0; - } sz = round_to(sz, HeapWordSize); - void* x = (p == NULL) ? os::malloc(sz, mtInternal) : os::realloc(p, sz, mtInternal); - if (x == NULL) { - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); - } + + void* x = os::realloc(p, sz, mtInternal); + return addr_to_java(x); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_FreeMemory(JNIEnv *env, jobject unsafe, jlong addr)) - UnsafeWrapper("Unsafe_FreeMemory"); +UNSAFE_ENTRY(void, Unsafe_FreeMemory0(JNIEnv *env, jobject unsafe, jlong addr)) { void* p = addr_from_java(addr); - if (p == NULL) { - return; - } - os::free(p); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_SetMemory(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value)) - UnsafeWrapper("Unsafe_SetMemory"); + os::free(p); +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_SetMemory0(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong size, jbyte value)) { size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW(vmSymbols::java_lang_IllegalArgumentException()); - } + oop base = JNIHandles::resolve(obj); void* p = index_oop_from_field_offset_long(base, offset); - Copy::fill_to_memory_atomic(p, sz, value); -UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_CopyMemory(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size)) - UnsafeWrapper("Unsafe_CopyMemory"); - if (size == 0) { - return; - } + Copy::fill_to_memory_atomic(p, sz, value); +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_CopyMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size)) { size_t sz = (size_t)size; - if (sz != (julong)size || size < 0) { - THROW(vmSymbols::java_lang_IllegalArgumentException()); - } + oop srcp = JNIHandles::resolve(srcObj); oop dstp = JNIHandles::resolve(dstObj); - if (dstp != NULL && !dstp->is_typeArray()) { - // NYI: This works only for non-oop arrays at present. - // Generalizing it would be reasonable, but requires card marking. - // Also, autoboxing a Long from 0L in copyMemory(x,y, 0L,z, n) would be bad. - THROW(vmSymbols::java_lang_IllegalArgumentException()); - } + void* src = index_oop_from_field_offset_long(srcp, srcOffset); void* dst = index_oop_from_field_offset_long(dstp, dstOffset); + Copy::conjoint_memory_atomic(src, dst, sz); -UNSAFE_END +} UNSAFE_END // This function is a leaf since if the source and destination are both in native memory // the copy may potentially be very large, and we don't want to disable GC if we can avoid it. // If either source or destination (or both) are on the heap, the function will enter VM using // JVM_ENTRY_FROM_LEAF -JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) { - UnsafeWrapper("Unsafe_CopySwapMemory0"); - +UNSAFE_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcObj, jlong srcOffset, jobject dstObj, jlong dstOffset, jlong size, jlong elemSize)) { size_t sz = (size_t)size; size_t esz = (size_t)elemSize; @@ -689,32 +600,24 @@ JVM_LEAF(void, Unsafe_CopySwapMemory0(JNIEnv *env, jobject unsafe, jobject srcOb Copy::conjoint_swap(src, dst, sz, esz); } JVM_END } -} JVM_END +} UNSAFE_END ////// Random queries -// See comment at file start about UNSAFE_LEAF -//UNSAFE_LEAF(jint, Unsafe_AddressSize()) -UNSAFE_ENTRY(jint, Unsafe_AddressSize(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_AddressSize"); +UNSAFE_LEAF(jint, Unsafe_AddressSize0(JNIEnv *env, jobject unsafe)) { return sizeof(void*); -UNSAFE_END +} UNSAFE_END -// See comment at file start about UNSAFE_LEAF -//UNSAFE_LEAF(jint, Unsafe_PageSize()) -UNSAFE_ENTRY(jint, Unsafe_PageSize(JNIEnv *env, jobject unsafe)) - UnsafeWrapper("Unsafe_PageSize"); +UNSAFE_LEAF(jint, Unsafe_PageSize()) { return os::vm_page_size(); -UNSAFE_END +} UNSAFE_END -jint find_field_offset(jobject field, int must_be_static, TRAPS) { - if (field == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); - } +static jint find_field_offset(jobject field, int must_be_static, TRAPS) { + assert(field != NULL, "field must not be NULL"); oop reflected = JNIHandles::resolve_non_null(field); oop mirror = java_lang_reflect_Field::clazz(reflected); - Klass* k = java_lang_Class::as_Klass(mirror); + Klass* k = java_lang_Class::as_Klass(mirror); int slot = java_lang_reflect_Field::slot(reflected); int modifiers = java_lang_reflect_Field::modifiers(reflected); @@ -729,18 +632,17 @@ jint find_field_offset(jobject field, int must_be_static, TRAPS) { return field_offset_from_byte_offset(offset); } -UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset(JNIEnv *env, jobject unsafe, jobject field)) - UnsafeWrapper("Unsafe_ObjectFieldOffset"); +UNSAFE_ENTRY(jlong, Unsafe_ObjectFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) { return find_field_offset(field, 0, THREAD); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset(JNIEnv *env, jobject unsafe, jobject field)) - UnsafeWrapper("Unsafe_StaticFieldOffset"); +UNSAFE_ENTRY(jlong, Unsafe_StaticFieldOffset0(JNIEnv *env, jobject unsafe, jobject field)) { return find_field_offset(field, 1, THREAD); -UNSAFE_END +} UNSAFE_END + +UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBase0(JNIEnv *env, jobject unsafe, jobject field)) { + assert(field != NULL, "field must not be NULL"); -UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsafe, jobject field)) - UnsafeWrapper("Unsafe_StaticFieldBase"); // Note: In this VM implementation, a field address is always a short // offset from the base of a a klass metaobject. Thus, the full dynamic // range of the return type is never used. However, some implementations @@ -749,8 +651,6 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsaf // large. In that last case, this function would return NULL, since // the address would operate alone, without any base pointer. - if (field == NULL) THROW_0(vmSymbols::java_lang_NullPointerException()); - oop reflected = JNIHandles::resolve_non_null(field); oop mirror = java_lang_reflect_Field::clazz(reflected); int modifiers = java_lang_reflect_Field::modifiers(reflected); @@ -760,13 +660,11 @@ UNSAFE_ENTRY(jobject, Unsafe_StaticFieldBaseFromField(JNIEnv *env, jobject unsaf } return JNIHandles::make_local(env, mirror); -UNSAFE_END +} UNSAFE_END + +UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) { + assert(clazz != NULL, "clazz must not be NULL"); -UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jobject clazz)) { - UnsafeWrapper("Unsafe_EnsureClassInitialized"); - if (clazz == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } oop mirror = JNIHandles::resolve_non_null(clazz); Klass* klass = java_lang_Class::as_Klass(mirror); @@ -777,26 +675,26 @@ UNSAFE_ENTRY(void, Unsafe_EnsureClassInitialized(JNIEnv *env, jobject unsafe, jo } UNSAFE_END -UNSAFE_ENTRY(jboolean, Unsafe_ShouldBeInitialized(JNIEnv *env, jobject unsafe, jobject clazz)) { - UnsafeWrapper("Unsafe_ShouldBeInitialized"); - if (clazz == NULL) { - THROW_(vmSymbols::java_lang_NullPointerException(), false); - } +UNSAFE_ENTRY(jboolean, Unsafe_ShouldBeInitialized0(JNIEnv *env, jobject unsafe, jobject clazz)) { + assert(clazz != NULL, "clazz must not be NULL"); + oop mirror = JNIHandles::resolve_non_null(clazz); Klass* klass = java_lang_Class::as_Klass(mirror); + if (klass != NULL && klass->should_be_initialized()) { return true; } + return false; } UNSAFE_END -static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { - if (acls == NULL) { - THROW(vmSymbols::java_lang_NullPointerException()); - } - oop mirror = JNIHandles::resolve_non_null(acls); - Klass* k = java_lang_Class::as_Klass(mirror); +static void getBaseAndScale(int& base, int& scale, jclass clazz, TRAPS) { + assert(clazz != NULL, "clazz must not be NULL"); + + oop mirror = JNIHandles::resolve_non_null(clazz); + Klass* k = java_lang_Class::as_Klass(mirror); + if (k == NULL || !k->is_array_klass()) { THROW(vmSymbols::java_lang_InvalidClassException()); } else if (k->is_objArray_klass()) { @@ -812,18 +710,18 @@ static void getBaseAndScale(int& base, int& scale, jclass acls, TRAPS) { } } -UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset(JNIEnv *env, jobject unsafe, jclass acls)) - UnsafeWrapper("Unsafe_ArrayBaseOffset"); +UNSAFE_ENTRY(jint, Unsafe_ArrayBaseOffset0(JNIEnv *env, jobject unsafe, jclass clazz)) { int base = 0, scale = 0; - getBaseAndScale(base, scale, acls, CHECK_0); + getBaseAndScale(base, scale, clazz, CHECK_0); + return field_offset_from_byte_offset(base); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass acls)) - UnsafeWrapper("Unsafe_ArrayIndexScale"); +UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale0(JNIEnv *env, jobject unsafe, jclass clazz)) { int base = 0, scale = 0; - getBaseAndScale(base, scale, acls, CHECK_0); + getBaseAndScale(base, scale, clazz, CHECK_0); + // This VM packs both fields and array elements down to the byte. // But watch out: If this changes, so that array references for // a given primitive type (say, T_BOOLEAN) use different memory units @@ -839,100 +737,88 @@ UNSAFE_ENTRY(jint, Unsafe_ArrayIndexScale(JNIEnv *env, jobject unsafe, jclass ac // The following allows for a pretty general fieldOffset cookie scheme, // but requires it to be linear in byte offset. return field_offset_from_byte_offset(scale) - field_offset_from_byte_offset(0); -UNSAFE_END +} UNSAFE_END static inline void throw_new(JNIEnv *env, const char *ename) { char buf[100]; + jio_snprintf(buf, 100, "%s%s", "java/lang/", ename); + jclass cls = env->FindClass(buf); if (env->ExceptionCheck()) { env->ExceptionClear(); tty->print_cr("Unsafe: cannot throw %s because FindClass has failed", buf); return; } - char* msg = NULL; - env->ThrowNew(cls, msg); + + env->ThrowNew(cls, NULL); } static jclass Unsafe_DefineClass_impl(JNIEnv *env, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd) { - { - // Code lifted from JDK 1.3 ClassLoader.c + // Code lifted from JDK 1.3 ClassLoader.c - jbyte *body; - char *utfName; - jclass result = 0; - char buf[128]; + jbyte *body; + char *utfName = NULL; + jclass result = 0; + char buf[128]; - if (UsePerfData) { - ClassLoader::unsafe_defineClassCallCounter()->inc(); - } + assert(data != NULL, "Class bytes must not be NULL"); + assert(length >= 0, "length must not be negative: %d", length); - if (data == NULL) { - throw_new(env, "NullPointerException"); - return 0; - } + if (UsePerfData) { + ClassLoader::unsafe_defineClassCallCounter()->inc(); + } - /* Work around 4153825. malloc crashes on Solaris when passed a - * negative size. - */ - if (length < 0) { - throw_new(env, "ArrayIndexOutOfBoundsException"); - return 0; - } + body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal); + if (body == NULL) { + throw_new(env, "OutOfMemoryError"); + return 0; + } - body = NEW_C_HEAP_ARRAY(jbyte, length, mtInternal); + env->GetByteArrayRegion(data, offset, length, body); + if (env->ExceptionOccurred()) { + goto free_body; + } - if (body == 0) { + if (name != NULL) { + uint len = env->GetStringUTFLength(name); + int unicode_len = env->GetStringLength(name); + + if (len >= sizeof(buf)) { + utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); + if (utfName == NULL) { throw_new(env, "OutOfMemoryError"); - return 0; - } - - env->GetByteArrayRegion(data, offset, length, body); - - if (env->ExceptionOccurred()) goto free_body; - - if (name != NULL) { - uint len = env->GetStringUTFLength(name); - int unicode_len = env->GetStringLength(name); - if (len >= sizeof(buf)) { - utfName = NEW_C_HEAP_ARRAY(char, len + 1, mtInternal); - if (utfName == NULL) { - throw_new(env, "OutOfMemoryError"); - goto free_body; - } - } else { - utfName = buf; - } - env->GetStringUTFRegion(name, 0, unicode_len, utfName); - //VerifyFixClassname(utfName); - for (uint i = 0; i < len; i++) { - if (utfName[i] == '.') utfName[i] = '/'; - } + } } else { - utfName = NULL; + utfName = buf; } - result = JVM_DefineClass(env, utfName, loader, body, length, pd); + env->GetStringUTFRegion(name, 0, unicode_len, utfName); - if (utfName && utfName != buf) - FREE_C_HEAP_ARRAY(char, utfName); + for (uint i = 0; i < len; i++) { + if (utfName[i] == '.') utfName[i] = '/'; + } + } + + result = JVM_DefineClass(env, utfName, loader, body, length, pd); + + if (utfName && utfName != buf) { + FREE_C_HEAP_ARRAY(char, utfName); + } free_body: - FREE_C_HEAP_ARRAY(jbyte, body); - return result; - } + FREE_C_HEAP_ARRAY(jbyte, body); + return result; } -UNSAFE_ENTRY(jclass, Unsafe_DefineClass(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd)) - UnsafeWrapper("Unsafe_DefineClass"); - { - ThreadToNativeFromVM ttnfv(thread); - return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd); - } -UNSAFE_END +UNSAFE_ENTRY(jclass, Unsafe_DefineClass0(JNIEnv *env, jobject unsafe, jstring name, jbyteArray data, int offset, int length, jobject loader, jobject pd)) { + ThreadToNativeFromVM ttnfv(thread); + + return Unsafe_DefineClass_impl(env, name, data, offset, length, loader, pd); +} UNSAFE_END // define a class but do not make it known to the class loader or system dictionary @@ -986,45 +872,35 @@ UNSAFE_END static instanceKlassHandle Unsafe_DefineAnonymousClass_impl(JNIEnv *env, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh, - HeapWord* *temp_alloc, + u1** temp_alloc, TRAPS) { + assert(host_class != NULL, "host_class must not be NULL"); + assert(data != NULL, "data must not be NULL"); if (UsePerfData) { ClassLoader::unsafe_defineClassCallCounter()->inc(); } - if (data == NULL) { - THROW_0(vmSymbols::java_lang_NullPointerException()); - } - jint length = typeArrayOop(JNIHandles::resolve_non_null(data))->length(); - jint word_length = (length + sizeof(HeapWord)-1) / sizeof(HeapWord); - HeapWord* body = NEW_C_HEAP_ARRAY(HeapWord, word_length, mtInternal); - if (body == NULL) { + assert(length >= 0, "class_bytes_length must not be negative: %d", length); + + int class_bytes_length = (int) length; + + u1* class_bytes = NEW_C_HEAP_ARRAY(u1, length, mtInternal); + if (class_bytes == NULL) { THROW_0(vmSymbols::java_lang_OutOfMemoryError()); } // caller responsible to free it: - (*temp_alloc) = body; + *temp_alloc = class_bytes; - { - jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0); - Copy::conjoint_words((HeapWord*) array_base, body, word_length); - } - - u1* class_bytes = (u1*) body; - int class_bytes_length = (int) length; - if (class_bytes_length < 0) class_bytes_length = 0; - if (class_bytes == NULL - || host_class == NULL - || length != class_bytes_length) - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + jbyte* array_base = typeArrayOop(JNIHandles::resolve_non_null(data))->byte_at_addr(0); + Copy::conjoint_jbytes(array_base, class_bytes, length); objArrayHandle cp_patches_h; if (cp_patches_jh != NULL) { oop p = JNIHandles::resolve_non_null(cp_patches_jh); - if (!p->is_objArray()) - THROW_0(vmSymbols::java_lang_IllegalArgumentException()); + assert(p->is_objArray(), "cp_patches must be an object[]"); cp_patches_h = objArrayHandle(THREAD, (objArrayOop)p); } @@ -1036,60 +912,56 @@ Unsafe_DefineAnonymousClass_impl(JNIEnv *env, Handle host_domain(THREAD, host_klass->protection_domain()); GrowableArray* cp_patches = NULL; + if (cp_patches_h.not_null()) { int alen = cp_patches_h->length(); + for (int i = alen-1; i >= 0; i--) { oop p = cp_patches_h->obj_at(i); if (p != NULL) { Handle patch(THREAD, p); - if (cp_patches == NULL) + + if (cp_patches == NULL) { cp_patches = new GrowableArray(i+1, i+1, Handle()); + } + cp_patches->at_put(i, patch); } } } - ClassFileStream st(class_bytes, - class_bytes_length, - host_source, - ClassFileStream::verify); + ClassFileStream st(class_bytes, class_bytes_length, host_source, ClassFileStream::verify); - instanceKlassHandle anon_klass; - { - Symbol* no_class_name = NULL; - Klass* anonk = SystemDictionary::parse_stream(no_class_name, - host_loader, - host_domain, - &st, - host_klass, - cp_patches, - CHECK_NULL); - if (anonk == NULL) return NULL; - anon_klass = instanceKlassHandle(THREAD, anonk); + Symbol* no_class_name = NULL; + Klass* anonk = SystemDictionary::parse_stream(no_class_name, + host_loader, + host_domain, + &st, + host_klass, + cp_patches, + CHECK_NULL); + if (anonk == NULL) { + return NULL; } - return anon_klass; + return instanceKlassHandle(THREAD, anonk); } -UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) -{ - instanceKlassHandle anon_klass; - jobject res_jh = NULL; - - UnsafeWrapper("Unsafe_DefineAnonymousClass"); +UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass0(JNIEnv *env, jobject unsafe, jclass host_class, jbyteArray data, jobjectArray cp_patches_jh)) { ResourceMark rm(THREAD); - HeapWord* temp_alloc = NULL; + instanceKlassHandle anon_klass; + jobject res_jh = NULL; + u1* temp_alloc = NULL; - anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, - cp_patches_jh, - &temp_alloc, THREAD); - if (anon_klass() != NULL) + anon_klass = Unsafe_DefineAnonymousClass_impl(env, host_class, data, cp_patches_jh, &temp_alloc, THREAD); + if (anon_klass() != NULL) { res_jh = JNIHandles::make_local(env, anon_klass->java_mirror()); + } // try/finally clause: if (temp_alloc != NULL) { - FREE_C_HEAP_ARRAY(HeapWord, temp_alloc); + FREE_C_HEAP_ARRAY(u1, temp_alloc); } // The anonymous class loader data has been artificially been kept alive to @@ -1102,100 +974,103 @@ UNSAFE_ENTRY(jclass, Unsafe_DefineAnonymousClass(JNIEnv *env, jobject unsafe, jc // let caller initialize it as needed... return (jclass) res_jh; -} -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) - UnsafeWrapper("Unsafe_ThrowException"); - { - ThreadToNativeFromVM ttnfv(thread); - env->Throw(thr); - } -UNSAFE_END +UNSAFE_ENTRY(void, Unsafe_ThrowException(JNIEnv *env, jobject unsafe, jthrowable thr)) { + ThreadToNativeFromVM ttnfv(thread); + env->Throw(thr); +} UNSAFE_END // JSR166 ------------------------------------------------------------------ -UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) - UnsafeWrapper("Unsafe_CompareAndExchangeObject"); +UNSAFE_ENTRY(jobject, Unsafe_CompareAndExchangeObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); - if (res == e) + if (res == e) { update_barrier_set((void*)addr, x); + } return JNIHandles::make_local(env, res); -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) - UnsafeWrapper("Unsafe_CompareAndExchangeInt"); +UNSAFE_ENTRY(jint, Unsafe_CompareAndExchangeInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { oop p = JNIHandles::resolve(obj); jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); - return (jint)(Atomic::cmpxchg(x, addr, e)); -UNSAFE_END -UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) - UnsafeWrapper("Unsafe_CompareAndExchangeLong"); + return (jint)(Atomic::cmpxchg(x, addr, e)); +} UNSAFE_END + +UNSAFE_ENTRY(jlong, Unsafe_CompareAndExchangeLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { Handle p (THREAD, JNIHandles::resolve(obj)); jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + #ifdef SUPPORTS_NATIVE_CX8 return (jlong)(Atomic::cmpxchg(x, addr, e)); #else - if (VM_Version::supports_cx8()) + if (VM_Version::supports_cx8()) { return (jlong)(Atomic::cmpxchg(x, addr, e)); - else { + } else { MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); - if (val == e) + if (val == e) { Atomic::store(x, addr); + } return val; } #endif -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) - UnsafeWrapper("Unsafe_CompareAndSwapObject"); +UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapObject(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jobject e_h, jobject x_h)) { oop x = JNIHandles::resolve(x_h); oop e = JNIHandles::resolve(e_h); oop p = JNIHandles::resolve(obj); HeapWord* addr = (HeapWord *)index_oop_from_field_offset_long(p, offset); oop res = oopDesc::atomic_compare_exchange_oop(x, addr, e, true); - jboolean success = (res == e); - if (success) - update_barrier_set((void*)addr, x); - return success; -UNSAFE_END + if (res != e) { + return false; + } -UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) - UnsafeWrapper("Unsafe_CompareAndSwapInt"); + update_barrier_set((void*)addr, x); + + return true; +} UNSAFE_END + +UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapInt(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jint e, jint x)) { oop p = JNIHandles::resolve(obj); jint* addr = (jint *) index_oop_from_field_offset_long(p, offset); - return (jint)(Atomic::cmpxchg(x, addr, e)) == e; -UNSAFE_END -UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) - UnsafeWrapper("Unsafe_CompareAndSwapLong"); - Handle p (THREAD, JNIHandles::resolve(obj)); - jlong* addr = (jlong*)(index_oop_from_field_offset_long(p(), offset)); + return (jint)(Atomic::cmpxchg(x, addr, e)) == e; +} UNSAFE_END + +UNSAFE_ENTRY(jboolean, Unsafe_CompareAndSwapLong(JNIEnv *env, jobject unsafe, jobject obj, jlong offset, jlong e, jlong x)) { + Handle p(THREAD, JNIHandles::resolve(obj)); + jlong* addr = (jlong*)index_oop_from_field_offset_long(p(), offset); + #ifdef SUPPORTS_NATIVE_CX8 return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; #else - if (VM_Version::supports_cx8()) + if (VM_Version::supports_cx8()) { return (jlong)(Atomic::cmpxchg(x, addr, e)) == e; - else { - jboolean success = false; + } else { MutexLockerEx mu(UnsafeJlong_lock, Mutex::_no_safepoint_check_flag); + jlong val = Atomic::load(addr); - if (val == e) { Atomic::store(x, addr); success = true; } - return success; + if (val != e) { + return false; + } + + Atomic::store(x, addr); + return true; } #endif -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) - UnsafeWrapper("Unsafe_Park"); +UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, jlong time)) { EventThreadPark event; HOTSPOT_THREAD_PARK_BEGIN((uintptr_t) thread->parker(), (int) isAbsolute, time); @@ -1203,6 +1078,7 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, thread->parker()->park(isAbsolute != 0, time); HOTSPOT_THREAD_PARK_END((uintptr_t) thread->parker()); + if (event.should_commit()) { oop obj = thread->current_park_blocker(); event.set_klass((obj != NULL) ? obj->klass() : NULL); @@ -1210,11 +1086,11 @@ UNSAFE_ENTRY(void, Unsafe_Park(JNIEnv *env, jobject unsafe, jboolean isAbsolute, event.set_address((obj != NULL) ? (TYPE_ADDRESS) cast_from_oop(obj) : 0); event.commit(); } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) - UnsafeWrapper("Unsafe_Unpark"); +UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) { Parker* p = NULL; + if (jthread != NULL) { oop java_thread = JNIHandles::resolve_non_null(jthread); if (java_thread != NULL) { @@ -1228,6 +1104,7 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) // Grab lock if apparently null or using older version of library MutexLocker mu(Threads_lock); java_thread = JNIHandles::resolve_non_null(jthread); + if (java_thread != NULL) { JavaThread* thr = java_lang_Thread::thread(java_thread); if (thr != NULL) { @@ -1240,14 +1117,14 @@ UNSAFE_ENTRY(void, Unsafe_Unpark(JNIEnv *env, jobject unsafe, jobject jthread)) } } } + if (p != NULL) { HOTSPOT_THREAD_UNPARK((uintptr_t) p); p->unpark(); } -UNSAFE_END +} UNSAFE_END -UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) - UnsafeWrapper("Unsafe_Loadavg"); +UNSAFE_ENTRY(jint, Unsafe_GetLoadAverage0(JNIEnv *env, jobject unsafe, jdoubleArray loadavg, jint nelem)) { const int max_nelem = 3; double la[max_nelem]; jint ret; @@ -1255,15 +1132,11 @@ UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray load typeArrayOop a = typeArrayOop(JNIHandles::resolve_non_null(loadavg)); assert(a->is_typeArray(), "must be type array"); - if (nelem < 0 || nelem > max_nelem || a->length() < nelem) { - ThreadToNativeFromVM ttnfv(thread); - throw_new(env, "ArrayIndexOutOfBoundsException"); + ret = os::loadavg(la, nelem); + if (ret == -1) { return -1; } - ret = os::loadavg(la, nelem); - if (ret == -1) return -1; - // if successful, ret is the number of samples actually retrieved. assert(ret >= 0 && ret <= max_nelem, "Unexpected loadavg return value"); switch(ret) { @@ -1271,8 +1144,9 @@ UNSAFE_ENTRY(jint, Unsafe_Loadavg(JNIEnv *env, jobject unsafe, jdoubleArray load case 2: a->double_at_put(1, (jdouble)la[1]); // fall through case 1: a->double_at_put(0, (jdouble)la[0]); break; } + return ret; -UNSAFE_END +} UNSAFE_END /// JVM_RegisterUnsafeMethods @@ -1292,87 +1166,17 @@ UNSAFE_END #define CC (char*) /*cast a literal from (const char*)*/ #define FN_PTR(f) CAST_FROM_FN_PTR(void*, &f) -#define DECLARE_GETPUTOOP(Boolean, Z) \ - {CC "get" #Boolean, CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean)}, \ - {CC "put" #Boolean, CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean)}, \ - {CC "get" #Boolean "Volatile", CC "(" OBJ "J)" #Z, FN_PTR(Unsafe_Get##Boolean##Volatile)}, \ - {CC "put" #Boolean "Volatile", CC "(" OBJ "J" #Z ")V", FN_PTR(Unsafe_Set##Boolean##Volatile)} +#define DECLARE_GETPUTOOP(Type, Desc) \ + {CC "get" #Type, CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type)}, \ + {CC "put" #Type, CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type)}, \ + {CC "get" #Type "Volatile", CC "(" OBJ "J)" #Desc, FN_PTR(Unsafe_Get##Type##Volatile)}, \ + {CC "put" #Type "Volatile", CC "(" OBJ "J" #Desc ")V", FN_PTR(Unsafe_Set##Type##Volatile)} #define DECLARE_GETPUTNATIVE(Byte, B) \ {CC "get" #Byte, CC "(" ADR ")" #B, FN_PTR(Unsafe_GetNative##Byte)}, \ {CC "put" #Byte, CC "(" ADR#B ")V", FN_PTR(Unsafe_SetNative##Byte)} - -static JNINativeMethod sun_misc_Unsafe_methods[] = { - {CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)}, - {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)}, - {CC "getObjectVolatile",CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObjectVolatile)}, - {CC "putObjectVolatile",CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObjectVolatile)}, - - {CC "getUncompressedObject", CC "(" ADR ")" OBJ, FN_PTR(Unsafe_GetUncompressedObject)}, - {CC "getJavaMirror", CC "(" ADR ")" CLS, FN_PTR(Unsafe_GetJavaMirror)}, - {CC "getKlassPointer", CC "(" OBJ ")" ADR, FN_PTR(Unsafe_GetKlassPointer)}, - - DECLARE_GETPUTOOP(Boolean, Z), - DECLARE_GETPUTOOP(Byte, B), - DECLARE_GETPUTOOP(Short, S), - DECLARE_GETPUTOOP(Char, C), - DECLARE_GETPUTOOP(Int, I), - DECLARE_GETPUTOOP(Long, J), - DECLARE_GETPUTOOP(Float, F), - DECLARE_GETPUTOOP(Double, D), - - DECLARE_GETPUTNATIVE(Byte, B), - DECLARE_GETPUTNATIVE(Short, S), - DECLARE_GETPUTNATIVE(Char, C), - DECLARE_GETPUTNATIVE(Int, I), - DECLARE_GETPUTNATIVE(Long, J), - DECLARE_GETPUTNATIVE(Float, F), - DECLARE_GETPUTNATIVE(Double, D), - - {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)}, - {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)}, - - {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)}, - {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)}, - {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)}, - - {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)}, - {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)}, - {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)}, - {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)}, - {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)}, - {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)}, - {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)}, - {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)}, - - {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)}, - {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)}, - {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}, - {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, - {CC "compareAndSwapInt", CC "(" OBJ "J""I""I"")Z", FN_PTR(Unsafe_CompareAndSwapInt)}, - {CC "compareAndSwapLong", CC "(" OBJ "J""J""J"")Z", FN_PTR(Unsafe_CompareAndSwapLong)}, - {CC "putOrderedObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetOrderedObject)}, - {CC "putOrderedInt", CC "(" OBJ "JI)V", FN_PTR(Unsafe_SetOrderedInt)}, - {CC "putOrderedLong", CC "(" OBJ "JJ)V", FN_PTR(Unsafe_SetOrderedLong)}, - {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)}, - {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}, - - {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)}, - - {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)}, - {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)}, - - {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, - - {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, - - {CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)}, - {CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)}, - {CC "fullFence", CC "()V", FN_PTR(Unsafe_FullFence)}, -}; - static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "getObject", CC "(" OBJ "J)" OBJ "", FN_PTR(Unsafe_GetObject)}, {CC "putObject", CC "(" OBJ "J" OBJ ")V", FN_PTR(Unsafe_SetObject)}, @@ -1403,20 +1207,20 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "getAddress", CC "(" ADR ")" ADR, FN_PTR(Unsafe_GetNativeAddress)}, {CC "putAddress", CC "(" ADR "" ADR ")V", FN_PTR(Unsafe_SetNativeAddress)}, - {CC "allocateMemory", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory)}, - {CC "reallocateMemory", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory)}, - {CC "freeMemory", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory)}, + {CC "allocateMemory0", CC "(J)" ADR, FN_PTR(Unsafe_AllocateMemory0)}, + {CC "reallocateMemory0", CC "(" ADR "J)" ADR, FN_PTR(Unsafe_ReallocateMemory0)}, + {CC "freeMemory0", CC "(" ADR ")V", FN_PTR(Unsafe_FreeMemory0)}, - {CC "objectFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset)}, - {CC "staticFieldOffset", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset)}, - {CC "staticFieldBase", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBaseFromField)}, - {CC "ensureClassInitialized",CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized)}, - {CC "arrayBaseOffset", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset)}, - {CC "arrayIndexScale", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale)}, - {CC "addressSize", CC "()I", FN_PTR(Unsafe_AddressSize)}, + {CC "objectFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_ObjectFieldOffset0)}, + {CC "staticFieldOffset0", CC "(" FLD ")J", FN_PTR(Unsafe_StaticFieldOffset0)}, + {CC "staticFieldBase0", CC "(" FLD ")" OBJ, FN_PTR(Unsafe_StaticFieldBase0)}, + {CC "ensureClassInitialized0", CC "(" CLS ")V", FN_PTR(Unsafe_EnsureClassInitialized0)}, + {CC "arrayBaseOffset0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayBaseOffset0)}, + {CC "arrayIndexScale0", CC "(" CLS ")I", FN_PTR(Unsafe_ArrayIndexScale0)}, + {CC "addressSize0", CC "()I", FN_PTR(Unsafe_AddressSize0)}, {CC "pageSize", CC "()I", FN_PTR(Unsafe_PageSize)}, - {CC "defineClass", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass)}, + {CC "defineClass0", CC "(" DC_Args ")" CLS, FN_PTR(Unsafe_DefineClass0)}, {CC "allocateInstance", CC "(" CLS ")" OBJ, FN_PTR(Unsafe_AllocateInstance)}, {CC "throwException", CC "(" THR ")V", FN_PTR(Unsafe_ThrowException)}, {CC "compareAndSwapObject", CC "(" OBJ "J" OBJ "" OBJ ")Z", FN_PTR(Unsafe_CompareAndSwapObject)}, @@ -1432,15 +1236,15 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { {CC "park", CC "(ZJ)V", FN_PTR(Unsafe_Park)}, {CC "unpark", CC "(" OBJ ")V", FN_PTR(Unsafe_Unpark)}, - {CC "getLoadAverage", CC "([DI)I", FN_PTR(Unsafe_Loadavg)}, + {CC "getLoadAverage0", CC "([DI)I", FN_PTR(Unsafe_GetLoadAverage0)}, - {CC "copyMemory", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory)}, + {CC "copyMemory0", CC "(" OBJ "J" OBJ "JJ)V", FN_PTR(Unsafe_CopyMemory0)}, {CC "copySwapMemory0", CC "(" OBJ "J" OBJ "JJJ)V", FN_PTR(Unsafe_CopySwapMemory0)}, - {CC "setMemory", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory)}, + {CC "setMemory0", CC "(" OBJ "JJB)V", FN_PTR(Unsafe_SetMemory0)}, - {CC "defineAnonymousClass", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass)}, + {CC "defineAnonymousClass0", CC "(" DAC_Args ")" CLS, FN_PTR(Unsafe_DefineAnonymousClass0)}, - {CC "shouldBeInitialized",CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized)}, + {CC "shouldBeInitialized0", CC "(" CLS ")Z", FN_PTR(Unsafe_ShouldBeInitialized0)}, {CC "loadFence", CC "()V", FN_PTR(Unsafe_LoadFence)}, {CC "storeFence", CC "()V", FN_PTR(Unsafe_StoreFence)}, @@ -1466,27 +1270,14 @@ static JNINativeMethod jdk_internal_misc_Unsafe_methods[] = { #undef DECLARE_GETPUTNATIVE -// These two functions are exported, used by NativeLookup. +// This function is exported, used by NativeLookup. // The Unsafe_xxx functions above are called only from the interpreter. // The optimizer looks at names and signatures to recognize // individual functions. -JVM_ENTRY(void, JVM_RegisterSunMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) - UnsafeWrapper("JVM_RegisterSunMiscUnsafeMethods"); - { - ThreadToNativeFromVM ttnfv(thread); +JVM_ENTRY(void, JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) { + ThreadToNativeFromVM ttnfv(thread); - int ok = env->RegisterNatives(unsafeclass, sun_misc_Unsafe_methods, sizeof(sun_misc_Unsafe_methods)/sizeof(JNINativeMethod)); - guarantee(ok == 0, "register sun.misc.Unsafe natives"); - } -JVM_END - -JVM_ENTRY(void, JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafeclass)) - UnsafeWrapper("JVM_RegisterJDKInternalMiscUnsafeMethods"); - { - ThreadToNativeFromVM ttnfv(thread); - - int ok = env->RegisterNatives(unsafeclass, jdk_internal_misc_Unsafe_methods, sizeof(jdk_internal_misc_Unsafe_methods)/sizeof(JNINativeMethod)); - guarantee(ok == 0, "register jdk.internal.misc.Unsafe natives"); - } -JVM_END + int ok = env->RegisterNatives(unsafeclass, jdk_internal_misc_Unsafe_methods, sizeof(jdk_internal_misc_Unsafe_methods)/sizeof(JNINativeMethod)); + guarantee(ok == 0, "register jdk.internal.misc.Unsafe natives"); +} JVM_END diff --git a/hotspot/src/share/vm/prims/unsafe.hpp b/hotspot/src/share/vm/prims/unsafe.hpp new file mode 100644 index 00000000000..e8ed3a2ad02 --- /dev/null +++ b/hotspot/src/share/vm/prims/unsafe.hpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + + +#ifndef SHARE_VM_PRIMS_UNSAFE_HPP +#define SHARE_VM_PRIMS_UNSAFE_HPP + +#include "jni.h" + +extern "C" { + void JNICALL JVM_RegisterJDKInternalMiscUnsafeMethods(JNIEnv *env, jclass unsafecls); +} + +jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); + +jlong Unsafe_field_offset_from_byte_offset(jlong byte_offset); + +#endif // SHARE_VM_PRIMS_UNSAFE_HPP diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 776df026f7d..3ba23806271 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -30,6 +30,7 @@ #include "classfile/stringTable.hpp" #include "code/codeCache.hpp" #include "compiler/methodMatcher.hpp" +#include "compiler/directivesParser.hpp" #include "jvmtifiles/jvmtiEnv.hpp" #include "memory/metadataFactory.hpp" #include "memory/metaspaceShared.hpp" @@ -636,6 +637,10 @@ WB_ENTRY(jboolean, WB_TestSetForceInlineMethod(JNIEnv* env, jobject o, jobject m WB_END WB_ENTRY(jboolean, WB_EnqueueMethodForCompilation(JNIEnv* env, jobject o, jobject method, jint comp_level, jint bci)) + // Screen for unavailable/bad comp level + if (CompileBroker::compiler(comp_level) == NULL) { + return false; + } jmethodID jmid = reflected_method_to_jmid(thread, env, method); CHECK_JNI_EXCEPTION_(env, JNI_FALSE); methodHandle mh(THREAD, Method::checked_resolve_jmethod_id(jmid)); @@ -1502,6 +1507,27 @@ void WhiteBox::register_methods(JNIEnv* env, jclass wbclass, JavaThread* thread, } } +WB_ENTRY(jint, WB_AddCompilerDirective(JNIEnv* env, jobject o, jstring compDirect)) + // can't be in VM when we call JNI + ThreadToNativeFromVM ttnfv(thread); + const char* dir = env->GetStringUTFChars(compDirect, NULL); + int ret; + { + ThreadInVMfromNative ttvfn(thread); // back to VM + ret = DirectivesParser::parse_string(dir, tty); + } + env->ReleaseStringUTFChars(compDirect, dir); + // -1 for error parsing directive. Return 0 as number of directives added. + if (ret == -1) { + ret = 0; + } + return (jint) ret; +WB_END + +WB_ENTRY(void, WB_RemoveCompilerDirective(JNIEnv* env, jobject o, jint count)) + DirectivesStack::pop(count); +WB_END + #define CC (char*) static JNINativeMethod methods[] = { @@ -1677,6 +1703,9 @@ static JNINativeMethod methods[] = { {CC"isShared", CC"(Ljava/lang/Object;)Z", (void*)&WB_IsShared }, {CC"areSharedStringsIgnored", CC"()Z", (void*)&WB_AreSharedStringsIgnored }, {CC"clearInlineCaches", CC"()V", (void*)&WB_ClearInlineCaches }, + {CC"addCompilerDirective", CC"(Ljava/lang/String;)I", + (void*)&WB_AddCompilerDirective }, + {CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective }, }; #undef CC diff --git a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp index 1d046e6abe0..ad739cf05d6 100644 --- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,17 +42,30 @@ void AdvancedThresholdPolicy::print_specific(EventType type, methodHandle mh, me } void AdvancedThresholdPolicy::initialize() { + int count = CICompilerCount; +#ifdef _LP64 // Turn on ergonomic compiler count selection if (FLAG_IS_DEFAULT(CICompilerCountPerCPU) && FLAG_IS_DEFAULT(CICompilerCount)) { FLAG_SET_DEFAULT(CICompilerCountPerCPU, true); } - int count = CICompilerCount; if (CICompilerCountPerCPU) { // Simple log n seems to grow too slowly for tiered, try something faster: log n * log log n int log_cpu = log2_intptr(os::active_processor_count()); int loglog_cpu = log2_intptr(MAX2(log_cpu, 1)); count = MAX2(log_cpu * loglog_cpu, 1) * 3 / 2; } +#else + // On 32-bit systems, the number of compiler threads is limited to 3. + // On these systems, the virtual address space available to the JVM + // is usually limited to 2-4 GB (the exact value depends on the platform). + // As the compilers (especially C2) can consume a large amount of + // memory, scaling the number of compiler threads with the number of + // available cores can result in the exhaustion of the address space + /// available to the VM and thus cause the VM to crash. + if (FLAG_IS_DEFAULT(CICompilerCount)) { + count = 3; + } +#endif set_c1_count(MAX2(count / 3, 1)); set_c2_count(MAX2(count - c1_count(), 1)); @@ -164,9 +177,7 @@ bool AdvancedThresholdPolicy::is_method_profiled(Method* method) { // Called with the queue locked and with at least one element CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { -#if INCLUDE_JVMCI CompileTask *max_blocking_task = NULL; -#endif CompileTask *max_task = NULL; Method* max_method = NULL; jlong t = os::javaTimeMillis(); @@ -180,7 +191,8 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { max_method = method; } else { // If a method has been stale for some time, remove it from the queue. - if (is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { + // Blocking tasks don't become stale + if (!task->is_blocking() && is_stale(t, TieredCompileTaskTimeout, method) && !is_old(method)) { if (PrintTieredEvents) { print_event(REMOVE_FROM_QUEUE, method, method, task->osr_bci(), (CompLevel)task->comp_level()); } @@ -197,29 +209,25 @@ CompileTask* AdvancedThresholdPolicy::select_task(CompileQueue* compile_queue) { max_method = method; } } -#if INCLUDE_JVMCI - if (UseJVMCICompiler && task->is_blocking()) { + + if (task->is_blocking()) { if (max_blocking_task == NULL || compare_methods(method, max_blocking_task->method())) { max_blocking_task = task; } } -#endif + task = next_task; } -#if INCLUDE_JVMCI - if (UseJVMCICompiler) { - if (max_blocking_task != NULL) { - // In blocking compilation mode, the CompileBroker will make - // compilations submitted by a JVMCI compiler thread non-blocking. These - // compilations should be scheduled after all blocking compilations - // to service non-compiler related compilations sooner and reduce the - // chance of such compilations timing out. - max_task = max_blocking_task; - max_method = max_task->method(); - } + if (max_blocking_task != NULL) { + // In blocking compilation mode, the CompileBroker will make + // compilations submitted by a JVMCI compiler thread non-blocking. These + // compilations should be scheduled after all blocking compilations + // to service non-compiler related compilations sooner and reduce the + // chance of such compilations timing out. + max_task = max_blocking_task; + max_method = max_task->method(); } -#endif if (max_task->comp_level() == CompLevel_full_profile && TieredStopAtLevel > CompLevel_full_profile && is_method_profiled(max_method)) { diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 3b335e39a36..fa307ff891c 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -221,8 +221,6 @@ void Arguments::init_system_properties() { // Set OS specific system properties values os::init_system_properties_values(); - - JVMCI_ONLY(JVMCIRuntime::init_system_properties(&_system_properties);) } // Update/Initialize System properties after JDK version number is known @@ -372,6 +370,7 @@ static SpecialFlag const special_jvm_flags[] = { { "PreInflateSpin", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "JNIDetachReleasesMonitors", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, { "UseAltSigs", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, + { "SegmentedHeapDumpThreshold", JDK_Version::undefined(), JDK_Version::jdk(9), JDK_Version::jdk(10) }, #ifdef TEST_VERIFY_SPECIAL_JVM_FLAGS { "dep > obs", JDK_Version::jdk(9), JDK_Version::jdk(8), JDK_Version::undefined() }, @@ -405,10 +404,12 @@ static AliasedFlag const aliased_jvm_flags[] = { static AliasedLoggingFlag const aliased_logging_flags[] = { { "TraceClassLoading", LogLevel::Info, true, LogTag::_classload }, - { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload }, + { "TraceClassPaths", LogLevel::Info, true, LogTag::_classpath }, { "TraceClassResolution", LogLevel::Info, true, LogTag::_classresolve }, + { "TraceClassUnloading", LogLevel::Info, true, LogTag::_classunload }, { "TraceExceptions", LogLevel::Info, true, LogTag::_exceptions }, { "TraceMonitorInflation", LogLevel::Debug, true, LogTag::_monitorinflation }, + { "TraceBiasedLocking", LogLevel::Info, true, LogTag::_biasedlocking }, { NULL, LogLevel::Off, false, LogTag::__NO_TAG } }; @@ -2471,9 +2472,11 @@ bool Arguments::check_vm_args_consistency() { status = false; } +#ifdef _LP64 if (!FLAG_IS_DEFAULT(CICompilerCount) && !FLAG_IS_DEFAULT(CICompilerCountPerCPU) && CICompilerCountPerCPU) { warning("The VM option CICompilerCountPerCPU overrides CICompilerCount."); } +#endif #ifndef SUPPORT_RESERVED_STACK_AREA if (StackReservedPages != 0) { @@ -3268,7 +3271,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // PrintSharedArchiveAndExit will turn on // -Xshare:on - // -XX:+TraceClassPaths + // -Xlog:classpath=info if (PrintSharedArchiveAndExit) { if (FLAG_SET_CMDLINE(bool, UseSharedSpaces, true) != Flag::SUCCESS) { return JNI_EINVAL; @@ -3276,9 +3279,7 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, if (FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true) != Flag::SUCCESS) { return JNI_EINVAL; } - if (FLAG_SET_CMDLINE(bool, TraceClassPaths, true) != Flag::SUCCESS) { - return JNI_EINVAL; - } + LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(classpath)); } // Change the default value for flags which have different default values @@ -3331,10 +3332,6 @@ void Arguments::fix_appclasspath() { _java_class_path->set_value(copy); FreeHeap(copy); // a copy was made by set_value, so don't need this anymore } - - if (!PrintSharedArchiveAndExit) { - ClassLoader::trace_class_path(tty, "[classpath: ", _java_class_path->value()); - } } static bool has_jar_files(const char* directory) { diff --git a/hotspot/src/share/vm/runtime/biasedLocking.cpp b/hotspot/src/share/vm/runtime/biasedLocking.cpp index c02d232139b..1be0d111e56 100644 --- a/hotspot/src/share/vm/runtime/biasedLocking.cpp +++ b/hotspot/src/share/vm/runtime/biasedLocking.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,8 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" +#include "memory/resourceArea.hpp" #include "oops/klass.inline.hpp" #include "oops/markOop.hpp" #include "oops/oop.inline.hpp" @@ -60,9 +62,7 @@ class VM_EnableBiasedLocking: public VM_Operation { // Indicate that future instances should enable it as well _biased_locking_enabled = true; - if (TraceBiasedLocking) { - tty->print_cr("Biased locking enabled"); - } + log_info(biasedlocking)("Biased locking enabled"); } bool allow_nested_vm_operations() const { return false; } @@ -144,14 +144,14 @@ static GrowableArray* get_or_compute_monitor_info(JavaThread* thre return info; } - static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_bulk, JavaThread* requesting_thread) { markOop mark = obj->mark(); if (!mark->has_bias_pattern()) { - if (TraceBiasedLocking) { + if (log_is_enabled(Info, biasedlocking)) { ResourceMark rm; - tty->print_cr(" (Skipping revocation of object of type %s because it's no longer biased)", - obj->klass()->external_name()); + log_info(biasedlocking)(" (Skipping revocation of object of type %s " + "because it's no longer biased)", + obj->klass()->external_name()); } return BiasedLocking::NOT_BIASED; } @@ -160,10 +160,29 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ markOop biased_prototype = markOopDesc::biased_locking_prototype()->set_age(age); markOop unbiased_prototype = markOopDesc::prototype()->set_age(age); - if (TraceBiasedLocking && (Verbose || !is_bulk)) { + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { ResourceMark rm; - tty->print_cr("Revoking bias of object " INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT " , allow rebias %d , requesting thread " INTPTR_FORMAT, - p2i((void *)obj), (intptr_t) mark, obj->klass()->external_name(), (intptr_t) obj->klass()->prototype_header(), (allow_rebias ? 1 : 0), (intptr_t) requesting_thread); + log_info(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " + INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT + " , allow rebias %d , requesting thread " INTPTR_FORMAT, + p2i((void *)obj), + (intptr_t) mark, + obj->klass()->external_name(), + (intptr_t) obj->klass()->prototype_header(), + (allow_rebias ? 1 : 0), + (intptr_t) requesting_thread); + } else { + ResourceMark rm; + log_trace(biasedlocking)("Revoking bias of object " INTPTR_FORMAT " , mark " + INTPTR_FORMAT " , type %s , prototype header " INTPTR_FORMAT + " , allow rebias %d , requesting thread " INTPTR_FORMAT, + p2i((void *)obj), + (intptr_t) mark, + obj->klass()->external_name(), + (intptr_t) obj->klass()->prototype_header(), + (allow_rebias ? 1 : 0), + (intptr_t) requesting_thread); } JavaThread* biased_thread = mark->biased_locker(); @@ -174,8 +193,11 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ if (!allow_rebias) { obj->set_mark(unbiased_prototype); } - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of anonymously-biased object"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of anonymously-biased object"); + } else { + log_trace(biasedlocking)(" Revoked bias of anonymously-biased object"); } return BiasedLocking::BIAS_REVOKED; } @@ -198,8 +220,11 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ } else { obj->set_mark(unbiased_prototype); } - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of object biased toward dead thread"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of object biased toward dead thread"); + } else { + log_trace(biasedlocking)(" Revoked bias of object biased toward dead thread"); } return BiasedLocking::BIAS_REVOKED; } @@ -214,21 +239,17 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ for (int i = 0; i < cached_monitor_info->length(); i++) { MonitorInfo* mon_info = cached_monitor_info->at(i); if (mon_info->owner() == obj) { - if (TraceBiasedLocking && Verbose) { - tty->print_cr(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", - p2i((void *) mon_info->owner()), - p2i((void *) obj)); - } + log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") == obj (" PTR_FORMAT ")", + p2i((void *) mon_info->owner()), + p2i((void *) obj)); // Assume recursive case and fix up highest lock later markOop mark = markOopDesc::encode((BasicLock*) NULL); highest_lock = mon_info->lock(); highest_lock->set_displaced_header(mark); } else { - if (TraceBiasedLocking && Verbose) { - tty->print_cr(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")", - p2i((void *) mon_info->owner()), - p2i((void *) obj)); - } + log_trace(biasedlocking)(" mon_info->owner (" PTR_FORMAT ") != obj (" PTR_FORMAT ")", + p2i((void *) mon_info->owner()), + p2i((void *) obj)); } } if (highest_lock != NULL) { @@ -240,12 +261,18 @@ static BiasedLocking::Condition revoke_bias(oop obj, bool allow_rebias, bool is_ // ordering (e.g. ppc). obj->release_set_mark(markOopDesc::encode(highest_lock)); assert(!obj->mark()->has_bias_pattern(), "illegal mark state: stack lock used bias bit"); - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of currently-locked object"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of currently-locked object"); + } else { + log_trace(biasedlocking)(" Revoked bias of currently-locked object"); } } else { - if (TraceBiasedLocking && (Verbose || !is_bulk)) { - tty->print_cr(" Revoked bias of currently-unlocked object"); + // Log at "info" level if not bulk, else "trace" level + if (!is_bulk) { + log_info(biasedlocking)(" Revoked bias of currently-unlocked object"); + } else { + log_trace(biasedlocking)(" Revoked bias of currently-unlocked object"); } if (allow_rebias) { obj->set_mark(biased_prototype); @@ -326,12 +353,12 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, JavaThread* requesting_thread) { assert(SafepointSynchronize::is_at_safepoint(), "must be done at safepoint"); - if (TraceBiasedLocking) { - tty->print_cr("* Beginning bulk revocation (kind == %s) because of object " - INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", - (bulk_rebias ? "rebias" : "revoke"), - p2i((void *) o), (intptr_t) o->mark(), o->klass()->external_name()); - } + log_info(biasedlocking)("* Beginning bulk revocation (kind == %s) because of object " + INTPTR_FORMAT " , mark " INTPTR_FORMAT " , type %s", + (bulk_rebias ? "rebias" : "revoke"), + p2i((void *) o), + (intptr_t) o->mark(), + o->klass()->external_name()); jlong cur_time = os::javaTimeMillis(); o->klass()->set_last_biased_lock_bulk_revocation_time(cur_time); @@ -377,9 +404,9 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, // adjust the header of the given object to revoke its bias. revoke_bias(o, attempt_rebias_of_object && klass->prototype_header()->has_bias_pattern(), true, requesting_thread); } else { - if (TraceBiasedLocking) { + if (log_is_enabled(Info, biasedlocking)) { ResourceMark rm; - tty->print_cr("* Disabling biased locking for type %s", klass->external_name()); + log_info(biasedlocking)("* Disabling biased locking for type %s", klass->external_name()); } // Disable biased locking for this data type. Not only will this @@ -407,9 +434,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, revoke_bias(o, false, true, requesting_thread); } - if (TraceBiasedLocking) { - tty->print_cr("* Ending bulk revocation"); - } + log_info(biasedlocking)("* Ending bulk revocation"); BiasedLocking::Condition status_code = BiasedLocking::BIAS_REVOKED; @@ -420,9 +445,7 @@ static BiasedLocking::Condition bulk_revoke_or_rebias_at_safepoint(oop o, klass->prototype_header()->bias_epoch()); o->set_mark(new_mark); status_code = BiasedLocking::BIAS_REVOKED_AND_REBIASED; - if (TraceBiasedLocking) { - tty->print_cr(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); - } + log_info(biasedlocking)(" Rebiased object toward thread " INTPTR_FORMAT, (intptr_t) requesting_thread); } assert(!o->mark()->has_bias_pattern() || @@ -485,16 +508,12 @@ public: virtual void doit() { if (_obj != NULL) { - if (TraceBiasedLocking) { - tty->print_cr("Revoking bias with potentially per-thread safepoint:"); - } + log_info(biasedlocking)("Revoking bias with potentially per-thread safepoint:"); _status_code = revoke_bias((*_obj)(), false, false, _requesting_thread); clean_up_cached_monitor_info(); return; } else { - if (TraceBiasedLocking) { - tty->print_cr("Revoking bias with global safepoint:"); - } + log_info(biasedlocking)("Revoking bias with global safepoint:"); BiasedLocking::revoke_at_safepoint(_objs); } } @@ -608,9 +627,7 @@ BiasedLocking::Condition BiasedLocking::revoke_and_rebias(Handle obj, bool attem // can come in with a CAS to steal the bias of an object that has a // stale epoch. ResourceMark rm; - if (TraceBiasedLocking) { - tty->print_cr("Revoking bias by walking my own stack:"); - } + log_info(biasedlocking)("Revoking bias by walking my own stack:"); BiasedLocking::Condition cond = revoke_bias(obj(), false, false, (JavaThread*) THREAD); ((JavaThread*) THREAD)->set_cached_monitor_info(NULL); assert(cond == BIAS_REVOKED, "why not?"); diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp index 1484cba01c8..bfadc319516 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.cpp @@ -354,6 +354,14 @@ Flag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose) { return Flag::SUCCESS; } +Flag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose) { + if (value % BytesPerLong != 0) { + return Flag::VIOLATES_CONSTRAINT; + } else { + return Flag::SUCCESS; + } +} + #ifdef COMPILER2 Flag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose) { if (InteriorEntryAlignment > CodeEntryAlignment) { diff --git a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp index f9d07848960..0038d52eac8 100644 --- a/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp +++ b/hotspot/src/share/vm/runtime/commandLineFlagConstraintsCompiler.hpp @@ -62,6 +62,8 @@ Flag::Error ArraycopySrcPrefetchDistanceConstraintFunc(uintx value, bool verbose Flag::Error TypeProfileLevelConstraintFunc(uintx value, bool verbose); +Flag::Error InitArrayShortSizeConstraintFunc(intx value, bool verbose); + #ifdef COMPILER2 Flag::Error InteriorEntryAlignmentConstraintFunc(intx value, bool verbose); diff --git a/hotspot/src/share/vm/runtime/fprofiler.cpp b/hotspot/src/share/vm/runtime/fprofiler.cpp index fbc51b4047d..fc687618e03 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.cpp +++ b/hotspot/src/share/vm/runtime/fprofiler.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -836,8 +836,7 @@ void FlatProfiler::record_vm_tick() { vm_thread_profiler->inc_thread_ticks(); // Get a snapshot of a current VMThread pc (and leave it running!) - // The call may fail if, for instance the VM thread is interrupted while - // holding the Interrupt_lock or for other reasons. + // The call may fail in some circumstances epc = os::get_thread_pc(VMThread::vm_thread()); if(epc.pc() != NULL) { if (os::dll_address_to_function_name(epc.pc(), buf, sizeof(buf), NULL)) { diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 3abf884cfbb..1a72cec46a8 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -662,14 +662,14 @@ void frame::print_on_error(outputStream* st, char* buf, int buflen, bool verbose st->print("J %d%s %s ", nm->compile_id(), (nm->is_osr_method() ? "%" : ""), ((nm->compiler() != NULL) ? nm->compiler()->name() : "")); + st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]", + buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin()); #if INCLUDE_JVMCI char* jvmciName = nm->jvmci_installed_code_name(buf, buflen); if (jvmciName != NULL) { st->print(" (%s)", jvmciName); } #endif - st->print("%s (%d bytes) @ " PTR_FORMAT " [" PTR_FORMAT "+" INTPTR_FORMAT "]", - buf, m->code_size(), p2i(_pc), p2i(_cb->code_begin()), _pc - _cb->code_begin()); } else { st->print("J " PTR_FORMAT, p2i(pc())); } diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index 638b15eaffc..ade6900975b 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -403,25 +403,20 @@ void Flag::print_on(outputStream* st, bool withComments, bool printRanges) { st->cr(); } else if (!is_bool() && !is_ccstr()) { + st->print("%9s %-50s ", _type, _name); - if (printRanges) { + CommandLineFlagRangeList::print(_name, st, true); - st->print("%9s %-50s ", _type, _name); - - CommandLineFlagRangeList::print(_name, st, true); - - st->print(" %-20s", " "); - print_kind(st); + st->print(" %-20s", " "); + print_kind(st); #ifndef PRODUCT - if (withComments) { - st->print("%s", _doc); - } + if (withComments) { + st->print("%s", _doc); + } #endif - st->cr(); - - } + st->cr(); } } @@ -1255,8 +1250,6 @@ void CommandLineFlags::verify() { #endif // PRODUCT -#define ONLY_PRINT_PRODUCT_FLAGS - void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool printRanges) { // Print the flags sorted by name // note: this method is called before the thread structure is in place @@ -1281,9 +1274,6 @@ void CommandLineFlags::printFlags(outputStream* out, bool withComments, bool pri for (size_t i = 0; i < length; i++) { if (array[i]->is_unlocked()) { -#ifdef ONLY_PRINT_PRODUCT_FLAGS - if (!array[i]->is_notproduct() && !array[i]->is_develop()) -#endif // ONLY_PRINT_PRODUCT_FLAGS array[i]->print_on(out, withComments, printRanges); } } diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index a15ea7db325..083d47b32e2 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -725,7 +725,7 @@ public: \ product(bool, UseSHA, false, \ "Control whether SHA instructions can be used " \ - "on SPARC and on ARM") \ + "on SPARC, on ARM and on x86") \ \ product(bool, UseGHASHIntrinsics, false, \ "Use intrinsics for GHASH versions of crypto") \ @@ -1055,10 +1055,6 @@ public: "directory) of the dump file (defaults to java_pid.hprof " \ "in the working directory)") \ \ - develop(size_t, SegmentedHeapDumpThreshold, 2*G, \ - "Generate a segmented heap dump (JAVA PROFILE 1.0.2 format) " \ - "when the heap usage is larger than this") \ - \ develop(size_t, HeapDumpSegmentSize, 1*G, \ "Approximate segment size when generating a segmented heap dump") \ \ @@ -1437,9 +1433,6 @@ public: product(bool, VerifyMergedCPBytecodes, true, \ "Verify bytecodes after RedefineClasses constant pool merging") \ \ - develop(bool, TraceJNIHandleAllocation, false, \ - "Trace allocation/deallocation of JNI handle blocks") \ - \ develop(bool, TraceBytecodes, false, \ "Trace bytecode execution") \ \ @@ -1482,18 +1475,9 @@ public: develop(bool, TraceCompiledIC, false, \ "Trace changes of compiled IC") \ \ - develop(bool, TraceStartupTime, false, \ - "Trace setup time") \ - \ - develop(bool, TraceProtectionDomainVerification, false, \ - "Trace protection domain verification") \ - \ develop(bool, TraceClearedExceptions, false, \ "Print when an exception is forcibly cleared") \ \ - product(bool, TraceBiasedLocking, false, \ - "Trace biased locking in JVM") \ - \ /* gc */ \ \ product(bool, UseSerialGC, false, \ @@ -2409,9 +2393,6 @@ public: product(bool, IgnoreEmptyClassPaths, false, \ "Ignore empty path elements in -classpath") \ \ - product(bool, TraceClassPaths, false, \ - "Trace processing of class paths") \ - \ product(bool, TraceClassLoadingPreorder, false, \ "Trace all classes loaded in order referenced (not loaded)") \ \ @@ -3098,16 +3079,16 @@ public: develop(intx, MethodHistogramCutoff, 100, \ "The cutoff value for method invocation histogram (+CountCalls)") \ \ - develop(intx, ProfilerNumberOfInterpretedMethods, 25, \ + diagnostic(intx, ProfilerNumberOfInterpretedMethods, 25, \ "Number of interpreted methods to show in profile") \ \ - develop(intx, ProfilerNumberOfCompiledMethods, 25, \ + diagnostic(intx, ProfilerNumberOfCompiledMethods, 25, \ "Number of compiled methods to show in profile") \ \ - develop(intx, ProfilerNumberOfStubMethods, 25, \ + diagnostic(intx, ProfilerNumberOfStubMethods, 25, \ "Number of stub methods to show in profile") \ \ - develop(intx, ProfilerNumberOfRuntimeStubNodes, 25, \ + diagnostic(intx, ProfilerNumberOfRuntimeStubNodes, 25, \ "Number of runtime stub nodes to show in profile") \ \ product(intx, ProfileIntervalsTicks, 100, \ @@ -4168,6 +4149,13 @@ public: "in the loaded class C. " \ "Check (3) is available only in debug builds.") \ \ + develop_pd(intx, InitArrayShortSize, \ + "Threshold small size (in bytes) for clearing arrays. " \ + "Anything this size or smaller may get converted to discrete " \ + "scalar stores.") \ + range(0, max_intx) \ + constraint(InitArrayShortSizeConstraintFunc, AfterErgo) \ + \ diagnostic(bool, CompilerDirectivesIgnoreCompileCommands, false, \ "Disable backwards compatibility for compile commands.") \ \ diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 84a6d6afafd..8dbc6be317c 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -521,9 +521,9 @@ class RuntimeHistogramElement : public HistogramElement { JNI_ENTRY_NO_PRESERVE(result_type, header) \ WeakPreserveExceptionMark __wem(thread); -#define JNI_ENTRY_NO_PRESERVE(result_type, header) \ +#define JNI_ENTRY_NO_PRESERVE(result_type, header) \ extern "C" { \ - result_type JNICALL header { \ + result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ ThreadInVMfromNative __tiv(thread); \ @@ -535,7 +535,7 @@ extern "C" { \ // a GC, is called outside the NoHandleMark (set via VM_QUICK_ENTRY_BASE). #define JNI_QUICK_ENTRY(result_type, header) \ extern "C" { \ - result_type JNICALL header { \ + result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ ThreadInVMfromNative __tiv(thread); \ @@ -545,7 +545,7 @@ extern "C" { \ #define JNI_LEAF(result_type, header) \ extern "C" { \ - result_type JNICALL header { \ + result_type JNICALL header { \ JavaThread* thread=JavaThread::thread_from_jni_environment(env); \ assert( !VerifyJNIEnvThread || (thread == Thread::current()), "JNIEnv is only valid in same thread"); \ VM_LEAF_BASE(result_type, header) diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index 84235d8803f..a30acc9a9bd 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -64,6 +64,7 @@ #include "runtime/timer.hpp" #include "runtime/vm_operations.hpp" #include "services/memTracker.hpp" +#include "trace/traceMacros.hpp" #include "trace/tracing.hpp" #include "utilities/dtrace.hpp" #include "utilities/globalDefinitions.hpp" @@ -485,7 +486,7 @@ void before_exit(JavaThread* thread) { EventThreadEnd event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(thread->threadObj())); + event.set_thread(THREAD_TRACE_ID(thread)); event.commit(); } diff --git a/hotspot/src/share/vm/runtime/jniHandles.cpp b/hotspot/src/share/vm/runtime/jniHandles.cpp index 3c4baed8e0e..8e4636bf640 100644 --- a/hotspot/src/share/vm/runtime/jniHandles.cpp +++ b/hotspot/src/share/vm/runtime/jniHandles.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -278,10 +278,6 @@ JNIHandleBlock* JNIHandleBlock::allocate_block(Thread* thread) { // Allocate new block block = new JNIHandleBlock(); _blocks_allocated++; - if (TraceJNIHandleAllocation) { - tty->print_cr("JNIHandleBlock " INTPTR_FORMAT " allocated (%d total blocks)", - p2i(block), _blocks_allocated); - } if (ZapJNIHandleArea) block->zap(); #ifndef PRODUCT // Link new block to list of all allocated blocks @@ -499,10 +495,6 @@ void JNIHandleBlock::rebuild_free_list() { // Not as many free handles as we would like - compute number of new blocks to append _allocate_before_rebuild = (extra + block_size_in_oops - 1) / block_size_in_oops; } - if (TraceJNIHandleAllocation) { - tty->print_cr("Rebuild free list JNIHandleBlock " INTPTR_FORMAT " blocks=%d used=%d free=%d add=%d", - p2i(this), blocks, total-free, free, _allocate_before_rebuild); - } } diff --git a/hotspot/src/share/vm/runtime/logTimer.hpp b/hotspot/src/share/vm/runtime/logTimer.hpp new file mode 100644 index 00000000000..81bbd085eb3 --- /dev/null +++ b/hotspot/src/share/vm/runtime/logTimer.hpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_RUNTIME_LOG_TIMER_HPP +#define SHARE_VM_RUNTIME_LOG_TIMER_HPP + +#include "logging/log.hpp" +#include "runtime/timer.hpp" + +// TraceStartupTime is used for tracing the execution time of a block with logging +// Usage: +// { TraceStartupTime t("block time") +// some_code(); +// } +// + +class TraceStartupTime : public TraceTime { + public: + TraceStartupTime(const char* s) : TraceTime(s, log_is_enabled(Info, startuptime), LogTag::_startuptime) {} +}; + +#endif // SHARE_VM_RUNTIME_LOG_TIMER_HPP diff --git a/hotspot/src/share/vm/runtime/mutex.cpp b/hotspot/src/share/vm/runtime/mutex.cpp index 81fa378d05c..ef6ac43b5d6 100644 --- a/hotspot/src/share/vm/runtime/mutex.cpp +++ b/hotspot/src/share/vm/runtime/mutex.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1320,15 +1320,12 @@ void Monitor::set_owner_implementation(Thread *new_owner) { // The rank Mutex::native is an exception in that it is not subject // to the verification rules. // Here are some further notes relating to mutex acquisition anomalies: - // . under Solaris, the interrupt lock gets acquired when doing - // profiling, so any lock could be held. // . it is also ok to acquire Safepoint_lock at the very end while we // already hold Terminator_lock - may happen because of periodic safepoints if (this->rank() != Mutex::native && this->rank() != Mutex::suspend_resume && locks != NULL && locks->rank() <= this->rank() && !SafepointSynchronize::is_at_safepoint() && - this != Interrupt_lock && this != ProfileVM_lock && !(this == Safepoint_lock && contains(locks, Terminator_lock) && SafepointSynchronize::is_synchronizing())) { new_owner->print_owned_locks(); diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index ae1d213b6e5..fa1aea26a55 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,6 @@ Mutex* JmethodIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL; Monitor* JNICritical_lock = NULL; Mutex* JvmtiThreadState_lock = NULL; -Monitor* JvmtiPendingEvent_lock = NULL; Monitor* Heap_lock = NULL; Mutex* ExpandHeap_lock = NULL; Mutex* AdapterHandlerLibrary_lock = NULL; @@ -73,8 +72,6 @@ Monitor* CGC_lock = NULL; Monitor* STS_lock = NULL; Monitor* SLT_lock = NULL; Monitor* FullGCCount_lock = NULL; -Monitor* CMark_lock = NULL; -Mutex* CMRegionStack_lock = NULL; Mutex* SATB_Q_FL_lock = NULL; Monitor* SATB_Q_CBL_mon = NULL; Mutex* Shared_SATB_Q_lock = NULL; @@ -94,11 +91,8 @@ Mutex* MultiArray_lock = NULL; Monitor* Terminator_lock = NULL; Monitor* BeforeExit_lock = NULL; Monitor* Notify_lock = NULL; -Monitor* Interrupt_lock = NULL; -Monitor* ProfileVM_lock = NULL; Mutex* ProfilePrint_lock = NULL; Mutex* ExceptionCache_lock = NULL; -Monitor* ObjAllocPost_lock = NULL; Mutex* OsrList_lock = NULL; #ifndef PRODUCT @@ -184,8 +178,6 @@ void mutex_init() { } if (UseG1GC) { - def(CMark_lock , Monitor, nonleaf, true, Monitor::_safepoint_check_never); // coordinate concurrent mark thread - def(CMRegionStack_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); def(SATB_Q_FL_lock , Mutex , special, true, Monitor::_safepoint_check_never); def(SATB_Q_CBL_mon , Monitor, nonleaf, true, Monitor::_safepoint_check_never); def(Shared_SATB_Q_lock , Mutex, nonleaf, true, Monitor::_safepoint_check_never); @@ -206,12 +198,10 @@ void mutex_init() { def(ParGCRareEvent_lock , Mutex , leaf , true, Monitor::_safepoint_check_sometimes); def(DerivedPointerTableGC_lock , Mutex, leaf, true, Monitor::_safepoint_check_never); def(CodeCache_lock , Mutex , special, true, Monitor::_safepoint_check_never); - def(Interrupt_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for interrupt processing def(RawMonitor_lock , Mutex, special, true, Monitor::_safepoint_check_never); def(OopMapCacheAlloc_lock , Mutex, leaf, true, Monitor::_safepoint_check_always); // used for oop_map_cache allocation. def(Patching_lock , Mutex , special, true, Monitor::_safepoint_check_never); // used for safepointing and code patching. - def(ObjAllocPost_lock , Monitor, special, false, Monitor::_safepoint_check_never); def(Service_lock , Monitor, special, true, Monitor::_safepoint_check_never); // used for service thread operations def(JmethodIdCreation_lock , Mutex , leaf, true, Monitor::_safepoint_check_always); // used for creating jmethodIDs. @@ -267,7 +257,6 @@ void mutex_init() { def(MultiArray_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // locks SymbolTable_lock def(JvmtiThreadState_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // Used by JvmtiThreadState/JvmtiEventController - def(JvmtiPendingEvent_lock , Monitor, nonleaf, false, Monitor::_safepoint_check_never); // Used by JvmtiCodeBlobEvents def(Management_lock , Mutex , nonleaf+2, false, Monitor::_safepoint_check_always); // used for JVM management def(Compile_lock , Mutex , nonleaf+3, true, Monitor::_safepoint_check_sometimes); @@ -277,7 +266,6 @@ void mutex_init() { def(MethodCompileQueue_lock , Monitor, nonleaf+4, true, Monitor::_safepoint_check_always); def(Debug2_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); def(Debug3_lock , Mutex , nonleaf+4, true, Monitor::_safepoint_check_never); - def(ProfileVM_lock , Monitor, special, false, Monitor::_safepoint_check_never); // used for profiling of the VMThread def(CompileThread_lock , Monitor, nonleaf+5, false, Monitor::_safepoint_check_always); def(PeriodicTask_lock , Monitor, nonleaf+5, true, Monitor::_safepoint_check_sometimes); if (WhiteBoxAPI) { diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index bbf6f143312..eccd3ca7314 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,6 @@ extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI metho extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers extern Monitor* JNICritical_lock; // a lock used while entering and exiting JNI critical regions, allows GC to sometimes get in extern Mutex* JvmtiThreadState_lock; // a lock on modification of JVMTI thread data -extern Monitor* JvmtiPendingEvent_lock; // a lock on the JVMTI pending events list extern Monitor* Heap_lock; // a lock on the heap extern Mutex* ExpandHeap_lock; // a lock on expanding the heap extern Mutex* AdapterHandlerLibrary_lock; // a lock on the AdapterHandlerLibrary @@ -68,8 +67,6 @@ extern Monitor* CGC_lock; // used for coordination betwee extern Monitor* STS_lock; // used for joining/leaving SuspendibleThreadSet. extern Monitor* SLT_lock; // used in CMS GC for acquiring PLL extern Monitor* FullGCCount_lock; // in support of "concurrent" full gc -extern Monitor* CMark_lock; // used for concurrent mark thread coordination -extern Mutex* CMRegionStack_lock; // used for protecting accesses to the CM region stack extern Mutex* SATB_Q_FL_lock; // Protects SATB Q // buffer free list. extern Monitor* SATB_Q_CBL_mon; // Protects SATB Q @@ -98,8 +95,6 @@ extern Mutex* MultiArray_lock; // a lock used to guard allocat extern Monitor* Terminator_lock; // a lock used to guard termination of the vm extern Monitor* BeforeExit_lock; // a lock used to guard cleanups and shutdown hooks extern Monitor* Notify_lock; // a lock used to synchronize the start-up of the vm -extern Monitor* Interrupt_lock; // a lock used for condition variable mediated interrupt processing -extern Monitor* ProfileVM_lock; // a lock used for profiling the VMThread extern Mutex* ProfilePrint_lock; // a lock used to serialize the printing of profiles extern Mutex* ExceptionCache_lock; // a lock used to synchronize exception cache updates extern Mutex* OsrList_lock; // a lock used to serialize access to OSR queues diff --git a/hotspot/src/share/vm/runtime/objectMonitor.cpp b/hotspot/src/share/vm/runtime/objectMonitor.cpp index 2f7937d4f3e..6258d64ad2f 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.cpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -401,7 +401,7 @@ void NOINLINE ObjectMonitor::enter(TRAPS) { if (event.should_commit()) { event.set_klass(((oop)this->object())->klass()); - event.set_previousOwner((TYPE_JAVALANGTHREAD)_previous_owner_tid); + event.set_previousOwner((TYPE_THREAD)_previous_owner_tid); event.set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); event.commit(); } @@ -937,7 +937,7 @@ void NOINLINE ObjectMonitor::exit(bool not_suspended, TRAPS) { // get the owner's thread id for the MonitorEnter event // if it is enabled and the thread isn't suspended if (not_suspended && Tracing::is_event_enabled(TraceJavaMonitorEnterEvent)) { - _previous_owner_tid = SharedRuntime::get_java_tid(Self); + _previous_owner_tid = THREAD_TRACE_ID(Self); } #endif @@ -1391,11 +1391,12 @@ void ObjectMonitor::post_monitor_wait_event(EventJavaMonitorWait* event, jlong notifier_tid, jlong timeout, bool timedout) { + assert(event != NULL, "invariant"); event->set_klass(((oop)this->object())->klass()); - event->set_timeout((TYPE_ULONG)timeout); - event->set_address((TYPE_ADDRESS)(uintptr_t)(this->object_addr())); - event->set_notifier((TYPE_OSTHREAD)notifier_tid); - event->set_timedOut((TYPE_BOOLEAN)timedout); + event->set_timeout(timeout); + event->set_address((TYPE_ADDRESS)this->object_addr()); + event->set_notifier(notifier_tid); + event->set_timedOut(timedout); event->commit(); } @@ -1655,7 +1656,7 @@ void ObjectMonitor::INotify(Thread * Self) { iterator->TState = ObjectWaiter::TS_ENTER; } iterator->_notified = 1; - iterator->_notifier_tid = Self->osthread()->thread_id(); + iterator->_notifier_tid = THREAD_TRACE_ID(Self); ObjectWaiter * list = _EntryList; if (list != NULL) { diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 9668104ef5d..128c73c3194 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -152,7 +152,6 @@ class os: AllStatic { static size_t page_size_for_region(size_t region_size, size_t min_pages, bool must_be_aligned); // Get summary strings for system information in buffer provided - static bool get_host_name(char* buf, size_t buflen) PRODUCT_RETURN_(return false;); // true if available static void get_summary_cpu_info(char* buf, size_t buflen); static void get_summary_os_info(char* buf, size_t buflen); @@ -595,6 +594,9 @@ class os: AllStatic { // Write to stream static int log_vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0); + // Get host name in buffer provided + static bool get_host_name(char* buf, size_t buflen); + // Print out system information; they are called by fatal error handler. // Output format may be different on different platforms. static void print_os_info(outputStream* st); diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 5b862a01fab..4adec0c45ca 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1134,12 +1134,19 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, MethodHandles::is_signature_polymorphic_intrinsic(id)) { bc = MethodHandles::signature_polymorphic_intrinsic_bytecode(id); - // Need to adjust invokehandle since inlining through signature-polymorphic - // method happened. - if (bc == Bytecodes::_invokehandle && - !MethodHandles::is_signature_polymorphic_method(attached_method())) { - bc = attached_method->is_static() ? Bytecodes::_invokestatic - : Bytecodes::_invokevirtual; + // Adjust invocation mode according to the attached method. + switch (bc) { + case Bytecodes::_invokeinterface: + if (!attached_method->method_holder()->is_interface()) { + bc = Bytecodes::_invokevirtual; + } + break; + case Bytecodes::_invokehandle: + if (!MethodHandles::is_signature_polymorphic_method(attached_method())) { + bc = attached_method->is_static() ? Bytecodes::_invokestatic + : Bytecodes::_invokevirtual; + } + break; } } } else { diff --git a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp index 187d3b1e208..3f8b76c9327 100644 --- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp +++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.cpp @@ -138,9 +138,15 @@ void SimpleThresholdPolicy::initialize() { FLAG_SET_DEFAULT(CICompilerCount, 3); } int count = CICompilerCount; +#ifdef _LP64 + // On 64-bit systems, scale the number of compiler threads with + // the number of cores available on the system. Scaling is not + // performed on 32-bit systems because it can lead to exhaustion + // of the virtual memory address space available to the JVM. if (CICompilerCountPerCPU) { count = MAX2(log2_intptr(os::active_processor_count()), 1) * 3 / 2; } +#endif set_c1_count(MAX2(count / 3, 1)); set_c2_count(MAX2(count - c1_count(), 1)); FLAG_SET_ERGO(intx, CICompilerCount, c1_count() + c2_count()); diff --git a/hotspot/src/share/vm/runtime/stubRoutines.cpp b/hotspot/src/share/vm/runtime/stubRoutines.cpp index 0f2c5b65e17..71080e5b76c 100644 --- a/hotspot/src/share/vm/runtime/stubRoutines.cpp +++ b/hotspot/src/share/vm/runtime/stubRoutines.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,9 +28,9 @@ #include "memory/resourceArea.hpp" #include "oops/oop.inline.hpp" #include "runtime/interfaceSupport.hpp" +#include "runtime/logTimer.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" -#include "runtime/timer.hpp" #include "utilities/copy.hpp" #ifdef COMPILER2 #include "opto/runtime.hpp" @@ -183,7 +183,7 @@ extern void StubGenerator_generate(CodeBuffer* code, bool all); // only interfac void StubRoutines::initialize1() { if (_code1 == NULL) { ResourceMark rm; - TraceTime timer("StubRoutines generation 1", TraceStartupTime); + TraceStartupTime timer("StubRoutines generation 1"); _code1 = BufferBlob::create("StubRoutines (1)", code_size1); if (_code1 == NULL) { vm_exit_out_of_memory(code_size1, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (1)"); @@ -276,7 +276,7 @@ static void test_safefetchN() { void StubRoutines::initialize2() { if (_code2 == NULL) { ResourceMark rm; - TraceTime timer("StubRoutines generation 2", TraceStartupTime); + TraceStartupTime timer("StubRoutines generation 2"); _code2 = BufferBlob::create("StubRoutines (2)", code_size2); if (_code2 == NULL) { vm_exit_out_of_memory(code_size2, OOM_MALLOC_ERROR, "CodeCache: no room for StubRoutines (2)"); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index e5d5c86e6e9..17479b47c6b 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -67,6 +67,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniPeriodicChecker.hpp" +#include "runtime/logTimer.hpp" #include "runtime/memprofiler.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.hpp" @@ -169,11 +170,10 @@ void* Thread::allocate(size_t size, bool throw_excpt, MEMFLAGS flags) { assert(((uintptr_t) aligned_addr + (uintptr_t) size) <= ((uintptr_t) real_malloc_addr + (uintptr_t) aligned_size), "JavaThread alignment code overflowed allocated storage"); - if (TraceBiasedLocking) { - if (aligned_addr != real_malloc_addr) { - tty->print_cr("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT, - p2i(real_malloc_addr), p2i(aligned_addr)); - } + if (aligned_addr != real_malloc_addr) { + log_info(biasedlocking)("Aligned thread " INTPTR_FORMAT " to " INTPTR_FORMAT, + p2i(real_malloc_addr), + p2i(aligned_addr)); } ((Thread*) aligned_addr)->_real_malloc_address = real_malloc_addr; return aligned_addr; @@ -324,6 +324,10 @@ void Thread::record_stack_base_and_size() { // record thread's native stack, stack grows downward MemTracker::record_thread_stack(stack_end(), stack_size()); #endif // INCLUDE_NMT + log_debug(os, thread)("Thread " UINTX_FORMAT " stack dimensions: " + PTR_FORMAT "-" PTR_FORMAT " (" SIZE_FORMAT "k).", + os::current_thread_id(), p2i(stack_base() - stack_size()), + p2i(stack_base()), stack_size()/1024); } @@ -1005,9 +1009,9 @@ static void call_initializeSystemClass(TRAPS) { char java_runtime_name[128] = ""; char java_runtime_version[128] = ""; -// extract the JRE name from sun.misc.Version.java_runtime_name +// extract the JRE name from java.lang.VersionProps.java_runtime_name static const char* get_java_runtime_name(TRAPS) { - Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(), + Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(), Handle(), Handle(), CHECK_AND_CLEAR_NULL); fieldDescriptor fd; bool found = k != NULL && @@ -1027,9 +1031,9 @@ static const char* get_java_runtime_name(TRAPS) { } } -// extract the JRE version from sun.misc.Version.java_runtime_version +// extract the JRE version from java.lang.VersionProps.java_runtime_version static const char* get_java_runtime_version(TRAPS) { - Klass* k = SystemDictionary::find(vmSymbols::sun_misc_Version(), + Klass* k = SystemDictionary::find(vmSymbols::java_lang_VersionProps(), Handle(), Handle(), CHECK_AND_CLEAR_NULL); fieldDescriptor fd; bool found = k != NULL && @@ -1690,7 +1694,7 @@ void JavaThread::run() { EventThreadStart event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.set_thread(THREAD_TRACE_ID(this)); event.commit(); } @@ -1795,7 +1799,7 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { // from java_lang_Thread object EventThreadEnd event; if (event.should_commit()) { - event.set_javalangthread(java_lang_Thread::thread_id(this->threadObj())); + event.set_thread(THREAD_TRACE_ID(this)); event.commit(); } @@ -1924,6 +1928,10 @@ void JavaThread::exit(bool destroy_vm, ExitType exit_type) { } #endif // INCLUDE_ALL_GCS + log_info(os, thread)("JavaThread %s (tid: " UINTX_FORMAT ").", + exit_type == JavaThread::normal_exit ? "exiting" : "detaching", + os::current_thread_id()); + // Remove from list of active threads list, and notify VM thread if we are the last non-daemon thread Threads::remove(this); } @@ -2491,18 +2499,25 @@ void JavaThread::create_stack_guard_pages() { // warning("Guarding at " PTR_FORMAT " for len " SIZE_FORMAT "\n", low_addr, len); if (allocate && !os::create_stack_guard_pages((char *) low_addr, len)) { - warning("Attempt to allocate stack guard pages failed."); + log_warning(os, thread)("Attempt to allocate stack guard pages failed."); return; } if (os::guard_memory((char *) low_addr, len)) { _stack_guard_state = stack_guard_enabled; } else { - warning("Attempt to protect stack guard pages failed."); + log_warning(os, thread)("Attempt to protect stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); if (os::uncommit_memory((char *) low_addr, len)) { - warning("Attempt to deallocate stack guard pages failed."); + log_warning(os, thread)("Attempt to deallocate stack guard pages failed."); } + return; } + + log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages activated: " + PTR_FORMAT "-" PTR_FORMAT ".", + os::current_thread_id(), p2i(low_addr), p2i(low_addr + len)); + } void JavaThread::remove_stack_guard_pages() { @@ -2515,16 +2530,25 @@ void JavaThread::remove_stack_guard_pages() { if (os::remove_stack_guard_pages((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { - warning("Attempt to deallocate stack guard pages failed."); + log_warning(os, thread)("Attempt to deallocate stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); + return; } } else { if (_stack_guard_state == stack_guard_unused) return; if (os::unguard_memory((char *) low_addr, len)) { _stack_guard_state = stack_guard_unused; } else { - warning("Attempt to unprotect stack guard pages failed."); + log_warning(os, thread)("Attempt to unprotect stack guard pages failed (" + PTR_FORMAT "-" PTR_FORMAT ").", p2i(low_addr), p2i(low_addr + len)); + return; } } + + log_debug(os, thread)("Thread " UINTX_FORMAT " stack guard pages removed: " + PTR_FORMAT "-" PTR_FORMAT ".", + os::current_thread_id(), p2i(low_addr), p2i(low_addr + len)); + } void JavaThread::enable_stack_reserved_zone() { @@ -3341,7 +3365,7 @@ void Threads::threads_do(ThreadClosure* tc) { } void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { - TraceTime timer("Initialize java.lang classes", TraceStartupTime); + TraceStartupTime timer("Initialize java.lang classes"); if (EagerXrunInit && Arguments::init_libraries_at_startup()) { create_vm_init_libraries(); @@ -3388,6 +3412,8 @@ void Threads::initialize_java_lang_classes(JavaThread* main_thread, TRAPS) { } void Threads::initialize_jsr292_core_classes(TRAPS) { + TraceStartupTime timer("Initialize java.lang.invoke classes"); + initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK); initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK); initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK); @@ -3457,7 +3483,7 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { HOTSPOT_VM_INIT_BEGIN(); // Timing (must come after argument parsing) - TraceTime timer("Create VM", TraceStartupTime); + TraceStartupTime timer("Create VM"); // Initialize the os module after parsing the args jint os_init_2_result = os::init_2(); @@ -3528,6 +3554,10 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { return status; } + if (TRACE_INITIALIZE() != JNI_OK) { + vm_exit_during_initialization("Failed to initialize tracing backend"); + } + // Should be done after the heap is fully created main_thread->cache_global_variables(); @@ -3542,8 +3572,9 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { JvmtiExport::transition_pending_onload_raw_monitors(); // Create the VMThread - { TraceTime timer("Start VMThread", TraceStartupTime); - VMThread::create(); + { TraceStartupTime timer("Start VMThread"); + + VMThread::create(); Thread* vmthread = VMThread::vm_thread(); if (!os::create_thread(vmthread, os::vm_thread)) { @@ -3595,11 +3626,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { quicken_jni_functions(); - // Must be run after init_ft which initializes ft_enabled - if (TRACE_INITIALIZE() != JNI_OK) { - vm_exit_during_initialization("Failed to initialize tracing backend"); - } - // No more stub generation allowed after that point. StubCodeDesc::freeze(); @@ -3670,15 +3696,6 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { Chunk::start_chunk_pool_cleaner_task(); } -#if INCLUDE_JVMCI - if (EnableJVMCI) { - const char* jvmciCompiler = Arguments::PropertyList_get_value(Arguments::system_properties(), "jvmci.compiler"); - if (jvmciCompiler != NULL) { - JVMCIRuntime::save_compiler(jvmciCompiler); - } - } -#endif // INCLUDE_JVMCI - // initialize compiler(s) #if defined(COMPILER1) || defined(COMPILER2) || defined(SHARK) || INCLUDE_JVMCI CompileBroker::compilation_init(CHECK_JNI_ERR); @@ -4107,6 +4124,7 @@ jboolean Threads::is_supported_jni_version(jint version) { if (version == JNI_VERSION_1_4) return JNI_TRUE; if (version == JNI_VERSION_1_6) return JNI_TRUE; if (version == JNI_VERSION_1_8) return JNI_TRUE; + if (version == JNI_VERSION_9) return JNI_TRUE; return JNI_FALSE; } diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 4d94026e313..eed983d3841 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -448,7 +448,8 @@ class Thread: public ThreadShadow { void incr_allocated_bytes(jlong size) { _allocated_bytes += size; } inline jlong cooked_allocated_bytes(); - TRACE_DATA* trace_data() { return &_trace_data; } + TRACE_DEFINE_THREAD_TRACE_DATA_OFFSET; + TRACE_DATA* trace_data() const { return &_trace_data; } const ThreadExt& ext() const { return _ext; } ThreadExt& ext() { return _ext; } diff --git a/hotspot/src/share/vm/runtime/timer.cpp b/hotspot/src/share/vm/runtime/timer.cpp index ec4ec0fa662..dddf328b302 100644 --- a/hotspot/src/share/vm/runtime/timer.cpp +++ b/hotspot/src/share/vm/runtime/timer.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "logging/log.hpp" #include "oops/oop.inline.hpp" #include "runtime/timer.hpp" #include "utilities/ostream.hpp" @@ -114,14 +115,15 @@ jlong TimeStamp::ticks_since_update() const { } TraceTime::TraceTime(const char* title, - bool doit) { + bool doit, + LogTagType tag) { _active = doit; _verbose = true; + _tag = tag; + _title = title; if (_active) { _accum = NULL; - tty->print("[%s", title); - tty->flush(); _t.start(); } } @@ -129,14 +131,14 @@ TraceTime::TraceTime(const char* title, TraceTime::TraceTime(const char* title, elapsedTimer* accumulator, bool doit, - bool verbose) { - _active = doit; - _verbose = verbose; + bool verbose, + LogTagType tag) { + _active = doit; + _verbose = verbose; + _tag = tag; + _title = title; + if (_active) { - if (_verbose) { - tty->print("[%s", title); - tty->flush(); - } _accum = accumulator; _t.start(); } @@ -147,8 +149,15 @@ TraceTime::~TraceTime() { _t.stop(); if (_accum!=NULL) _accum->add(_t); if (_verbose) { - tty->print_cr(", %3.7f secs]", _t.seconds()); - tty->flush(); + switch (_tag) { + case LogTag::_startuptime : + log_info(startuptime)("%s, %3.7f secs", _title, _t.seconds()); + break; + case LogTag::__NO_TAG : + default : + tty->print_cr("[%s, %3.7f secs]", _title, _t.seconds()); + tty->flush(); + } } } } diff --git a/hotspot/src/share/vm/runtime/timer.hpp b/hotspot/src/share/vm/runtime/timer.hpp index bd003eb40e6..c14e2522917 100644 --- a/hotspot/src/share/vm/runtime/timer.hpp +++ b/hotspot/src/share/vm/runtime/timer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,7 @@ #ifndef SHARE_VM_RUNTIME_TIMER_HPP #define SHARE_VM_RUNTIME_TIMER_HPP +#include "logging/logTag.hpp" #include "utilities/globalDefinitions.hpp" // Timers for simple measurement. @@ -85,14 +86,19 @@ class TraceTime: public StackObj { bool _verbose; // report every timing elapsedTimer _t; // timer elapsedTimer* _accum; // accumulator + const char* _title; // name of timer + LogTagType _tag; // stream to print to + public: // Constructors TraceTime(const char* title, - bool doit = true); + bool doit = true, + LogTagType tag = LogTag::__NO_TAG); TraceTime(const char* title, elapsedTimer* accumulator, bool doit = true, - bool verbose = false); + bool verbose = false, + LogTagType tag = LogTag::__NO_TAG); ~TraceTime(); // Accessors diff --git a/hotspot/src/share/vm/runtime/vmThread.cpp b/hotspot/src/share/vm/runtime/vmThread.cpp index 77935603075..f4584b1fc9b 100644 --- a/hotspot/src/share/vm/runtime/vmThread.cpp +++ b/hotspot/src/share/vm/runtime/vmThread.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -359,7 +359,7 @@ void VMThread::evaluate_operation(VM_Operation* op) { // Only write caller thread information for non-concurrent vm operations. // For concurrent vm operations, the thread id is set to 0 indicating thread is unknown. // This is because the caller thread could have exited already. - event.set_caller(is_concurrent ? 0 : op->calling_thread()->osthread()->thread_id()); + event.set_caller(is_concurrent ? 0 : THREAD_TRACE_ID(op->calling_thread())); event.commit(); } diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index c634edfce73..3beb7786c16 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,6 +71,7 @@ void DCmdRegistrant::register_dcmds(){ #endif // INCLUDE_SERVICES #if INCLUDE_JVMTI DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); #endif // INCLUDE_JVMTI DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); @@ -254,6 +255,66 @@ void JVMTIDataDumpDCmd::execute(DCmdSource source, TRAPS) { } } +JVMTIAgentLoadDCmd::JVMTIAgentLoadDCmd(outputStream* output, bool heap) : + DCmdWithParser(output, heap), + _libpath("library path", "Absolute path of the JVMTI agent to load.", + "STRING", true), + _option("agent option", "Option string to pass the agent.", "STRING", false) { + _dcmdparser.add_dcmd_argument(&_libpath); + _dcmdparser.add_dcmd_argument(&_option); +} + +void JVMTIAgentLoadDCmd::execute(DCmdSource source, TRAPS) { + + if (_libpath.value() == NULL) { + output()->print_cr("JVMTI.agent_load dcmd needs library path."); + return; + } + + char *suffix = strrchr(_libpath.value(), '.'); + bool is_java_agent = (suffix != NULL) && (strncmp(".jar", suffix, 4) == 0); + + if (is_java_agent) { + if (_option.value() == NULL) { + JvmtiExport::load_agent_library("instrument", "false", + _libpath.value(), output()); + } else { + size_t opt_len = strlen(_libpath.value()) + strlen(_option.value()) + 2; + if (opt_len > 4096) { + output()->print_cr("JVMTI agent attach failed: Options is too long."); + return; + } + + char *opt = (char *)os::malloc(opt_len, mtInternal); + if (opt == NULL) { + output()->print_cr("JVMTI agent attach failed: " + "Could not allocate %zu bytes for argument.", + opt_len); + return; + } + + jio_snprintf(opt, opt_len, "%s=%s", _libpath.value(), _option.value()); + JvmtiExport::load_agent_library("instrument", "false", opt, output()); + + os::free(opt); + } + } else { + JvmtiExport::load_agent_library(_libpath.value(), "true", + _option.value(), output()); + } +} + +int JVMTIAgentLoadDCmd::num_arguments() { + ResourceMark rm; + JVMTIAgentLoadDCmd* dcmd = new JVMTIAgentLoadDCmd(NULL, false); + if (dcmd != NULL) { + DCmdMark mark(dcmd); + return dcmd->_dcmdparser.num_arguments(); + } else { + return 0; + } +} + void PrintSystemPropertiesDCmd::execute(DCmdSource source, TRAPS) { // load sun.misc.VMSupport Symbol* klass = vmSymbols::sun_misc_VMSupport(); @@ -870,7 +931,7 @@ int CompilerDirectivesAddDCmd::num_arguments() { } void CompilerDirectivesRemoveDCmd::execute(DCmdSource source, TRAPS) { - DirectivesStack::pop(); + DirectivesStack::pop(1); } void CompilerDirectivesClearDCmd::execute(DCmdSource source, TRAPS) { diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index ea3ddfe588a..8f5dc9172ae 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -174,6 +174,26 @@ public: virtual void execute(DCmdSource source, TRAPS); }; +class JVMTIAgentLoadDCmd : public DCmdWithParser { +protected: + DCmdArgument _libpath; + DCmdArgument _option; +public: + JVMTIAgentLoadDCmd(outputStream* output, bool heap); + static const char* name() { return "JVMTI.agent_load"; } + static const char* description() { + return "Load JVMTI native agent."; + } + static const char* impact() { return "Low"; } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "control", NULL}; + return p; + } + static int num_arguments(); + virtual void execute(DCmdSource source, TRAPS); +}; + class VMDynamicLibrariesDCmd : public DCmd { public: VMDynamicLibrariesDCmd(outputStream* output, bool heap); diff --git a/hotspot/src/share/vm/services/heapDumper.cpp b/hotspot/src/share/vm/services/heapDumper.cpp index 2f01fab4cc9..986855894d2 100644 --- a/hotspot/src/share/vm/services/heapDumper.cpp +++ b/hotspot/src/share/vm/services/heapDumper.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,8 +53,7 @@ * src/share/demo/jvmti/hprof/hprof_io.c * * - * header "JAVA PROFILE 1.0.1" or "JAVA PROFILE 1.0.2" - * (0-terminated) + * header "JAVA PROFILE 1.0.2" (0-terminated) * * u4 size of identifiers. Identifiers are used to represent * UTF8 strings, objects, stack traces, etc. They usually @@ -385,6 +384,8 @@ class DumpWriter : public StackObj { size_t _size; size_t _pos; + jlong _dump_start; + char* _error; // error message when I/O fails void set_file_descriptor(int fd) { _fd = fd; } @@ -408,6 +409,10 @@ class DumpWriter : public StackObj { bool is_open() const { return file_descriptor() >= 0; } void flush(); + jlong dump_start() const { return _dump_start; } + void set_dump_start(jlong pos); + julong current_record_length(); + // total number of bytes written to the disk julong bytes_written() const { return _bytes_written; } @@ -449,6 +454,7 @@ DumpWriter::DumpWriter(const char* path) { _pos = 0; _error = NULL; _bytes_written = 0L; + _dump_start = (jlong)-1; _fd = os::create_binary_file(path, false); // don't replace existing file // if the open failed we record the error @@ -476,6 +482,22 @@ void DumpWriter::close() { } } +// sets the dump starting position +void DumpWriter::set_dump_start(jlong pos) { + _dump_start = pos; +} + +julong DumpWriter::current_record_length() { + if (is_open()) { + // calculate the size of the dump record + julong dump_end = bytes_written() + bytes_unwritten(); + assert(dump_end == (size_t)current_offset(), "checking"); + julong dump_len = dump_end - dump_start() - 4; + return dump_len; + } + return 0; +} + // write directly to the file void DumpWriter::write_internal(void* s, size_t len) { if (is_open()) { @@ -645,6 +667,18 @@ class DumperSupport : AllStatic { static void dump_prim_array(DumpWriter* writer, typeArrayOop array); // create HPROF_FRAME record for the given method and bci static void dump_stack_frame(DumpWriter* writer, int frame_serial_num, int class_serial_num, Method* m, int bci); + + // check if we need to truncate an array + static int calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size); + + // writes a HPROF_HEAP_DUMP_SEGMENT record + static void write_dump_header(DumpWriter* writer); + + // fixes up the length of the current dump record + static void write_current_dump_record_length(DumpWriter* writer); + + // fixes up the current dump record and writes HPROF_HEAP_DUMP_END record + static void end_of_dump(DumpWriter* writer); }; // write a header of the given type @@ -1005,50 +1039,102 @@ void DumperSupport::dump_basic_type_array_class(DumpWriter* writer, Klass* k) { } } +// Hprof uses an u4 as record length field, +// which means we need to truncate arrays that are too long. +int DumperSupport::calculate_array_max_length(DumpWriter* writer, arrayOop array, short header_size) { + BasicType type = ArrayKlass::cast(array->klass())->element_type(); + assert(type >= T_BOOLEAN && type <= T_OBJECT, "invalid array element type"); + + int length = array->length(); + + int type_size; + if (type == T_OBJECT) { + type_size = sizeof(address); + } else { + type_size = type2aelembytes(type); + } + + size_t length_in_bytes = (size_t)length * type_size; + + // Create a new record if the current record is non-empty and the array can't fit. + julong current_record_length = writer->current_record_length(); + if (current_record_length > 0 && + (current_record_length + header_size + length_in_bytes) > max_juint) { + write_current_dump_record_length(writer); + write_dump_header(writer); + + // We now have an empty record. + current_record_length = 0; + } + + // Calculate max bytes we can use. + uint max_bytes = max_juint - (header_size + current_record_length); + + // Array too long for the record? + // Calculate max length and return it. + if (length_in_bytes > max_bytes) { + length = max_bytes / type_size; + length_in_bytes = (size_t)length * type_size; + + warning("cannot dump array of type %s[] with length %d; truncating to length %d", + type2name_tab[type], array->length(), length); + } + return length; +} + // creates HPROF_GC_OBJ_ARRAY_DUMP record for the given object array void DumperSupport::dump_object_array(DumpWriter* writer, objArrayOop array) { + // sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + sizeof(classID) + short header_size = 1 + 2 * 4 + 2 * sizeof(address); + + int length = calculate_array_max_length(writer, array, header_size); writer->write_u1(HPROF_GC_OBJ_ARRAY_DUMP); writer->write_objectID(array); writer->write_u4(STACK_TRACE_ID); - writer->write_u4((u4)array->length()); + writer->write_u4(length); // array class ID writer->write_classID(array->klass()); // [id]* elements - for (int index=0; indexlength(); index++) { + for (int index = 0; index < length; index++) { oop o = array->obj_at(index); writer->write_objectID(o); } } -#define WRITE_ARRAY(Array, Type, Size) \ - for (int i=0; ilength(); i++) { writer->write_##Size((Size)array->Type##_at(i)); } - +#define WRITE_ARRAY(Array, Type, Size, Length) \ + for (int i = 0; i < Length; i++) { writer->write_##Size((Size)Array->Type##_at(i)); } // creates HPROF_GC_PRIM_ARRAY_DUMP record for the given type array void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { BasicType type = TypeArrayKlass::cast(array->klass())->element_type(); + // 2 * sizeof(u1) + 2 * sizeof(u4) + sizeof(objectID) + short header_size = 2 * 1 + 2 * 4 + sizeof(address); + + int length = calculate_array_max_length(writer, array, header_size); + int type_size = type2aelembytes(type); + u4 length_in_bytes = (u4)length * type_size; + writer->write_u1(HPROF_GC_PRIM_ARRAY_DUMP); writer->write_objectID(array); writer->write_u4(STACK_TRACE_ID); - writer->write_u4((u4)array->length()); + writer->write_u4(length); writer->write_u1(type2tag(type)); // nothing to copy - if (array->length() == 0) { + if (length == 0) { return; } // If the byte ordering is big endian then we can copy most types directly - u4 length_in_bytes = (u4)array->length() * type2aelembytes(type); switch (type) { case T_INT : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, int, u4); + WRITE_ARRAY(array, int, u4, length); } else { writer->write_raw((void*)(array->int_at_addr(0)), length_in_bytes); } @@ -1060,7 +1146,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_CHAR : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, char, u2); + WRITE_ARRAY(array, char, u2, length); } else { writer->write_raw((void*)(array->char_at_addr(0)), length_in_bytes); } @@ -1068,7 +1154,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_SHORT : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, short, u2); + WRITE_ARRAY(array, short, u2, length); } else { writer->write_raw((void*)(array->short_at_addr(0)), length_in_bytes); } @@ -1076,7 +1162,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_BOOLEAN : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, bool, u1); + WRITE_ARRAY(array, bool, u1, length); } else { writer->write_raw((void*)(array->bool_at_addr(0)), length_in_bytes); } @@ -1084,7 +1170,7 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { } case T_LONG : { if (Bytes::is_Java_byte_ordering_different()) { - WRITE_ARRAY(array, long, u8); + WRITE_ARRAY(array, long, u8, length); } else { writer->write_raw((void*)(array->long_at_addr(0)), length_in_bytes); } @@ -1096,14 +1182,14 @@ void DumperSupport::dump_prim_array(DumpWriter* writer, typeArrayOop array) { // use IEEE 754. case T_FLOAT : { - for (int i=0; ilength(); i++) { - dump_float( writer, array->float_at(i) ); + for (int i = 0; i < length; i++) { + dump_float(writer, array->float_at(i)); } break; } case T_DOUBLE : { - for (int i=0; ilength(); i++) { - dump_double( writer, array->double_at(i) ); + for (int i = 0; i < length; i++) { + dump_double(writer, array->double_at(i)); } break; } @@ -1320,8 +1406,6 @@ class VM_HeapDumper : public VM_GC_Operation { JavaThread* _oome_thread; Method* _oome_constructor; bool _gc_before_heap_dump; - bool _is_segmented_dump; - jlong _dump_start; GrowableArray* _klass_map; ThreadStackTrace** _stack_traces; int _num_threads; @@ -1340,11 +1424,6 @@ class VM_HeapDumper : public VM_GC_Operation { void clear_global_dumper() { _global_dumper = NULL; } void clear_global_writer() { _global_writer = NULL; } - bool is_segmented_dump() const { return _is_segmented_dump; } - void set_segmented_dump() { _is_segmented_dump = true; } - jlong dump_start() const { return _dump_start; } - void set_dump_start(jlong pos); - bool skip_operation() const; // writes a HPROF_LOAD_CLASS record @@ -1369,16 +1448,6 @@ class VM_HeapDumper : public VM_GC_Operation { // HPROF_TRACE and HPROF_FRAME records void dump_stack_traces(); - // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record - void write_dump_header(); - - // fixes up the length of the current dump record - void write_current_dump_record_length(); - - // fixes up the current dump record )and writes HPROF_HEAP_DUMP_END - // record in the case of a segmented heap dump) - void end_of_dump(); - public: VM_HeapDumper(DumpWriter* writer, bool gc_before_heap_dump, bool oome) : VM_GC_Operation(0 /* total collections, dummy, ignored */, @@ -1387,8 +1456,6 @@ class VM_HeapDumper : public VM_GC_Operation { gc_before_heap_dump) { _local_writer = writer; _gc_before_heap_dump = gc_before_heap_dump; - _is_segmented_dump = false; - _dump_start = (jlong)-1; _klass_map = new (ResourceObj::C_HEAP, mtInternal) GrowableArray(INITIAL_CLASS_COUNT, true); _stack_traces = NULL; _num_threads = 0; @@ -1428,35 +1495,23 @@ bool VM_HeapDumper::skip_operation() const { return false; } -// sets the dump starting position -void VM_HeapDumper::set_dump_start(jlong pos) { - _dump_start = pos; -} - - // writes a HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT record -void VM_HeapDumper::write_dump_header() { - if (writer()->is_open()) { - if (is_segmented_dump()) { - writer()->write_u1(HPROF_HEAP_DUMP_SEGMENT); - } else { - writer()->write_u1(HPROF_HEAP_DUMP); - } - writer()->write_u4(0); // current ticks + // writes a HPROF_HEAP_DUMP_SEGMENT record +void DumperSupport::write_dump_header(DumpWriter* writer) { + if (writer->is_open()) { + writer->write_u1(HPROF_HEAP_DUMP_SEGMENT); + writer->write_u4(0); // current ticks // record the starting position for the dump (its length will be fixed up later) - set_dump_start(writer()->current_offset()); - writer()->write_u4(0); + writer->set_dump_start(writer->current_offset()); + writer->write_u4(0); } } // fixes up the length of the current dump record -void VM_HeapDumper::write_current_dump_record_length() { - if (writer()->is_open()) { - assert(dump_start() >= 0, "no dump start recorded"); - - // calculate the size of the dump record - julong dump_end = writer()->current_offset(); - julong dump_len = (dump_end - dump_start() - 4); +void DumperSupport::write_current_dump_record_length(DumpWriter* writer) { + if (writer->is_open()) { + julong dump_end = writer->bytes_written() + writer->bytes_unwritten(); + julong dump_len = writer->current_record_length(); // record length must fit in a u4 if (dump_len > max_juint) { @@ -1464,17 +1519,18 @@ void VM_HeapDumper::write_current_dump_record_length() { } // seek to the dump start and fix-up the length - writer()->seek_to_offset(dump_start()); - writer()->write_u4((u4)dump_len); + assert(writer->dump_start() >= 0, "no dump start recorded"); + writer->seek_to_offset(writer->dump_start()); + writer->write_u4((u4)dump_len); // adjust the total size written to keep the bytes written correct. - writer()->adjust_bytes_written(-((jlong) sizeof(u4))); + writer->adjust_bytes_written(-((jlong) sizeof(u4))); // seek to dump end so we can continue - writer()->seek_to_offset(dump_end); + writer->seek_to_offset(dump_end); // no current dump record - set_dump_start((jlong)-1); + writer->set_dump_start((jlong)-1); } } @@ -1482,33 +1538,23 @@ void VM_HeapDumper::write_current_dump_record_length() { // new segment. void VM_HeapDumper::check_segment_length() { if (writer()->is_open()) { - if (is_segmented_dump()) { - // don't use current_offset that would be too expensive on a per record basis - julong dump_end = writer()->bytes_written() + writer()->bytes_unwritten(); - assert(dump_end == (julong)writer()->current_offset(), "checking"); - julong dump_len = (dump_end - dump_start() - 4); - assert(dump_len <= max_juint, "bad dump length"); + julong dump_len = writer()->current_record_length(); - if (dump_len > HeapDumpSegmentSize) { - write_current_dump_record_length(); - write_dump_header(); - } + if (dump_len > 2UL*G) { + DumperSupport::write_current_dump_record_length(writer()); + DumperSupport::write_dump_header(writer()); } } } -// fixes up the current dump record )and writes HPROF_HEAP_DUMP_END -// record in the case of a segmented heap dump) -void VM_HeapDumper::end_of_dump() { - if (writer()->is_open()) { - write_current_dump_record_length(); +// fixes up the current dump record and writes HPROF_HEAP_DUMP_END record +void DumperSupport::end_of_dump(DumpWriter* writer) { + if (writer->is_open()) { + write_current_dump_record_length(writer); - // for segmented dump we write the end record - if (is_segmented_dump()) { - writer()->write_u1(HPROF_HEAP_DUMP_END); - writer()->write_u4(0); - writer()->write_u4(0); - } + writer->write_u1(HPROF_HEAP_DUMP_END); + writer->write_u4(0); + writer->write_u4(0); } } @@ -1686,16 +1732,17 @@ void VM_HeapDumper::do_threads() { // [HPROF_LOAD_CLASS]* // [[HPROF_FRAME]*|HPROF_TRACE]* // [HPROF_GC_CLASS_DUMP]* -// HPROF_HEAP_DUMP +// [HPROF_HEAP_DUMP_SEGMENT]* +// HPROF_HEAP_DUMP_END // // The HPROF_TRACE records represent the stack traces where the heap dump // is generated and a "dummy trace" record which does not include // any frames. The dummy trace record is used to be referenced as the // unknown object alloc site. // -// The HPROF_HEAP_DUMP record has a length following by sub-records. To allow -// the heap dump be generated in a single pass we remember the position of -// the dump length and fix it up after all sub-records have been written. +// Each HPROF_HEAP_DUMP_SEGMENT record has a length followed by sub-records. +// To allow the heap dump be generated in a single pass we remember the position +// of the dump length and fix it up after all sub-records have been written. // To generate the sub-records we iterate over the heap, writing // HPROF_GC_INSTANCE_DUMP, HPROF_GC_OBJ_ARRAY_DUMP, and HPROF_GC_PRIM_ARRAY_DUMP // records as we go. Once that is done we write records for some of the GC @@ -1722,15 +1769,9 @@ void VM_HeapDumper::doit() { set_global_dumper(); set_global_writer(); - // Write the file header - use 1.0.2 for large heaps, otherwise 1.0.1 + // Write the file header - we always use 1.0.2 size_t used = ch->used(); - const char* header; - if (used > SegmentedHeapDumpThreshold) { - set_segmented_dump(); - header = "JAVA PROFILE 1.0.2"; - } else { - header = "JAVA PROFILE 1.0.1"; - } + const char* header = "JAVA PROFILE 1.0.2"; // header is few bytes long - no chance to overflow int writer()->write_raw((void*)header, (int)strlen(header)); @@ -1750,8 +1791,8 @@ void VM_HeapDumper::doit() { // this must be called after _klass_map is built when iterating the classes above. dump_stack_traces(); - // write HPROF_HEAP_DUMP or HPROF_HEAP_DUMP_SEGMENT - write_dump_header(); + // write HPROF_HEAP_DUMP_SEGMENT + DumperSupport::write_dump_header(writer()); // Writes HPROF_GC_CLASS_DUMP records ClassLoaderDataGraph::classes_do(&do_class_dump); @@ -1759,9 +1800,9 @@ void VM_HeapDumper::doit() { check_segment_length(); // writes HPROF_GC_INSTANCE_DUMP records. - // After each sub-record is written check_segment_length will be invoked. When - // generated a segmented heap dump this allows us to check if the current - // segment exceeds a threshold and if so, then a new segment is started. + // After each sub-record is written check_segment_length will be invoked + // to check if the current segment exceeds a threshold. If so, a new + // segment is started. // The HPROF_GC_CLASS_DUMP and HPROF_GC_INSTANCE_DUMP are the vast bulk // of the heap dump. HeapObjectDumper obj_dumper(this, writer()); @@ -1785,9 +1826,8 @@ void VM_HeapDumper::doit() { StickyClassDumper class_dumper(writer()); SystemDictionary::always_strong_classes_do(&class_dumper); - // fixes up the length of the dump record. In the case of a segmented - // heap then the HPROF_HEAP_DUMP_END record is also written. - end_of_dump(); + // fixes up the length of the dump record and writes the HPROF_HEAP_DUMP_END record. + DumperSupport::end_of_dump(writer()); // Now we clear the global variables, so that a future dumper might run. clear_global_dumper(); diff --git a/hotspot/src/share/vm/shark/sharkBuilder.cpp b/hotspot/src/share/vm/shark/sharkBuilder.cpp index 0fcc8107fc9..ab4dcdcefbf 100644 --- a/hotspot/src/share/vm/shark/sharkBuilder.cpp +++ b/hotspot/src/share/vm/shark/sharkBuilder.cpp @@ -29,6 +29,7 @@ #include "gc/shared/cardTableModRefBS.hpp" #include "memory/resourceArea.hpp" #include "oops/method.hpp" +#include "prims/unsafe.hpp" #include "runtime/os.hpp" #include "runtime/synchronizer.hpp" #include "runtime/thread.hpp" @@ -326,7 +327,6 @@ Value* SharkBuilder::fabs() { } Value* SharkBuilder::unsafe_field_offset_to_byte_offset() { - extern jlong Unsafe_field_offset_to_byte_offset(jlong field_offset); return make_function((address) Unsafe_field_offset_to_byte_offset, "l", "l"); } diff --git a/hotspot/src/share/vm/trace/trace.xml b/hotspot/src/share/vm/trace/trace.xml index 7e357f4c106..d6d76d9398f 100644 --- a/hotspot/src/share/vm/trace/trace.xml +++ b/hotspot/src/share/vm/trace/trace.xml @@ -1,6 +1,6 @@ - + diff --git a/hotspot/src/share/vm/trace/traceBackend.hpp b/hotspot/src/share/vm/trace/traceBackend.hpp index c65d89e41d8..36635321ad6 100644 --- a/hotspot/src/share/vm/trace/traceBackend.hpp +++ b/hotspot/src/share/vm/trace/traceBackend.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,6 +47,10 @@ public: static void on_unloading_classes(void) { } + + static void on_vm_error(bool) { + } + }; class TraceThreadData { diff --git a/hotspot/src/share/vm/trace/traceDataTypes.hpp b/hotspot/src/share/vm/trace/traceDataTypes.hpp index 31004d934b5..b51343d9575 100644 --- a/hotspot/src/share/vm/trace/traceDataTypes.hpp +++ b/hotspot/src/share/vm/trace/traceDataTypes.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,39 +31,32 @@ enum { CONTENT_TYPE_NONE = 0, - CONTENT_TYPE_BYTES = 1, - CONTENT_TYPE_EPOCHMILLIS = 2, - CONTENT_TYPE_MILLIS = 3, - CONTENT_TYPE_NANOS = 4, - CONTENT_TYPE_TICKS = 5, - CONTENT_TYPE_ADDRESS = 6, + CONTENT_TYPE_CLASS = 20, + CONTENT_TYPE_UTF8 = 21, + CONTENT_TYPE_THREAD = 22, + CONTENT_TYPE_STACKTRACE = 23, + CONTENT_TYPE_BYTES = 24, + CONTENT_TYPE_EPOCHMILLIS = 25, + CONTENT_TYPE_MILLIS = 26, + CONTENT_TYPE_NANOS = 27, + CONTENT_TYPE_TICKS = 28, + CONTENT_TYPE_ADDRESS = 29, + CONTENT_TYPE_PERCENTAGE = 30, - CONTENT_TYPE_OSTHREAD, - CONTENT_TYPE_JAVALANGTHREAD, - CONTENT_TYPE_STACKTRACE, - CONTENT_TYPE_CLASS, - CONTENT_TYPE_PERCENTAGE, - - JVM_CONTENT_TYPES_START = 30, - JVM_CONTENT_TYPES_END = 100 + JVM_CONTENT_TYPES_START = 33, + JVM_CONTENT_TYPES_END = 255 }; enum ReservedEvent { - EVENT_PRODUCERS, + EVENT_METADATA, EVENT_CHECKPOINT, EVENT_BUFFERLOST, - NUM_RESERVED_EVENTS + NUM_RESERVED_EVENTS = JVM_CONTENT_TYPES_END }; typedef enum ReservedEvent ReservedEvent; -typedef u8 classid; -typedef u8 stacktraceid; -typedef u8 methodid; -typedef u8 fieldid; - -class TraceUnicodeString; +class Symbol; #endif // SHARE_VM_TRACE_TRACEDATATYPES_HPP - diff --git a/hotspot/src/share/vm/trace/traceEvent.hpp b/hotspot/src/share/vm/trace/traceEvent.hpp index a0548d76513..3a083c402ce 100644 --- a/hotspot/src/share/vm/trace/traceEvent.hpp +++ b/hotspot/src/share/vm/trace/traceEvent.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,6 @@ class TraceEvent : public StackObj { _endTime = time; } - public: TraceEvent(EventStartTime timing=TIMED) : _startTime(0), _endTime(0), @@ -76,12 +75,21 @@ class TraceEvent : public StackObj { { if (T::is_enabled()) { _started = true; - if (timing == TIMED && !T::isInstant) { - static_cast(this)->set_starttime(Tracing::time()); + if (TIMED == timing && !T::isInstant) { + static_cast(this)->set_starttime(Tracing::time()); } } } + public: + void set_starttime(const Ticks& time) { + _startTime = time.value(); + } + + void set_endtime(const Ticks& time) { + _endTime = time.value(); + } + static bool is_enabled() { return Tracing::is_event_enabled(T::eventId); } @@ -90,67 +98,68 @@ class TraceEvent : public StackObj { return _started; } - void ignoreCheck() { - DEBUG_ONLY(_ignore_check = true); - } - void commit() { if (!should_commit()) { - cancel(); - return; + DEBUG_ONLY(cancel()); + return; } - if (_endTime == 0) { + assert(!_cancelled, "Committing an event that has already been cancelled"); + if (_startTime == 0) { + static_cast(this)->set_starttime(Tracing::time()); + } else if (_endTime == 0) { static_cast(this)->set_endtime(Tracing::time()); } if (static_cast(this)->should_write()) { static_cast(this)->writeEvent(); } - set_commited(); + DEBUG_ONLY(set_commited()); } - void set_starttime(const Ticks& time) { - _startTime = time.value(); - } - - void set_endtime(const Ticks& time) { - _endTime = time.value(); - } - - TraceEventId id() const { + static TraceEventId id() { return T::eventId; } - bool is_instant() const { + static bool is_instant() { return T::isInstant; } - bool is_requestable() const { + static bool is_requestable() { return T::isRequestable; } - bool has_thread() const { + static bool has_thread() { return T::hasThread; } - bool has_stacktrace() const { + static bool has_stacktrace() { return T::hasStackTrace; } void cancel() { - assert(!_committed && !_cancelled, "event was already committed/cancelled"); + assert(!_committed && !_cancelled, + "event was already committed/cancelled"); DEBUG_ONLY(_cancelled = true); } - void set_commited() { - assert(!_committed, "event has already been committed"); - DEBUG_ONLY(_committed = true); - } - ~TraceEvent() { if (_started) { - assert(_ignore_check || _committed || _cancelled, "event was not committed/cancelled"); + assert(_ignore_check || _committed || _cancelled, + "event was not committed/cancelled"); } } + +#ifdef ASSERT + protected: + void ignoreCheck() { + _ignore_check = true; + } + + private: + void set_commited() { + assert(!_committed, "event has already been committed"); + _committed = true; + } +#endif // ASSERT }; #endif // INCLUDE_TRACE diff --git a/hotspot/src/share/vm/trace/traceEventClasses.xsl b/hotspot/src/share/vm/trace/traceEventClasses.xsl index 41d3a446a9e..16b30c7b909 100644 --- a/hotspot/src/share/vm/trace/traceEventClasses.xsl +++ b/hotspot/src/share/vm/trace/traceEventClasses.xsl @@ -1,6 +1,6 @@ - + - + - - + - - - + type="const char*" sizeop="sizeof_utf(%)"/> + type="const Symbol*" sizeop="sizeof(u8)"/> + type="const Klass*" sizeop="sizeof(u8)"/> + type="const Method*" sizeop="sizeof(u8)"/> - - - - - - - - + + - + sizeop="sizeof(u8)"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + diff --git a/hotspot/src/share/vm/utilities/debug.cpp b/hotspot/src/share/vm/utilities/debug.cpp index 8d6a9398764..f0aa8371f17 100644 --- a/hotspot/src/share/vm/utilities/debug.cpp +++ b/hotspot/src/share/vm/utilities/debug.cpp @@ -51,9 +51,14 @@ #include "services/heapDumper.hpp" #include "utilities/defaultStream.hpp" #include "utilities/events.hpp" +#include "utilities/macros.hpp" #include "utilities/top.hpp" #include "utilities/vmError.hpp" +#if INCLUDE_TRACE +#include "trace/tracing.hpp" +#endif + #ifndef ASSERT # ifdef _DEBUG // NOTE: don't turn the lines below into a comment -- if you're getting @@ -280,6 +285,12 @@ void report_out_of_shared_space(SharedSpaceType shared_space) { exit(2); } +static void notify_tracing() { +#if INCLUDE_TRACE + Tracing::on_vm_error(true); +#endif +} + void report_insufficient_metaspace(size_t required_size) { warning("\nThe MaxMetaspaceSize of " SIZE_FORMAT " bytes is not large enough.\n" "Either don't specify the -XX:MaxMetaspaceSize=\n" @@ -302,6 +313,8 @@ void report_java_out_of_memory(const char* message) { HeapDumper::dump_heap_from_oome(); } + notify_tracing(); + if (OnOutOfMemoryError && OnOutOfMemoryError[0]) { VMError::report_java_out_of_memory(message); } diff --git a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp index f594bafbc2f..038f348a434 100644 --- a/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp +++ b/hotspot/src/share/vm/utilities/globalDefinitions_visCPP.hpp @@ -174,6 +174,8 @@ const jlong max_jlong = CONST64(0x7fffffffffffffff); #if _MSC_VER < 1800 // Visual Studio 2013 introduced strtoull(); before, one has to use _strtoui64() instead. #define strtoull _strtoui64 +// Visual Studio prior to 2013 had no va_copy, but could safely copy va_list by assignement +#define va_copy(dest, src) dest = src // Fixes some wrong warnings about 'this' : used in base member initializer list #pragma warning( disable : 4355 ) #endif diff --git a/hotspot/src/share/vm/utilities/hashtable.cpp b/hotspot/src/share/vm/utilities/hashtable.cpp index 10f4456274a..8af6156ed45 100644 --- a/hotspot/src/share/vm/utilities/hashtable.cpp +++ b/hotspot/src/share/vm/utilities/hashtable.cpp @@ -383,4 +383,9 @@ template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; template class BasicHashtable; +#if INCLUDE_TRACE +template class Hashtable; +template class HashtableEntry; +template class BasicHashtable; +#endif template class BasicHashtable; diff --git a/hotspot/test/TEST.ROOT b/hotspot/test/TEST.ROOT index 57f0e0ae061..8dd7c84e9ee 100644 --- a/hotspot/test/TEST.ROOT +++ b/hotspot/test/TEST.ROOT @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ keys=cte_test jcmd nmt regression gc stress groups=TEST.groups [closed/TEST.groups] -requires.properties=sun.arch.data.model java.version +requires.properties=sun.arch.data.model # Tests using jtreg 4.1 b12 features requiredVersion=4.1 b12 diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index f7d983f5a8f..11b95da776b 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -297,7 +297,8 @@ hotspot_compiler_3 = \ compiler/types/ \ compiler/uncommontrap/ \ compiler/unsafe/ \ - -compiler/intrinsics/bmi/verifycode \ + -compiler/intrinsics/adler32 \ + -compiler/intrinsics/bmi \ -compiler/intrinsics/mathexact \ -compiler/intrinsics/multiplytolen \ -compiler/intrinsics/sha \ diff --git a/hotspot/test/compiler/c1/CanonicalizeArrayLength.java b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java index 9971d25bde8..ee2649a3b3a 100644 --- a/hotspot/test/compiler/c1/CanonicalizeArrayLength.java +++ b/hotspot/test/compiler/c1/CanonicalizeArrayLength.java @@ -25,10 +25,10 @@ * @test * @bug 8150102 8150514 8150534 * @summary C1 crashes in Canonicalizer::do_ArrayLength() after fix for JDK-8150102 - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation CanonicalizeArrayLength - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:+PatchALot CanonicalizeArrayLength - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=0 CanonicalizeArrayLength - * @run main/othervm -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=1 CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:+PatchALot CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=0 CanonicalizeArrayLength + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:CompileThreshold=100 -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:-BackgroundCompilation -XX:ScavengeRootsInCode=1 CanonicalizeArrayLength */ public class CanonicalizeArrayLength { int[] arr = new int[42]; diff --git a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java index dd4daef9849..12c14cb2ee5 100644 --- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java +++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java index 3074acbc1a8..097cf9d9349 100644 --- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java +++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java index b06cbf5c89c..98baacb6c86 100644 --- a/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java +++ b/hotspot/test/compiler/calls/fromCompiled/CompiledInvokeDynamic2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java index 28b38025db6..ffc4fa94e0e 100644 --- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java +++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2CompiledTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java index 3359e8104be..9579fc2e1ce 100644 --- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java +++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2InterpretedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java index 03fbfdda2a4..78f2f556fa4 100644 --- a/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java +++ b/hotspot/test/compiler/calls/fromInterpreted/InterpretedInvokeDynamic2NativeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,9 +24,10 @@ /* * @test * @library /test/lib /testlibrary / + * @modules java.base/jdk.internal.org.objectweb.asm * @build compiler.calls.common.InvokeDynamic * @build compiler.calls.common.InvokeDynamicPatcher - * @run driver compiler.calls.common.InvokeDynamicPatcher + * @run main compiler.calls.common.InvokeDynamicPatcher * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java index 3bb001802ae..dced25799d7 100644 --- a/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java +++ b/hotspot/test/compiler/codecache/jmx/PeakUsageTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import sun.hotspot.code.BlobType; /* * @test PeakUsageTest + * @ignore 8151345 * @library /testlibrary /test/lib * @modules java.base/sun.misc * java.management diff --git a/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java index e128f500901..2541d9d0b83 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/CompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commandfile.CompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.CompileOnlyTest + * @run driver compiler.compilercontrol.commandfile.CompileOnlyTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java index 2b40af6182e..77c2a2e0748 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/ExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commandfile.ExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.ExcludeTest + * @run driver compiler.compilercontrol.commandfile.ExcludeTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java index a35474235e8..ce45d52b11c 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/LogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commandfile.LogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.LogTest + * @run driver compiler.compilercontrol.commandfile.LogTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java index ede2eb65776..5e90521eabf 100644 --- a/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/commandfile/PrintTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.commandfile.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commandfile.PrintTest + * @run driver compiler.compilercontrol.commandfile.PrintTest */ package compiler.compilercontrol.commandfile; diff --git a/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java index f08fb34e318..7a1b0c1da40 100644 --- a/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/CompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commands.CompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.CompileOnlyTest + * @run driver compiler.compilercontrol.commands.CompileOnlyTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java index 0af19c1a35e..b84befca8c2 100644 --- a/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/ExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commands.ExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.ExcludeTest + * @run driver compiler.compilercontrol.commands.ExcludeTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/commands/LogTest.java b/hotspot/test/compiler/compilercontrol/commands/LogTest.java index 07a437853cc..4ffebe41a32 100644 --- a/hotspot/test/compiler/compilercontrol/commands/LogTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/LogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.commands.LogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.LogTest + * @run driver compiler.compilercontrol.commands.LogTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/commands/PrintTest.java b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java index eddeadbfbe7..d9ac685ca8f 100644 --- a/hotspot/test/compiler/compilercontrol/commands/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/commands/PrintTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.commands.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.commands.PrintTest + * @run driver compiler.compilercontrol.commands.PrintTest */ package compiler.compilercontrol.commands; diff --git a/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java index bdc3a39f32f..439e5e9505d 100644 --- a/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/CompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.directives.CompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.CompileOnlyTest + * @run driver compiler.compilercontrol.directives.CompileOnlyTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java index 44b33dd43c1..0569cdfe323 100644 --- a/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/ExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.directives.ExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.ExcludeTest + * @run driver compiler.compilercontrol.directives.ExcludeTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/directives/LogTest.java b/hotspot/test/compiler/compilercontrol/directives/LogTest.java index 634aee5cb01..1f84d4aea5e 100644 --- a/hotspot/test/compiler/compilercontrol/directives/LogTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/LogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.directives.LogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.LogTest + * @run driver compiler.compilercontrol.directives.LogTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/directives/PrintTest.java b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java index 78ac4de4cee..bbd92c1704b 100644 --- a/hotspot/test/compiler/compilercontrol/directives/PrintTest.java +++ b/hotspot/test/compiler/compilercontrol/directives/PrintTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.directives.PrintTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.directives.PrintTest + * @run driver compiler.compilercontrol.directives.PrintTest */ package compiler.compilercontrol.directives; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java index 21d7af2efb7..372b50a72b6 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddAndRemoveTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddAndRemoveTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddAndRemoveTest + * @run driver compiler.compilercontrol.jcmd.AddAndRemoveTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java index 5f17ad0cc27..5b2a9e26843 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddCompileOnlyTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddCompileOnlyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddCompileOnlyTest + * @run driver compiler.compilercontrol.jcmd.AddCompileOnlyTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java index c72b6c06e4e..a06c32616d8 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddExcludeTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddExcludeTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddExcludeTest + * @run driver compiler.compilercontrol.jcmd.AddExcludeTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java index 900c57978ab..266cf3c5dda 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddLogTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.AddLogTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddLogTest + * @run driver compiler.compilercontrol.jcmd.AddLogTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java index 8f9c0250138..9697711c294 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/AddPrintAssemblyTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.jcmd.AddPrintAssemblyTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.AddPrintAssemblyTest + * @run driver compiler.compilercontrol.jcmd.AddPrintAssemblyTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java index 25966f9f726..da1fef49141 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest + * @run driver compiler.compilercontrol.jcmd.ClearDirectivesFileStackTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java index f9f382da110..c9d9f8dcfd0 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/ClearDirectivesStackTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.jcmd.ClearDirectivesStackTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.ClearDirectivesStackTest + * @run driver compiler.compilercontrol.jcmd.ClearDirectivesStackTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java index 5821de76d75..7afd4d6f8b3 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/PrintDirectivesTest.java @@ -30,9 +30,9 @@ * @build compiler.compilercontrol.jcmd.PrintDirectivesTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm compiler.compilercontrol.jcmd.PrintDirectivesTest + * @run driver compiler.compilercontrol.jcmd.PrintDirectivesTest */ package compiler.compilercontrol.jcmd; diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java index 1da46dedf00..580d9b614ff 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddJcmdBase.java @@ -32,74 +32,99 @@ import jdk.test.lib.TimeLimitedRunner; import jdk.test.lib.Utils; import pool.PoolHelper; +import java.util.ArrayList; import java.util.List; +import java.util.Random; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import java.util.stream.Stream; public abstract class StressAddJcmdBase { private static final int DIRECTIVES_AMOUNT = Integer.getInteger( "compiler.compilercontrol.jcmd.StressAddJcmdBase.directivesAmount", - 1000); - private static final int DIRECTIVE_FILES = Integer.getInteger( - "compiler.compilercontrol.jcmd.StressAddJcmdBase.directiveFiles", - 5); + 200); + private static final int TIMEOUT = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddJcmdBase.timeout", + 30); private static final List DESCRIPTORS = new PoolHelper() .getAllMethods().stream() .map(pair -> AbstractTestBase .getValidMethodDescriptor(pair.first)) .collect(Collectors.toList()); + private static final String DIRECTIVE_FILE = "directives.json"; + private static final List VM_OPTIONS = new ArrayList<>(); + private static final Random RANDOM = Utils.getRandomInstance(); + + static { + VM_OPTIONS.add("-Xmixed"); + VM_OPTIONS.add("-XX:+UnlockDiagnosticVMOptions"); + VM_OPTIONS.add("-XX:+LogCompilation"); + VM_OPTIONS.add("-XX:CompilerDirectivesLimit=1001"); + } /** * Performs test */ public void test() { - List commands = prepareCommands(); - Executor executor = new TimeLimitedExecutor(commands); + HugeDirectiveUtil.createHugeFile(DESCRIPTORS, DIRECTIVE_FILE, + DIRECTIVES_AMOUNT); + Executor executor = new TimeLimitedExecutor(); List outputAnalyzers = executor.execute(); outputAnalyzers.get(0).shouldHaveExitValue(0); } /** - * Makes connection to the test VM + * Makes connection to the test VM and performs a diagnostic command * - * @param pid a pid of the VM under test - * @param commands a list of jcmd commands to be executed + * @param pid a pid of the VM under test * @return true if the test should continue invocation of this method */ - protected abstract boolean makeConnection(int pid, List commands); + protected abstract boolean makeConnection(int pid); /** * Finish test executions */ protected void finish() { } - private List prepareCommands() { - String[] files = new String[DIRECTIVE_FILES]; - for (int i = 0; i < DIRECTIVE_FILES; i++) { - files[i] = "directives" + i + ".json"; - HugeDirectiveUtil.createHugeFile(DESCRIPTORS, files[i], - DIRECTIVES_AMOUNT); + protected String nextCommand() { + int i = RANDOM.nextInt(JcmdCommand.values().length); + JcmdCommand jcmdCommand = JcmdCommand.values()[i]; + switch (jcmdCommand) { + case ADD: + return jcmdCommand.command + " " + DIRECTIVE_FILE; + case PRINT: + case CLEAR: + case REMOVE: + return jcmdCommand.command; + default: + throw new Error("TESTBUG: incorrect command: " + jcmdCommand); + } + } + + private enum JcmdCommand { + ADD("Compiler.directives_add"), + PRINT("Compiler.directives_print"), + CLEAR("Compiler.directives_clear"), + REMOVE("Compiler.directives_remove"); + + public final String command; + + JcmdCommand(String command) { + this.command = command; } - return Stream.of(files) - .map(file -> "Compiler.directives_add " + file) - .collect(Collectors.toList()); } private class TimeLimitedExecutor extends Executor { - private final List jcmdCommands; - - public TimeLimitedExecutor(List jcmdCommands) { + public TimeLimitedExecutor() { /* There are no need to check the state */ - super(true, null, null, jcmdCommands); - this.jcmdCommands = jcmdCommands; + super(true, VM_OPTIONS, null, null); } @Override protected OutputAnalyzer[] executeJCMD(int pid) { TimeLimitedRunner runner = new TimeLimitedRunner( - Utils.DEFAULT_TEST_TIMEOUT, + TimeUnit.SECONDS.toMillis(TIMEOUT), Utils.TIMEOUT_FACTOR, - () -> makeConnection(pid, jcmdCommands)); + () -> makeConnection(pid)); try { runner.call(); } catch (Exception e) { diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java index b2ad879351a..26c225380ac 100644 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java +++ b/hotspot/test/compiler/compilercontrol/jcmd/StressAddMultiThreadedTest.java @@ -27,21 +27,19 @@ * @summary Tests jcmd to be able to add a lot of huge directive files with * parallel executed jcmds until timeout has reached * @library /testlibrary /test/lib /compiler/testlibrary ../share / - * @ignore 8148563 * @build compiler.compilercontrol.jcmd.StressAddMultiThreadedTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils * compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=360 compiler.compilercontrol.jcmd.StressAddMultiThreadedTest + * @run driver compiler.compilercontrol.jcmd.StressAddMultiThreadedTest */ package compiler.compilercontrol.jcmd; import jdk.test.lib.dcmd.PidJcmdExecutor; -import java.util.List; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; @@ -49,16 +47,15 @@ import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public class StressAddMultiThreadedTest extends StressAddJcmdBase { - private static final int THREADS; + private static final int THREADS = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddMultiThreadedTest.threads", + 5); + private volatile int commands = Integer.getInteger( + "compiler.compilercontrol.jcmd.StressAddMultiThreadedTest.commands", + 20); private final BlockingQueue queue; private final ExecutorService executor; - static { - THREADS = Runtime.getRuntime().availableProcessors() - * Integer.getInteger("compiler.compilercontrol.jcmd" + - ".StressAddMultiThreadedTest.threadFactor", 10); - } - public StressAddMultiThreadedTest() { queue = new ArrayBlockingQueue<>(THREADS); executor = new ThreadPoolExecutor(THREADS, THREADS, 100, @@ -71,14 +68,10 @@ public class StressAddMultiThreadedTest extends StressAddJcmdBase { } @Override - protected boolean makeConnection(int pid, List commands) { - commands.forEach(command -> { - if (!executor.isShutdown()) { - executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid)) - .execute(command)); - } - }); - return !executor.isShutdown(); + protected boolean makeConnection(int pid) { + executor.submit(() -> new PidJcmdExecutor(String.valueOf(pid)) + .execute(nextCommand())); + return (--commands != 0); } @Override diff --git a/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java b/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java deleted file mode 100644 index f8509128321..00000000000 --- a/hotspot/test/compiler/compilercontrol/jcmd/StressAddSequentiallyTest.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * 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 8137167 - * @summary Tests jcmd to be able to add a lot of huge directives - * @library /testlibrary /test/lib /compiler/testlibrary ../share / - * @build compiler.compilercontrol.jcmd.StressAddSequentiallyTest - * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox - * compiler.testlibrary.CompilerUtils - * compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox - * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=300 compiler.compilercontrol.jcmd.StressAddSequentiallyTest - */ - -package compiler.compilercontrol.jcmd; - -import jdk.test.lib.dcmd.PidJcmdExecutor; - -import java.util.List; - -public class StressAddSequentiallyTest extends StressAddJcmdBase { - public static void main(String[] args) { - new StressAddSequentiallyTest().test(); - } - - @Override - protected boolean makeConnection(int pid, List commands) { - commands.forEach(command -> new PidJcmdExecutor(String.valueOf(pid)) - .execute(command)); - return true; - } -} diff --git a/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java index 00ca74d108d..87cd26a8958 100644 --- a/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java +++ b/hotspot/test/compiler/compilercontrol/matcher/MethodMatcherTest.java @@ -42,7 +42,7 @@ import java.util.regex.Pattern; * @summary Tests CompilerCommand's method matcher * @library /testlibrary /test/lib /compiler/whitebox ../share / * @build compiler.compilercontrol.matcher.MethodMatcherTest - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions * -XX:+WhiteBoxAPI compiler.compilercontrol.matcher.MethodMatcherTest diff --git a/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java index 13df53afdfe..c954dba9011 100644 --- a/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomCommandsTest.java @@ -29,9 +29,9 @@ * @build compiler.compilercontrol.mixed.RandomCommandsTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomCommandsTest + * @run driver/timeout=600 compiler.compilercontrol.mixed.RandomCommandsTest */ package compiler.compilercontrol.mixed; diff --git a/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java index 7b837e672c5..e8739e8abde 100644 --- a/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java +++ b/hotspot/test/compiler/compilercontrol/mixed/RandomValidCommandsTest.java @@ -30,7 +30,7 @@ * @build compiler.compilercontrol.mixed.RandomValidCommandsTest * pool.sub.* pool.subpack.* sun.hotspot.WhiteBox * compiler.testlibrary.CompilerUtils compiler.compilercontrol.share.actions.* - * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run driver ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main/othervm/timeout=600 compiler.compilercontrol.mixed.RandomValidCommandsTest */ diff --git a/hotspot/test/compiler/compilercontrol/share/MultiCommand.java b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java index 4eac177223b..f85591da663 100644 --- a/hotspot/test/compiler/compilercontrol/share/MultiCommand.java +++ b/hotspot/test/compiler/compilercontrol/share/MultiCommand.java @@ -53,8 +53,8 @@ public class MultiCommand extends AbstractTestBase { List testCases = new ArrayList<>(); for (Command cmd : commands) { if (validOnly && cmd == Command.NONEXISTENT) { - // skip invalid command - continue; + // replace with a valid command + cmd = Command.EXCLUDE; } Executable exec = Utils.getRandomElement(METHODS).first; MethodDescriptor md; @@ -72,6 +72,7 @@ public class MultiCommand extends AbstractTestBase { @Override public void test() { Scenario.Builder builder = Scenario.getBuilder(); + builder.addFlag("-Xmixed"); for (CompileCommand cc : testCases) { cc.print(); builder.add(cc); diff --git a/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java index 49109151d82..a2408da7fbb 100644 --- a/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java +++ b/hotspot/test/compiler/compilercontrol/share/scenario/Scenario.java @@ -200,6 +200,7 @@ public final class Scenario { private final List jcmdCommands = new ArrayList<>(); public Builder() { + addFlag("-Xmixed"); builders.put(Type.FILE, new CommandFileBuilder(Type.FILE.fileName)); builders.put(Type.OPTION, new CommandOptionsBuilder()); builders.put(Type.DIRECTIVE, new DirectiveBuilder( diff --git a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java index d96de812faa..1fdaf805f9a 100644 --- a/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java +++ b/hotspot/test/compiler/intrinsics/IntrinsicDisabledTest.java @@ -33,8 +33,8 @@ * -XX:+WhiteBoxAPI * -XX:DisableIntrinsic=_putCharVolatile,_putInt * -XX:DisableIntrinsic=_putIntVolatile - * -XX:CompileCommand=option,sun.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt - * -XX:CompileCommand=option,sun.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile + * -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putChar,ccstrlist,DisableIntrinsic,_getCharVolatile,_getInt + * -XX:CompileCommand=option,jdk.internal.misc.Unsafe::putCharVolatile,ccstrlist,DisableIntrinsic,_getIntVolatile * IntrinsicDisabledTest */ @@ -60,7 +60,7 @@ public class IntrinsicDisabledTest { return Boolean.valueOf(Objects.toString(wb.getVMFlag("TieredCompilation"))); } - /* This test uses several methods from sun.misc.Unsafe. The method + /* This test uses several methods from jdk.internal.misc.Unsafe. The method * getMethod() returns a different Executable for each different * combination of its input parameters. There are eight possible * combinations, getMethod can return an Executable representing @@ -74,7 +74,7 @@ public class IntrinsicDisabledTest { String methodTypeName = isChar ? "Char" : "Int"; try { - Class aClass = Class.forName("sun.misc.Unsafe"); + Class aClass = Class.forName("jdk.internal.misc.Unsafe"); if (isPut) { aMethod = aClass.getDeclaredMethod("put" + methodTypeName + (isVolatile ? "Volatile" : ""), Object.class, diff --git a/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java b/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java new file mode 100644 index 00000000000..76a2812e733 --- /dev/null +++ b/hotspot/test/compiler/intrinsics/class/TestClassIsPrimitive.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8150669 + * @summary C1 intrinsic for Class.isPrimitive + * @modules java.base/jdk.internal.misc + * @run main/othervm -ea -Diters=200 -Xint TestClassIsPrimitive + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 TestClassIsPrimitive + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 TestClassIsPrimitive + */ +import java.lang.reflect.Field; +import java.lang.reflect.Array; +import java.util.concurrent.Callable; + +public class TestClassIsPrimitive { + static final int ITERS = Integer.getInteger("iters", 1); + + public static void main(String... args) throws Exception { + testOK(true, InlineConstants::testBoolean); + testOK(true, InlineConstants::testByte); + testOK(true, InlineConstants::testShort); + testOK(true, InlineConstants::testChar); + testOK(true, InlineConstants::testInt); + testOK(true, InlineConstants::testFloat); + testOK(true, InlineConstants::testLong); + testOK(true, InlineConstants::testDouble); + testOK(false, InlineConstants::testObject); + testOK(false, InlineConstants::testArray); + + testOK(true, StaticConstants::testBoolean); + testOK(true, StaticConstants::testByte); + testOK(true, StaticConstants::testShort); + testOK(true, StaticConstants::testChar); + testOK(true, StaticConstants::testInt); + testOK(true, StaticConstants::testFloat); + testOK(true, StaticConstants::testLong); + testOK(true, StaticConstants::testDouble); + testOK(false, StaticConstants::testObject); + testOK(false, StaticConstants::testArray); + testNPE( StaticConstants::testNull); + + testOK(true, NoConstants::testBoolean); + testOK(true, NoConstants::testByte); + testOK(true, NoConstants::testShort); + testOK(true, NoConstants::testChar); + testOK(true, NoConstants::testInt); + testOK(true, NoConstants::testFloat); + testOK(true, NoConstants::testLong); + testOK(true, NoConstants::testDouble); + testOK(false, NoConstants::testObject); + testOK(false, NoConstants::testArray); + testNPE( NoConstants::testNull); + } + + public static void testOK(boolean expected, Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + Object res = test.call(); + if (!res.equals(expected)) { + throw new IllegalStateException("Wrong result: expected = " + expected + ", but got " + res); + } + } + } + + static volatile Object sink; + + public static void testNPE(Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + try { + sink = test.call(); + throw new IllegalStateException("Expected NPE"); + } catch (NullPointerException iae) { + // expected + } + } + } + + static volatile Class classBoolean = boolean.class; + static volatile Class classByte = byte.class; + static volatile Class classShort = short.class; + static volatile Class classChar = char.class; + static volatile Class classInt = int.class; + static volatile Class classFloat = float.class; + static volatile Class classLong = long.class; + static volatile Class classDouble = double.class; + static volatile Class classObject = Object.class; + static volatile Class classArray = Object[].class; + static volatile Class classNull = null; + + static final Class staticClassBoolean = boolean.class; + static final Class staticClassByte = byte.class; + static final Class staticClassShort = short.class; + static final Class staticClassChar = char.class; + static final Class staticClassInt = int.class; + static final Class staticClassFloat = float.class; + static final Class staticClassLong = long.class; + static final Class staticClassDouble = double.class; + static final Class staticClassObject = Object.class; + static final Class staticClassArray = Object[].class; + static final Class staticClassNull = null; + + static class InlineConstants { + static boolean testBoolean() { return boolean.class.isPrimitive(); } + static boolean testByte() { return byte.class.isPrimitive(); } + static boolean testShort() { return short.class.isPrimitive(); } + static boolean testChar() { return char.class.isPrimitive(); } + static boolean testInt() { return int.class.isPrimitive(); } + static boolean testFloat() { return float.class.isPrimitive(); } + static boolean testLong() { return long.class.isPrimitive(); } + static boolean testDouble() { return double.class.isPrimitive(); } + static boolean testObject() { return Object.class.isPrimitive(); } + static boolean testArray() { return Object[].class.isPrimitive(); } + } + + static class StaticConstants { + static boolean testBoolean() { return staticClassBoolean.isPrimitive(); } + static boolean testByte() { return staticClassByte.isPrimitive(); } + static boolean testShort() { return staticClassShort.isPrimitive(); } + static boolean testChar() { return staticClassChar.isPrimitive(); } + static boolean testInt() { return staticClassInt.isPrimitive(); } + static boolean testFloat() { return staticClassFloat.isPrimitive(); } + static boolean testLong() { return staticClassLong.isPrimitive(); } + static boolean testDouble() { return staticClassDouble.isPrimitive(); } + static boolean testObject() { return staticClassObject.isPrimitive(); } + static boolean testArray() { return staticClassArray.isPrimitive(); } + static boolean testNull() { return staticClassNull.isPrimitive(); } + } + + static class NoConstants { + static boolean testBoolean() { return classBoolean.isPrimitive(); } + static boolean testByte() { return classByte.isPrimitive(); } + static boolean testShort() { return classShort.isPrimitive(); } + static boolean testChar() { return classChar.isPrimitive(); } + static boolean testInt() { return classInt.isPrimitive(); } + static boolean testFloat() { return classFloat.isPrimitive(); } + static boolean testLong() { return classLong.isPrimitive(); } + static boolean testDouble() { return classDouble.isPrimitive(); } + static boolean testObject() { return classObject.isPrimitive(); } + static boolean testArray() { return classArray.isPrimitive(); } + static boolean testNull() { return classNull.isPrimitive(); } + } + +} + diff --git a/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java new file mode 100644 index 00000000000..404ccc6c60d --- /dev/null +++ b/hotspot/test/compiler/intrinsics/unsafe/AllocateUninitializedArray.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/* + * @test + * @bug 8150465 + * @summary Unsafe methods to produce uninitialized arrays + * @modules java.base/jdk.internal.misc + * @run main/othervm -ea -Diters=200 -Xint AllocateUninitializedArray + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=1 AllocateUninitializedArray + * @run main/othervm -ea -Diters=30000 -XX:TieredStopAtLevel=4 AllocateUninitializedArray + */ +import java.lang.reflect.Field; +import java.lang.reflect.Array; +import java.util.concurrent.Callable; + +public class AllocateUninitializedArray { + static final int ITERS = Integer.getInteger("iters", 1); + static final jdk.internal.misc.Unsafe UNSAFE; + + static { + try { + Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + public static void main(String... args) throws Exception { + testIAE(AllConstants::testObject); + testIAE(LengthIsConstant::testObject); + testIAE(ClassIsConstant::testObject); + testIAE(NothingIsConstant::testObject); + + testIAE(AllConstants::testArray); + testIAE(LengthIsConstant::testArray); + testIAE(ClassIsConstant::testArray); + testIAE(NothingIsConstant::testArray); + + testIAE(AllConstants::testNull); + testIAE(LengthIsConstant::testNull); + testIAE(ClassIsConstant::testNull); + testIAE(NothingIsConstant::testNull); + + testOK(boolean[].class, 10, AllConstants::testBoolean); + testOK(byte[].class, 10, AllConstants::testByte); + testOK(short[].class, 10, AllConstants::testShort); + testOK(char[].class, 10, AllConstants::testChar); + testOK(int[].class, 10, AllConstants::testInt); + testOK(float[].class, 10, AllConstants::testFloat); + testOK(long[].class, 10, AllConstants::testLong); + testOK(double[].class, 10, AllConstants::testDouble); + + testOK(boolean[].class, 10, LengthIsConstant::testBoolean); + testOK(byte[].class, 10, LengthIsConstant::testByte); + testOK(short[].class, 10, LengthIsConstant::testShort); + testOK(char[].class, 10, LengthIsConstant::testChar); + testOK(int[].class, 10, LengthIsConstant::testInt); + testOK(float[].class, 10, LengthIsConstant::testFloat); + testOK(long[].class, 10, LengthIsConstant::testLong); + testOK(double[].class, 10, LengthIsConstant::testDouble); + + testOK(boolean[].class, 10, ClassIsConstant::testBoolean); + testOK(byte[].class, 10, ClassIsConstant::testByte); + testOK(short[].class, 10, ClassIsConstant::testShort); + testOK(char[].class, 10, ClassIsConstant::testChar); + testOK(int[].class, 10, ClassIsConstant::testInt); + testOK(float[].class, 10, ClassIsConstant::testFloat); + testOK(long[].class, 10, ClassIsConstant::testLong); + testOK(double[].class, 10, ClassIsConstant::testDouble); + + testOK(boolean[].class, 10, NothingIsConstant::testBoolean); + testOK(byte[].class, 10, NothingIsConstant::testByte); + testOK(short[].class, 10, NothingIsConstant::testShort); + testOK(char[].class, 10, NothingIsConstant::testChar); + testOK(int[].class, 10, NothingIsConstant::testInt); + testOK(float[].class, 10, NothingIsConstant::testFloat); + testOK(long[].class, 10, NothingIsConstant::testLong); + testOK(double[].class, 10, NothingIsConstant::testDouble); + } + + public static void testOK(Class expectClass, int expectLen, Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + Object res = test.call(); + Class actualClass = res.getClass(); + if (!actualClass.equals(expectClass)) { + throw new IllegalStateException("Wrong class: expected = " + expectClass + ", but got " + actualClass); + } + int actualLen = Array.getLength(res); + if (actualLen != expectLen) { + throw new IllegalStateException("Wrong length: expected = " + expectLen + ", but got " + actualLen); + } + } + } + + static volatile Object sink; + + public static void testIAE(Callable test) throws Exception { + for (int c = 0; c < ITERS; c++) { + try { + sink = test.call(); + throw new IllegalStateException("Expected IAE"); + } catch (IllegalArgumentException iae) { + // expected + } + } + } + + static volatile int sampleLenNeg = -1; + static volatile int sampleLenZero = 0; + static volatile int sampleLen = 10; + + + static volatile Class classBoolean = boolean.class; + static volatile Class classByte = byte.class; + static volatile Class classShort = short.class; + static volatile Class classChar = char.class; + static volatile Class classInt = int.class; + static volatile Class classFloat = float.class; + static volatile Class classLong = long.class; + static volatile Class classDouble = double.class; + static volatile Class classObject = Object.class; + static volatile Class classArray = Object[].class; + static volatile Class classNull = null; + + static class AllConstants { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class, 10); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(byte.class, 10); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(short.class, 10); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(char.class, 10); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(int.class, 10); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(float.class, 10); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(long.class, 10); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(double.class, 10); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(Object.class, 10); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(Object[].class, 10); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(null, 10); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(int.class, 0); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(int.class, -1); } + } + + static class ClassIsConstant { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(boolean.class, sampleLen); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(byte.class, sampleLen); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(short.class, sampleLen); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(char.class, sampleLen); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(int.class, sampleLen); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(float.class, sampleLen); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(long.class, sampleLen); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(double.class, sampleLen); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(Object.class, sampleLen); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(Object[].class, sampleLen); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(null, sampleLen); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(int.class, sampleLenZero); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(int.class, sampleLenNeg); } + } + + static class LengthIsConstant { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, 10); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(classByte, 10); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(classShort, 10); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(classChar, 10); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(classInt, 10); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(classFloat, 10); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(classLong, 10); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(classDouble, 10); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(classObject, 10); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(classArray, 10); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(classNull, 10); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(classInt, 0); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(classInt, -1); } + } + + static class NothingIsConstant { + static Object testBoolean() { return UNSAFE.allocateUninitializedArray(classBoolean, sampleLen); } + static Object testByte() { return UNSAFE.allocateUninitializedArray(classByte, sampleLen); } + static Object testShort() { return UNSAFE.allocateUninitializedArray(classShort, sampleLen); } + static Object testChar() { return UNSAFE.allocateUninitializedArray(classChar, sampleLen); } + static Object testInt() { return UNSAFE.allocateUninitializedArray(classInt, sampleLen); } + static Object testFloat() { return UNSAFE.allocateUninitializedArray(classFloat, sampleLen); } + static Object testLong() { return UNSAFE.allocateUninitializedArray(classLong, sampleLen); } + static Object testDouble() { return UNSAFE.allocateUninitializedArray(classDouble, sampleLen); } + static Object testObject() { return UNSAFE.allocateUninitializedArray(classObject, sampleLen); } + static Object testArray() { return UNSAFE.allocateUninitializedArray(classArray, sampleLen); } + static Object testNull() { return UNSAFE.allocateUninitializedArray(classNull, sampleLen); } + static Object testZero() { return UNSAFE.allocateUninitializedArray(classInt, sampleLenZero); } + static Object testNeg() { return UNSAFE.allocateUninitializedArray(classInt, sampleLenNeg); } + } +} + diff --git a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java index b6a64e13a67..d1ca58c35bb 100644 --- a/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java +++ b/hotspot/test/compiler/intrinsics/unsafe/TestUnsafeUnalignedMismatchedAccesses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @test * @bug 8136473 * @summary Mismatched stores on same slice possible with Unsafe.Put*Unaligned methods + * @modules java.base/jdk.internal.misc * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestUnsafeUnalignedMismatchedAccesses * @run main/othervm -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -XX:+UnlockDiagnosticVMOptions -XX:-UseUnalignedAccesses TestUnsafeUnalignedMismatchedAccesses * diff --git a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java index 02bdef91a10..90724b371a8 100644 --- a/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java +++ b/hotspot/test/compiler/jsr292/NonInlinedCall/InvokeTest.java @@ -180,7 +180,10 @@ public class InvokeTest { static void testInterface() { System.out.println("linkToInterface"); - // Monomorphic case (optimized virtual call) + // Monomorphic case (optimized virtual call), concrete target method + run(() -> linkToInterface(new P1(), P1.class)); + + // Monomorphic case (optimized virtual call), default target method run(() -> linkToInterface(new T(), I.class)); // Megamorphic case (virtual call) diff --git a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java index 30bcd1e63b4..0504798c50a 100644 --- a/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java +++ b/hotspot/test/compiler/jvmci/JVM_GetJVMCIRuntimeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary / + * @modules jdk.vm.ci/jdk.vm.ci.runtime * @run main/othervm -XX:+UnlockExperimentalVMOptions * -Dcompiler.jvmci.JVM_GetJVMCIRuntimeTest.positive=true * -XX:+EnableJVMCI diff --git a/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java b/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java index 9f5e9cfe106..59c3e228c7a 100644 --- a/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java +++ b/hotspot/test/compiler/jvmci/code/InterpreterFrameSizeTest.java @@ -24,6 +24,14 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9") & os.arch != "aarch64" + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common + * jdk.vm.ci/jdk.vm.ci.amd64 + * jdk.vm.ci/jdk.vm.ci.sparc * @compile CodeInstallationTest.java DebugInfoTest.java TestAssembler.java amd64/AMD64TestAssembler.java sparc/SPARCTestAssembler.java * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.code.InterpreterFrameSizeTest */ diff --git a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java index 5a18a6ad29a..ac42d62f543 100644 --- a/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java +++ b/hotspot/test/compiler/jvmci/compilerToVM/JVM_RegisterJVMCINatives.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary / + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.runtime * @run main/othervm -XX:+UnlockExperimentalVMOptions * -Dcompiler.jvmci.compilerToVM.JVM_RegisterJVMCINatives.positive=true * -XX:+EnableJVMCI diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java index 90284c115de..75d70e7baa7 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidCompilationResult.java @@ -24,7 +24,14 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common * @compile CodeInstallerTest.java + * @build compiler.jvmci.errors.TestInvalidCompilationResult * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidCompilationResult */ diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java index 6ca22fa9cab..53db53e7d1d 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidDebugInfo.java @@ -24,6 +24,12 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common * @compile CodeInstallerTest.java * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidDebugInfo */ diff --git a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java index 0f1fe6e873c..7fe01e55470 100644 --- a/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java +++ b/hotspot/test/compiler/jvmci/errors/TestInvalidOopMap.java @@ -24,6 +24,12 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.code.site + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime + * jdk.vm.ci/jdk.vm.ci.common * @compile CodeInstallerTest.java * @run junit/othervm -da:jdk.vm.ci... -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI compiler.jvmci.errors.TestInvalidOopMap */ diff --git a/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java index 7dae44ee86c..7dbbf8e35fa 100644 --- a/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java +++ b/hotspot/test/compiler/jvmci/events/JvmciShutdownEventTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,10 @@ * @bug 8136421 * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") * @library /testlibrary / + * @modules jdk.vm.ci/jdk.vm.ci.hotspot + * jdk.vm.ci/jdk.vm.ci.code + * jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime * @build compiler.jvmci.common.JVMCIHelpers * compiler.jvmci.events.JvmciShutdownEventListener * compiler.jvmci.events.JvmciShutdownEventTest @@ -36,10 +40,11 @@ * compiler.jvmci.common.JVMCIHelpers$EmptyHotspotCompiler * compiler.jvmci.common.JVMCIHelpers$EmptyCompilerFactory * compiler.jvmci.events.JvmciShutdownEventListener - * @run driver - * compiler.jvmci.events.JvmciShutdownEventTest + * @run main/othervm compiler.jvmci.events.JvmciShutdownEventTest */ + // as soon as CODETOOLS-7901589 fixed, '@run main/othervm' at L43 should be replaced w/ '@run driver' + package compiler.jvmci.events; import jdk.test.lib.ExitCode; diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java index 37b54a14796..6f1f1759e8e 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveConcreteMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveConcreteMethodTest */ diff --git a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java index 043aba3d9bb..ba62291d47c 100644 --- a/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java +++ b/hotspot/test/compiler/jvmci/jdk.vm.ci.runtime.test/src/jdk/vm/ci/runtime/test/ResolvedJavaTypeResolveMethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,8 @@ /** * @test * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @modules jdk.vm.ci/jdk.vm.ci.meta + * jdk.vm.ci/jdk.vm.ci.runtime * @run junit/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI jdk.vm.ci.runtime.test.ResolvedJavaTypeResolveMethodTest */ diff --git a/hotspot/test/compiler/jvmci/meta/StableFieldTest.java b/hotspot/test/compiler/jvmci/meta/StableFieldTest.java new file mode 100644 index 00000000000..80ff0d7dbaa --- /dev/null +++ b/hotspot/test/compiler/jvmci/meta/StableFieldTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8151664 + * @requires (os.simpleArch == "x64" | os.simpleArch == "sparcv9" | os.simpleArch == "aarch64") + * @library /testlibrary /test/lib / + * @compile StableFieldTest.java + * @run main ClassFileInstaller compiler.jvmci.meta.StableFieldTest + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -Xbootclasspath/a:. compiler.jvmci.meta.StableFieldTest + */ + +package compiler.jvmci.meta; + +import java.lang.reflect.Field; +import jdk.internal.vm.annotation.Stable; +import jdk.vm.ci.hotspot.HotSpotResolvedJavaField; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.runtime.JVMCI; + +public class StableFieldTest { + + @Stable static int myStaticField = 5; + @Stable int myInstanceField = 10; + + public static void main(String[] args) throws Throwable { + MetaAccessProvider metaAccess = JVMCI.getRuntime().getHostJVMCIBackend().getMetaAccess(); + for (String name : new String[] {"myStaticField", "myInstanceField"}) { + java.lang.reflect.Field javaField = StableFieldTest.class.getDeclaredField(name); + HotSpotResolvedJavaField field = (HotSpotResolvedJavaField) metaAccess.lookupJavaField(javaField); + if (!field.isStable()) { + throw new AssertionError("Expected HotSpotResolvedJavaField.isStable() to return true for " + javaField); + } + } + } +} diff --git a/hotspot/test/compiler/stable/StableConfiguration.java b/hotspot/test/compiler/stable/StableConfiguration.java index be69081640c..c224b6db151 100644 --- a/hotspot/test/compiler/stable/StableConfiguration.java +++ b/hotspot/test/compiler/stable/StableConfiguration.java @@ -31,54 +31,10 @@ import sun.hotspot.WhiteBox; public class StableConfiguration { static final WhiteBox WB = WhiteBox.getWhiteBox(); static final boolean isStableEnabled; - static final boolean isServerWithStable; static { Boolean value = WB.getBooleanVMFlag("FoldStableValues"); isStableEnabled = (value == null ? false : value); - isServerWithStable = isStableEnabled && get(); System.out.println("@Stable: " + (isStableEnabled ? "enabled" : "disabled")); - System.out.println("Server Compiler: " + get()); } - - // The method 'get' below returns true if the method is server compiled - // and is used by the Stable tests to determine whether methods in - // general are being server compiled or not as the -XX:+FoldStableValues - // option is only applicable to -server. - // - // On aarch64 we DeOptimize when patching. This means that when the - // method is compiled as a result of -Xcomp it DeOptimizes immediately. - // The result is that getMethodCompilationLevel returns 0. This means - // the method returns true based on java.vm.name. - // - // However when the tests are run with -XX:+TieredCompilation and - // -XX:TieredStopAtLevel=1 this fails because methods will always - // be client compiled. - // - // Solution is to add a simple method 'get1' which should never be - // DeOpted and use that to determine the compilation level instead. - static void get1() { - } - - - - // ::get() is among immediately compiled methods. - static boolean get() { - try { - get1(); - Method m = StableConfiguration.class.getDeclaredMethod("get1"); - int level = WB.getMethodCompilationLevel(m); - if (level > 0) { - return (level == 4); - } else { - String javaVM = System.getProperty("java.vm.name", ""); - if (javaVM.contains("Server")) return true; - if (javaVM.contains("Client")) return false; - throw new Error("Unknown VM type: "+javaVM); - } - } catch (NoSuchMethodException e) { - throw new Error(e); - } - } - } diff --git a/hotspot/test/compiler/stable/TestStableBoolean.java b/hotspot/test/compiler/stable/TestStableBoolean.java index 168ddf48da7..e9d2e1eb703 100644 --- a/hotspot/test/compiler/stable/TestStableBoolean.java +++ b/hotspot/test/compiler/stable/TestStableBoolean.java @@ -87,8 +87,7 @@ import jdk.internal.vm.annotation.Stable; import java.lang.reflect.InvocationTargetException; public class TestStableBoolean { - static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; + static final boolean isStableEnabled = StableConfiguration.isStableEnabled; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,14 +208,14 @@ public class TestStableBoolean { c.v = new boolean[1]; c.v[0] = true; boolean val1 = get(); c.v[0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); } { c.v = new boolean[20]; c.v[10] = true; boolean val1 = get1(); c.v[10] = false; boolean val2 = get1(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); } { @@ -241,19 +240,19 @@ public class TestStableBoolean { c.v = new boolean[1][1]; c.v[0][0] = true; boolean val1 = get(); c.v[0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); c.v = new boolean[1][1]; c.v[0][0] = false; boolean val3 = get(); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); c.v[0] = new boolean[1]; c.v[0][0] = false; boolean val4 = get(); - assertEquals(val4, (isServerWithStable ? true : false)); + assertEquals(val4, (isStableEnabled ? true : false)); } { c.v = new boolean[1][1]; boolean[] val1 = get1(); c.v[0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -279,28 +278,28 @@ public class TestStableBoolean { c.v = new boolean[1][1][1]; c.v[0][0][0] = true; boolean val1 = get(); c.v[0][0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); c.v = new boolean[1][1][1]; c.v[0][0][0] = false; boolean val3 = get(); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); c.v[0] = new boolean[1][1]; c.v[0][0][0] = false; boolean val4 = get(); - assertEquals(val4, (isServerWithStable ? true : false)); + assertEquals(val4, (isStableEnabled ? true : false)); c.v[0][0] = new boolean[1]; c.v[0][0][0] = false; boolean val5 = get(); - assertEquals(val5, (isServerWithStable ? true : false)); + assertEquals(val5, (isStableEnabled ? true : false)); } { c.v = new boolean[1][1][1]; boolean[] val1 = get1(); c.v[0][0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1]; boolean[][] val1 = get2(); c.v[0] = new boolean[1][1]; boolean[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -327,37 +326,37 @@ public class TestStableBoolean { c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = true; boolean val1 = get(); c.v[0][0][0][0] = false; boolean val2 = get(); assertEquals(val1, true); - assertEquals(val2, (isServerWithStable ? true : false)); + assertEquals(val2, (isStableEnabled ? true : false)); c.v = new boolean[1][1][1][1]; c.v[0][0][0][0] = false; boolean val3 = get(); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); c.v[0] = new boolean[1][1][1]; c.v[0][0][0][0] = false; boolean val4 = get(); - assertEquals(val4, (isServerWithStable ? true : false)); + assertEquals(val4, (isStableEnabled ? true : false)); c.v[0][0] = new boolean[1][1]; c.v[0][0][0][0] = false; boolean val5 = get(); - assertEquals(val5, (isServerWithStable ? true : false)); + assertEquals(val5, (isStableEnabled ? true : false)); c.v[0][0][0] = new boolean[1]; c.v[0][0][0][0] = false; boolean val6 = get(); - assertEquals(val6, (isServerWithStable ? true : false)); + assertEquals(val6, (isStableEnabled ? true : false)); } { c.v = new boolean[1][1][1][1]; boolean[] val1 = get1(); c.v[0][0][0] = new boolean[1]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1][1]; boolean[][] val1 = get2(); c.v[0][0] = new boolean[1][1]; boolean[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1][1]; boolean[][][] val1 = get3(); c.v[0] = new boolean[1][1][1]; boolean[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -420,7 +419,7 @@ public class TestStableBoolean { c.v = new boolean[1][1]; c.v[0] = new boolean[0]; boolean[] val1 = get1(); c.v[0] = new boolean[0]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -456,14 +455,14 @@ public class TestStableBoolean { c.v = new boolean[1][1][1]; c.v[0][0] = new boolean[0]; boolean[] val1 = get1(); c.v[0][0] = new boolean[0]; boolean[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new boolean[1][1][1]; c.v[0] = new boolean[0][0]; boolean[][] val1 = get2(); c.v[0] = new boolean[0][0]; boolean[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -598,7 +597,7 @@ public class TestStableBoolean { elem.a = false; boolean val3 = get(); boolean val4 = get1(); assertEquals(val1, true); - assertEquals(val3, (isServerWithStable ? true : false)); + assertEquals(val3, (isStableEnabled ? true : false)); assertEquals(val2, true); assertEquals(val4, false); diff --git a/hotspot/test/compiler/stable/TestStableByte.java b/hotspot/test/compiler/stable/TestStableByte.java index 694205e8e55..ad3653f78be 100644 --- a/hotspot/test/compiler/stable/TestStableByte.java +++ b/hotspot/test/compiler/stable/TestStableByte.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableByte { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableByte { c.v = new byte[1]; c.v[0] = 1; byte val1 = get(); c.v[0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1]; c.v[0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableByte { c.v = new byte[20]; c.v[10] = 1; byte val1 = get1(); c.v[10] = 2; byte val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[20]; c.v[10] = 3; byte val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableByte { c.v = new byte[1][1]; c.v[0][0] = 1; byte val1 = get(); c.v[0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1][1]; c.v[0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new byte[1]; c.v[0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new byte[1][1]; byte[] val1 = get1(); c.v[0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableByte { c.v = new byte[1][1][1]; c.v[0][0][0] = 1; byte val1 = get(); c.v[0][0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1][1][1]; c.v[0][0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new byte[1][1]; c.v[0][0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new byte[1]; c.v[0][0][0] = 5; byte val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new byte[1][1][1]; byte[] val1 = get1(); c.v[0][0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1]; byte[][] val1 = get2(); c.v[0] = new byte[1][1]; byte[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableByte { c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 1; byte val1 = get(); c.v[0][0][0][0] = 2; byte val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new byte[1][1][1][1]; c.v[0][0][0][0] = 3; byte val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new byte[1][1][1]; c.v[0][0][0][0] = 4; byte val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new byte[1][1]; c.v[0][0][0][0] = 5; byte val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new byte[1]; c.v[0][0][0][0] = 6; byte val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new byte[1][1][1][1]; byte[] val1 = get1(); c.v[0][0][0] = new byte[1]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1][1]; byte[][] val1 = get2(); c.v[0][0] = new byte[1][1]; byte[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1][1]; byte[][][] val1 = get3(); c.v[0] = new byte[1][1][1]; byte[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -436,7 +435,7 @@ public class TestStableByte { c.v = new byte[1][1]; c.v[0] = new byte[0]; byte[] val1 = get1(); c.v[0] = new byte[0]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -472,14 +471,14 @@ public class TestStableByte { c.v = new byte[1][1][1]; c.v[0][0] = new byte[0]; byte[] val1 = get1(); c.v[0][0] = new byte[0]; byte[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new byte[1][1][1]; c.v[0] = new byte[0][0]; byte[][] val1 = get2(); c.v[0] = new byte[0][0]; byte[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -614,7 +613,7 @@ public class TestStableByte { elem.a = 2; byte val3 = get(); byte val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/stable/TestStableChar.java b/hotspot/test/compiler/stable/TestStableChar.java index d92dfb67c73..1fdcca19496 100644 --- a/hotspot/test/compiler/stable/TestStableChar.java +++ b/hotspot/test/compiler/stable/TestStableChar.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableChar { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableChar { c.v = new char[1]; c.v[0] = 'a'; char val1 = get(); c.v[0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1]; c.v[0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); } @@ -220,10 +219,10 @@ public class TestStableChar { c.v = new char[20]; c.v[10] = 'a'; char val1 = get1(); c.v[10] = 'b'; char val2 = get1(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[20]; c.v[10] = 'c'; char val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); } @@ -249,21 +248,21 @@ public class TestStableChar { c.v = new char[1][1]; c.v[0][0] = 'a'; char val1 = get(); c.v[0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1][1]; c.v[0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); c.v[0] = new char[1]; c.v[0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'd')); } { c.v = new char[1][1]; char[] val1 = get1(); c.v[0] = new char[1]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableChar { c.v = new char[1][1][1]; c.v[0][0][0] = 'a'; char val1 = get(); c.v[0][0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1][1][1]; c.v[0][0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); c.v[0] = new char[1][1]; c.v[0][0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'd')); c.v[0][0] = new char[1]; c.v[0][0][0] = 'e'; char val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'e')); } { c.v = new char[1][1][1]; char[] val1 = get1(); c.v[0][0] = new char[1]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1]; char[][] val1 = get2(); c.v[0] = new char[1][1]; char[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableChar { c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'a'; char val1 = get(); c.v[0][0][0][0] = 'b'; char val2 = get(); assertEquals(val1, 'a'); - assertEquals(val2, (isServerWithStable ? 'a' : 'b')); + assertEquals(val2, (isStableEnabled ? 'a' : 'b')); c.v = new char[1][1][1][1]; c.v[0][0][0][0] = 'c'; char val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'c')); c.v[0] = new char[1][1][1]; c.v[0][0][0][0] = 'd'; char val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'd')); c.v[0][0] = new char[1][1]; c.v[0][0][0][0] = 'e'; char val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'e')); c.v[0][0][0] = new char[1]; c.v[0][0][0][0] = 'f'; char val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 'a' : 'b') + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 'a' : 'b') : 'f')); } { c.v = new char[1][1][1][1]; char[] val1 = get1(); c.v[0][0][0] = new char[1]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1][1]; char[][] val1 = get2(); c.v[0][0] = new char[1][1]; char[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1][1]; char[][][] val1 = get3(); c.v[0] = new char[1][1][1]; char[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableChar { c.v = new char[1][1]; c.v[0] = new char[0]; char[] val1 = get1(); c.v[0] = new char[0]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableChar { c.v = new char[1][1][1]; c.v[0][0] = new char[0]; char[] val1 = get1(); c.v[0][0] = new char[0]; char[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new char[1][1][1]; c.v[0] = new char[0][0]; char[][] val1 = get2(); c.v[0] = new char[0][0]; char[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableChar { elem.a = 'b'; char val3 = get(); char val4 = get1(); assertEquals(val1, 'a'); - assertEquals(val3, (isServerWithStable ? 'a' : 'b')); + assertEquals(val3, (isStableEnabled ? 'a' : 'b')); assertEquals(val2, 'a'); assertEquals(val4, 'b'); diff --git a/hotspot/test/compiler/stable/TestStableDouble.java b/hotspot/test/compiler/stable/TestStableDouble.java index 5e55a0f8597..770d25df10c 100644 --- a/hotspot/test/compiler/stable/TestStableDouble.java +++ b/hotspot/test/compiler/stable/TestStableDouble.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableDouble { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableDouble { c.v = new double[1]; c.v[0] = 1.0; double val1 = get(); c.v[0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1]; c.v[0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); } @@ -220,10 +219,10 @@ public class TestStableDouble { c.v = new double[20]; c.v[10] = 1.0; double val1 = get1(); c.v[10] = 2.0; double val2 = get1(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[20]; c.v[10] = 3.0; double val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); } @@ -249,21 +248,21 @@ public class TestStableDouble { c.v = new double[1][1]; c.v[0][0] = 1.0; double val1 = get(); c.v[0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1][1]; c.v[0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); c.v[0] = new double[1]; c.v[0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 4.0)); } { c.v = new double[1][1]; double[] val1 = get1(); c.v[0] = new double[1]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableDouble { c.v = new double[1][1][1]; c.v[0][0][0] = 1.0; double val1 = get(); c.v[0][0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1][1][1]; c.v[0][0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); c.v[0] = new double[1][1]; c.v[0][0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 4.0)); c.v[0][0] = new double[1]; c.v[0][0][0] = 5.0; double val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 5.0)); } { c.v = new double[1][1][1]; double[] val1 = get1(); c.v[0][0] = new double[1]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1]; double[][] val1 = get2(); c.v[0] = new double[1][1]; double[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableDouble { c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 1.0; double val1 = get(); c.v[0][0][0][0] = 2.0; double val2 = get(); assertEquals(val1, 1.0); - assertEquals(val2, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val2, (isStableEnabled ? 1.0 : 2.0)); c.v = new double[1][1][1][1]; c.v[0][0][0][0] = 3.0; double val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 3.0)); c.v[0] = new double[1][1][1]; c.v[0][0][0][0] = 4.0; double val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 4.0)); c.v[0][0] = new double[1][1]; c.v[0][0][0][0] = 5.0; double val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 5.0)); c.v[0][0][0] = new double[1]; c.v[0][0][0][0] = 6.0; double val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0 : 2.0) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1.0 : 2.0) : 6.0)); } { c.v = new double[1][1][1][1]; double[] val1 = get1(); c.v[0][0][0] = new double[1]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1][1]; double[][] val1 = get2(); c.v[0][0] = new double[1][1]; double[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1][1]; double[][][] val1 = get3(); c.v[0] = new double[1][1][1]; double[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableDouble { c.v = new double[1][1]; c.v[0] = new double[0]; double[] val1 = get1(); c.v[0] = new double[0]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableDouble { c.v = new double[1][1][1]; c.v[0][0] = new double[0]; double[] val1 = get1(); c.v[0][0] = new double[0]; double[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new double[1][1][1]; c.v[0] = new double[0][0]; double[][] val1 = get2(); c.v[0] = new double[0][0]; double[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableDouble { elem.a = 2.0; double val3 = get(); double val4 = get1(); assertEquals(val1, 1.0); - assertEquals(val3, (isServerWithStable ? 1.0 : 2.0)); + assertEquals(val3, (isStableEnabled ? 1.0 : 2.0)); assertEquals(val2, 1.0); assertEquals(val4, 2.0); diff --git a/hotspot/test/compiler/stable/TestStableFloat.java b/hotspot/test/compiler/stable/TestStableFloat.java index 04acead22ef..d2f417c8ad3 100644 --- a/hotspot/test/compiler/stable/TestStableFloat.java +++ b/hotspot/test/compiler/stable/TestStableFloat.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableFloat { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableFloat { c.v = new float[1]; c.v[0] = 1.0F; float val1 = get(); c.v[0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1]; c.v[0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); } @@ -220,10 +219,10 @@ public class TestStableFloat { c.v = new float[20]; c.v[10] = 1.0F; float val1 = get1(); c.v[10] = 2.0F; float val2 = get1(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[20]; c.v[10] = 3.0F; float val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); } @@ -249,21 +248,21 @@ public class TestStableFloat { c.v = new float[1][1]; c.v[0][0] = 1.0F; float val1 = get(); c.v[0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1][1]; c.v[0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); c.v[0] = new float[1]; c.v[0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 4.0F)); } { c.v = new float[1][1]; float[] val1 = get1(); c.v[0] = new float[1]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableFloat { c.v = new float[1][1][1]; c.v[0][0][0] = 1.0F; float val1 = get(); c.v[0][0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1][1][1]; c.v[0][0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); c.v[0] = new float[1][1]; c.v[0][0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 4.0F)); c.v[0][0] = new float[1]; c.v[0][0][0] = 5.0F; float val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 5.0F)); } { c.v = new float[1][1][1]; float[] val1 = get1(); c.v[0][0] = new float[1]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1]; float[][] val1 = get2(); c.v[0] = new float[1][1]; float[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableFloat { c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 1.0F; float val1 = get(); c.v[0][0][0][0] = 2.0F; float val2 = get(); assertEquals(val1, 1.0F); - assertEquals(val2, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val2, (isStableEnabled ? 1.0F : 2.0F)); c.v = new float[1][1][1][1]; c.v[0][0][0][0] = 3.0F; float val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 3.0F)); c.v[0] = new float[1][1][1]; c.v[0][0][0][0] = 4.0F; float val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 4.0F)); c.v[0][0] = new float[1][1]; c.v[0][0][0][0] = 5.0F; float val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 5.0F)); c.v[0][0][0] = new float[1]; c.v[0][0][0][0] = 6.0F; float val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1.0F : 2.0F) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1.0F : 2.0F) : 6.0F)); } { c.v = new float[1][1][1][1]; float[] val1 = get1(); c.v[0][0][0] = new float[1]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1][1]; float[][] val1 = get2(); c.v[0][0] = new float[1][1]; float[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1][1]; float[][][] val1 = get3(); c.v[0] = new float[1][1][1]; float[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableFloat { c.v = new float[1][1]; c.v[0] = new float[0]; float[] val1 = get1(); c.v[0] = new float[0]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableFloat { c.v = new float[1][1][1]; c.v[0][0] = new float[0]; float[] val1 = get1(); c.v[0][0] = new float[0]; float[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new float[1][1][1]; c.v[0] = new float[0][0]; float[][] val1 = get2(); c.v[0] = new float[0][0]; float[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableFloat { elem.a = 2.0F; float val3 = get(); float val4 = get1(); assertEquals(val1, 1.0F); - assertEquals(val3, (isServerWithStable ? 1.0F : 2.0F)); + assertEquals(val3, (isStableEnabled ? 1.0F : 2.0F)); assertEquals(val2, 1.0F); assertEquals(val4, 2.0F); diff --git a/hotspot/test/compiler/stable/TestStableInt.java b/hotspot/test/compiler/stable/TestStableInt.java index 2837bd3d1a5..4b99f95e2d5 100644 --- a/hotspot/test/compiler/stable/TestStableInt.java +++ b/hotspot/test/compiler/stable/TestStableInt.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableInt { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableInt { c.v = new int[1]; c.v[0] = 1; int val1 = get(); c.v[0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1]; c.v[0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableInt { c.v = new int[20]; c.v[10] = 1; int val1 = get1(); c.v[10] = 2; int val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[20]; c.v[10] = 3; int val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableInt { c.v = new int[1][1]; c.v[0][0] = 1; int val1 = get(); c.v[0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1][1]; c.v[0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new int[1]; c.v[0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new int[1][1]; int[] val1 = get1(); c.v[0] = new int[1]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableInt { c.v = new int[1][1][1]; c.v[0][0][0] = 1; int val1 = get(); c.v[0][0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1][1][1]; c.v[0][0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new int[1][1]; c.v[0][0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new int[1]; c.v[0][0][0] = 5; int val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new int[1][1][1]; int[] val1 = get1(); c.v[0][0] = new int[1]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1]; int[][] val1 = get2(); c.v[0] = new int[1][1]; int[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableInt { c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 1; int val1 = get(); c.v[0][0][0][0] = 2; int val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new int[1][1][1][1]; c.v[0][0][0][0] = 3; int val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new int[1][1][1]; c.v[0][0][0][0] = 4; int val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new int[1][1]; c.v[0][0][0][0] = 5; int val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new int[1]; c.v[0][0][0][0] = 6; int val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new int[1][1][1][1]; int[] val1 = get1(); c.v[0][0][0] = new int[1]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1][1]; int[][] val1 = get2(); c.v[0][0] = new int[1][1]; int[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1][1]; int[][][] val1 = get3(); c.v[0] = new int[1][1][1]; int[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableInt { c.v = new int[1][1]; c.v[0] = new int[0]; int[] val1 = get1(); c.v[0] = new int[0]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableInt { c.v = new int[1][1][1]; c.v[0][0] = new int[0]; int[] val1 = get1(); c.v[0][0] = new int[0]; int[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new int[1][1][1]; c.v[0] = new int[0][0]; int[][] val1 = get2(); c.v[0] = new int[0][0]; int[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableInt { elem.a = 2; int val3 = get(); int val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/stable/TestStableLong.java b/hotspot/test/compiler/stable/TestStableLong.java index b6c2fbb0be6..00e9863cca0 100644 --- a/hotspot/test/compiler/stable/TestStableLong.java +++ b/hotspot/test/compiler/stable/TestStableLong.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableLong { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableLong { c.v = new long[1]; c.v[0] = 1; long val1 = get(); c.v[0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1]; c.v[0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableLong { c.v = new long[20]; c.v[10] = 1; long val1 = get1(); c.v[10] = 2; long val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[20]; c.v[10] = 3; long val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableLong { c.v = new long[1][1]; c.v[0][0] = 1; long val1 = get(); c.v[0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1][1]; c.v[0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new long[1]; c.v[0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new long[1][1]; long[] val1 = get1(); c.v[0] = new long[1]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableLong { c.v = new long[1][1][1]; c.v[0][0][0] = 1; long val1 = get(); c.v[0][0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1][1][1]; c.v[0][0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new long[1][1]; c.v[0][0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new long[1]; c.v[0][0][0] = 5; long val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new long[1][1][1]; long[] val1 = get1(); c.v[0][0] = new long[1]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1]; long[][] val1 = get2(); c.v[0] = new long[1][1]; long[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableLong { c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 1; long val1 = get(); c.v[0][0][0][0] = 2; long val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new long[1][1][1][1]; c.v[0][0][0][0] = 3; long val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new long[1][1][1]; c.v[0][0][0][0] = 4; long val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new long[1][1]; c.v[0][0][0][0] = 5; long val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new long[1]; c.v[0][0][0][0] = 6; long val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new long[1][1][1][1]; long[] val1 = get1(); c.v[0][0][0] = new long[1]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1][1]; long[][] val1 = get2(); c.v[0][0] = new long[1][1]; long[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1][1]; long[][][] val1 = get3(); c.v[0] = new long[1][1][1]; long[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableLong { c.v = new long[1][1]; c.v[0] = new long[0]; long[] val1 = get1(); c.v[0] = new long[0]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableLong { c.v = new long[1][1][1]; c.v[0][0] = new long[0]; long[] val1 = get1(); c.v[0][0] = new long[0]; long[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new long[1][1][1]; c.v[0] = new long[0][0]; long[][] val1 = get2(); c.v[0] = new long[0][0]; long[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableLong { elem.a = 2; long val3 = get(); long val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/stable/TestStableObject.java b/hotspot/test/compiler/stable/TestStableObject.java index b61736b6e32..4602a064468 100644 --- a/hotspot/test/compiler/stable/TestStableObject.java +++ b/hotspot/test/compiler/stable/TestStableObject.java @@ -89,7 +89,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableObject { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -212,10 +211,10 @@ public class TestStableObject { c.v = new Object[1]; c.v[0] = Values.A; Object val1 = get(); c.v[0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1]; c.v[0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); } @@ -223,10 +222,10 @@ public class TestStableObject { c.v = new Object[20]; c.v[10] = Values.A; Object val1 = get1(); c.v[10] = Values.B; Object val2 = get1(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[20]; c.v[10] = Values.C; Object val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); } @@ -252,21 +251,21 @@ public class TestStableObject { c.v = new Object[1][1]; c.v[0][0] = Values.A; Object val1 = get(); c.v[0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1][1]; c.v[0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); c.v[0] = new Object[1]; c.v[0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.D)); } { c.v = new Object[1][1]; Object[] val1 = get1(); c.v[0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -292,31 +291,31 @@ public class TestStableObject { c.v = new Object[1][1][1]; c.v[0][0][0] = Values.A; Object val1 = get(); c.v[0][0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1][1][1]; c.v[0][0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); c.v[0] = new Object[1][1]; c.v[0][0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.D)); c.v[0][0] = new Object[1]; c.v[0][0][0] = Values.E; Object val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.E)); } { c.v = new Object[1][1][1]; Object[] val1 = get1(); c.v[0][0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1]; Object[][] val1 = get2(); c.v[0] = new Object[1][1]; Object[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -343,41 +342,41 @@ public class TestStableObject { c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.A; Object val1 = get(); c.v[0][0][0][0] = Values.B; Object val2 = get(); assertEquals(val1, Values.A); - assertEquals(val2, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val2, (isStableEnabled ? Values.A : Values.B)); c.v = new Object[1][1][1][1]; c.v[0][0][0][0] = Values.C; Object val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.C)); c.v[0] = new Object[1][1][1]; c.v[0][0][0][0] = Values.D; Object val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.D)); c.v[0][0] = new Object[1][1]; c.v[0][0][0][0] = Values.E; Object val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.E)); c.v[0][0][0] = new Object[1]; c.v[0][0][0][0] = Values.F; Object val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? Values.A : Values.B) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? Values.A : Values.B) : Values.F)); } { c.v = new Object[1][1][1][1]; Object[] val1 = get1(); c.v[0][0][0] = new Object[1]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1][1]; Object[][] val1 = get2(); c.v[0][0] = new Object[1][1]; Object[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1][1]; Object[][][] val1 = get3(); c.v[0] = new Object[1][1][1]; Object[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -437,7 +436,7 @@ public class TestStableObject { c.v = new Object[1][1]; c.v[0] = new Object[0]; Object[] val1 = get1(); c.v[0] = new Object[0]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -473,14 +472,14 @@ public class TestStableObject { c.v = new Object[1][1][1]; c.v[0][0] = new Object[0]; Object[] val1 = get1(); c.v[0][0] = new Object[0]; Object[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new Object[1][1][1]; c.v[0] = new Object[0][0]; Object[][] val1 = get2(); c.v[0] = new Object[0][0]; Object[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -615,7 +614,7 @@ public class TestStableObject { elem.a = Values.B; Object val3 = get(); Object val4 = get1(); assertEquals(val1, Values.A); - assertEquals(val3, (isServerWithStable ? Values.A : Values.B)); + assertEquals(val3, (isStableEnabled ? Values.A : Values.B)); assertEquals(val2, Values.A); assertEquals(val4, Values.B); diff --git a/hotspot/test/compiler/stable/TestStableShort.java b/hotspot/test/compiler/stable/TestStableShort.java index 1b0f127785c..9e9b50d05d6 100644 --- a/hotspot/test/compiler/stable/TestStableShort.java +++ b/hotspot/test/compiler/stable/TestStableShort.java @@ -88,7 +88,6 @@ import java.lang.reflect.InvocationTargetException; public class TestStableShort { static final boolean isStableEnabled = StableConfiguration.isStableEnabled; - static final boolean isServerWithStable = StableConfiguration.isServerWithStable; public static void main(String[] args) throws Exception { run(DefaultValue.class); @@ -209,10 +208,10 @@ public class TestStableShort { c.v = new short[1]; c.v[0] = 1; short val1 = get(); c.v[0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1]; c.v[0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -220,10 +219,10 @@ public class TestStableShort { c.v = new short[20]; c.v[10] = 1; short val1 = get1(); c.v[10] = 2; short val2 = get1(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[20]; c.v[10] = 3; short val3 = get1(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); } @@ -249,21 +248,21 @@ public class TestStableShort { c.v = new short[1][1]; c.v[0][0] = 1; short val1 = get(); c.v[0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1][1]; c.v[0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new short[1]; c.v[0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); } { c.v = new short[1][1]; short[] val1 = get1(); c.v[0] = new short[1]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -289,31 +288,31 @@ public class TestStableShort { c.v = new short[1][1][1]; c.v[0][0][0] = 1; short val1 = get(); c.v[0][0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1][1][1]; c.v[0][0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new short[1][1]; c.v[0][0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new short[1]; c.v[0][0][0] = 5; short val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); } { c.v = new short[1][1][1]; short[] val1 = get1(); c.v[0][0] = new short[1]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1]; short[][] val1 = get2(); c.v[0] = new short[1][1]; short[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -340,41 +339,41 @@ public class TestStableShort { c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 1; short val1 = get(); c.v[0][0][0][0] = 2; short val2 = get(); assertEquals(val1, 1); - assertEquals(val2, (isServerWithStable ? 1 : 2)); + assertEquals(val2, (isStableEnabled ? 1 : 2)); c.v = new short[1][1][1][1]; c.v[0][0][0][0] = 3; short val3 = get(); - assertEquals(val3, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val3, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 3)); c.v[0] = new short[1][1][1]; c.v[0][0][0][0] = 4; short val4 = get(); - assertEquals(val4, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val4, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 4)); c.v[0][0] = new short[1][1]; c.v[0][0][0][0] = 5; short val5 = get(); - assertEquals(val5, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val5, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 5)); c.v[0][0][0] = new short[1]; c.v[0][0][0][0] = 6; short val6 = get(); - assertEquals(val6, (isStableEnabled ? (isServerWithStable ? 1 : 2) + assertEquals(val6, (isStableEnabled ? (isStableEnabled ? 1 : 2) : 6)); } { c.v = new short[1][1][1][1]; short[] val1 = get1(); c.v[0][0][0] = new short[1]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1][1]; short[][] val1 = get2(); c.v[0][0] = new short[1][1]; short[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1][1]; short[][][] val1 = get3(); c.v[0] = new short[1][1][1]; short[][][] val2 = get3(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -434,7 +433,7 @@ public class TestStableShort { c.v = new short[1][1]; c.v[0] = new short[0]; short[] val1 = get1(); c.v[0] = new short[0]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -470,14 +469,14 @@ public class TestStableShort { c.v = new short[1][1][1]; c.v[0][0] = new short[0]; short[] val1 = get1(); c.v[0][0] = new short[0]; short[] val2 = get1(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { c.v = new short[1][1][1]; c.v[0] = new short[0][0]; short[][] val1 = get2(); c.v[0] = new short[0][0]; short[][] val2 = get2(); - assertTrue((isServerWithStable ? (val1 == val2) : (val1 != val2))); + assertTrue((isStableEnabled ? (val1 == val2) : (val1 != val2))); } { @@ -612,7 +611,7 @@ public class TestStableShort { elem.a = 2; short val3 = get(); short val4 = get1(); assertEquals(val1, 1); - assertEquals(val3, (isServerWithStable ? 1 : 2)); + assertEquals(val3, (isStableEnabled ? 1 : 2)); assertEquals(val2, 1); assertEquals(val4, 2); diff --git a/hotspot/test/compiler/types/TestPhiElimination.java b/hotspot/test/compiler/types/TestPhiElimination.java new file mode 100644 index 00000000000..5029b99ee77 --- /dev/null +++ b/hotspot/test/compiler/types/TestPhiElimination.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +/** + * @test + * @bug 8150804 + * @summary Tests elimination of Phi nodes without losing type information. + * @run main/othervm -XX:-BackgroundCompilation -XX:-UseOnStackReplacement TestPhiElimination + */ +public class TestPhiElimination { + /* + A::get() is inlined into test(obj) producing the following graph: + + Parm (obj) + TestPhiElimination + | + CastPP + TestPhiElimination:NotNull + | + CheckCastPP + A:NotNull + / \ + CheckCastPP | + A:NotNull | + \ / + Phi + A + | + Safepoint + + PhiNode::ideal() then replaces the Phi by a CheckCastPP: + + Parm (obj) + TestPhiElimination + | + CheckCastPP + A + | + Safepoint + + losing the :NotNull information. Therefore, we cannot prove that obj != null + when accessing a field and add an uncommon trap. Since obj is used as monitor, we + set it to TOP in the uncommon trap branch and later fail in Process_OopMap_Node + because the monitor object is TOP. + */ + public Object test(TestPhiElimination obj) { + if (obj instanceof A) { + return ((A) obj).get(); + } + return null; + } + + static public void main(String[] args) { + TestPhiElimination t = new TestPhiElimination(); + + // Warmup + B b = new B(); + for (int i = 0; i < 1_000; ++i) { + t.test(b); + } + + // Compile + A a = new A(); + for (int i = 0; i < 20_000; ++i) { + if (i % 2 == 0) { + a.f = null; + } + t.test(a); + } + } + +} + +class A extends TestPhiElimination { + public Object f; + + public A create() { + return new A(); + } + + public synchronized Object get() { + if (f == null) { + f = create(); + } + return f; + } +} + +class B extends A { + +} diff --git a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java index 8c144143d62..c1d6b057e14 100644 --- a/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java +++ b/hotspot/test/compiler/unsafe/UnsafeGetConstantField.java @@ -27,6 +27,9 @@ * @test * @summary tests on constant folding of unsafe get operations * @library /testlibrary /test/lib + * + * @requires vm.flavor != "client" + * * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions * -Xbatch -XX:-TieredCompilation * -XX:+FoldStableValues diff --git a/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java new file mode 100644 index 00000000000..1ec5dc5ba17 --- /dev/null +++ b/hotspot/test/compiler/unsafe/UnsafeGetStableArrayElement.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary tests on constant folding of unsafe get operations from stable arrays + * @library /testlibrary /test/lib + * @ignore 8151137 + * + * @requires vm.flavor != "client" + * + * @run main/bootclasspath -XX:+UnlockDiagnosticVMOptions + * -Xbatch -XX:-TieredCompilation + * -XX:+FoldStableValues + * -XX:CompileCommand=dontinline,*Test::test* + * UnsafeGetStableArrayElement + */ +import jdk.internal.misc.Unsafe; +import jdk.internal.vm.annotation.Stable; +import java.util.concurrent.Callable; + +import static jdk.internal.misc.Unsafe.*; +import static jdk.test.lib.Asserts.*; + +public class UnsafeGetStableArrayElement { + @Stable static final boolean[] STABLE_BOOLEAN_ARRAY = new boolean[16]; + @Stable static final byte[] STABLE_BYTE_ARRAY = new byte[16]; + @Stable static final short[] STABLE_SHORT_ARRAY = new short[8]; + @Stable static final char[] STABLE_CHAR_ARRAY = new char[8]; + @Stable static final int[] STABLE_INT_ARRAY = new int[4]; + @Stable static final long[] STABLE_LONG_ARRAY = new long[2]; + @Stable static final float[] STABLE_FLOAT_ARRAY = new float[4]; + @Stable static final double[] STABLE_DOUBLE_ARRAY = new double[2]; + @Stable static final Object[] STABLE_OBJECT_ARRAY = new Object[4]; + + static { + Setter.reset(); + } + static final Unsafe U = Unsafe.getUnsafe(); + + static class Setter { + private static void setZ(boolean defaultVal) { STABLE_BOOLEAN_ARRAY[0] = defaultVal ? false : true; } + private static void setB(boolean defaultVal) { STABLE_BYTE_ARRAY[0] = defaultVal ? 0 : Byte.MAX_VALUE; } + private static void setS(boolean defaultVal) { STABLE_SHORT_ARRAY[0] = defaultVal ? 0 : Short.MAX_VALUE; } + private static void setC(boolean defaultVal) { STABLE_CHAR_ARRAY[0] = defaultVal ? 0 : Character.MAX_VALUE; } + private static void setI(boolean defaultVal) { STABLE_INT_ARRAY[0] = defaultVal ? 0 : Integer.MAX_VALUE; } + private static void setJ(boolean defaultVal) { STABLE_LONG_ARRAY[0] = defaultVal ? 0 : Long.MAX_VALUE; } + private static void setF(boolean defaultVal) { STABLE_FLOAT_ARRAY[0] = defaultVal ? 0 : Float.MAX_VALUE; } + private static void setD(boolean defaultVal) { STABLE_DOUBLE_ARRAY[0] = defaultVal ? 0 : Double.MAX_VALUE; } + private static void setL(boolean defaultVal) { STABLE_OBJECT_ARRAY[0] = defaultVal ? null : new Object(); } + + static void reset() { + setZ(false); + setB(false); + setS(false); + setC(false); + setI(false); + setJ(false); + setF(false); + setD(false); + setL(false); + } + } + + static class Test { + static void changeZ() { Setter.setZ(true); } + static void changeB() { Setter.setB(true); } + static void changeS() { Setter.setS(true); } + static void changeC() { Setter.setC(true); } + static void changeI() { Setter.setI(true); } + static void changeJ() { Setter.setJ(true); } + static void changeF() { Setter.setF(true); } + static void changeD() { Setter.setD(true); } + static void changeL() { Setter.setL(true); } + + static boolean testZ_Z() { return U.getBoolean(STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static byte testZ_B() { return U.getByte( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static short testZ_S() { return U.getShort( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static char testZ_C() { return U.getChar( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static int testZ_I() { return U.getInt( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static long testZ_J() { return U.getLong( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static float testZ_F() { return U.getFloat( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + static double testZ_D() { return U.getDouble( STABLE_BOOLEAN_ARRAY, ARRAY_BOOLEAN_BASE_OFFSET); } + + static boolean testB_Z() { return U.getBoolean(STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static byte testB_B() { return U.getByte( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static short testB_S() { return U.getShort( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static char testB_C() { return U.getChar( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static int testB_I() { return U.getInt( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static long testB_J() { return U.getLong( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static float testB_F() { return U.getFloat( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + static double testB_D() { return U.getDouble( STABLE_BYTE_ARRAY, ARRAY_BYTE_BASE_OFFSET); } + + static boolean testS_Z() { return U.getBoolean(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static byte testS_B() { return U.getByte( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static short testS_S() { return U.getShort( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static char testS_C() { return U.getChar( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static int testS_I() { return U.getInt( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static long testS_J() { return U.getLong( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static float testS_F() { return U.getFloat( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + static double testS_D() { return U.getDouble( STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET); } + + static boolean testC_Z() { return U.getBoolean(STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static byte testC_B() { return U.getByte( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static short testC_S() { return U.getShort( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static char testC_C() { return U.getChar( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static int testC_I() { return U.getInt( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static long testC_J() { return U.getLong( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static float testC_F() { return U.getFloat( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + static double testC_D() { return U.getDouble( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET); } + + static boolean testI_Z() { return U.getBoolean(STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static byte testI_B() { return U.getByte( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static short testI_S() { return U.getShort( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static char testI_C() { return U.getChar( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static int testI_I() { return U.getInt( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static long testI_J() { return U.getLong( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static float testI_F() { return U.getFloat( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + static double testI_D() { return U.getDouble( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET); } + + static boolean testJ_Z() { return U.getBoolean(STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static byte testJ_B() { return U.getByte( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static short testJ_S() { return U.getShort( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static char testJ_C() { return U.getChar( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static int testJ_I() { return U.getInt( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static long testJ_J() { return U.getLong( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static float testJ_F() { return U.getFloat( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + static double testJ_D() { return U.getDouble( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET); } + + static boolean testF_Z() { return U.getBoolean(STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static byte testF_B() { return U.getByte( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static short testF_S() { return U.getShort( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static char testF_C() { return U.getChar( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static int testF_I() { return U.getInt( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static long testF_J() { return U.getLong( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static float testF_F() { return U.getFloat( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + static double testF_D() { return U.getDouble( STABLE_FLOAT_ARRAY, ARRAY_FLOAT_BASE_OFFSET); } + + static boolean testD_Z() { return U.getBoolean(STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static byte testD_B() { return U.getByte( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static short testD_S() { return U.getShort( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static char testD_C() { return U.getChar( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static int testD_I() { return U.getInt( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static long testD_J() { return U.getLong( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static float testD_F() { return U.getFloat( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + static double testD_D() { return U.getDouble( STABLE_DOUBLE_ARRAY, ARRAY_DOUBLE_BASE_OFFSET); } + + static Object testL_L() { return U.getObject( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static boolean testL_Z() { return U.getBoolean(STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static byte testL_B() { return U.getByte( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static short testL_S() { return U.getShort( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static char testL_C() { return U.getChar( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static int testL_I() { return U.getInt( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static long testL_J() { return U.getLong( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static float testL_F() { return U.getFloat( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + static double testL_D() { return U.getDouble( STABLE_OBJECT_ARRAY, ARRAY_OBJECT_BASE_OFFSET); } + + static short testS_U() { return U.getShortUnaligned(STABLE_SHORT_ARRAY, ARRAY_SHORT_BASE_OFFSET + 1); } + static char testC_U() { return U.getCharUnaligned( STABLE_CHAR_ARRAY, ARRAY_CHAR_BASE_OFFSET + 1); } + static int testI_U() { return U.getIntUnaligned( STABLE_INT_ARRAY, ARRAY_INT_BASE_OFFSET + 1); } + static long testJ_U() { return U.getLongUnaligned( STABLE_LONG_ARRAY, ARRAY_LONG_BASE_OFFSET + 1); } + } + + static void run(Callable c) throws Exception { + run(c, null, null); + } + + static void run(Callable c, Runnable sameResultAction, Runnable changeResultAction) throws Exception { + Object first = c.call(); + + // Trigger compilation. + for (int i = 0; i < 20_000; i++) { + // Don't compare results here, since most of Test::testL_* results vary across iterations (due to GC). + c.call(); + } + + if (sameResultAction != null) { + sameResultAction.run(); + assertEQ(first, c.call()); + } + + if (changeResultAction != null) { + changeResultAction.run(); + assertNE(first, c.call()); + assertEQ(c.call(), c.call()); + } + } + + static void testMatched(Callable c, Runnable setDefaultAction) throws Exception { + run(c, setDefaultAction, null); + Setter.reset(); + } + + static void testMismatched(Callable c, Runnable setDefaultAction) throws Exception { + run(c, null, setDefaultAction); + Setter.reset(); + } + + public static void main(String[] args) throws Exception { + // boolean[], aligned accesses + testMatched( Test::testZ_Z, Test::changeZ); + testMismatched(Test::testZ_B, Test::changeZ); + testMismatched(Test::testZ_S, Test::changeZ); + testMismatched(Test::testZ_C, Test::changeZ); + testMismatched(Test::testZ_I, Test::changeZ); + testMismatched(Test::testZ_J, Test::changeZ); + testMismatched(Test::testZ_F, Test::changeZ); + testMismatched(Test::testZ_D, Test::changeZ); + + // byte[], aligned accesses + testMismatched(Test::testB_Z, Test::changeB); + testMatched( Test::testB_B, Test::changeB); + testMismatched(Test::testB_S, Test::changeB); + testMismatched(Test::testB_C, Test::changeB); + testMismatched(Test::testB_I, Test::changeB); + testMismatched(Test::testB_J, Test::changeB); + testMismatched(Test::testB_F, Test::changeB); + testMismatched(Test::testB_D, Test::changeB); + + // short[], aligned accesses + testMismatched(Test::testS_Z, Test::changeS); + testMismatched(Test::testS_B, Test::changeS); + testMatched( Test::testS_S, Test::changeS); + testMismatched(Test::testS_C, Test::changeS); + testMismatched(Test::testS_I, Test::changeS); + testMismatched(Test::testS_J, Test::changeS); + testMismatched(Test::testS_F, Test::changeS); + testMismatched(Test::testS_D, Test::changeS); + + // char[], aligned accesses + testMismatched(Test::testC_Z, Test::changeC); + testMismatched(Test::testC_B, Test::changeC); + testMismatched(Test::testC_S, Test::changeC); + testMatched( Test::testC_C, Test::changeC); + testMismatched(Test::testC_I, Test::changeC); + testMismatched(Test::testC_J, Test::changeC); + testMismatched(Test::testC_F, Test::changeC); + testMismatched(Test::testC_D, Test::changeC); + + // int[], aligned accesses + testMismatched(Test::testI_Z, Test::changeI); + testMismatched(Test::testI_B, Test::changeI); + testMismatched(Test::testI_S, Test::changeI); + testMismatched(Test::testI_C, Test::changeI); + testMatched( Test::testI_I, Test::changeI); + testMismatched(Test::testI_J, Test::changeI); + testMismatched(Test::testI_F, Test::changeI); + testMismatched(Test::testI_D, Test::changeI); + + // long[], aligned accesses + testMismatched(Test::testJ_Z, Test::changeJ); + testMismatched(Test::testJ_B, Test::changeJ); + testMismatched(Test::testJ_S, Test::changeJ); + testMismatched(Test::testJ_C, Test::changeJ); + testMismatched(Test::testJ_I, Test::changeJ); + testMatched( Test::testJ_J, Test::changeJ); + testMismatched(Test::testJ_F, Test::changeJ); + testMismatched(Test::testJ_D, Test::changeJ); + + // float[], aligned accesses + testMismatched(Test::testF_Z, Test::changeF); + testMismatched(Test::testF_B, Test::changeF); + testMismatched(Test::testF_S, Test::changeF); + testMismatched(Test::testF_C, Test::changeF); + testMismatched(Test::testF_I, Test::changeF); + testMismatched(Test::testF_J, Test::changeF); + testMatched( Test::testF_F, Test::changeF); + testMismatched(Test::testF_D, Test::changeF); + + // double[], aligned accesses + testMismatched(Test::testD_Z, Test::changeD); + testMismatched(Test::testD_B, Test::changeD); + testMismatched(Test::testD_S, Test::changeD); + testMismatched(Test::testD_C, Test::changeD); + testMismatched(Test::testD_I, Test::changeD); + testMismatched(Test::testD_J, Test::changeD); + testMismatched(Test::testD_F, Test::changeD); + testMatched( Test::testD_D, Test::changeD); + + // Object[], aligned accesses + testMismatched(Test::testL_J, Test::changeL); // long & double are always as large as an OOP + testMismatched(Test::testL_D, Test::changeL); + testMatched( Test::testL_L, Test::changeL); + + // Unaligned accesses + testMismatched(Test::testS_U, Test::changeS); + testMismatched(Test::testC_U, Test::changeC); + testMismatched(Test::testI_U, Test::changeI); + testMismatched(Test::testJ_U, Test::changeJ); + + // No way to reliably check the expected behavior: + // (1) OOPs change during GC; + // (2) there's no way to reliably change some part of an OOP (e.g., when reading a byte from it). + // + // Just trigger the compilation hoping to catch any problems with asserts. + run(Test::testL_B); + run(Test::testL_Z); + run(Test::testL_S); + run(Test::testL_C); + run(Test::testL_I); + run(Test::testL_F); + } +} diff --git a/hotspot/test/compiler/whitebox/BlockingCompilation.java b/hotspot/test/compiler/whitebox/BlockingCompilation.java new file mode 100644 index 00000000000..d960ff4264a --- /dev/null +++ b/hotspot/test/compiler/whitebox/BlockingCompilation.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2016 SAP SE. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * 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 8150646 + * @summary Add support for blocking compiles through whitebox API + * @library /testlibrary /test/lib / + * @build sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * + * @run main/othervm/timeout=60 + * -Xbootclasspath/a:. + * -Xmixed + * -XX:+UnlockDiagnosticVMOptions + * -XX:+WhiteBoxAPI + * -XX:+PrintCompilation + * BlockingCompilation + */ + +import java.lang.reflect.Method; +import java.util.Random; + +import sun.hotspot.WhiteBox; +import compiler.testlibrary.CompilerUtils; + +public class BlockingCompilation { + private static final WhiteBox WB = WhiteBox.getWhiteBox(); + private static final Random RANDOM = new Random(); + + public static int foo() { + return RANDOM.nextInt(); + } + + public static void main(String[] args) throws Exception { + Method m = BlockingCompilation.class.getMethod("foo"); + int[] levels = CompilerUtils.getAvailableCompilationLevels(); + int highest_level = levels[levels.length-1]; + + // If there are no compilers available these tests don't make any sense. + if (levels.length == 0) return; + + // Make sure no compilations can progress, blocking compiles will hang + WB.lockCompilation(); + + // Verify method state before test + if (WB.isMethodCompiled(m)) { + throw new Exception("Should not be compiled after deoptimization"); + } + if (WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Should not be enqueued on any level"); + } + + // Try compiling on highest available comp level. + // If the compiles are blocking, this call will block until the test time out, + // Progress == success + // (Don't run with -Xcomp since that can cause long timeouts due to many compiles) + WB.enqueueMethodForCompilation(m, highest_level); + + // restore state + WB.unlockCompilation(); + while (!WB.isMethodCompiled(m)) { + Thread.sleep(100); + } + WB.deoptimizeMethod(m); + WB.clearMethodState(m); + + // Blocking compilations on all levels, using the default versions of + // WB.enqueueMethodForCompilation() and manually setting compiler directives. + String directive = "[{ match: \"BlockingCompilation.foo\", BackgroundCompilation: false }]"; + if (WB.addCompilerDirective(directive) != 1) { + throw new Exception("Failed to add compiler directive"); + } + + try { + for (int l : levels) { + // Make uncompiled + WB.deoptimizeMethod(m); + + // Verify that it's not compiled + if (WB.isMethodCompiled(m)) { + throw new Exception("Should not be compiled after deoptimization"); + } + if (WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Should not be enqueued on any level"); + } + + // Add to queue and verify that it went well + if (!WB.enqueueMethodForCompilation(m, l)) { + throw new Exception("Could not be enqueued for compilation"); + } + + // Verify that it is compiled + if (!WB.isMethodCompiled(m)) { + throw new Exception("Must be compiled here"); + } + // And verify the level + if (WB.getMethodCompilationLevel(m) != l) { + String msg = m + " should be compiled at level " + l + + "(but is actually compiled at level " + + WB.getMethodCompilationLevel(m) + ")"; + System.out.println("==> " + msg); + throw new Exception(msg); + } + } + } finally { + WB.removeCompilerDirective(1); + } + + // Clean up + WB.deoptimizeMethod(m); + WB.clearMethodState(m); + + // Make sure no compilations can progress, blocking compiles will hang + WB.lockCompilation(); + + // Verify method state before test + if (WB.isMethodCompiled(m)) { + throw new Exception("Should not be compiled after deoptimization"); + } + if (WB.isMethodQueuedForCompilation(m)) { + throw new Exception("Should not be enqueued on any level"); + } + + // Try compiling on highest available comp level. + // If the compiles are blocking, this call will block until the test time out, + // Progress == success + // (Don't run with -Xcomp since that can cause long timeouts due to many compiles) + WB.enqueueMethodForCompilation(m, highest_level); + + // restore state + WB.unlockCompilation(); + } +} diff --git a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java index 2b93fad4bba..dfc630155fe 100644 --- a/hotspot/test/compiler/whitebox/ClearMethodStateTest.java +++ b/hotspot/test/compiler/whitebox/ClearMethodStateTest.java @@ -22,6 +22,7 @@ */ import java.util.function.Function; + import compiler.whitebox.CompilerWhiteBoxTest; /* @@ -32,14 +33,24 @@ import compiler.whitebox.CompilerWhiteBoxTest; * @build ClearMethodStateTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* ClearMethodStateTest + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI ClearMethodStateTest * @summary testing of WB::clearMethodState() * @author igor.ignatyev@oracle.com */ public class ClearMethodStateTest extends CompilerWhiteBoxTest { public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(ClearMethodStateTest::new, args); + String directive = + "[{ match:\"*SimpleTestCase$Helper.*\", BackgroundCompilation: false }, " + + " { match:\"*.*\", inline:\"-*SimpleTestCase$Helper.*\"}]"; + if (WHITE_BOX.addCompilerDirective(directive) != 2) { + throw new RuntimeException("Could not add directive"); + } + try { + CompilerWhiteBoxTest.main(ClearMethodStateTest::new, args); + } finally { + WHITE_BOX.removeCompilerDirective(2); + } } private ClearMethodStateTest(TestCase testCase) { @@ -58,6 +69,7 @@ public class ClearMethodStateTest extends CompilerWhiteBoxTest { */ @Override protected void test() throws Exception { + checkNotCompiled(); compile(); WHITE_BOX.clearMethodState(method); diff --git a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java index 269113074e4..5bec2eabd84 100644 --- a/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java +++ b/hotspot/test/compiler/whitebox/CompilerWhiteBoxTest.java @@ -213,6 +213,7 @@ public abstract class CompilerWhiteBoxTest { * compilation level. */ protected final void checkNotCompiled() { + waitBackgroundCompilation(); checkNotCompiled(true); checkNotCompiled(false); } @@ -226,7 +227,6 @@ public abstract class CompilerWhiteBoxTest { * compilation level. */ protected final void checkNotCompiled(boolean isOsr) { - waitBackgroundCompilation(); if (WHITE_BOX.isMethodQueuedForCompilation(method)) { throw new RuntimeException(method + " must not be in queue"); } @@ -315,11 +315,11 @@ public abstract class CompilerWhiteBoxTest { return; } final Object obj = new Object(); - for (int i = 0; i < 10 + for (int i = 0; i < 100 && WHITE_BOX.isMethodQueuedForCompilation(executable); ++i) { synchronized (obj) { try { - obj.wait(1000); + obj.wait(100); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } diff --git a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java index cec51a811bc..cde67e20f60 100644 --- a/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java +++ b/hotspot/test/compiler/whitebox/EnqueueMethodForCompilationTest.java @@ -31,14 +31,24 @@ import compiler.whitebox.CompilerWhiteBoxTest; * @build EnqueueMethodForCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* EnqueueMethodForCompilationTest + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI EnqueueMethodForCompilationTest * @summary testing of WB::enqueueMethodForCompilation() * @author igor.ignatyev@oracle.com */ public class EnqueueMethodForCompilationTest extends CompilerWhiteBoxTest { public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(EnqueueMethodForCompilationTest::new, args); + String directive = + "[{ match:\"*SimpleTestCase$Helper.*\", BackgroundCompilation: false }, " + + " { match:\"*.*\", inline:\"-*SimpleTestCase$Helper.*\"}]"; + if (WHITE_BOX.addCompilerDirective(directive) != 2) { + throw new RuntimeException("Could not add directive"); + } + try { + CompilerWhiteBoxTest.main(EnqueueMethodForCompilationTest::new, args); + } finally { + WHITE_BOX.removeCompilerDirective(2); + } } private EnqueueMethodForCompilationTest(TestCase testCase) { diff --git a/hotspot/test/compiler/whitebox/LockCompilationTest.java b/hotspot/test/compiler/whitebox/LockCompilationTest.java index 2dd5275dc5e..3efe08edf8f 100644 --- a/hotspot/test/compiler/whitebox/LockCompilationTest.java +++ b/hotspot/test/compiler/whitebox/LockCompilationTest.java @@ -29,7 +29,7 @@ * @build LockCompilationTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=600 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* LockCompilationTest + * @run main/othervm -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI LockCompilationTest * @summary testing of WB::lock/unlockCompilation() */ @@ -37,12 +37,15 @@ import java.io.OutputStream; import java.io.PrintWriter; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.CyclicBarrier; + import compiler.whitebox.CompilerWhiteBoxTest; import jdk.test.lib.Asserts; public class LockCompilationTest extends CompilerWhiteBoxTest { public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(LockCompilationTest::new, args); + // This case waits for 10 seconds and verifies that the method hasn't been + // compiled during that time. Only do that for one of the test cases. + CompilerWhiteBoxTest.main(LockCompilationTest::new, new String[] {"METHOD_TEST"}); } private LockCompilationTest(TestCase testCase) { diff --git a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java index 82b568a30c6..1e86bfb5594 100644 --- a/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java +++ b/hotspot/test/compiler/whitebox/MakeMethodNotCompilableTest.java @@ -31,14 +31,24 @@ import compiler.whitebox.CompilerWhiteBoxTest; * @build MakeMethodNotCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission - * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=compileonly,compiler.whitebox.SimpleTestCase$Helper::* MakeMethodNotCompilableTest + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xmixed MakeMethodNotCompilableTest * @summary testing of WB::makeMethodNotCompilable() * @author igor.ignatyev@oracle.com */ public class MakeMethodNotCompilableTest extends CompilerWhiteBoxTest { private int bci; public static void main(String[] args) throws Exception { - CompilerWhiteBoxTest.main(MakeMethodNotCompilableTest::new, args); + String directive = + "[{ match:\"*SimpleTestCase$Helper.*\", BackgroundCompilation: false }, " + + " { match:\"*.*\", inline:\"-*SimpleTestCase$Helper.*\"}]"; + if (WHITE_BOX.addCompilerDirective(directive) != 2) { + throw new RuntimeException("Could not add directive"); + } + try { + CompilerWhiteBoxTest.main(MakeMethodNotCompilableTest::new, args); + } finally { + WHITE_BOX.removeCompilerDirective(2); + } } private MakeMethodNotCompilableTest(TestCase testCase) { diff --git a/hotspot/test/gc/g1/TestGCLogMessages.java b/hotspot/test/gc/g1/TestGCLogMessages.java index 8ab921b0186..81526644c59 100644 --- a/hotspot/test/gc/g1/TestGCLogMessages.java +++ b/hotspot/test/gc/g1/TestGCLogMessages.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test TestGCLogMessages - * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 + * @bug 8035406 8027295 8035398 8019342 8027959 8048179 8027962 8069330 8076463 8150630 * @summary Ensure the output for a minor GC with G1 * includes the expected necessary messages. * @key gc @@ -38,10 +38,24 @@ import jdk.test.lib.OutputAnalyzer; public class TestGCLogMessages { private enum Level { - OFF, DEBUG, TRACE; - public boolean lessOrEqualTo(Level other) { + OFF(""), + INFO("info"), + DEBUG("debug"), + TRACE("trace"); + + private String logName; + + Level(String logName) { + this.logName = logName; + } + + public boolean lessThan(Level other) { return this.compareTo(other) < 0; } + + public String toString() { + return logName; + } } private class LogMessageWithLevel { @@ -56,44 +70,48 @@ public class TestGCLogMessages { private LogMessageWithLevel allLogMessages[] = new LogMessageWithLevel[] { // Update RS - new LogMessageWithLevel("Scan HCC", Level.DEBUG), + new LogMessageWithLevel("Scan HCC", Level.TRACE), // Ext Root Scan - new LogMessageWithLevel("Thread Roots:", Level.DEBUG), - new LogMessageWithLevel("StringTable Roots:", Level.DEBUG), - new LogMessageWithLevel("Universe Roots:", Level.DEBUG), - new LogMessageWithLevel("JNI Handles Roots:", Level.DEBUG), - new LogMessageWithLevel("ObjectSynchronizer Roots:", Level.DEBUG), - new LogMessageWithLevel("FlatProfiler Roots", Level.DEBUG), - new LogMessageWithLevel("Management Roots", Level.DEBUG), - new LogMessageWithLevel("SystemDictionary Roots", Level.DEBUG), - new LogMessageWithLevel("CLDG Roots", Level.DEBUG), - new LogMessageWithLevel("JVMTI Roots", Level.DEBUG), - new LogMessageWithLevel("SATB Filtering", Level.DEBUG), - new LogMessageWithLevel("CM RefProcessor Roots", Level.DEBUG), - new LogMessageWithLevel("Wait For Strong CLD", Level.DEBUG), - new LogMessageWithLevel("Weak CLD Roots", Level.DEBUG), + new LogMessageWithLevel("Thread Roots", Level.TRACE), + new LogMessageWithLevel("StringTable Roots", Level.TRACE), + new LogMessageWithLevel("Universe Roots", Level.TRACE), + new LogMessageWithLevel("JNI Handles Roots", Level.TRACE), + new LogMessageWithLevel("ObjectSynchronizer Roots", Level.TRACE), + new LogMessageWithLevel("FlatProfiler Roots", Level.TRACE), + new LogMessageWithLevel("Management Roots", Level.TRACE), + new LogMessageWithLevel("SystemDictionary Roots", Level.TRACE), + new LogMessageWithLevel("CLDG Roots", Level.TRACE), + new LogMessageWithLevel("JVMTI Roots", Level.TRACE), + new LogMessageWithLevel("SATB Filtering", Level.TRACE), + new LogMessageWithLevel("CM RefProcessor Roots", Level.TRACE), + new LogMessageWithLevel("Wait For Strong CLD", Level.TRACE), + new LogMessageWithLevel("Weak CLD Roots", Level.TRACE), // Redirty Cards new LogMessageWithLevel("Redirty Cards", Level.DEBUG), - new LogMessageWithLevel("Parallel Redirty", Level.DEBUG), - new LogMessageWithLevel("Redirtied Cards", Level.DEBUG), + new LogMessageWithLevel("Parallel Redirty", Level.TRACE), + new LogMessageWithLevel("Redirtied Cards", Level.TRACE), // Misc Top-level - new LogMessageWithLevel("Code Root Purge", Level.DEBUG), - new LogMessageWithLevel("String Dedup Fixup", Level.DEBUG), - new LogMessageWithLevel("Expand Heap After Collection", Level.DEBUG), + new LogMessageWithLevel("Code Roots Purge", Level.DEBUG), + new LogMessageWithLevel("String Dedup Fixup", Level.INFO), + new LogMessageWithLevel("Expand Heap After Collection", Level.INFO), // Free CSet - new LogMessageWithLevel("Young Free CSet", Level.TRACE), - new LogMessageWithLevel("Non-Young Free CSet", Level.TRACE), + new LogMessageWithLevel("Young Free Collection Set", Level.DEBUG), + new LogMessageWithLevel("Non-Young Free Collection Set", Level.DEBUG), // Humongous Eager Reclaim new LogMessageWithLevel("Humongous Reclaim", Level.DEBUG), new LogMessageWithLevel("Humongous Register", Level.DEBUG), + // Preserve CM Referents + new LogMessageWithLevel("Preserve CM Refs", Level.DEBUG), + // Merge PSS + new LogMessageWithLevel("Merge Per-Thread State", Level.INFO), }; void checkMessagesAtLevel(OutputAnalyzer output, LogMessageWithLevel messages[], Level level) throws Exception { for (LogMessageWithLevel l : messages) { - if (level.lessOrEqualTo(l.level)) { + if (level.lessThan(l.level)) { output.shouldNotContain(l.message); } else { - output.shouldContain(l.message); + output.shouldMatch("\\[" + l.level + ".*" + l.message); } } } diff --git a/hotspot/test/gc/g1/TestPLABOutput.java b/hotspot/test/gc/g1/TestPLABOutput.java index a8265ac00c1..4b85b1cbcd6 100644 --- a/hotspot/test/gc/g1/TestPLABOutput.java +++ b/hotspot/test/gc/g1/TestPLABOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,7 +65,7 @@ public class TestPLABOutput { System.out.println(output.getStdout()); - String pattern = ".*GC\\(0\\) .*allocated = (\\d+).*"; + String pattern = ".*GC\\(0\\) .*allocated: (\\d+).*"; Pattern r = Pattern.compile(pattern); Matcher m = r.matcher(output.getStdout()); diff --git a/hotspot/test/gc/g1/plab/TestPLABPromotion.java b/hotspot/test/gc/g1/plab/TestPLABPromotion.java index 54a56bb5092..7b892f29fa3 100644 --- a/hotspot/test/gc/g1/plab/TestPLABPromotion.java +++ b/hotspot/test/gc/g1/plab/TestPLABPromotion.java @@ -23,7 +23,7 @@ /* * @test TestPLABPromotion - * @bug 8141278 + * @bug 8141278 8141141 * @summary Test PLAB promotion * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true @@ -130,16 +130,15 @@ public class TestPLABPromotion { long plabAllocatedOld; long directAllocatedOld; long memAllocated = testCase.getMemToFill(); - long wordSize = Platform.is32bit() ? 4l : 8l; LogParser logParser = new LogParser(output); Map survivorStats = getPlabStats(logParser, LogParser.ReportType.SURVIVOR_STATS, GC_ID_SURVIVOR_STATS); Map oldStats = getPlabStats(logParser, LogParser.ReportType.OLD_STATS, GC_ID_OLD_STATS); - plabAllocatedSurvivor = wordSize * survivorStats.get("used"); - directAllocatedSurvivor = wordSize * survivorStats.get("direct_allocated"); - plabAllocatedOld = wordSize * oldStats.get("used"); - directAllocatedOld = wordSize * oldStats.get("direct_allocated"); + plabAllocatedSurvivor = survivorStats.get("used"); + directAllocatedSurvivor = survivorStats.get("direct allocated"); + plabAllocatedOld = oldStats.get("used"); + directAllocatedOld = oldStats.get("direct allocated"); System.out.printf("Survivor PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedSurvivor, directAllocatedSurvivor, memAllocated); System.out.printf("Old PLAB allocated:%17d Direct allocated: %17d Mem consumed:%17d%n", plabAllocatedOld, directAllocatedOld, memAllocated); diff --git a/hotspot/test/gc/g1/plab/TestPLABResize.java b/hotspot/test/gc/g1/plab/TestPLABResize.java index 07a05ce90c3..e9aef79c07f 100644 --- a/hotspot/test/gc/g1/plab/TestPLABResize.java +++ b/hotspot/test/gc/g1/plab/TestPLABResize.java @@ -23,7 +23,7 @@ /* * @test TestPLABResize - * @bug 8141278 + * @bug 8141278 8141141 * @summary Test for PLAB resizing * @requires vm.gc=="G1" | vm.gc=="null" * @requires vm.opt.FlightRecorder != true @@ -35,6 +35,7 @@ * gc.g1.plab.lib.MemoryConsumer * gc.g1.plab.lib.PLABUtils * gc.g1.plab.lib.AppPLABResize + * @ignore 8150183 * @run main ClassFileInstaller sun.hotspot.WhiteBox * sun.hotspot.WhiteBox$WhiteBoxPermission * @run main gc.g1.plab.TestPLABResize @@ -116,7 +117,7 @@ public class TestPLABResize { .map(item -> { return item.getValue() .get(LogParser.ReportType.SURVIVOR_STATS) - .get("desired_plab_sz"); + .get("actual"); }) .collect(Collectors.toCollection(ArrayList::new)); diff --git a/hotspot/test/gc/g1/plab/lib/LogParser.java b/hotspot/test/gc/g1/plab/lib/LogParser.java index ce2f94ef6e6..2bf933edabd 100644 --- a/hotspot/test/gc/g1/plab/lib/LogParser.java +++ b/hotspot/test/gc/g1/plab/lib/LogParser.java @@ -35,14 +35,12 @@ import java.util.regex.Pattern; * * Typical GC log with PLAB statistics (options - -Xlog:gc=debug,gc+plab=debug) looks like: * - * [2,244s][info ][gc ] GC(30) Concurrent Mark abort - * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,245s][debug ][gc,plab] GC(33) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,245s][info ][gc ] GC(33) Pause Young (G1 Evacuation Pause) 127M->127M(128M) (2,244s, 2,245s) 0,899ms - * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,246s][debug ][gc,plab] GC(34) (allocated = 1 wasted = 0 unused = 0 used = 1 undo_waste = 0 region_end_waste = 0 regions filled = 0 direct_allocated = 0 failure_used = 0 failure_waste = 0) (plab_sz = 0 desired_plab_sz = 258) - * [2,246s][info ][gc ] GC(34) Pause Initial Mark (G1 Evacuation Pause) 127M->127M(128M) (2,245s, 2,246s) 0,907ms - + * [0.330s][debug][gc,plab ] GC(0) Young PLAB allocation: allocated: 1825632B, wasted: 29424B, unused: 2320B, used: 1793888B, undo waste: 0B, + * [0.330s][debug][gc,plab ] GC(0) Young other allocation: region end waste: 0B, regions filled: 2, direct allocated: 271520B, failure used: 0B, failure wasted: 0B + * [0.330s][debug][gc,plab ] GC(0) Young sizing: calculated: 358776B, actual: 358776B + * [0.330s][debug][gc,plab ] GC(0) Old PLAB allocation: allocated: 427248B, wasted: 592B, unused: 368584B, used: 58072B, undo waste: 0B, + * [0.330s][debug][gc,plab ] GC(0) Old other allocation: region end waste: 0B, regions filled: 1, direct allocated: 41704B, failure used: 0B, failure wasted: 0B + * [0.330s][debug][gc,plab ] GC(0) Old sizing: calculated: 11608B, actual: 11608B */ final public class LogParser { @@ -53,7 +51,6 @@ final public class LogParser { * Type of parsed log element. */ public static enum ReportType { - SURVIVOR_STATS, OLD_STATS } @@ -64,8 +61,8 @@ final public class LogParser { // GC ID private static final Pattern GC_ID_PATTERN = Pattern.compile("\\[gc,plab\\s*\\] GC\\((\\d+)\\)"); - // Pattern for extraction pair = - private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w+\\s+=\\s+\\d+"); + // Pattern for extraction pair : + private static final Pattern PAIRS_PATTERN = Pattern.compile("\\w* \\w+:\\s+\\d+"); /** * Construct LogParser Object @@ -108,24 +105,29 @@ final public class LogParser { if (matcher.find()) { Map> oneReportItem; ReportType reportType; - // Second line in log is statistics for Old PLAB allocation - if ( !allocationStatistics.containsKey(gc_id.get()) ) { - oneReportItem = new EnumMap<>(ReportType.class); + + if (!allocationStatistics.containsKey(gc_id.get())) { + allocationStatistics.put(gc_id.get(), new EnumMap<>(ReportType.class)); + } + + if ( line.contains("Young") ) { reportType = ReportType.SURVIVOR_STATS; - allocationStatistics.put(gc_id.get(), oneReportItem); } else { - oneReportItem = allocationStatistics.get(gc_id.get()); reportType = ReportType.OLD_STATS; } + oneReportItem = allocationStatistics.get(gc_id.get()); + if (!oneReportItem.containsKey(reportType)) { + oneReportItem.put(reportType,new HashMap()); + } + // Extract all pairs from log. - HashMap plabStats = new HashMap<>(); + Map plabStats = oneReportItem.get(reportType); do { String pair = matcher.group(); - String[] nameValue = pair.replaceAll(" ", "").split("="); - plabStats.put(nameValue[0], Long.parseLong(nameValue[1])); + String[] nameValue = pair.replaceAll(": ", ":").split(":"); + plabStats.put(nameValue[0].trim(), Long.parseLong(nameValue[1])); } while (matcher.find()); - oneReportItem.put(reportType,plabStats); } } } diff --git a/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java b/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java index 8e138db694d..1a7501e0981 100644 --- a/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java +++ b/hotspot/test/gc/parallel/TestPrintGCDetailsVerbose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,12 +24,11 @@ /* * @test TestPrintGCDetailsVerbose * @bug 8016740 - * @summary Tests that jvm with PrintGCDetails and Verbose flags do not crash when ParOldGC has no memory + * @summary Tests that jvm with maximally verbose GC logging does not crash when ParOldGC has no memory * @key gc - * @requires java.version ~= ".*fastdebug" * @requires vm.gc=="Parallel" | vm.gc=="null" * @library /testlibrary - * @run main/othervm -Xmx50m -XX:+UseParallelOldGC -XX:+PrintGCDetails -XX:+Verbose TestPrintGCDetailsVerbose + * @run main/othervm -Xmx50m -XX:+UseParallelGC -Xlog:gc*=trace TestPrintGCDetailsVerbose */ public class TestPrintGCDetailsVerbose { diff --git a/hotspot/test/native_sanity/JniVersion.java b/hotspot/test/native_sanity/JniVersion.java index a85a184c241..e1451d2e9a5 100644 --- a/hotspot/test/native_sanity/JniVersion.java +++ b/hotspot/test/native_sanity/JniVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,12 +27,12 @@ */ public class JniVersion { - public static final int JNI_VERSION_1_8 = 0x00010008; + public static final int JNI_VERSION_9 = 0x00090000; public static void main(String... args) throws Exception { System.loadLibrary("JniVersion"); int res = getJniVersion(); - if (res < JNI_VERSION_1_8) { + if (res != JNI_VERSION_9) { throw new Exception("Unexpected value returned from getJniVersion(): 0x" + Integer.toHexString(res)); } } diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java index f762017bff2..27ccc5d546b 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,7 @@ public class TestOptionsWithRanges { int failedTests; List allOptions; - allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap(); + allOptionsAsMap = JVMOptionsUtils.getOptionsWithRangeAsMap(origin -> (!(origin.contains("develop") || origin.contains("notproduct")))); /* Shared flags can cause JVM to exit with error code 2 */ setAllowedExitCodes("SharedReadWriteSize", 2); @@ -83,6 +83,13 @@ public class TestOptionsWithRanges { setAllowedExitCodes("SharedMiscDataSize", 2); setAllowedExitCodes("SharedMiscCodeSize", 2); + /* + * JDK-8145204 + * Temporarily remove testing of max range for ParGCArrayScanChunk because + * JVM can hang when ParGCArrayScanChunk=4294967296 and ParallelGC is used + */ + excludeTestMaxRange("ParGCArrayScanChunk"); + /* * Remove CICompilerCount from testing because currently it can hang system */ diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java index d4d54669987..031d6a2cc64 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import jdk.test.lib.dcmd.JMXExecutor; import sun.tools.attach.HotSpotVirtualMachine; import static optionsvalidation.JVMOptionsUtils.failedMessage; +import static optionsvalidation.JVMOptionsUtils.GCType; import static optionsvalidation.JVMOptionsUtils.printOutputContent; import static optionsvalidation.JVMOptionsUtils.VMType; @@ -374,17 +375,21 @@ public abstract class JVMOption { private boolean runJavaWithParam(String optionValue, boolean valid) throws Exception { int exitCode; boolean result = true; - String value = optionValue.substring(optionValue.lastIndexOf("=") + 1); - String fullOptionString = prependString.toString() + optionValue; + String errorMessage = null; List runJava = new ArrayList<>(); OutputAnalyzer out; if (VMType != null) { runJava.add(VMType); } + + if (GCType != null) { + runJava.add(GCType); + } + runJava.addAll(prepend); runJava.add(optionValue); - runJava.add(JVMOptionsUtils.class.getName()); + runJava.add(JVMStartup.class.getName()); out = new OutputAnalyzer(ProcessTools.createJavaProcessBuilder(runJava.toArray(new String[0])).start()); @@ -392,40 +397,37 @@ public abstract class JVMOption { if (out.getOutput().contains("A fatal error has been detected by the Java Runtime Environment")) { /* Always consider "fatal error" in output as fail */ - failedMessage(name, fullOptionString, valid, "JVM output reports a fatal error. JVM exited with code " + exitCode + "!"); - printOutputContent(out); - result = false; + errorMessage = "JVM output reports a fatal error. JVM exited with code " + exitCode + "!"; } else if (valid == true) { if (!allowedExitCodes.contains(exitCode)) { - failedMessage(name, fullOptionString, valid, "JVM exited with unexpected error code = " + exitCode); - printOutputContent(out); - result = false; + errorMessage = "JVM exited with unexpected error code = " + exitCode; } else if ((exitCode != 0) && (out.getOutput().isEmpty() == true)) { - failedMessage(name, fullOptionString, valid, "JVM exited with error(exitcode == " + exitCode + - "), but with empty stdout and stderr. Description of error is needed!"); - result = false; + errorMessage = "JVM exited with error(exitcode == " + exitCode + "), but with empty stdout and stderr. " + + "Description of error is needed!"; } else if (out.getOutput().contains("is outside the allowed range")) { - failedMessage(name, fullOptionString, valid, "JVM output contains \"is outside the allowed range\""); - printOutputContent(out); - result = false; + errorMessage = "JVM output contains \"is outside the allowed range\""; } } else { // valid == false + String value = optionValue.substring(optionValue.lastIndexOf("=") + 1); + String errorMessageCommandLineValue = getErrorMessageCommandLine(value); if (exitCode == 0) { - failedMessage(name, fullOptionString, valid, "JVM successfully exit"); - result = false; + errorMessage = "JVM successfully exit"; } else if (exitCode != 1) { - failedMessage(name, fullOptionString, valid, "JVM exited with code " - + exitCode + " which not equal to 1"); - result = false; - } else if (!out.getOutput().contains(getErrorMessageCommandLine(value))) { - failedMessage(name, fullOptionString, valid, "JVM output does not contain " - + "expected output \"" + getErrorMessageCommandLine(value) + "\""); - printOutputContent(out); - result = false; + errorMessage = "JVM exited with code " + exitCode + " which not equal to 1"; + } else if (!out.getOutput().contains(errorMessageCommandLineValue)) { + errorMessage = "JVM output does not contain expected output \"" + errorMessageCommandLineValue + "\""; } } + if (errorMessage != null) { + String fullOptionString = String.format("%s %s %s %s", + VMType == null ? "" : VMType, GCType == null ? "" : GCType, prependString.toString(), optionValue).trim().replaceAll(" +", " "); + failedMessage(name, fullOptionString, valid, errorMessage); + printOutputContent(out); + result = false; + } + System.out.println(""); return result; diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java index 944b8d5964c..cfde0ee0e3d 100644 --- a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMOptionsUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,8 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.Reader; +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Arrays; @@ -50,6 +52,9 @@ public class JVMOptionsUtils { /* Used to start the JVM with the same type as current */ static String VMType; + /* Used to start the JVM with the same GC type as current */ + static String GCType; + private static Map optionsAsMap; static { @@ -64,6 +69,27 @@ public class JVMOptionsUtils { } else { VMType = null; } + + List gcMxBeans = ManagementFactory.getGarbageCollectorMXBeans(); + + GCType = null; + + for (GarbageCollectorMXBean gcMxBean : gcMxBeans) { + switch (gcMxBean.getName()) { + case "ConcurrentMarkSweep": + GCType = "-XX:+UseConcMarkSweepGC"; + break; + case "MarkSweepCompact": + GCType = "-XX:+UseSerialGC"; + break; + case "PS Scavenge": + GCType = "-XX:+UseParallelGC"; + break; + case "G1 Old Generation": + GCType = "-XX:+UseG1GC"; + break; + } + } } public static boolean fitsRange(String optionName, BigDecimal number) throws Exception { @@ -443,6 +469,10 @@ public class JVMOptionsUtils { if (VMType != null) { runJava.add(VMType); } + + if (GCType != null) { + runJava.add(GCType); + } runJava.add(PRINT_FLAGS_RANGES); runJava.add("-version"); @@ -534,9 +564,4 @@ public class JVMOptionsUtils { public static Map getOptionsWithRangeAsMap(String... additionalArgs) throws Exception { return getOptionsWithRangeAsMap(origin -> true, additionalArgs); } - - /* Simple method to test that java start-up. Used for testing options. */ - public static void main(String[] args) { - System.out.print("Java start-up!"); - } } diff --git a/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java new file mode 100644 index 00000000000..5b5d96e5576 --- /dev/null +++ b/hotspot/test/runtime/CommandLine/OptionsValidation/common/optionsvalidation/JVMStartup.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package optionsvalidation; + +import java.lang.ref.WeakReference; + +class JVMStartup { + private static volatile WeakReference weakRef; + + private static synchronized void createWeakRef() { + Object o = new Object(); + weakRef = new WeakReference<>(o); + } + + /* Simple method to test that java start-up. Used for testing options. */ + public static void main(String[] args) throws Exception { + byte[] garbage = new byte[8192]; + int i = 0; + createWeakRef(); + do { + garbage = new byte[8192]; + i++; + /* Initiate GC after 5 iterations */ + if (i > 5) { + System.gc(); + } + } while(weakRef.get() != null); + System.out.println("Java start-up!"); + } +} diff --git a/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java index e4cff831d69..29247220f69 100644 --- a/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java +++ b/hotspot/test/runtime/RedefineTests/RedefineRunningMethodsWithResolutionErrors.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,9 @@ * @bug 8076110 * @summary Redefine running methods that have cached resolution errors * @library /testlibrary - * @modules java.instrument - * java.base/jdk.internal.org.objectweb.asm + * @modules java.base/jdk.internal.org.objectweb.asm + * java.instrument + * jdk.jartool/sun.tools.jar * @build RedefineClassHelper * @run main RedefineClassHelper * @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethodsWithResolutionErrors diff --git a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java index b8d93be3eb7..43177dda31e 100644 --- a/hotspot/test/runtime/ReservedStack/ReservedStackTest.java +++ b/hotspot/test/runtime/ReservedStack/ReservedStackTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test ReservedStackTest * @library /testlibrary + * @modules java.base/jdk.internal.vm.annotation * @build jdk.test.lib.* * @run main/othervm -XX:-Inline -XX:CompileCommand=exclude,java/util/concurrent/locks/AbstractOwnableSynchronizer.setExclusiveOwnerThread ReservedStackTest */ diff --git a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java index 824fd94f41f..c774111f210 100644 --- a/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java +++ b/hotspot/test/runtime/SharedArchiveFile/LimitSharedSizes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @library /testlibrary /runtime/CommandLine/OptionsValidation/common * @modules java.base/sun.misc * java.management + * jdk.attach/sun.tools.attach * @run main LimitSharedSizes */ diff --git a/hotspot/test/runtime/contended/Basic.java b/hotspot/test/runtime/contended/Basic.java index 3ce7eb20e82..bf64e946f29 100644 --- a/hotspot/test/runtime/contended/Basic.java +++ b/hotspot/test/runtime/contended/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ import jdk.internal.vm.annotation.Contended; * @test * @bug 8003985 * @summary Support Contended Annotation - JEP 142 - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended Basic */ public class Basic { diff --git a/hotspot/test/runtime/contended/DefaultValue.java b/hotspot/test/runtime/contended/DefaultValue.java index a121c7a63e9..8ed4f064088 100644 --- a/hotspot/test/runtime/contended/DefaultValue.java +++ b/hotspot/test/runtime/contended/DefaultValue.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8014509 * @summary \@Contended: explicit default value behaves differently from the implicit value * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended DefaultValue */ public class DefaultValue { diff --git a/hotspot/test/runtime/contended/HasNonStatic.java b/hotspot/test/runtime/contended/HasNonStatic.java index 33878fa6115..3e07c09fcfe 100644 --- a/hotspot/test/runtime/contended/HasNonStatic.java +++ b/hotspot/test/runtime/contended/HasNonStatic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8015270 * @summary \@Contended: fix multiple issues in the layout code * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended HasNonStatic */ public class HasNonStatic { diff --git a/hotspot/test/runtime/contended/Inheritance1.java b/hotspot/test/runtime/contended/Inheritance1.java index 3ea318c40dc..f3333610cf3 100644 --- a/hotspot/test/runtime/contended/Inheritance1.java +++ b/hotspot/test/runtime/contended/Inheritance1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8012939 * @summary \@Contended doesn't work correctly with inheritance * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended Inheritance1 */ public class Inheritance1 { diff --git a/hotspot/test/runtime/contended/OopMaps.java b/hotspot/test/runtime/contended/OopMaps.java index 5e1b39c8271..27d5ba8ddf8 100644 --- a/hotspot/test/runtime/contended/OopMaps.java +++ b/hotspot/test/runtime/contended/OopMaps.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8015493 * @summary \@Contended: fix multiple issues in the layout code * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMaps */ public class OopMaps { diff --git a/hotspot/test/runtime/contended/OopMapsSameGroup.java b/hotspot/test/runtime/contended/OopMapsSameGroup.java index af441a576b9..6975fd3dc68 100644 --- a/hotspot/test/runtime/contended/OopMapsSameGroup.java +++ b/hotspot/test/runtime/contended/OopMapsSameGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import jdk.internal.vm.annotation.Contended; * @bug 8015272 * @summary \@Contended within the same group to use the same oop map * - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.vm.annotation * @run main/othervm -XX:-RestrictContended -XX:ContendedPaddingWidth=128 -Xmx128m OopMapsSameGroup */ public class OopMapsSameGroup { diff --git a/hotspot/test/runtime/lambda-features/TestStaticandInstance.java b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java index 021ac48bf8a..328f252e771 100644 --- a/hotspot/test/runtime/lambda-features/TestStaticandInstance.java +++ b/hotspot/test/runtime/lambda-features/TestStaticandInstance.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @test * @bug 8087342 * @summary Test linkresolver search static, instance and overpass duplicates + * @modules java.base/jdk.internal.org.objectweb.asm * @run main/othervm -Xverify:none TestStaticandInstance */ diff --git a/hotspot/test/runtime/logging/BiasedLockingTest.java b/hotspot/test/runtime/logging/BiasedLockingTest.java new file mode 100644 index 00000000000..36afcea3c75 --- /dev/null +++ b/hotspot/test/runtime/logging/BiasedLockingTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149383 + * @summary -Xlog:biasedlocking should have logging from statements in the source code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver BiasedLockingTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class BiasedLockingTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("Biased locking enabled"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[biasedlocking]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:biasedlocking", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:+TraceBiasedLocking", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:biasedlocking=off", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOff(pb); + + pb = ProcessTools.createJavaProcessBuilder("-XX:-TraceBiasedLocking", + "-XX:BiasedLockingStartupDelay=0", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) { + System.out.println("Biased Locking test"); + } + } +} diff --git a/hotspot/test/runtime/logging/ItablesTest.java b/hotspot/test/runtime/logging/ItablesTest.java index c1cfd33d865..0fe9d84213c 100644 --- a/hotspot/test/runtime/logging/ItablesTest.java +++ b/hotspot/test/runtime/logging/ItablesTest.java @@ -49,7 +49,6 @@ public class ItablesTest { output.shouldContain("invokespecial resolved method: caller-class:ClassB"); output.shouldContain("invokespecial selected method: resolved-class:ClassB"); output.shouldContain("invokeinterface selected method: receiver-class"); - output.shouldContain("Resolving: klass: "); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder("-Xlog:itables=trace", "ItablesVtableTest"); diff --git a/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java b/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java new file mode 100644 index 00000000000..57790ad1248 --- /dev/null +++ b/hotspot/test/runtime/logging/ProtectionDomainVerificationTest.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test ProtectionDomainVerificationTest + * @bug 8149064 + * @library /testlibrary + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.Platform jdk.test.lib.ProcessTools + * @run driver ProtectionDomainVerificationTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.Platform; +import jdk.test.lib.ProcessTools; + +public class ProtectionDomainVerificationTest { + + public static void main(String... args) throws Exception { + + // -Xlog:protectiondomain=trace + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=trace", + "-Xmx64m", + Hello.class.getName()); + OutputAnalyzer out = new OutputAnalyzer(pb.start()); + out.shouldContain("[protectiondomain] Checking package access"); + out.shouldContain("[protectiondomain] pd set count = #"); + + // -Xlog:protectiondomain=debug + pb = ProcessTools.createJavaProcessBuilder("-Xlog:protectiondomain=debug", + "-Xmx64m", + Hello.class.getName()); + out = new OutputAnalyzer(pb.start()); + out.shouldContain("[protectiondomain] Checking package access"); + out.shouldNotContain("pd set count = #"); + } + + public static class Hello { + public static void main(String[] args) { + System.out.print("Hello!"); + } + } +} diff --git a/hotspot/test/runtime/logging/StartupTimeTest.java b/hotspot/test/runtime/logging/StartupTimeTest.java new file mode 100644 index 00000000000..1c8c0a0f87f --- /dev/null +++ b/hotspot/test/runtime/logging/StartupTimeTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8148630 + * @summary -Xlog:startuptime should produce logging from the source code + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver StartupTimeTest + */ + +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class StartupTimeTest { + static void analyzeOutputOn(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldMatch("(Genesis, [0-9]+.[0-9]+ secs)"); + output.shouldMatch("(Start VMThread, [0-9]+.[0-9]+ secs)"); + output.shouldMatch("(Create VM, [0-9]+.[0-9]+ secs)"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputOff(ProcessBuilder pb) throws Exception { + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldNotContain("[startuptime]"); + output.shouldHaveExitValue(0); + } + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:startuptime", + InnerClass.class.getName()); + analyzeOutputOn(pb); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:startuptime=off", + InnerClass.class.getName()); + analyzeOutputOff(pb); + } + + public static class InnerClass { + public static void main(String[] args) throws Exception { + System.out.println("Testing startuptime."); + } + } +} diff --git a/hotspot/test/runtime/logging/ThreadLoggingTest.java b/hotspot/test/runtime/logging/ThreadLoggingTest.java new file mode 100644 index 00000000000..a5cde9c845c --- /dev/null +++ b/hotspot/test/runtime/logging/ThreadLoggingTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, SAP SE and/or its affiliates. All rights reserved. + * 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 8149036 8150619 + * @summary os+thread output should contain logging calls for thread start stop attaches detaches + * @library /testlibrary + * @modules java.base/sun.misc + * java.management + * @build jdk.test.lib.OutputAnalyzer jdk.test.lib.ProcessTools + * @run driver ThreadLoggingTest + * @author Thomas Stuefe (SAP) + */ + +import java.io.File; +import java.util.Map; +import jdk.test.lib.OutputAnalyzer; +import jdk.test.lib.ProcessTools; + +public class ThreadLoggingTest { + + static void analyzeOutputForInfoLevel(OutputAnalyzer output) throws Exception { + output.shouldContain("Thread started"); + output.shouldContain("Thread is alive"); + output.shouldContain("Thread finished"); + output.shouldHaveExitValue(0); + } + + static void analyzeOutputForDebugLevel(OutputAnalyzer output) throws Exception { + analyzeOutputForInfoLevel(output); + output.shouldContain("stack dimensions"); + output.shouldContain("stack guard pages"); + } + + public static void main(String[] args) throws Exception { + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread", "-version"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + analyzeOutputForInfoLevel(output); + + pb = ProcessTools.createJavaProcessBuilder("-Xlog:os+thread=debug", "-version"); + output = new OutputAnalyzer(pb.start()); + analyzeOutputForDebugLevel(output); + + } + +} diff --git a/hotspot/test/serviceability/attach/AttachSetGetFlag.java b/hotspot/test/serviceability/attach/AttachSetGetFlag.java index 64adb3984bb..a78edaafff1 100644 --- a/hotspot/test/serviceability/attach/AttachSetGetFlag.java +++ b/hotspot/test/serviceability/attach/AttachSetGetFlag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ * jdk.attach/sun.tools.attach * jdk.jvmstat/sun.jvmstat.monitor * @build jdk.test.lib.* AttachSetGetFlag - * @run driver AttachSetGetFlag + * @run main AttachSetGetFlag */ import java.io.BufferedReader; diff --git a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java index 1986ebd4beb..8ed9b479f63 100644 --- a/hotspot/test/serviceability/attach/AttachWithStalePidFile.java +++ b/hotspot/test/serviceability/attach/AttachWithStalePidFile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 7162400 * @key regression * @summary Regression test for attach issue where stale pid files in /tmp lead to connection issues + * @modules jdk.attach/sun.tools.attach * @library /testlibrary * @build jdk.test.lib.* AttachWithStalePidFileTarget * @run main AttachWithStalePidFile diff --git a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java index 0201e2ceeec..d5360de229d 100644 --- a/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java +++ b/hotspot/test/serviceability/dcmd/compiler/CodelistTest.java @@ -24,26 +24,39 @@ /* * @test CodelistTest * @bug 8054889 - * @library /testlibrary + * @library /testlibrary /test/lib / * @modules java.base/sun.misc * java.compiler * java.management * jdk.jvmstat/sun.jvmstat.monitor * @build jdk.test.lib.* - * @build jdk.test.lib.dcmd.* - * @build MethodIdentifierParser - * @run testng CodelistTest + * jdk.test.lib.dcmd.* + * sun.hotspot.WhiteBox + * compiler.testlibrary.CompilerUtils + * @run driver ClassFileInstaller sun.hotspot.WhiteBox + * sun.hotspot.WhiteBox$WhiteBoxPermission + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -Xmixed CodelistTest + * @run testng/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-UseCodeCacheFlushing -Xint CodelistTest * @summary Test of diagnostic command Compiler.codelist + * + * Flag comment: + * -XX:-UseCodeCacheFlushing - to prevent methods from being removed from the code cache before we have checked the results + * + * This test should never run in the same VM as other tests - the code cache may get huge which will + * create an enormous amount of output to parse. Same for -Xcomp. */ -import org.testng.annotations.Test; -import org.testng.Assert; - +import compiler.testlibrary.CompilerUtils; +import compiler.whitebox.CompilerWhiteBoxTest; import jdk.test.lib.OutputAnalyzer; import jdk.test.lib.dcmd.CommandExecutor; import jdk.test.lib.dcmd.JMXExecutor; +import org.testng.annotations.Test; +import org.testng.Assert; +import sun.hotspot.WhiteBox; import java.lang.reflect.Method; +import java.util.Iterator; public class CodelistTest { @@ -62,58 +75,68 @@ public class CodelistTest { * */ + protected static final WhiteBox WB = WhiteBox.getWhiteBox(); + public void run(CommandExecutor executor) { - int ok = 0; - int fail = 0; + + TestCase[] testcases = { + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_SIMPLE, "testcaseMethod1"), + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_LIMITED_PROFILE, "testcaseMethod2"), + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_FULL_PROFILE, "testcaseMethod3"), + new TestCase(CompilerWhiteBoxTest.COMP_LEVEL_FULL_OPTIMIZATION, "testcaseMethod4"), + }; + + String directive = "{ match: \"CodelistTest.testcaseMethod*\", " + + "BackgroundCompilation: false }"; + Assert.assertTrue( + WB.addCompilerDirective(directive) == 1, + "Must succeed"); + + try { + // Enqueue one test method for each available level + int[] complevels = CompilerUtils.getAvailableCompilationLevels(); + for (int level : complevels) { + // Only test comp level 1 and 4 - level 1, 2 and 3 may interfere with each other + if (level == 1 || level == 4) { + TestCase testcase = testcases[level - 1]; + WB.enqueueMethodForCompilation(testcase.method, testcase.level); + // Set results to false for those methods we must to find + // We will also assert if we find any test method we don't expect + testcase.check = false; + } + } + } finally { + WB.removeCompilerDirective(1); + } // Get output from dcmd (diagnostic command) OutputAnalyzer output = executor.execute("Compiler.codelist"); + Iterator lines = output.asLines().iterator(); - // Grab a method name from the output - int count = 0; + // Loop over output set result for all found methods + while (lines.hasNext()) { + String line = lines.next(); - for (String line : output.asLines()) { - count++; + // Fast check for common part of method name + if (line.contains("CodelistTest.testcaseMethod")) { + String[] parts = line.split(" "); + int compileID = Integer.parseInt(parts[0]); + int compileLevel = Integer.parseInt(parts[1]); + String str = parts[2]; - String[] parts = line.split(" "); - // int compileID = Integer.parseInt(parts[0]); - // int compileLevel = Integer.parseInt(parts[1]); - String methodPrintedInLogFormat = parts[2]; + for (TestCase testcase : testcases) { + if (str.contains(testcase.methodName)) { + Assert.assertFalse(testcase.check, "Must not be found or already found."); + Assert.assertTrue(testcase.level == compileLevel, "Must have correct level"); + testcase.check = true; + } + } + } + } - // skip inits, clinits, methodHandles and getUnsafe - - // they can not be reflected - if (methodPrintedInLogFormat.contains("")) { - continue; - } - if (methodPrintedInLogFormat.contains("")) { - continue; - } - if (methodPrintedInLogFormat.contains("MethodHandle")) { - continue; - } - if (methodPrintedInLogFormat.contains("sun.misc.Unsafe.getUnsafe")) { - continue; - } - if (methodPrintedInLogFormat.contains("jdk.internal.misc.Unsafe.getUnsafe")) { - continue; - } - - MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat); - Method m = null; - try { - m = mf.getMethod(); - } catch (NoSuchMethodException e) { - m = null; - } catch (ClassNotFoundException e) { - Assert.fail("Test error: Caught unexpected exception", e); - } - if (m == null) { - Assert.fail("Test failed on: " + methodPrintedInLogFormat); - } - if (count > 10) { - // Testing 10 entries is enough. Lets not waste time. - break; - } + // Check all testcases that was run + for (TestCase testcase : testcases) { + Assert.assertTrue(testcase.check, "Missing testcase " + testcase.methodName); } } @@ -121,4 +144,38 @@ public class CodelistTest { public void jmx() { run(new JMXExecutor()); } + + public void testcaseMethod1() { + } + + public void testcaseMethod2() { + } + + public void testcaseMethod3() { + } + + public void testcaseMethod4() { + } + + public static Method getMethod(Class klass, String name, Class... parameterTypes) { + try { + return klass.getDeclaredMethod(name, parameterTypes); + } catch (NoSuchMethodException | SecurityException e) { + throw new RuntimeException("exception on getting method Helper." + name, e); + } + } + + class TestCase { + Method method; + int level; + String methodName; + Boolean check; + + public TestCase(int level, String methodName) { + this.method = getMethod(CodelistTest.class, methodName); + this.level = level; + this.methodName = methodName; + this.check = true; + } + } } diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java index 63e80ab05bd..6b7cc7608e1 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpAllTest.java @@ -35,7 +35,7 @@ * @build jdk.test.lib.hprof.* * @build jdk.test.lib.hprof.model.* * @build jdk.test.lib.hprof.parser.* - * @build jdk.test.lib.hprof.utils.* + * @build jdk.test.lib.hprof.util.* * @build HeapDumpTest * @run testng HeapDumpAllTest */ diff --git a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java index aefd604c25c..16dfdee007a 100644 --- a/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java +++ b/hotspot/test/serviceability/dcmd/gc/HeapDumpTest.java @@ -51,7 +51,7 @@ import jdk.test.lib.dcmd.PidJcmdExecutor; * @build jdk.test.lib.hprof.* * @build jdk.test.lib.hprof.model.* * @build jdk.test.lib.hprof.parser.* - * @build jdk.test.lib.hprof.utils.* + * @build jdk.test.lib.hprof.util.* * @run testng HeapDumpTest */ public class HeapDumpTest { diff --git a/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java new file mode 100644 index 00000000000..da7224583e0 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/jvmti/LoadAgentDcmdTest.java @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.*; +import java.nio.file.*; +import java.util.jar.Attributes; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; +import jdk.test.lib.*; +import jdk.test.lib.dcmd.*; +import org.testng.annotations.Test; + +/* + * Test to attach JVMTI java agent. + * + * @test + * @bug 8147388 + * @library /testlibrary + * @modules java.base/sun.misc + * java.compiler + * java.instrument + * java.management + * jdk.jvmstat/sun.jvmstat.monitor + * @build ClassFileInstaller jdk.test.lib.* SimpleJvmtiAgent + * @ignore 8150318 + * @run main ClassFileInstaller SimpleJvmtiAgent + * @run testng LoadAgentDcmdTest + */ +public class LoadAgentDcmdTest { + + public String getLibInstrumentPath() throws FileNotFoundException { + String jdkPath = System.getProperty("test.jdk"); + + if (jdkPath == null) { + throw new RuntimeException( + "System property 'test.jdk' not set. " + + "This property is normally set by jtreg. " + + "When running test separately, set this property using " + + "'-Dtest.jdk=/path/to/jdk'."); + } + + Path libpath = Paths.get(jdkPath, Platform.jdkLibPath(), Platform.sharedObjectName("instrument")); + + if (!libpath.toFile().exists()) { + throw new FileNotFoundException( + "Could not find " + libpath.toAbsolutePath()); + } + + return libpath.toAbsolutePath().toString(); + } + + + public void createJarFileForAgent() + throws IOException { + + final String jarName = "agent.jar"; + final String agentClass = "SimpleJvmtiAgent"; + + Manifest manifest = new Manifest(); + + manifest.getMainAttributes().put( + Attributes.Name.MANIFEST_VERSION, "1.0"); + + manifest.getMainAttributes().put( + new Attributes.Name("Agent-Class"), agentClass); + + JarOutputStream target = null; + + try { + target = new + JarOutputStream(new FileOutputStream(jarName), manifest); + JarEntry entry = new JarEntry(agentClass + ".class"); + target.putNextEntry(entry); + target.closeEntry(); + } finally { + target.close(); + } + } + + public void run(CommandExecutor executor) { + try{ + + createJarFileForAgent(); + + String libpath = getLibInstrumentPath(); + OutputAnalyzer output = null; + + // Test 1: Native agent, no arguments + output = executor.execute("JVMTI.agent_load " + + libpath + " agent.jar"); + output.stderrShouldBeEmpty(); + + // Test 2: Native agent, with arguments + output = executor.execute("JVMTI.agent_load " + + libpath + " \"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + + // Test 3: Java agent, no arguments + output = executor.execute("JVMTI.agent_load " + + "agent.jar"); + output.stderrShouldBeEmpty(); + + // Test 4: Java agent, with arguments + output = executor.execute("JVMTI.agent_load " + + "\"agent.jar=foo=bar\""); + output.stderrShouldBeEmpty(); + + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + @Test + public void jmx() throws Throwable { + run(new JMXExecutor()); + } + + @Test + public void cli() throws Throwable { + run(new PidJcmdExecutor()); + } +} diff --git a/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java b/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java new file mode 100644 index 00000000000..6d92ff32f66 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/jvmti/SimpleJvmtiAgent.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.instrument.*; + +public class SimpleJvmtiAgent { + public static void agentmain(String agentArgs, Instrumentation instrumentation) { + System.out.println("attach succeeded (args: \"" + agentArgs + "\")"); + } +} diff --git a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java index 3ef260a5dfd..33b59c9af07 100644 --- a/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java +++ b/hotspot/test/serviceability/sa/jmap-hprof/JMapHProfLargeHeapTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,6 @@ import jdk.test.lib.ProcessTools; public class JMapHProfLargeHeapTest { private static final String HEAP_DUMP_FILE_NAME = "heap.hprof"; - private static final String HPROF_HEADER_1_0_1 = "JAVA PROFILE 1.0.1"; private static final String HPROF_HEADER_1_0_2 = "JAVA PROFILE 1.0.2"; private static final long M = 1024L; private static final long G = 1024L * M; @@ -79,8 +78,8 @@ public class JMapHProfLargeHeapTest { } } - // Small heap 22 megabytes, should create 1.0.1 file format - testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_1); + // All heap dumps should create 1.0.2 file format + testHProfFileFormat("-Xmx1g", 22 * M, HPROF_HEADER_1_0_2); /** * This test was deliberately commented out since the test system lacks diff --git a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java index 3b63e0210d1..6ec4db9829b 100644 --- a/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java +++ b/hotspot/test/serviceability/tmtools/jstat/GcCapacityTest.java @@ -27,6 +27,7 @@ import utils.*; * @test * @summary Test checks the consistency of the output * displayed with jstat -gccapacity. + * @ignore 8149778 * @library /test/lib/share/classes * @library ../share * @requires vm.opt.ExplicitGCInvokesConcurrent != true diff --git a/hotspot/test/testlibrary/jdk/test/lib/Platform.java b/hotspot/test/testlibrary/jdk/test/lib/Platform.java index ecd6a0f64d5..64773223556 100644 --- a/hotspot/test/testlibrary/jdk/test/lib/Platform.java +++ b/hotspot/test/testlibrary/jdk/test/lib/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -203,4 +203,31 @@ public class Platform { public static boolean canAttachOSX() throws Exception { return userName.equals("root"); } + + /** + * return path to library inside jdk tree + */ + public static String jdkLibPath() { + if (isWindows()) { + return "bin"; + } + if (isOSX()) { + return "lib"; + } + + return "lib/" + getOsArch(); + } + + /** + * Build name of shared object according to platform rules + */ + public static String sharedObjectName(String name) { + if (isWindows()) { + return name + ".dll"; + } + if (isOSX()) { + return "lib" + name + ".dylib"; + } + return "lib" + name + ".so"; + } } diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java index 8560fa6c5b3..f507fb068c5 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesDirTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.management * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar diff --git a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java index cb91c22bfe7..5a792a0c413 100644 --- a/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java +++ b/hotspot/test/testlibrary_tests/ctw/ClassesListTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.management * @build ClassFileInstaller sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox Foo Bar diff --git a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java index c8ab89ca846..1bfdc45db93 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarDirTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarDirTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.compiler * java.management diff --git a/hotspot/test/testlibrary_tests/ctw/JarsTest.java b/hotspot/test/testlibrary_tests/ctw/JarsTest.java index f9ec895df38..1050e512583 100644 --- a/hotspot/test/testlibrary_tests/ctw/JarsTest.java +++ b/hotspot/test/testlibrary_tests/ctw/JarsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ * @test * @bug 8012447 * @library /testlibrary /test/lib /testlibrary/ctw/src - * @modules java.base/sun.misc + * @modules java.base/jdk.internal.misc * java.base/sun.reflect * java.compiler * java.management diff --git a/jaxp/.hgtags b/jaxp/.hgtags index a985e31fc94..9a01ef541fc 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -349,3 +349,6 @@ bdbf2342b21bd8ecad1b4e6499a0dfb314952bd7 jdk-9+103 58448465334e1d8bf1cfc09052783937b1cc21c0 jdk-9+104 5acf6071d4d610068a19c79e004ba8e59cf1b087 jdk-9+105 65d615f71e81bae46dcb4d053e590582e5705879 jdk-9+106 +781b83dadcae89b8ae7545bb4044ddc62c6fa006 jdk-9+107 +3b9fa8b1491479f7ae18131a34036b58b647493e jdk-9+108 +24e247ee1fffaa625d480b2a4eef2d3a8a59f5cb jdk-9+109 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java index 1e6be9a9d85..47534bc4a8e 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/DOM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: DOM.java,v 1.2.4.1 2005/08/31 10:18:49 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc; @@ -102,4 +99,5 @@ public interface DOM { public int getDocument(); public String getUnparsedEntityURI(String name); public Map getElementsWithIDs(); + public void release(); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java index 6d6a47c157a..fbbb5c8e986 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/ApplyTemplates.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: ApplyTemplates.java,v 1.2.4.1 2005/09/12 09:59:21 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -122,12 +119,10 @@ final class ApplyTemplates extends Instruction { final int current = methodGen.getLocalIndex("current"); // check if sorting nodes is required - final Vector sortObjects = new Vector(); - final Iterator children = elements(); - while (children.hasNext()) { - final SyntaxTreeNode child = children.next(); + final Vector sortObjects = new Vector<>(); + for (final SyntaxTreeNode child : getContents()) { if (child instanceof Sort) { - sortObjects.addElement(child); + sortObjects.addElement((Sort)child); } } @@ -193,6 +188,13 @@ final class ApplyTemplates extends Instruction { applyTemplatesSig); il.append(new INVOKEVIRTUAL(applyTemplates)); + // unmap parameters to release temporary result trees + for (final SyntaxTreeNode child : getContents()) { + if (child instanceof WithParam) { + ((WithParam)child).releaseResultTree(classGen, methodGen); + } + } + // Pop parameter frame if (stylesheet.hasLocalParams() || hasContents()) { il.append(classGen.loadTranslet()); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java index caace085213..2e2ca146e84 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/CallTemplate.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,18 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: CallTemplate.java,v 1.2.4.1 2005/09/12 10:02:41 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import com.sun.org.apache.bcel.internal.generic.ALOAD; -import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionList; -import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; @@ -56,7 +49,7 @@ final class CallTemplate extends Instruction { * this array can be either a WithParam or a Param if no WithParam * exists for a particular parameter. */ - private Object[] _parameters = null; + private SyntaxTreeNode[] _parameters = null; /** * The corresponding template which this CallTemplate calls. @@ -147,11 +140,10 @@ final class CallTemplate extends Instruction { // If calling a simply named template, push actual arguments if (_calleeTemplate != null) { - Vector calleeParams = _calleeTemplate.getParameters(); int numParams = _parameters.length; for (int i = 0; i < numParams; i++) { - SyntaxTreeNode node = (SyntaxTreeNode)_parameters[i]; + SyntaxTreeNode node = _parameters[i]; methodSig.append(OBJECT_SIG); // append Object to signature // Push 'null' if Param to indicate no actual parameter specified @@ -170,6 +162,15 @@ final class CallTemplate extends Instruction { methodName, methodSig.toString()))); + // release temporary result trees + if (_parameters != null) { + for (int i = 0; i < _parameters.length; i++) { + if (_parameters[i] instanceof WithParam) { + ((WithParam)_parameters[i]).releaseResultTree(classGen, methodGen); + } + } + } + // Do not need to call Translet.popParamFrame() if we are // calling a simple named template. if (_calleeTemplate == null && (stylesheet.hasLocalParams() || hasContents())) { @@ -203,9 +204,9 @@ final class CallTemplate extends Instruction { private void buildParameterList() { // Put the parameters from the called template into the array first. // This is to ensure the order of the parameters. - Vector defaultParams = _calleeTemplate.getParameters(); + Vector defaultParams = _calleeTemplate.getParameters(); int numParams = defaultParams.size(); - _parameters = new Object[numParams]; + _parameters = new SyntaxTreeNode[numParams]; for (int i = 0; i < numParams; i++) { _parameters[i] = defaultParams.elementAt(i); } @@ -222,15 +223,15 @@ final class CallTemplate extends Instruction { // Search for a Param with the same name for (int k = 0; k < numParams; k++) { - Object object = _parameters[k]; - if (object instanceof Param - && ((Param)object).getName().equals(name)) { + SyntaxTreeNode parm = _parameters[k]; + if (parm instanceof Param + && ((Param)parm).getName().equals(name)) { withParam.setDoParameterOptimization(true); _parameters[k] = withParam; break; } - else if (object instanceof WithParam - && ((WithParam)object).getName().equals(name)) { + else if (parm instanceof WithParam + && ((WithParam)parm).getName().equals(name)) { withParam.setDoParameterOptimization(true); _parameters[k] = withParam; break; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java index d8264a23f93..f7309e50125 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Sort.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2005 The Apache Software Foundation. @@ -17,32 +16,22 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Sort.java,v 1.2.4.1 2005/09/12 11:08:12 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; -import java.text.Collator; import java.util.ArrayList; -import java.util.NoSuchElementException; -import java.util.StringTokenizer; import java.util.Vector; import com.sun.org.apache.bcel.internal.classfile.Field; -import com.sun.org.apache.bcel.internal.classfile.Method; import com.sun.org.apache.bcel.internal.generic.ALOAD; import com.sun.org.apache.bcel.internal.generic.ANEWARRAY; import com.sun.org.apache.bcel.internal.generic.ASTORE; import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.GETFIELD; -import com.sun.org.apache.bcel.internal.generic.ICONST; import com.sun.org.apache.bcel.internal.generic.ILOAD; import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; -import com.sun.org.apache.bcel.internal.generic.INVOKESTATIC; -import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionHandle; import com.sun.org.apache.bcel.internal.generic.InstructionList; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; @@ -76,13 +65,10 @@ final class Sort extends Instruction implements Closure { private AttributeValue _order; private AttributeValue _caseOrder; private AttributeValue _dataType; - private String _lang; // bug! see 26869 - - private String _data = null; - + private String _lang; // bug! see 26869 private String _className = null; - private ArrayList _closureVars = null; + private ArrayList _closureVars = null; private boolean _needsSortRecordFactory = false; // -- Begin Closure interface -------------------- @@ -115,7 +101,7 @@ final class Sort extends Instruction implements Closure { */ public void addVariable(VariableRefBase variableRef) { if (_closureVars == null) { - _closureVars = new ArrayList(); + _closureVars = new ArrayList<>(); } // Only one reference per variable @@ -246,7 +232,7 @@ final class Sort extends Instruction implements Closure { public static void translateSortIterator(ClassGenerator classGen, MethodGenerator methodGen, Expression nodeSet, - Vector sortObjects) + Vector sortObjects) { final ConstantPoolGen cpg = classGen.getConstantPool(); final InstructionList il = methodGen.getInstructionList(); @@ -312,7 +298,7 @@ final class Sort extends Instruction implements Closure { * Compiles code that instantiates a NodeSortRecordFactory object which * will produce NodeSortRecord objects of a specific type. */ - public static void compileSortRecordFactory(Vector sortObjects, + public static void compileSortRecordFactory(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { String sortRecordClass = @@ -321,7 +307,7 @@ final class Sort extends Instruction implements Closure { boolean needsSortRecordFactory = false; final int nsorts = sortObjects.size(); for (int i = 0; i < nsorts; i++) { - final Sort sort = (Sort) sortObjects.elementAt(i); + final Sort sort = sortObjects.elementAt(i); needsSortRecordFactory |= sort._needsSortRecordFactory; } @@ -429,7 +415,7 @@ final class Sort extends Instruction implements Closure { + "[" + STRING_SIG + ")V"))); // Initialize closure variables in sortRecordFactory - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { final Sort sort = (Sort) sortObjects.get(j); @@ -437,7 +423,7 @@ final class Sort extends Instruction implements Closure { sort._closureVars.size(); for (int i = 0; i < length; i++) { - VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); + VariableRefBase varRef = sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; @@ -455,11 +441,11 @@ final class Sort extends Instruction implements Closure { } } - public static String compileSortRecordFactory(Vector sortObjects, + public static String compileSortRecordFactory(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen, String sortRecordClass) { - final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); + final XSLTC xsltc = (sortObjects.firstElement()).getXSLTC(); final String className = xsltc.getHelperClassName(); final NodeSortRecordFactGenerator sortRecordFactory = @@ -474,15 +460,15 @@ final class Sort extends Instruction implements Closure { // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { - final Sort sort = (Sort) sortObjects.get(j); + final Sort sort = sortObjects.get(j); final int length = (sort._closureVars == null) ? 0 : sort._closureVars.size(); for (int i = 0; i < length; i++) { - final VariableRefBase varRef = (VariableRefBase) sort._closureVars.get(i); + final VariableRefBase varRef = sort._closureVars.get(i); // Discard duplicate variable references if (dups.contains(varRef)) continue; @@ -600,10 +586,10 @@ final class Sort extends Instruction implements Closure { /** * Create a new auxillary class extending NodeSortRecord. */ - private static String compileSortRecord(Vector sortObjects, + private static String compileSortRecord(Vector sortObjects, ClassGenerator classGen, MethodGenerator methodGen) { - final XSLTC xsltc = ((Sort)sortObjects.firstElement()).getXSLTC(); + final XSLTC xsltc = sortObjects.firstElement().getXSLTC(); final String className = xsltc.getHelperClassName(); // This generates a new class for handling this specific sort @@ -619,10 +605,10 @@ final class Sort extends Instruction implements Closure { // Add a new instance variable for each var in closure final int nsorts = sortObjects.size(); - final ArrayList dups = new ArrayList(); + final ArrayList dups = new ArrayList<>(); for (int j = 0; j < nsorts; j++) { - final Sort sort = (Sort) sortObjects.get(j); + final Sort sort = sortObjects.get(j); // Set the name of the inner class in this sort object sort.setInnerClassName(className); @@ -644,8 +630,7 @@ final class Sort extends Instruction implements Closure { } } - MethodGenerator init = compileInit(sortObjects, sortRecord, - cpg, className); + MethodGenerator init = compileInit(sortRecord, cpg, className); MethodGenerator extract = compileExtract(sortObjects, sortRecord, cpg, className); sortRecord.addMethod(init); @@ -660,8 +645,7 @@ final class Sort extends Instruction implements Closure { * collator in the super calls only when the stylesheet specifies a new * language in xsl:sort. */ - private static MethodGenerator compileInit(Vector sortObjects, - NodeSortRecordGenerator sortRecord, + private static MethodGenerator compileInit(NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) { @@ -688,7 +672,7 @@ final class Sort extends Instruction implements Closure { /** * Compiles a method that overloads NodeSortRecord.extractValueFromDOM() */ - private static MethodGenerator compileExtract(Vector sortObjects, + private static MethodGenerator compileExtract(Vector sortObjects, NodeSortRecordGenerator sortRecord, ConstantPoolGen cpg, String className) { @@ -730,7 +714,7 @@ final class Sort extends Instruction implements Closure { // Append all the cases for the switch statment for (int level = 0; level < levels; level++) { match[level] = level; - final Sort sort = (Sort)sortObjects.elementAt(level); + final Sort sort = sortObjects.elementAt(level); target[level] = il.append(NOP); sort.translateSelect(sortRecord, extractMethod); il.append(ARETURN); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java index bfa00213915..3b921a1b815 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/SyntaxTreeNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SyntaxTreeNode.java,v 1.6 2006/06/06 22:34:33 spericas Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -519,9 +516,9 @@ public abstract class SyntaxTreeNode implements Constants { // references falling out-of-scope inside the for-each element. // (the cause of which being 'lazy' register allocation for references) for (int i = 0; i < n; i++) { - if( _contents.get(i) instanceof VariableBase) { + if ( _contents.get(i) instanceof VariableBase) { final VariableBase var = (VariableBase)_contents.get(i); - var.unmapRegister(methodGen); + var.unmapRegister(classGen, methodGen); } } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java index 9450702c90c..9284f2a03a3 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/Template.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: Template.java,v 1.2.4.1 2005/09/12 11:30:11 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; @@ -63,7 +60,7 @@ public final class Template extends TopLevelElement { // The list of parameters in this template. This is only used // for simple named templates. - private Vector _parameters = new Vector(); + private Vector _parameters = new Vector<>(); public boolean hasParams() { return _parameters.size() > 0; @@ -85,7 +82,7 @@ public final class Template extends TopLevelElement { _parameters.addElement(param); } - public Vector getParameters() { + public Vector getParameters() { return _parameters; } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java index 7ef4c1cabd6..02e1a5f3ef4 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/VariableBase.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,18 +16,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: VariableBase.java,v 1.5 2005/09/28 13:48:18 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; import java.util.Vector; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; import com.sun.org.apache.bcel.internal.generic.Instruction; import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKESPECIAL; +import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.bcel.internal.generic.NEW; import com.sun.org.apache.bcel.internal.generic.PUSH; @@ -36,6 +35,7 @@ import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.MethodGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.NodeSetType; +import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ResultTreeType; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Type; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.Util; import com.sun.org.apache.xml.internal.utils.XML11Char; @@ -49,21 +49,18 @@ import com.sun.org.apache.xml.internal.utils.XML11Char; */ class VariableBase extends TopLevelElement { - protected QName _name; // The name of the variable. - protected String _escapedName; // The escaped qname of the variable. - protected Type _type; // The type of this variable. - protected boolean _isLocal; // True if the variable is local. - protected LocalVariableGen _local; // Reference to JVM variable - protected Instruction _loadInstruction; // Instruction to load JVM variable + protected QName _name; // The name of the variable. + protected String _escapedName; // The escaped qname of the variable. + protected Type _type; // The type of this variable. + protected boolean _isLocal; // True if the variable is local. + protected LocalVariableGen _local; // Reference to JVM variable + protected Instruction _loadInstruction; // Instruction to load JVM variable protected Instruction _storeInstruction; // Instruction to load JVM variable - protected Expression _select; // Reference to variable expression - protected String select; // Textual repr. of variable expr. + protected Expression _select; // Reference to variable expression + protected String select; // Textual repr. of variable expr. // References to this variable (when local) - protected Vector _refs = new Vector(2); - - // Dependencies to other variables/parameters (for globals only) - protected Vector _dependencies = null; + protected Vector _refs = new Vector<>(2); // Used to make sure parameter field is not added twice protected boolean _ignore = false; @@ -92,7 +89,7 @@ class VariableBase extends TopLevelElement { public void copyReferences(VariableBase var) { final int size = _refs.size(); for (int i = 0; i < size; i++) { - var.addReference((VariableRefBase) _refs.get(i)); + var.addReference(_refs.get(i)); } } @@ -112,8 +109,24 @@ class VariableBase extends TopLevelElement { * Remove the mapping of this variable to a register. * Called when we leave the AST scope of the variable's declaration */ - public void unmapRegister(MethodGenerator methodGen) { + public void unmapRegister(ClassGenerator classGen, MethodGenerator methodGen) { if (_local != null) { + if (_type instanceof ResultTreeType) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + if (classGen.getStylesheet().callsNodeset() && classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeDA = cpg.addMethodref(MULTI_DOM_CLASS, "removeDOMAdapter", "(" + DOM_ADAPTER_SIG + ")V"); + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(loadInstruction()); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeDA)); + } + final int release = cpg.addInterfaceMethodref(DOM_IMPL_CLASS, "release", "()V"); + il.append(loadInstruction()); + il.append(new INVOKEINTERFACE(release, 1)); + } + _local.setEnd(methodGen.getInstructionList().getEnd()); methodGen.removeLocalVariable(_local); _refs = null; @@ -126,7 +139,6 @@ class VariableBase extends TopLevelElement { * the JVM stack. */ public Instruction loadInstruction() { - final Instruction instr = _loadInstruction; if (_loadInstruction == null) { _loadInstruction = _type.LOAD(_local.getIndex()); } @@ -138,7 +150,6 @@ class VariableBase extends TopLevelElement { * into this variable. */ public Instruction storeInstruction() { - final Instruction instr = _storeInstruction; if (_storeInstruction == null) { _storeInstruction = _type.STORE(_local.getIndex()); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java index 3a87d59313c..fc2b202ceea 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/WithParam.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 2001-2004 The Apache Software Foundation. @@ -17,15 +16,17 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: WithParam.java,v 1.2.4.1 2005/09/12 11:38:01 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.compiler; +import com.sun.org.apache.bcel.internal.generic.ALOAD; +import com.sun.org.apache.bcel.internal.generic.ASTORE; +import com.sun.org.apache.bcel.internal.generic.CHECKCAST; import com.sun.org.apache.bcel.internal.generic.ConstantPoolGen; +import com.sun.org.apache.bcel.internal.generic.INVOKEINTERFACE; import com.sun.org.apache.bcel.internal.generic.INVOKEVIRTUAL; import com.sun.org.apache.bcel.internal.generic.InstructionList; +import com.sun.org.apache.bcel.internal.generic.LocalVariableGen; import com.sun.org.apache.bcel.internal.generic.PUSH; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ClassGenerator; import com.sun.org.apache.xalan.internal.xsltc.compiler.util.ErrorMsg; @@ -59,6 +60,11 @@ final class WithParam extends Instruction { */ private Expression _select; + /** + * Reference to JVM variable holding temporary result tree. + */ + private LocalVariableGen _domAdapter; + /** * %OPT% This is set to true when the WithParam is used in a CallTemplate * for a simple named template. If this is true, the parameters are @@ -164,8 +170,13 @@ final class WithParam extends Instruction { _select.startIterator(classGen, methodGen); } // If not, compile result tree from parameter body if present. + // Store result tree into local variable for releasing it later else if (hasContents()) { + final InstructionList il = methodGen.getInstructionList(); compileResultTree(classGen, methodGen); + _domAdapter = methodGen.addLocalVariable2("@" + _escapedName, Type.ResultTree.toJCType(), il.getEnd()); + il.append(DUP); + il.append(new ASTORE(_domAdapter.getIndex())); } // If neither are present then store empty string in parameter slot else { @@ -208,4 +219,26 @@ final class WithParam extends Instruction { ADD_PARAMETER_SIG))); il.append(POP); // cleanup stack } + + /** + * Release the compiled result tree. + */ + public void releaseResultTree(ClassGenerator classGen, MethodGenerator methodGen) { + if (_domAdapter != null) { + final ConstantPoolGen cpg = classGen.getConstantPool(); + final InstructionList il = methodGen.getInstructionList(); + if (classGen.getStylesheet().callsNodeset() && classGen.getDOMClass().equals(MULTI_DOM_CLASS)) { + final int removeDA = cpg.addMethodref(MULTI_DOM_CLASS, "removeDOMAdapter", "(" + DOM_ADAPTER_SIG + ")V"); + il.append(methodGen.loadDOM()); + il.append(new CHECKCAST(cpg.addClass(MULTI_DOM_CLASS))); + il.append(new ALOAD(_domAdapter.getIndex())); + il.append(new CHECKCAST(cpg.addClass(DOM_ADAPTER_CLASS))); + il.append(new INVOKEVIRTUAL(removeDA)); + } + final int release = cpg.addInterfaceMethodref(DOM_IMPL_CLASS, "release", "()V"); + il.append(new ALOAD(_domAdapter.getIndex())); + il.append(new INVOKEINTERFACE(release, 1)); + _domAdapter = null; + } + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java index fc1b1d9412c..cb50cf5d779 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/AdaptiveResultTreeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: AdaptiveResultTreeImpl.java,v 1.2.4.1 2005/09/06 05:52:18 pvedula Exp $ - */ + package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.DOM; @@ -1338,4 +1336,11 @@ public class AdaptiveResultTreeImpl extends SimpleResultTreeImpl } } + public void release() { + if (_dom != null) { + _dom.release(); + _dom = null; + } + super.release(); + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java index a12d9e42c85..4f44ae1baa6 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/DOMAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: DOMAdapter.java,v 1.2.4.1 2005/09/06 06:07:28 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.dom; @@ -56,8 +53,6 @@ public final class DOMAdapter implements DOM { private short[] _NSmapping = null; private short[] _NSreverse = null; - private StripFilter _filter = null; - private int _multiDOMMask; public DOMAdapter(DOM dom, @@ -165,9 +160,7 @@ public final class DOMAdapter implements DOM { } } - public void setFilter(StripFilter filter) { - _filter = filter; - } + public void setFilter(StripFilter filter) {} public DTMAxisIterator getTypedChildren(final int type) { final int[] reverse = getReverse(); @@ -464,4 +457,8 @@ public final class DOMAdapter implements DOM { public Map getElementsWithIDs() { return _dom.getElementsWithIDs(); } + + public void release() { + _dom.release(); + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java index fae254fabc8..cf22c31920f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/MultiDOM.java @@ -1,7 +1,6 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ - /* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with @@ -30,8 +29,8 @@ import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; import com.sun.org.apache.xml.internal.dtm.DTMManager; import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIteratorBase; -import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; import com.sun.org.apache.xml.internal.dtm.ref.DTMAxisIterNodeList; +import com.sun.org.apache.xml.internal.dtm.ref.DTMDefaultBase; import com.sun.org.apache.xml.internal.serializer.SerializationHandler; import com.sun.org.apache.xml.internal.utils.SuballocatedIntVector; import java.util.HashMap; @@ -671,4 +670,51 @@ public final class MultiDOM implements DOM { public Map getElementsWithIDs() { return _main.getElementsWithIDs(); } + + public void release() { + _main.release(); + } + + private boolean isMatchingAdapterEntry(DOM entry, DOMAdapter adapter) { + DOM dom = adapter.getDOMImpl(); + + return (entry == adapter) || ( + /* + * Method addDOMAdapter overwrites for AdaptiveResultTreeImpl + * objects the usual entry with an adapter to the nested + * DOM, so we must check this here. See last 'if' statement + * of addDOMAdapter. + */ + (dom instanceof AdaptiveResultTreeImpl) && + (entry instanceof DOMAdapter) && + (((AdaptiveResultTreeImpl)dom).getNestedDOM() == ((DOMAdapter)entry).getDOMImpl()) + ); + } + + public void removeDOMAdapter(DOMAdapter adapter) { + _documents.remove(adapter.getDocumentURI(0)); + DOM dom = adapter.getDOMImpl(); + + if (dom instanceof DTMDefaultBase) { + SuballocatedIntVector ids = ((DTMDefaultBase) dom).getDTMIDs(); + int idsSize = ids.size(); + for (int i = 0; i < idsSize; i++) { + _adapters[ids.elementAt(i) >>> DTMManager.IDENT_DTM_NODE_BITS] = null; + } + } else { + int id = dom.getDocument() >>> DTMManager.IDENT_DTM_NODE_BITS; + if ((id > 0) && (id < _adapters.length) && isMatchingAdapterEntry(_adapters[id], adapter)) { + _adapters[id] = null; + } else { + boolean found = false; + for (int i = 0; i < _adapters.length; i++) { + if (isMatchingAdapterEntry(_adapters[id], adapter)) { + _adapters[i] = null; + found = true; + break; + } + } + } + } + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java index c6b06931702..9a8bc34892a 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SAXImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -17,9 +17,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SAXImpl.java,v 1.5 2005/09/28 13:48:37 pvedula Exp $ - */ package com.sun.org.apache.xalan.internal.xsltc.dom; @@ -82,7 +79,7 @@ public final class SAXImpl extends SAX2DTM2 // Namespace prefix-to-uri mapping stuff private int _uriCount = 0; - private int _prefixCount = 0; + // private int _prefixCount = 0; // Stack used to keep track of what whitespace text nodes are protected // by xml:space="preserve" attributes and which nodes that are not. @@ -90,11 +87,11 @@ public final class SAXImpl extends SAX2DTM2 private int _idx = 1; private boolean _preserve = false; - private static final String XML_STRING = "xml:"; + // private static final String XML_STRING = "xml:"; private static final String XML_PREFIX = "xml"; private static final String XMLSPACE_STRING = "xml:space"; private static final String PRESERVE_STRING = "preserve"; - private static final String XMLNS_PREFIX = "xmlns"; + // private static final String XMLNS_PREFIX = "xmlns"; private static final String XML_URI = "http://www.w3.org/XML/1998/namespace"; private boolean _escaping = true; @@ -123,7 +120,7 @@ public final class SAXImpl extends SAX2DTM2 private BitArray _dontEscape = null; // The URI to this document - private String _documentURI = null; + // private String _documentURI = null; static private int _documentURIIndex = 0; // The owner Document when the input source is DOMSource. @@ -143,8 +140,7 @@ public final class SAXImpl extends SAX2DTM2 // Support for access/navigation through org.w3c.dom API private Node[] _nodes; private NodeList[] _nodeLists; - private final static String XML_LANG_ATTRIBUTE = - "http://www.w3.org/XML/1998/namespace:@lang"; + // private final static String XML_LANG_ATTRIBUTE = "http://www.w3.org/XML/1998/namespace:@lang"; /** * Define the origin of the document from which the tree was built @@ -491,6 +487,7 @@ public final class SAXImpl extends SAX2DTM2 /** * Sets up a translet-to-dom type mapping table */ + /* private int[] setupMapping(String[] names, String[] uris, int[] types, int nNames) { // Padding with number of names, because they // may need to be added, i.e for RTFs. See copy03 @@ -502,6 +499,7 @@ public final class SAXImpl extends SAX2DTM2 } return result; } + */ /** * Returns the internal type associated with an expanded QName @@ -1230,9 +1228,6 @@ public final class SAXImpl extends SAX2DTM2 */ public DTMAxisIterator getNamespaceAxisIterator(int axis, int ns) { - - DTMAxisIterator iterator = null; - if (ns == NO_TYPE) { return EMPTYITERATOR; } @@ -1546,7 +1541,6 @@ public final class SAXImpl extends SAX2DTM2 */ public DTMAxisIterator getNthDescendant(int type, int n, boolean includeself) { - DTMAxisIterator source = (DTMAxisIterator) new TypedDescendantIterator(type); return new NthDescendantIterator(n); } @@ -1882,4 +1876,7 @@ public final class SAXImpl extends SAX2DTM2 } } + public void release() { + _dtmManager.release(this, true); + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java index 6739458a94b..812258a8f76 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/dom/SimpleResultTreeImpl.java @@ -1,6 +1,5 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Copyright 1999-2004 The Apache Software Foundation. @@ -17,15 +16,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -/* - * $Id: SimpleResultTreeImpl.java,v 1.2.4.1 2005/09/06 10:09:25 pvedula Exp $ - */ + package com.sun.org.apache.xalan.internal.xsltc.dom; import com.sun.org.apache.xalan.internal.xsltc.DOM; import com.sun.org.apache.xalan.internal.xsltc.StripFilter; import com.sun.org.apache.xalan.internal.xsltc.TransletException; - import com.sun.org.apache.xml.internal.dtm.Axis; import com.sun.org.apache.xml.internal.dtm.DTM; import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator; @@ -1014,4 +1010,12 @@ public class SimpleResultTreeImpl extends EmptySerializer implements DOM, DTM public void migrateTo(DTMManager manager) { } + + public void release() + { + if (_documentID != 0) { + _dtmManager.release(this, true); + _documentID = 0; + } + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java index e3336e3bee4..d6648b75bcb 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XML11DTDScannerImpl.java @@ -97,19 +97,9 @@ import com.sun.org.apache.xerces.internal.xni.XNIException; public class XML11DTDScannerImpl extends XMLDTDScannerImpl { - /** Array of 3 strings. */ - private String[] fStrings = new String[3]; - - /** String. */ - private XMLString fString = new XMLString(); - /** String buffer. */ private XMLStringBuffer fStringBuffer = new XMLStringBuffer(); - /** String buffer. */ - private XMLStringBuffer fStringBuffer2 = new XMLStringBuffer(); - private XMLStringBuffer fStringBuffer3 = new XMLStringBuffer(); - // // Constructors // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java index 591e4601efe..4daa5f0e333 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDTDScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -46,7 +46,6 @@ import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; -import com.sun.xml.internal.stream.Entity; /** * This class is responsible for scanning the declarations found diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java index 1ea57877573..e31e838c8e8 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentFragmentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -23,7 +23,6 @@ package com.sun.org.apache.xerces.internal.impl; import com.sun.xml.internal.stream.XMLBufferListener; import com.sun.xml.internal.stream.XMLEntityStorage; -import com.sun.xml.internal.stream.XMLInputFactoryImpl; import com.sun.xml.internal.stream.dtd.DTDGrammarUtil; import java.io.EOFException; @@ -50,17 +49,11 @@ import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.impl.Constants; import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler; -import com.sun.org.apache.xerces.internal.util.NamespaceSupport; import com.sun.org.apache.xerces.internal.utils.SecuritySupport; -import com.sun.org.apache.xerces.internal.utils.XMLLimitAnalyzer; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.Limit; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager.State; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; -import com.sun.org.apache.xerces.internal.xni.NamespaceContext; -import javax.xml.XMLConstants; import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.events.XMLEvent; /** * @@ -210,12 +203,12 @@ public class XMLDocumentFragmentScannerImpl null, null, null, - EXTERNAL_ACCESS_DEFAULT + null }; private static final char [] cdata = {'[','C','D','A','T','A','['}; static final char [] xmlDecl = {'<','?','x','m','l'}; - private static final char [] endTag = {'<','/'}; + // private static final char [] endTag = {'<','/'}; // debugging /** Debug scanner state. */ @@ -2066,7 +2059,7 @@ public class XMLDocumentFragmentScannerImpl */ String checkAccess(String systemId, String allowedProtocols) throws IOException { String baseSystemId = fEntityScanner.getBaseSystemId(); - String expandedSystemId = fEntityManager.expandSystemId(systemId, baseSystemId,fStrictURI); + String expandedSystemId = XMLEntityManager.expandSystemId(systemId, baseSystemId, fStrictURI); return SecuritySupport.checkAccess(expandedSystemId, allowedProtocols, Constants.ACCESS_EXTERNAL_ALL); } @@ -2602,8 +2595,6 @@ public class XMLDocumentFragmentScannerImpl // // Driver methods // - private boolean fContinueDispatching = true; - private boolean fScanningForMarkup = true; /** * decides the appropriate state of the parser @@ -3266,7 +3257,7 @@ public class XMLDocumentFragmentScannerImpl protected XMLString getString(){ if(fAttributeCacheUsedCount < initialCacheCount || fAttributeCacheUsedCount < attributeValueCache.size()){ - return (XMLString)attributeValueCache.get(fAttributeCacheUsedCount++); + return attributeValueCache.get(fAttributeCacheUsedCount++); } else{ XMLString str = new XMLString(); fAttributeCacheUsedCount++; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java index 5a48b73aa52..7f1bbf10226 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLDocumentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -31,7 +31,6 @@ import com.sun.org.apache.xerces.internal.utils.SecuritySupport; import com.sun.org.apache.xerces.internal.xni.Augmentations; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier; -import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; @@ -224,9 +223,6 @@ public class XMLDocumentScannerImpl /** A DTD Description. */ private final XMLDTDDescription fDTDDescription = new XMLDTDDescription(null, null, null, null, null); - /** String. */ - private XMLString fString = new XMLString(); - private static final char [] DOCTYPE = {'D','O','C','T','Y','P','E'}; private static final char [] COMMENTSTRING = {'-','-'}; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java index ff96275c433..d405a33cdcd 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLEntityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -370,7 +370,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { protected Map fEntities = new HashMap<>(); /** Entity stack. */ - protected Stack fEntityStack = new Stack(); + protected Stack fEntityStack = new Stack<>(); /** Current entity. */ protected Entity.ScannedEntity fCurrentEntity = null; @@ -633,10 +633,10 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { final HTTPInputSource httpInputSource = (HTTPInputSource) xmlInputSource; // set request properties - Iterator propIter = httpInputSource.getHTTPRequestProperties(); + Iterator> propIter = httpInputSource.getHTTPRequestProperties(); while (propIter.hasNext()) { - Map.Entry entry = (Map.Entry) propIter.next(); - urlConnection.setRequestProperty((String) entry.getKey(), (String) entry.getValue()); + Map.Entry entry = propIter.next(); + urlConnection.setRequestProperty(entry.getKey(), entry.getValue()); } // set preference for redirection @@ -1057,7 +1057,6 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { String literalSystemId = resourceIdentifier.getLiteralSystemId(); String baseSystemId = resourceIdentifier.getBaseSystemId(); String expandedSystemId = resourceIdentifier.getExpandedSystemId(); - String namespace = resourceIdentifier.getNamespace(); // if no base systemId given, assume that it's relative // to the systemId of the current scanned entity @@ -2067,14 +2066,6 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { // system id has to be a valid URI if (strict) { - - - // check if there is a system id before - // trying to expand it. - if (systemId == null) { - return null; - } - try { // if it's already an absolute one, return it new URI(systemId); @@ -2968,7 +2959,7 @@ public class XMLEntityManager implements XMLComponent, XMLEntityResolver { if (!fCurrentEntity.xmlDeclChunkRead) { fCurrentEntity.xmlDeclChunkRead = true; - len = fCurrentEntity.DEFAULT_XMLDECL_BUFFER_SIZE; + len = Entity.ScannedEntity.DEFAULT_XMLDECL_BUFFER_SIZE; } return fInputStream.read(b, off, len); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java index 8badd36d876..2cdb0001322 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLNSDocumentScannerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -25,8 +25,6 @@ import com.sun.org.apache.xerces.internal.xni.XMLString; import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidatorFilter; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; -import com.sun.org.apache.xerces.internal.util.XMLAttributesIteratorImpl; -import com.sun.org.apache.xerces.internal.util.XMLStringBuffer; import com.sun.org.apache.xerces.internal.util.XMLSymbols; import com.sun.org.apache.xerces.internal.xni.NamespaceContext; import com.sun.org.apache.xerces.internal.xni.QName; @@ -34,13 +32,9 @@ import com.sun.org.apache.xerces.internal.xni.XNIException; import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager; import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException; import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler; -import com.sun.org.apache.xerces.internal.xni.XMLAttributes; import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource; -import com.sun.org.apache.xerces.internal.util.XMLAttributesImpl; import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamConstants; import javax.xml.stream.events.XMLEvent; /** diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java index 10c484ac3a3..5ead2dd1fc6 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. */ /* @@ -25,7 +25,6 @@ import com.sun.org.apache.xerces.internal.util.Status; import com.sun.xml.internal.stream.XMLEntityStorage; import java.io.IOException; import java.util.ArrayList; -import java.util.HashMap; import javax.xml.stream.events.XMLEvent; import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter; import com.sun.org.apache.xerces.internal.util.SymbolTable; @@ -120,8 +119,8 @@ public abstract class XMLScanner //we should have a feature when set to true computes this value private boolean fNeedNonNormalizedValue = false; - protected ArrayList attributeValueCache = new ArrayList(); - protected ArrayList stringBufferCache = new ArrayList(); + protected ArrayList attributeValueCache = new ArrayList<>(); + protected ArrayList stringBufferCache = new ArrayList<>(); protected int fStringBufferIndex = 0; protected boolean fAttributeCacheInitDone = false; protected int fAttributeCacheUsedCount = 0; @@ -1470,7 +1469,7 @@ public abstract class XMLScanner XMLStringBuffer getStringBuffer(){ if((fStringBufferIndex < initialCacheCount )|| (fStringBufferIndex < stringBufferCache.size())){ - return (XMLStringBuffer)stringBufferCache.get(fStringBufferIndex++); + return stringBufferCache.get(fStringBufferIndex++); }else{ XMLStringBuffer tmpObj = new XMLStringBuffer(); fStringBufferIndex++; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java index f9a9fe309ac..816cdaa4757 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSAttributeChecker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -1172,7 +1172,7 @@ public class XSAttributeChecker { if (max != SchemaSymbols.OCCURRENCE_UNBOUNDED) { // maxOccurLimit is only check in secure mode - if (fSchemaHandler.fSecureProcessing != null) { + if (fSchemaHandler.fSecurityManager != null) { String localName = element.getLocalName(); // The maxOccurs restriction no longer applies to elements @@ -1191,8 +1191,8 @@ public class XSAttributeChecker { if (!optimize) { //Revisit :: IMO this is not right place to check // maxOccurNodeLimit. - int maxOccurNodeLimit = fSchemaHandler.fSecureProcessing.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT); - if (max > maxOccurNodeLimit && !fSchemaHandler.fSecureProcessing.isNoLimit(maxOccurNodeLimit)) { + int maxOccurNodeLimit = fSchemaHandler.fSecurityManager.getLimit(XMLSecurityManager.Limit.MAX_OCCUR_NODE_LIMIT); + if (max > maxOccurNodeLimit && !fSchemaHandler.fSecurityManager.isNoLimit(maxOccurNodeLimit)) { reportSchemaFatalError("MaxOccurLimit", new Object[] {new Integer(maxOccurNodeLimit)}, element); // reset max values in case processing continues on error diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java index 852a09fb87f..d1671179b00 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/traversers/XSDHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -194,6 +194,7 @@ public class XSDHandler { /** Property identifier: entity resolver. */ public static final String ENTITY_RESOLVER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; + /** Property identifier: entity manager. */ protected static final String ENTITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY; @@ -214,16 +215,13 @@ public class XSDHandler { protected static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; - private static final String SECURE_PROCESSING = - Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY; - /** Property identifier: locale. */ protected static final String LOCALE = Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; - /** Property identifier: Security property manager. */ + /** Property identifier: Security property manager. */ private static final String XML_SECURITY_PROPERTY_MANAGER = - Constants.XML_SECURITY_PROPERTY_MANAGER; + Constants.XML_SECURITY_PROPERTY_MANAGER; protected static final boolean DEBUG_NODE_POOL = false; @@ -243,17 +241,12 @@ public class XSDHandler { // as unlikely as possible to cause collisions. public final static String REDEF_IDENTIFIER = "_fn3dktizrknc9pi"; - // - //protected data that can be accessable by any traverser + //protected data that can be accessible by any traverser protected XSDeclarationPool fDeclPool = null; - /** - *

Security manager in effect.

- * - *

Protected to allow access by any traverser.

- */ - protected XMLSecurityManager fSecureProcessing = null; + // the Security manager in effect. + protected XMLSecurityManager fSecurityManager = null; private String fAccessExternalSchema; private String fAccessExternalDTD; @@ -266,27 +259,28 @@ public class XSDHandler { // XSDocumentInfoRegistry we can easily get the corresponding // XSDocumentInfo object. private boolean registryEmpty = true; - private Map fUnparsedAttributeRegistry = new HashMap(); - private Map fUnparsedAttributeGroupRegistry = new HashMap(); - private Map fUnparsedElementRegistry = new HashMap(); - private Map fUnparsedGroupRegistry = new HashMap(); - private Map fUnparsedIdentityConstraintRegistry = new HashMap(); - private Map fUnparsedNotationRegistry = new HashMap(); - private Map fUnparsedTypeRegistry = new HashMap(); + private Map fUnparsedAttributeRegistry = new HashMap<>(); + private Map fUnparsedAttributeGroupRegistry = new HashMap<>(); + private Map fUnparsedElementRegistry = new HashMap<>(); + private Map fUnparsedGroupRegistry = new HashMap<>(); + private Map fUnparsedIdentityConstraintRegistry = new HashMap<>(); + private Map fUnparsedNotationRegistry = new HashMap<>(); + private Map fUnparsedTypeRegistry = new HashMap<>(); // Compensation for the above maps to locate XSDocumentInfo, // Since we may take Schema Element directly, so can not get the // corresponding XSDocumentInfo object just using above maps. - private Map fUnparsedAttributeRegistrySub = new HashMap(); - private Map fUnparsedAttributeGroupRegistrySub = new HashMap(); - private Map fUnparsedElementRegistrySub = new HashMap(); - private Map fUnparsedGroupRegistrySub = new HashMap(); - private Map fUnparsedIdentityConstraintRegistrySub = new HashMap(); - private Map fUnparsedNotationRegistrySub = new HashMap(); - private Map fUnparsedTypeRegistrySub = new HashMap(); + private Map fUnparsedAttributeRegistrySub = new HashMap<>(); + private Map fUnparsedAttributeGroupRegistrySub = new HashMap<>(); + private Map fUnparsedElementRegistrySub = new HashMap<>(); + private Map fUnparsedGroupRegistrySub = new HashMap<>(); + private Map fUnparsedIdentityConstraintRegistrySub = new HashMap<>(); + private Map fUnparsedNotationRegistrySub = new HashMap<>(); + private Map fUnparsedTypeRegistrySub = new HashMap<>(); // Stores XSDocumentInfo (keyed by component name), to check for duplicate // components declared within the same xsd document - private Map fUnparsedRegistriesExt[] = new HashMap[] { + @SuppressWarnings("unchecked") + private Map fUnparsedRegistriesExt[] = new HashMap[] { null, null, // ATTRIBUTE_TYPE null, // ATTRIBUTEGROUP_TYPE @@ -300,17 +294,19 @@ public class XSDHandler { // this map is keyed on by XSDocumentInfo objects. Its values // are Vectors containing the XSDocumentInfo objects d, // ed or d by the key XSDocumentInfo. - private Map fDependencyMap = new HashMap(); + private Map> fDependencyMap = new HashMap<>(); // this map is keyed on by a target namespace. Its values // are Vectors containing namespaces imported by schema documents // with the key target namespace. - // if an imprted schema has absent namespace, the value "null" is stored. - private Map fImportMap = new HashMap(); + // if an imported schema has absent namespace, the value "null" is stored. + private Map fImportMap = new HashMap<> (); + // all namespaces that imports other namespaces // if the importing schema has absent namespace, empty string is stored. // (because the key of a map can't be null.) - private Vector fAllTNSs = new Vector(); + private Vector fAllTNSs = new Vector<>(); + // stores instance document mappings between namespaces and schema hints private Map fLocationPairs = null; @@ -333,7 +329,7 @@ public class XSDHandler { if(ele.getOwnerDocument() instanceof com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM){ documentURI = ((com.sun.org.apache.xerces.internal.impl.xs.opti.SchemaDOM) ele.getOwnerDocument()).getDocumentURI(); } - return documentURI != null ? documentURI : (String) fDoc2SystemId.get(ele); + return documentURI != null ? documentURI : fDoc2SystemId.get(ele); } // This vector stores strings which are combinations of the @@ -341,11 +337,11 @@ public class XSDHandler { // schema document. This combination is used so that the user's // EntityResolver can provide a consistent way of identifying a // schema document that is included in multiple other schemas. - private Map fTraversed = new HashMap(); + private Map fTraversed = new HashMap<>(); // this map contains a mapping from Schema Element to its systemId // this is useful to resolve a uri relative to the referring document - private Map fDoc2SystemId = new HashMap(); + private Map fDoc2SystemId = new HashMap<>(); // the primary XSDocumentInfo we were called to parse private XSDocumentInfo fRoot = null; @@ -387,7 +383,15 @@ public class XSDHandler { // the XMLErrorReporter private XMLErrorReporter fErrorReporter; - private XMLEntityResolver fEntityResolver; + + // the XMLErrorHandler + private XMLErrorHandler fErrorHandler; + + // the Locale + private Locale fLocale; + + // the XMLEntityManager + private XMLEntityResolver fEntityManager; // the XSAttributeChecker private XSAttributeChecker fAttributeChecker; @@ -404,6 +408,9 @@ public class XSDHandler { // the Grammar Pool private XMLGrammarPool fGrammarPool; + // the security property manager + private XMLSecurityPropertyManager fSecurityPropertyMgr = null; + //************ Traversers ********** XSDAttributeGroupTraverser fAttributeGroupTraverser; XSDAttributeTraverser fAttributeTraverser; @@ -638,7 +645,7 @@ public class XSDHandler { // for all grammars with s for (int i = fAllTNSs.size() - 1; i >= 0; i--) { // get its target namespace - String tns = (String)fAllTNSs.elementAt(i); + String tns = fAllTNSs.elementAt(i); // get all namespaces it imports Vector ins = (Vector)fImportMap.get(tns); // get the grammar @@ -696,12 +703,13 @@ public class XSDHandler { fAnnotationValidator.setFeature(VALIDATION, true); fAnnotationValidator.setFeature(XMLSCHEMA_VALIDATION, true); fAnnotationValidator.setProperty(XMLGRAMMAR_POOL, fGrammarBucketAdapter); + /** set security manager and XML Security Property Manager **/ + fAnnotationValidator.setProperty(SECURITY_MANAGER, (fSecurityManager != null) ? fSecurityManager : new XMLSecurityManager(true)); + fAnnotationValidator.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); /** Set error handler. **/ - XMLErrorHandler errorHandler = fErrorReporter.getErrorHandler(); - fAnnotationValidator.setProperty(ERROR_HANDLER, (errorHandler != null) ? errorHandler : new DefaultErrorHandler()); + fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); /** Set locale. **/ - Locale locale = fErrorReporter.getLocale(); - fAnnotationValidator.setProperty(LOCALE, locale); + fAnnotationValidator.setProperty(LOCALE, fLocale); } /** @@ -880,10 +888,10 @@ public class XSDHandler { // store the document and its location // REVISIT: don't expose the DOM tree - sg.addDocument(null, (String)fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); + sg.addDocument(null, fDoc2SystemId.get(currSchemaInfo.fSchemaElement)); fDoc2XSDocumentMap.put(schemaRoot, currSchemaInfo); - Vector dependencies = new Vector(); + Vector dependencies = new Vector<>(); Element rootNode = schemaRoot; Element newSchemaRoot = null; @@ -1334,9 +1342,9 @@ public class XSDHandler { } // end for // now we're done with this one! - DOMUtil.setHidden(currDoc, fHiddenNodes); + DOMUtil.setHidden(currDoc, fHiddenNodes); // now add the schemas this guy depends on - Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); + Vector currSchemaDepends = fDependencyMap.get(currSchemaDoc); for (int i = 0; i < currSchemaDepends.size(); i++) { schemasToProcess.push(currSchemaDepends.elementAt(i)); } @@ -1466,7 +1474,7 @@ public class XSDHandler { DOMUtil.setHidden(currDoc, fHiddenNodes); // now add the schemas this guy depends on - Vector currSchemaDepends = (Vector)fDependencyMap.get(currSchemaDoc); + Vector currSchemaDepends = fDependencyMap.get(currSchemaDoc); for (int i = 0; i < currSchemaDepends.size(); i++) { schemasToProcess.push(currSchemaDepends.elementAt(i)); } @@ -1915,7 +1923,7 @@ public class XSDHandler { } public String schemaDocument2SystemId(XSDocumentInfo schemaDoc) { - return (String)fDoc2SystemId.get(schemaDoc.fSchemaElement); + return fDoc2SystemId.get(schemaDoc.fSchemaElement); } // This method determines whether there is a group @@ -2044,7 +2052,7 @@ public class XSDHandler { XMLInputSource schemaSource = null; try { Map pairs = usePairs ? fLocationPairs : Collections.emptyMap(); - schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); + schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager); } catch (IOException ex) { if (mustResolve) { @@ -2097,7 +2105,7 @@ public class XSDHandler { XMLInputSource schemaSource = null; try { Map pairs = usePairs ? fLocationPairs : Collections.emptyMap(); - schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityResolver); + schemaSource = XMLSchemaLoader.resolveDocument(desc, pairs, fEntityManager); } catch (IOException ex) { if (mustResolve) { @@ -2152,7 +2160,7 @@ public class XSDHandler { if (referType != XSDDescription.CONTEXT_PREPARSE){ schemaId = XMLEntityManager.expandSystemId(schemaSource.getSystemId(), schemaSource.getBaseSystemId(), false); key = new XSDKey(schemaId, referType, schemaNamespace); - if((schemaElement = (Element)fTraversed.get(key)) != null) { + if((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -2211,7 +2219,7 @@ public class XSDHandler { if (referType != XSDDescription.CONTEXT_PREPARSE) { schemaId = XMLEntityManager.expandSystemId(inputSource.getSystemId(), schemaSource.getBaseSystemId(), false); key = new XSDKey(schemaId, referType, schemaNamespace); - if ((schemaElement = (Element) fTraversed.get(key)) != null) { + if ((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -2238,9 +2246,8 @@ public class XSDHandler { namespacePrefixes = true; // If this is a Xerces SAX parser set the security manager if there is one if (parser instanceof SAXParser) { - Object securityManager = fSchemaParser.getProperty(SECURITY_MANAGER); - if (securityManager != null) { - parser.setProperty(SECURITY_MANAGER, securityManager); + if (fSecurityManager != null) { + parser.setProperty(SECURITY_MANAGER, fSecurityManager); } } } @@ -2347,7 +2354,7 @@ public class XSDHandler { } if (isDocument) { key = new XSDKey(schemaId, referType, schemaNamespace); - if ((schemaElement = (Element) fTraversed.get(key)) != null) { + if ((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -2402,7 +2409,7 @@ public class XSDHandler { } if (isDocument) { key = new XSDKey(schemaId, referType, schemaNamespace); - if ((schemaElement = (Element) fTraversed.get(key)) != null) { + if ((schemaElement = fTraversed.get(key)) != null) { fLastSchemaWasDuplicate = true; return schemaElement; } @@ -3502,40 +3509,21 @@ public class XSDHandler { // set symbol table fSymbolTable = (SymbolTable) componentManager.getProperty(SYMBOL_TABLE); - fSecureProcessing = null; - if( componentManager!=null ) { - fSecureProcessing = (XMLSecurityManager) componentManager.getProperty(SECURE_PROCESSING, null); - } + // set security manager + fSecurityManager = (XMLSecurityManager) componentManager.getProperty(SECURITY_MANAGER, null); + + //set entity manager + fEntityManager = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER); //set entity resolver - fEntityResolver = (XMLEntityResolver) componentManager.getProperty(ENTITY_MANAGER); XMLEntityResolver er = (XMLEntityResolver)componentManager.getProperty(ENTITY_RESOLVER); if (er != null) fSchemaParser.setEntityResolver(er); // set error reporter - fErrorReporter = - (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); - try { - XMLErrorHandler currErrorHandler = fErrorReporter.getErrorHandler(); - // Setting a parser property can be much more expensive - // than checking its value. Don't set the ERROR_HANDLER - // or LOCALE properties unless they've actually changed. - if (currErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { - fSchemaParser.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); - if (fAnnotationValidator != null) { - fAnnotationValidator.setProperty(ERROR_HANDLER, (currErrorHandler != null) ? currErrorHandler : new DefaultErrorHandler()); - } - } - Locale currentLocale = fErrorReporter.getLocale(); - if (currentLocale != fSchemaParser.getProperty(LOCALE)) { - fSchemaParser.setProperty(LOCALE, currentLocale); - if (fAnnotationValidator != null) { - fAnnotationValidator.setProperty(LOCALE, currentLocale); - } - } - } - catch (XMLConfigurationException e) {} + fErrorReporter = (XMLErrorReporter) componentManager.getProperty(ERROR_REPORTER); + fErrorHandler = fErrorReporter.getErrorHandler(); + fLocale = fErrorReporter.getLocale(); fValidateAnnotations = componentManager.getFeature(VALIDATE_ANNOTATIONS, false); fHonourAllSchemaLocations = componentManager.getFeature(HONOUR_ALL_SCHEMALOCATIONS, false); @@ -3543,56 +3531,66 @@ public class XSDHandler { fTolerateDuplicates = componentManager.getFeature(TOLERATE_DUPLICATES, false); try { - fSchemaParser.setFeature( - CONTINUE_AFTER_FATAL_ERROR, - fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); - } catch (XMLConfigurationException e) { + // Setting a parser property can be much more expensive + // than checking its value. Don't set the ERROR_HANDLER + // or LOCALE properties unless they've actually changed. + if (fErrorHandler != fSchemaParser.getProperty(ERROR_HANDLER)) { + fSchemaParser.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); + if (fAnnotationValidator != null) { + fAnnotationValidator.setProperty(ERROR_HANDLER, (fErrorHandler != null) ? fErrorHandler : new DefaultErrorHandler()); + } + } + if (fLocale != fSchemaParser.getProperty(LOCALE)) { + fSchemaParser.setProperty(LOCALE, fLocale); + if (fAnnotationValidator != null) { + fAnnotationValidator.setProperty(LOCALE, fLocale); + } + } } + catch (XMLConfigurationException e) {} + + try { + fSchemaParser.setFeature(CONTINUE_AFTER_FATAL_ERROR, fErrorReporter.getFeature(CONTINUE_AFTER_FATAL_ERROR)); + } catch (XMLConfigurationException e) {} try { if (componentManager.getFeature(ALLOW_JAVA_ENCODINGS, false)) { fSchemaParser.setFeature(ALLOW_JAVA_ENCODINGS, true); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} + try { if (componentManager.getFeature(STANDARD_URI_CONFORMANT_FEATURE, false)) { fSchemaParser.setFeature(STANDARD_URI_CONFORMANT_FEATURE, true); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} try { - fGrammarPool = - (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); + fGrammarPool = (XMLGrammarPool) componentManager.getProperty(XMLGRAMMAR_POOL); } catch (XMLConfigurationException e) { fGrammarPool = null; } + // security features try { if (componentManager.getFeature(DISALLOW_DOCTYPE, false)) { fSchemaParser.setFeature(DISALLOW_DOCTYPE, true); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} + try { - Object security = componentManager.getProperty(SECURITY_MANAGER, null); - if (security != null){ - fSchemaParser.setProperty(SECURITY_MANAGER, security); + if (fSecurityManager != null) { + fSchemaParser.setProperty(SECURITY_MANAGER, fSecurityManager); } - } catch (XMLConfigurationException e) { - } + } catch (XMLConfigurationException e) {} + + fSecurityPropertyMgr = (XMLSecurityPropertyManager) componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); - XMLSecurityPropertyManager securityPropertyMgr = (XMLSecurityPropertyManager) - componentManager.getProperty(XML_SECURITY_PROPERTY_MANAGER); //Passing on the setting to the parser - fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, securityPropertyMgr); + fSchemaParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); - fAccessExternalDTD = securityPropertyMgr.getValue( - XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD); - - fAccessExternalSchema = securityPropertyMgr.getValue( - XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); + fAccessExternalDTD = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD); + fAccessExternalSchema = fSecurityPropertyMgr.getValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA); } // reset(XMLComponentManager) @@ -4051,7 +4049,7 @@ public class XSDHandler { so long as there's some include/import/redefine path amongst them. If they rver reverse this decision the code's right here though... - neilg // now look in fDependencyMap to see if this is reachable - if(((Vector)fDependencyMap.get(currSchema)).contains(declDocInfo)) { + if((fDependencyMap.get(currSchema)).contains(declDocInfo)) { return declDocInfo; } // obviously the requesting doc didn't include, redefine or @@ -4072,9 +4070,9 @@ public class XSDHandler { if (DOMUtil.isHidden(startSchema.fSchemaElement, fHiddenNodes)) { // make it visible DOMUtil.setVisible(startSchema.fSchemaElement, fHiddenNodes); - Vector dependingSchemas = (Vector)fDependencyMap.get(startSchema); + Vector dependingSchemas = fDependencyMap.get(startSchema); for (int i = 0; i < dependingSchemas.size(); i++) { - setSchemasVisible((XSDocumentInfo)dependingSchemas.elementAt(i)); + setSchemasVisible(dependingSchemas.elementAt(i)); } } // if it's visible already than so must be its children @@ -4107,7 +4105,7 @@ public class XSDHandler { ElementImpl ele = (ElementImpl)e; // get system id from document object Document doc = ele.getOwnerDocument(); - String sid = (String)fDoc2SystemId.get(DOMUtil.getRoot(doc)); + String sid = fDoc2SystemId.get(DOMUtil.getRoot(doc)); // line/column numbers are stored in the element node int line = ele.getLineNumber(); int column = ele.getColumnNumber(); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java index 459067067a1..3c4dd4f810e 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -52,7 +52,6 @@ import com.sun.org.apache.xerces.internal.util.FeatureState; import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings; import com.sun.org.apache.xerces.internal.util.PropertyState; import com.sun.org.apache.xerces.internal.util.SymbolTable; -import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager; import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager; import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler; import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler; @@ -166,59 +165,57 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String USE_GRAMMAR_POOL_ONLY = Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; - // feature identifiers + // feature identifiers - /** Feature identifier: validation. */ - protected static final String VALIDATION = - Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; + /** Feature identifier: validation. */ + protected static final String VALIDATION = + Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; - /** Feature identifier: namespaces. */ - protected static final String NAMESPACES = - Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; + /** Feature identifier: namespaces. */ + protected static final String NAMESPACES = + Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE; - /** Feature identifier: external general entities. */ - protected static final String EXTERNAL_GENERAL_ENTITIES = - Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE; + /** Feature identifier: external general entities. */ + protected static final String EXTERNAL_GENERAL_ENTITIES = + Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE; - /** Feature identifier: external parameter entities. */ - protected static final String EXTERNAL_PARAMETER_ENTITIES = - Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; + /** Feature identifier: external parameter entities. */ + protected static final String EXTERNAL_PARAMETER_ENTITIES = + Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; - /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ - protected static final String IGNORE_XSI_TYPE = - Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; - /** Feature identifier: whether to ignore ID/IDREF errors */ - protected static final String ID_IDREF_CHECKING = - Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; - /** Feature identifier: whether to ignore unparsed entity errors */ - protected static final String UNPARSED_ENTITY_CHECKING = - Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; - /** Feature identifier: whether to ignore identity constraint errors */ - protected static final String IDENTITY_CONSTRAINT_CHECKING = - Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; // property identifiers + /** Property identifier: xml string. */ + protected static final String XML_STRING = + Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY; - /** Property identifier: xml string. */ - protected static final String XML_STRING = - Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY; + /** Property identifier: symbol table. */ + protected static final String SYMBOL_TABLE = + Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; - /** Property identifier: symbol table. */ - protected static final String SYMBOL_TABLE = - Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY; - - /** Property identifier: error handler. */ - protected static final String ERROR_HANDLER = - Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; - - /** Property identifier: entity resolver. */ - protected static final String ENTITY_RESOLVER = - Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; + /** Property identifier: error handler. */ + protected static final String ERROR_HANDLER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY; + /** Property identifier: entity resolver. */ + protected static final String ENTITY_RESOLVER = + Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY; /** Property identifier: XML Schema validator. */ protected static final String SCHEMA_VALIDATOR = @@ -232,8 +229,6 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String SCHEMA_NONS_LOCATION = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION; - // property identifiers - /** Property identifier: error reporter. */ protected static final String ERROR_REPORTER = Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY; @@ -313,33 +308,33 @@ public class XML11Configuration extends ParserConfigurationSettings // Data // - protected SymbolTable fSymbolTable; + protected SymbolTable fSymbolTable; protected XMLInputSource fInputSource; protected ValidationManager fValidationManager; - protected XMLVersionDetector fVersionDetector; + protected XMLVersionDetector fVersionDetector; protected XMLLocator fLocator; - protected Locale fLocale; + protected Locale fLocale; - /** XML 1.0 Components. */ - protected ArrayList fComponents; + /** XML 1.0 Components. */ + protected ArrayList fComponents; - /** XML 1.1. Components. */ - protected ArrayList fXML11Components = null; + /** XML 1.1. Components. */ + protected ArrayList fXML11Components = null; - /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */ - protected ArrayList fCommonComponents = null; + /** Common components: XMLEntityManager, XMLErrorReporter, XMLSchemaValidator */ + protected ArrayList fCommonComponents = null; - /** The document handler. */ - protected XMLDocumentHandler fDocumentHandler; + /** The document handler. */ + protected XMLDocumentHandler fDocumentHandler; - /** The DTD handler. */ - protected XMLDTDHandler fDTDHandler; + /** The DTD handler. */ + protected XMLDTDHandler fDTDHandler; - /** The DTD content model handler. */ - protected XMLDTDContentModelHandler fDTDContentModelHandler; + /** The DTD content model handler. */ + protected XMLDTDContentModelHandler fDTDContentModelHandler; - /** Last component in the document pipeline */ - protected XMLDocumentSource fLastComponent; + /** Last component in the document pipeline */ + protected XMLDocumentSource fLastComponent; /** * True if a parse is in progress. This state is needed because @@ -477,15 +472,15 @@ public class XML11Configuration extends ParserConfigurationSettings // create a vector to hold all the components in use // XML 1.0 specialized components - fComponents = new ArrayList(); + fComponents = new ArrayList<>(); // XML 1.1 specialized components - fXML11Components = new ArrayList(); + fXML11Components = new ArrayList<>(); // Common components for XML 1.1. and XML 1.0 - fCommonComponents = new ArrayList(); + fCommonComponents = new ArrayList<>(); // create table for features and properties - fFeatures = new HashMap(); - fProperties = new HashMap(); + fFeatures = new HashMap<>(); + fProperties = new HashMap<>(); // add default recognized features final String[] recognizedFeatures = @@ -580,35 +575,35 @@ public class XML11Configuration extends ParserConfigurationSettings } fEntityManager = new XMLEntityManager(); - fProperties.put(ENTITY_MANAGER, fEntityManager); + fProperties.put(ENTITY_MANAGER, fEntityManager); addCommonComponent(fEntityManager); fErrorReporter = new XMLErrorReporter(); fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner()); - fProperties.put(ERROR_REPORTER, fErrorReporter); + fProperties.put(ERROR_REPORTER, fErrorReporter); addCommonComponent(fErrorReporter); fNamespaceScanner = new XMLNSDocumentScannerImpl(); - fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner); + fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner); addComponent((XMLComponent) fNamespaceScanner); fDTDScanner = new XMLDTDScannerImpl(); - fProperties.put(DTD_SCANNER, fDTDScanner); + fProperties.put(DTD_SCANNER, fDTDScanner); addComponent((XMLComponent) fDTDScanner); fDTDProcessor = new XMLDTDProcessor(); - fProperties.put(DTD_PROCESSOR, fDTDProcessor); + fProperties.put(DTD_PROCESSOR, fDTDProcessor); addComponent((XMLComponent) fDTDProcessor); fDTDValidator = new XMLNSDTDValidator(); - fProperties.put(DTD_VALIDATOR, fDTDValidator); + fProperties.put(DTD_VALIDATOR, fDTDValidator); addComponent(fDTDValidator); fDatatypeValidatorFactory = DTDDVFactory.getInstance(); - fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory); + fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory); fValidationManager = new ValidationManager(); - fProperties.put(VALIDATION_MANAGER, fValidationManager); + fProperties.put(VALIDATION_MANAGER, fValidationManager); fVersionDetector = new XMLVersionDetector(); @@ -935,20 +930,20 @@ public class XML11Configuration extends ParserConfigurationSettings // forward to every XML 1.0 component int count = fComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fComponents.get(i); + XMLComponent c = fComponents.get(i); c.setFeature(featureId, state); } // forward it to common components count = fCommonComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fCommonComponents.get(i); + XMLComponent c = fCommonComponents.get(i); c.setFeature(featureId, state); } // forward to every XML 1.1 component count = fXML11Components.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fXML11Components.get(i); + XMLComponent c = fXML11Components.get(i); try{ c.setFeature(featureId, state); } @@ -996,19 +991,19 @@ public class XML11Configuration extends ParserConfigurationSettings // forward to every XML 1.0 component int count = fComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fComponents.get(i); + XMLComponent c = fComponents.get(i); c.setProperty(propertyId, value); } // forward it to every common Component count = fCommonComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fCommonComponents.get(i); + XMLComponent c = fCommonComponents.get(i); c.setProperty(propertyId, value); } // forward it to every XML 1.1 component count = fXML11Components.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fXML11Components.get(i); + XMLComponent c = fXML11Components.get(i); try{ c.setProperty(propertyId, value); } @@ -1034,7 +1029,7 @@ public class XML11Configuration extends ParserConfigurationSettings protected void reset() throws XNIException { int count = fComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fComponents.get(i); + XMLComponent c = fComponents.get(i); c.reset(this); } @@ -1047,7 +1042,7 @@ public class XML11Configuration extends ParserConfigurationSettings // reset common components int count = fCommonComponents.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fCommonComponents.get(i); + XMLComponent c = fCommonComponents.get(i); c.reset(this); } @@ -1061,7 +1056,7 @@ public class XML11Configuration extends ParserConfigurationSettings // reset every component int count = fXML11Components.size(); for (int i = 0; i < count; i++) { - XMLComponent c = (XMLComponent) fXML11Components.get(i); + XMLComponent c = fXML11Components.get(i); c.reset(this); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java index f4e29a3a856..bdd0750d0fa 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/util/HTTPInputSource.java @@ -51,7 +51,7 @@ public final class HTTPInputSource extends XMLInputSource { protected boolean fFollowRedirects = true; /** HTTP request properties. **/ - protected Map fHTTPRequestProperties = new HashMap(); + protected Map fHTTPRequestProperties = new HashMap<>(); // // Constructors @@ -159,7 +159,7 @@ public final class HTTPInputSource extends XMLInputSource { * been set */ public String getHTTPRequestProperty(String key) { - return (String) fHTTPRequestProperties.get(key); + return fHTTPRequestProperties.get(key); } // getHTTPRequestProperty(String):String /** @@ -172,7 +172,7 @@ public final class HTTPInputSource extends XMLInputSource { * @return an iterator for the request properties this * input source contains */ - public Iterator getHTTPRequestProperties() { + public Iterator> getHTTPRequestProperties() { return fHTTPRequestProperties.entrySet().iterator(); } // getHTTPRequestProperties():Iterator diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out deleted file mode 100644 index e946a45a944..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341.out +++ /dev/null @@ -1,19 +0,0 @@ - - -10016 -Wed May 29 12:45:00 PDT 2002 - -ABC -XYZ -1234 Anywhere Street -Palo Alto -California -USA -94303 -NULL -NULL - - - - - \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java index f0dc71feb5a..8daef2e5cce 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ package transform; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; import java.net.URL; import javax.xml.parsers.SAXParser; @@ -45,16 +46,27 @@ import org.xml.sax.helpers.DefaultHandler; * @summary Test transform with external dtd. */ public class Bug4693341Test { + // save dtd file to current working directory to avoid writing into source repository + public void copyDTDtoWorkDir() throws IOException { + try (FileInputStream dtdres = new FileInputStream(getClass().getResource("Bug4693341.dtd").getPath()); + FileOutputStream dtdwork = new FileOutputStream("Bug4693341.dtd");) { + int n; + byte[] buffer = new byte[1024]; + while((n = dtdres.read(buffer)) > -1) { + dtdwork.write(buffer, 0, n); + } + } + } @Test public void test() { - boolean status = false; - try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); - String out = getClass().getResource("Bug4693341.out").getPath(); - StreamResult result = new StreamResult(new FileOutputStream(out)); + copyDTDtoWorkDir(); + + File outf = new File("Bug4693341.out"); + StreamResult result = new StreamResult(new FileOutputStream(outf)); String in = getClass().getResource("Bug4693341.xml").getPath(); File file = new File(in); @@ -63,7 +75,7 @@ public class Bug4693341Test { transformer.transform(source, result); //URL inputsource = new URL("file", "", golden); - URL output = new URL("file", "", out); + URL output = new URL("file", "", outf.getPath()); // error happens when trying to parse output String systemId = output.toExternalForm(); @@ -71,10 +83,8 @@ public class Bug4693341Test { InputSource is = new InputSource(systemId); SAXParser parser = SAXParserFactory.newInstance().newSAXParser(); parser.parse(is, new DefaultHandler()); - } catch (Exception ex) { Assert.fail(ex.getMessage()); } } - } diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd deleted file mode 100644 index 9e4dd578483..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.dtd +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml deleted file mode 100644 index 5c0928e85ab..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug4693341_golden.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - -10016 -Wed May 29 12:45:00 PDT 2002 - -ABC -XYZ -1234 Anywhere Street -Palo Alto -California -USA -94303 -NULL -NULL - - - - - diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java deleted file mode 100644 index d3fa4fd30f4..00000000000 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug6505031.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package transform; - -import java.io.StringWriter; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.stream.StreamResult; -import javax.xml.transform.stream.StreamSource; - -import org.testng.Assert; -import org.testng.annotations.Test; - -/* - * @bug 6505031 - * @summary Test transformer parses keys and their values coming from different xml documents. - */ -public class Bug6505031 { - - private String getResource(String s) { - return getClass().getResource(s).toString(); - - } - - @Test - public void test() { - Map params = new HashMap(); - - params.put("config", getResource("config.xml")); - params.put("mapsFile", getResource("maps.xml")); - generate(getResource("template.xml"), getResource("transform.xsl"), params); - } - - private void generate(String in, String xsl, Map params) { - try { - Transformer transformer = getTransformer(xsl); - - for (Iterator i = params.entrySet().iterator(); i.hasNext();) { - Map.Entry entry = (Map.Entry) i.next(); - - transformer.setParameter((String) entry.getKey(), entry.getValue()); - } - transform(in, transformer); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - - private Transformer getTransformer(String transform) throws Exception { - TransformerFactory tfactory = TransformerFactory.newInstance(); - - try { - // tfactory.setAttribute("generate-translet", Boolean.TRUE); - } catch (Exception e) { - // Ignore - } - - Transformer transformer = tfactory.newTransformer(new StreamSource(transform)); - return (transformer); - } - - private void transform(String in, Transformer transformer) throws Exception { - StringWriter sw = new StringWriter(); - transformer.transform(new StreamSource(in), new StreamResult(sw)); - String s = sw.toString(); - Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); - } - -} diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref new file mode 100644 index 00000000000..0af2588d894 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.ref @@ -0,0 +1 @@ +................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................ diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml new file mode 100644 index 00000000000..382a25f08fb --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xml @@ -0,0 +1,5 @@ + + + + . + diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl new file mode 100644 index 00000000000..f390323c2f9 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-1.xsl @@ -0,0 +1,76 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref new file mode 100644 index 00000000000..b012e31307c --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.ref @@ -0,0 +1,83 @@ +0fto-erech 200amos-batch 00000000X/ +1FB01 20150709 EWF 2016021207USD 0000,9302122026623 ////////91284422 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007366,71//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D8OOoOOooooOoooooO////15/07 P0480715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40090597 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150630 EWF 2016021206USD 0000,9302122026624 ////////1500006837 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000003844,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////b3oooooooooooooooo////15/07 R1683315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40127254 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207CHF 0001,0000022026625 ////////94043801 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000438,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0CooOooooooooooOOo////15/07 P0472115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30092874 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150702 EWF 2016021207EUR 0001,0468822026626 ////////TL152062 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000661,30//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3coooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150617 EWF 2016021206EUR 0001,0468822026627 ////////TKL100216 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000699,92//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////55oooooOoOooooOoOo////15/07 L0032815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2014686 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150702 EWF 2016021207EUR 0001,0468822026628 ////////TL152063 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001983,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9boooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207EUR 0001,0468822026629 ////////000359084 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002230,76//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////51oOoOoOoOoooooOOO////15/07 R1735915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207CHF 0001,0000022026630 ////////90864081 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001893,20//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////acoooooooooooooooo////15/07 P0470615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090668 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026631 ////////123939 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007896,34//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////09oooooooooooooooo////15/07 P0400015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128846 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207USD 0000,9302122026633 ////////000358117 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000006810,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////f5oooooooooooooooo////15/07 P0462815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40128088 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207CHF 0001,0000022026635 ////////M90257500 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000016300,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////C3oOOOooOoOooOOOoo////15/07 R1488615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207USD 0000,9302122026637 ////////M90257457 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000831,90//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////60ooooOooOOOoOoOoo////15/07 P0463815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000055,22//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0463815 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207USD 0000,9302122026638 ////////M90257509 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002218,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////60OoooooOOooooOooo////15/07 P0491115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000055,22//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0491115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207CHF 0001,0000022026639 ////////M90257515 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000005833,20//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////A6OOooOoOoOooOoooo////15/07 R1575215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026642 ////////C/5 335835 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////16OooooOooOOoOoooo////15/07 R1612715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026643 ////////C/5 335833 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////58OOoOOooooOooOOoo////15/07 R1441715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026644 ////////C/5 336036 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6BooooOOoooOooOooo////15/07 R1659015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026645 ////////C/5 335836 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6DoOoooOooOOoOooOo////15/07 R1613415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026646 ////////C/5 336201 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////74ooOoOooooooooOoO////15/07 R1728915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026647 ////////C/5 336035 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000515,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////86OoooOOoooOoooOOo////15/07 R1612615 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207USD 0000,9302122026648 ////////C/5 336034 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////99OOooooooOooOoooo////15/07 R1445115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207USD 0000,9302122026649 ////////C/5 335834 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000835,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D8OOoooOOOooooOOoo////15/07 R1445315 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126141 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026650 ////////351732 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000192,80//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4BooOooooOOOoOOOOo////15/07 P0448015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026651 ////////351730 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000057,25//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////69ooOoOooooooooooO////15/07 P0451715 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000007,02//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0451715 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150706 EWF 2016021207CHF 0001,0000022026652 ////////351731 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000100,05//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////A9oooooooOoOooOOOo////15/07 P0448015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30090682 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207EUR 0001,0468822026653 ////////05/91014407 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000225,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////22oooOooooOooOooOO////15/07 R1727915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207EUR 0001,0468822026654 ////////05/91015508 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000225,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////24OooooOOoOooOoOoO////15/07 R1728015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150701 EWF 2016021207EUR 0001,0468822026655 ////////05/91015531 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000768,45//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////76oOOOOooOoOooooOO////15/07 W0054415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207USD 0000,9302122026656 ////////SI156008034 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000261,79//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////96OooooOoOoooOOOoo////15/07 P0479215 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40126601 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207EUR 0001,0468822026657 ////////05/91015509 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000705,35//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////99ooOoOOoooooOoooo////15/07 R1625015 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40096899 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150713 EWF 2016021207EUR 0001,0468822026662 ////////55941607 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000725,60//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////4BOoooOOOoOoooooOo////15/07 P0486115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40091085 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150708 EWF 2016021207CHF 0001,0000022026663 ////////100-120606 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000004229,50//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////0boooooooooooooooo////15/07 P0474115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30094003 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000430,56//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0474115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400158 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000054,38//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0474115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150707 EWF 2016021207CHF 0001,0000022026664 ////////13143106 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000318,65//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6eoooooooooooooooo////15/07 P0468115 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30092269 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 40///////////////0000000000014,04//////////////////////////////////////////////// /////////////////////////////////////7000 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////P0468115 ////15/07 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////400122 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150709 EWF 2016021207EUR 0001,0468822026665 ////////TL152315 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001983,90//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////74oooooooooooooooo////15/07 P0431815 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40099751 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150710 EWF 2016021207EUR 0001,0468822026667 ////////11321 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000000840,00//////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////caoooooooooooooooo////15/07 P0471915 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////950//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////40129316 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20150401 EWF 2016021204EUR 0001,0553176278995 ////////76278995 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000007833,33//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////15/04 S0026415 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VERB05001 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20110209 EWF 2016021202CHF 0001,0000090149059 ////////M90149059 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000001077,30//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////11/03 S0080410 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124373 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +1FB01 20110209 EWF 2016021202USD 0000,9570290149062 ////////90149062 ///////////////////////////////////////////////////////////X/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +2BBSEG 31///////////////0000000002185,78//////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////11/03 S0125011 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////566//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////30124374 //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml new file mode 100644 index 00000000000..19a8381e919 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xml @@ -0,0 +1,2438 @@ + + + + 22026623 + + + CRX + CHF + + OPEN + I + V0409 + CAGE1 + 40090597 + + 91284422 + 2015-07-09 + + 2015-07-15 + 2015-07-15 + D8OOoOOooooOoooooOOOOooOoooOoOoo + + 7366.71 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0480715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026624 + + + CRX + CHF + + OPEN + I + V0307 + CAGE2 + 40127254 + + 1500006837 + 2015-06-30 + + 2015-07-16 + 2015-07-16 + b3oooooooooooooooooooooooooooooo + + 3844.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1683315 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-30 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026625 + + + CRX + CHF + + CLOSED + I + V0568 + 30092874 + + 94043801 + 2015-07-09 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 0CooOooooooooooOOoooOooOoOOoooOo + + 438.5 + 190.008 + 0.0 + 0.0 + + 4V + 32.48 + + + + P + P0472115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026626 + + + CRX + CHF + + OPEN + I + V0316 + CAGE3 + 40099751 + + TL152062 + 2015-07-02 + + 2015-07-16 + 2015-07-16 + 3coooooooooooooooooooooooooooooo + + 661.3 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-01 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026627 + + + CRX + CHF + + OPEN + I + V0440 + 2014686 + + TKL100216 + 2015-06-17 + + 2015-07-16 + 2015-07-16 + 55oooooOoOooooOoOoOOOoOOOoooOOoo + + 699.92 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + L + L0032815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-17 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026628 + + + CRX + CHF + + OPEN + I + V0316 + CAGE4 + 40099751 + + TL152063 + 2015-07-02 + + 2015-07-16 + 2015-07-16 + 9boooooooooooooooooooooooooooooo + + 1983.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-01 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026629 + + + CRX + CHF + + OPEN + I + V0506 + 40128088 + + 000359084 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + 51oOoOoOoOoooooOOOoOooooOOoooOoO + + 2230.76 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1735915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026630 + + + CRX + CHF + + OPEN + I + V0497 + 30090668 + + 90864081 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + acoooooooooooooooooooooooooooooo + + 1893.2 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0470615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026631 + + + CRX + CHF + + OPEN + I + V0512 + 40128846 + + 123939 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 09oooooooooooooooooooooooooooooo + + 7896.34 + 0.0 + 0.0 + 0.0 + + TAX + 0.0 + + + + P + P0400015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026633 + + + CRX + CHF + + CLOSED + I + V0202 + 40128088 + + 000358117 + 2015-07-07 + 2015-07-16 + 2015-07-16 + 2015-07-16 + f5oooooooooooooooooooooooooooooo + + 6810.0 + 3187.08 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0462815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026635 + + + CRX + CHF + + OPEN + I + V0011 + 30124373 + + M90257500 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + C3oOOOooOoOooOOOoooOOOoOOoooOoOO + + 16300.5 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1488615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026637 + + + CRX + CHF + + CLOSED + I + V0139 + 30124373 + + M90257457 + 2015-07-13 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 60ooooOooOOOoOoOoooooooOOOOoooOO + + 831.9 + 334.1052 + 118.0 + 0.0 + + V0 + 0.0 + + + + P + P0463815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 55.224 + 55.224 + + V0 + V0 + 0.0 + + + D + + + + 22026638 + + + CRX + CHF + + CLOSED + I + V0139 + 30124373 + + M90257509 + 2015-07-13 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 60OoooooOOooooOoooooooooOOooOOOO + + 2218.0 + 982.8 + 118.0 + 0.0 + + V0 + 0.0 + + + + P + P0491115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 55.224 + 55.224 + + V0 + V0 + 0.0 + + + D + + + + 22026639 + + + CRX + CHF + + OPEN + I + V0162 + 30124373 + + M90257515 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + A6OOooOoOoOooOoooooooooOooooOOoo + + 5833.2 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1575215 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026642 + + + CRX + CHF + + OPEN + I + V0400 + CAGE5 + 40126141 + + C/5 335835 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 16OooooOooOOoOooooOoooooooooooOO + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1612715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026643 + + + CRX + CHF + + OPEN + I + V0400 + CAGE6 + 40126141 + + C/5 335833 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 58OOoOOooooOooOOooOoooOooooOOoOo + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1441715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026644 + + + CRX + CHF + + OPEN + I + V0400 + CAGE7 + 40126141 + + C/5 336036 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 6BooooOOoooOooOooooOooooOoOOoooo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1659015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026645 + + + CRX + CHF + + OPEN + I + V0400 + CAGE8 + 40126141 + + C/5 335836 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + 6DoOoooOooOOoOooOoOoOoOOOoOoOooo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1613415 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026646 + + + CRX + CHF + + OPEN + I + V0400 + CAGE9 + 40126141 + + C/5 336201 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 74ooOoOooooooooOoOOOoOoOooOoooOO + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1728915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026647 + + + CRX + CHF + + OPEN + I + V0400 + CAGEA + 40126141 + + C/5 336035 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 86OoooOOoooOoooOOoOooOoooOOoOoOo + + 515.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1612615 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026648 + + + CRX + CHF + + OPEN + I + V0400 + CAGEB + 40126141 + + C/5 336034 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 99OOooooooOooOooooOooOooOoOOoOoo + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1445115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026649 + + + CRX + CHF + + OPEN + I + V0400 + CAGEC + 40126141 + + C/5 335834 + 2015-07-01 + + 2015-07-16 + 2015-07-16 + D8OOoooOOOooooOOoooOOoOoooOoOOOO + + 835.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1445315 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026650 + + + CRX + CHF + + OPEN + I + V0429 + 30090682 + + 351732 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + 4BooOooooOOOoOOOOooo + + 192.8 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0448015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026651 + + + CRX + CHF + + CLOSED + I + V0429 + 30090682 + + 351730 + 2015-07-06 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 69ooOoOooooooooooOoOooOOOOoooOoO + + 57.25 + 17.784 + 15.0 + 0.0 + + 4V + 4.24 + + + + P + P0451715 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 7.02 + 7.02 + + 4V + 4V + 0.5616 + + + D + + + + 22026652 + + + CRX + CHF + + OPEN + I + V0429 + 30090682 + + 351731 + 2015-07-06 + + 2015-07-16 + 2015-07-16 + A9oooooooOoOooOOOoOO + + 100.05 + 0.0 + 0.0 + 0.0 + + 4V + 0.0 + + + + P + P0448015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-05 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + 22026653 + + + CRX + CHF + + OPEN + I + V0028 + CAGED + 40096899 + + 05/91014407 + 2015-07-07 + + 2015-07-16 + 2015-07-16 + 22oooOooooOooOooOOoOooOoooooOooO + + 225.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1727915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026654 + + + CRX + CHF + + OPEN + I + V0028 + CAGEE + 40096899 + + 05/91015508 + 2015-07-07 + + 2015-07-16 + 2015-07-16 + 24OooooOOoOooOoOoOoOoooOOoOOooOo + + 225.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1728015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026655 + + + CRX + CHF + + CLOSED + I + V0028 + CAGEF + 40096899 + + 05/91015531 + 2015-07-01 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 76oOOOOooOoOooooOOoOoOOooOooOoOO + + 768.45 + 359.6346 + 0.0 + 0.0 + + V0 + 0.0 + + + + W + W0054415 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-07-31 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026656 + + + CRX + CHF + + OPEN + I + V0651 + 40126601 + + SI156008034 + 2015-07-08 + + 2015-07-16 + 2015-07-16 + 96OooooOoOoooOOOoooOOoooOoOOOOoO + + 261.79 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0479215 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + USD + CHF + 0.93021 + + + + + 22026657 + + + CRX + CHF + + CLOSED + I + V0028 + CAGEG + 40096899 + + 05/91015509 + 2015-07-09 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 99ooOoOOoooooOooooOOOOoooOOoOOoO + + 705.35 + 330.1038 + 0.0 + 0.0 + + V0 + 0.0 + + + + R + R1625015 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026662 + + + CRX + CHF + + OPEN + I + V0495 + CAGEH + 40091085 + + 55941607 + 2015-07-13 + + 2015-07-16 + 2015-07-16 + 4BOoooOOOoOoooooOoOOooOooooOoOoo + + 725.6 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0486115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-12 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026663 + + + CRX + CHF + + CLOSED + I + V0604 + 30094003 + + 100-120606 + 2015-07-08 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 0boooooooooooooooooooooooooooooo + + 4229.5 + 1347.84 + 1036.2 + 0.0 + + TAX + 313.3 + + + + P + P0474115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-07 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + H + HANDLING CHARGE + N + N + + 400158 + + 7000 + 7000 + + + 430.56 + 430.56 + + 4V + 4V + 34.4448 + + + D + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 54.3816 + 54.3816 + + 4V + 4V + 4.3524 + + + D + + + + 22026664 + + + CRX + CHF + + CLOSED + I + V0634 + 30092269 + + 13143106 + 2015-07-07 + 2015-07-16 + 2015-07-16 + 2015-07-16 + 6eoooooooooooooooooooooooooooooo + + 318.65 + 124.0434 + 30.0 + 0.0 + + 4V + 23.599999999999998 + + + + P + P0468115 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-06 + 0 + Y + + + 07 + 2015 + + + CHF + CHF + 1.0 + + + + + F + FREIGHT + N + N + + 400122 + + 7000 + 7000 + + + 14.04 + 14.04 + + 4V + 4V + 1.1232 + + + D + + + + 22026665 + + + CRX + CHF + + OPEN + I + V0316 + CAGEI + 40099751 + + TL152315 + 2015-07-09 + + 2015-07-16 + 2015-07-16 + 74oooooooooooooooooooooooooooooo + + 1983.9 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0431815 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-08 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 22026667 + + + CRX + CHF + + OPEN + I + V0642 + 40129316 + + 11321 + 2015-07-10 + + 2015-07-16 + 2015-07-16 + caoooooooooooooooooooooooooooooo + + 840.0 + 0.0 + 0.0 + 0.0 + + V0 + 0.0 + + + + P + P0471915 + + + 2016-02-12 + + Y + + + + 30D + + + + + + 2015-08-09 + 0 + Y + + + 07 + 2015 + + + EUR + CHF + 1.04688 + + + + + 76278995 + + + CRX + CHF + + CLOSED + I + V0166 + CAGEJ + VERB05001 + + 76278995 + 2015-04-01 + 2015-04-17 + 2015-04-17 + 2015-04-17 + + 7833.33 + 3394.4414 + 0.0 + 0.0 + + V0 + 580.25 + + + + S + S0026415 + + + 2016-02-12 + + Y + + + + + + + + + + 2015-04-01 + 0 + Y + + + 04 + 2015 + + + EUR + CHF + 1.05531 + + + + + 90149059 + + + CRX + CHF + + CLOSED + I + V0016 + 30124373 + + M90149059 + 2011-02-09 + 2011-02-18 + 2011-02-18 + 2011-02-18 + + 1077.3 + 504.1764 + 0.0 + 0.0 + + TAX + 0.0 + + + + S + S0080410 + + + 2016-02-12 + + N + + + + 5 + + + + + + 2011-02-09 + 0 + N + + + 03 + 2011 + + + CHF + CHF + 1.0 + + + + + 90149062 + + + CRX + CHF + + CLOSED + I + V0016 + 30124374 + + 90149062 + 2011-02-09 + 2011-02-21 + 2011-02-21 + 2011-02-21 + + 2185.78 + 1022.945 + 0.0 + 0.0 + + TAX + 0.0 + + + + S + S0125011 + + + 2016-02-12 + + N + + + + 6 + + + + + + 2011-02-09 + 0 + N + + + 03 + 2011 + + + USD + CHF + 0.95702 + + + + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl new file mode 100644 index 00000000000..3fd6282b3de --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/Bug8150704-2.xsl @@ -0,0 +1,1935 @@ + + + + + + + + + +0 +fto-erech +200 +amos-batch +00000000 +X + + +FB01 +TP +EWF + + +566 +950 + + +2w + +V0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +1 + + + + + + + + + + + + + + + + + + + + +KA +EA + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +/ + + + +/ +/ +/ +/ +/ +X +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + +2 +BBSEG + +31 +21 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + + +/ +/ + + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + +2 +BBSEG + +40 +50 + +/ +/ +/ + + + + +/ +/ +/ + + + +/ +/ +/ +/ + + + + + + + + + + +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + +/ +/ +/ +/ + + +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ +/ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +INVALID ALIGN + + + + \ No newline at end of file diff --git a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java index 18229dc28c9..2e01c5dbe59 100644 --- a/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java +++ b/jaxp/test/javax/xml/jaxp/unittest/transform/TransformerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,13 @@ package transform; +import com.sun.org.apache.xml.internal.serialize.OutputFormat; +import com.sun.org.apache.xml.internal.serialize.XMLSerializer; + +import java.io.BufferedReader; import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; @@ -55,56 +61,67 @@ import org.xml.sax.XMLReader; import org.xml.sax.helpers.AttributesImpl; /* - * @summary Test Transformer. + * @summary Transformer Tests + * @bug 6272879 6305029 6505031 8150704 */ public class TransformerTest { - - private static final String LINE_SEPARATOR = System.getProperty("line.separator"); - - private static final String XML_DOCUMENT = "" + ""; - - //Test for JDK-6305029 - @Test - public final void testTransform() throws TransformerException { - - // test SAXSource - SAXSource saxSource = new SAXSource(new MyXMLReader(), new InputSource()); - - StringWriter builder = new StringWriter(); - TransformerFactory.newInstance().newTransformer().transform(saxSource, new StreamResult(builder)); - - AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, builder.toString()); - - // test StreamSource - StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); - - StringWriter streamResult = new StringWriter(); - - TransformerFactory.newInstance().newTransformer().transform(streamSource, new StreamResult(streamResult)); - - AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, streamResult.toString()); + private Transformer createTransformer() throws TransformerException { + return TransformerFactory.newInstance().newTransformer(); } - private static class MyXMLReader implements XMLReader { + private Transformer createTransformerFromInputstream(InputStream xslStream) throws TransformerException { + return TransformerFactory.newInstance().newTransformer(new StreamSource(xslStream)); + } + private Transformer createTransformerFromResource(String xslResource) throws TransformerException { + return TransformerFactory.newInstance().newTransformer(new StreamSource(getClass().getResource(xslResource).toString())); + } + + private Document transformInputStreamToDocument(Transformer transformer, InputStream sourceStream) throws TransformerException { + DOMResult response = new DOMResult(); + transformer.transform(new StreamSource(sourceStream), response); + return (Document)response.getNode(); + } + + private StringWriter transformResourceToStringWriter(Transformer transformer, String xmlResource) throws TransformerException { + StringWriter sw = new StringWriter(); + transformer.transform(new StreamSource(getClass().getResource(xmlResource).toString()), new StreamResult(sw)); + return sw; + } + + /** + * Reads the contents of the given file into a string. + * WARNING: this method adds a final line feed even if the last line of the file doesn't contain one. + * + * @param f + * The file to read + * @return The content of the file as a string, with line terminators as \"n" + * for all platforms + * @throws IOException + * If there was an error reading + */ + private String getFileContentAsString(File f) throws IOException { + try (BufferedReader reader = new BufferedReader(new FileReader(f))) { + String line; + StringBuilder sb = new StringBuilder(); + while ((line = reader.readLine()) != null) { + sb.append(line).append("\n"); + } + return sb.toString(); + } + } + + private class XMLReaderFor6305029 implements XMLReader { private static final String NAMESPACES = "http://xml.org/sax/features/namespaces"; - private static final String NAMESPACE_PREFIXES = "http://xml.org/sax/features/namespace-prefixes"; - private boolean namespaces = true; - private boolean namespacePrefixes = false; - private EntityResolver resolver; - private DTDHandler dtdHandler; - private ContentHandler contentHandler; - private ErrorHandler errorHandler; public boolean getFeature(final String name) throws SAXNotRecognizedException, SAXNotSupportedException { - if (name.equals(NAMESPACES)) { return namespaces; } else if (name.equals(NAMESPACE_PREFIXES)) { @@ -115,7 +132,6 @@ public class TransformerTest { } public void setFeature(final String name, final boolean value) throws SAXNotRecognizedException, SAXNotSupportedException { - if (name.equals(NAMESPACES)) { namespaces = value; } else if (name.equals(NAMESPACE_PREFIXES)) { @@ -165,12 +181,10 @@ public class TransformerTest { } public void parse(final InputSource input) throws IOException, SAXException { - parse(); } public void parse(final String systemId) throws IOException, SAXException { - parse(); } @@ -190,30 +204,50 @@ public class TransformerTest { } } + /* + * @bug 6272879 + * @summary Test for JDK-6272879 + */ @Test - public final void testCR6272879() { + public final void testBug6272879() throws IOException, TransformerException { + final String LINE_SEPARATOR = System.getProperty("line.separator"); - final String xsl = "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + " " - + LINE_SEPARATOR + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + "" + LINE_SEPARATOR - + "" + LINE_SEPARATOR + ""; + final String xsl = + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + "" + LINE_SEPARATOR + + ""; - final String sourceXml = "" - + LINE_SEPARATOR + final String sourceXml = + "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "" + LINE_SEPARATOR + // "]>" + // LINE_SEPARATOR + - + "" + LINE_SEPARATOR + " " + LINE_SEPARATOR + " Valeur 1" + LINE_SEPARATOR - + " " + LINE_SEPARATOR + " " + LINE_SEPARATOR + " Valeur 2" + LINE_SEPARATOR - + " " + LINE_SEPARATOR + ""; + "" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " Valeur 1" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + " Valeur 2" + LINE_SEPARATOR + + " " + LINE_SEPARATOR + + ""; Document document; Node node; @@ -230,9 +264,12 @@ public class TransformerTest { System.out.println("Source file after transformation:"); System.out.println("================================="); - document = getTransformation(xsl, sourceXml); - - System.out.println(document); + document = transformInputStreamToDocument(createTransformerFromInputstream(new ByteArrayInputStream(xsl.getBytes())), + new ByteArrayInputStream(sourceXml.getBytes())); + OutputFormat format = new OutputFormat(); + format.setIndenting(true); + new XMLSerializer(System.out, format).serialize(document); + System.out.println(); System.out.println("Node content for element valeur2:"); System.out.println("================================="); @@ -248,25 +285,60 @@ public class TransformerTest { } } - private static Document getTransformation(final String xsl, final String sourceXml) { + /* + * @bug 6305029 + * @summary Test for JDK-6305029 + */ + @Test + public final void testBug6305029() throws TransformerException { + final String XML_DOCUMENT = "" + ""; - Transformer transformer; - DOMResult reponse; - Document document = null; + // test SAXSource + SAXSource saxSource = new SAXSource(new XMLReaderFor6305029(), new InputSource()); + StringWriter resultWriter = new StringWriter(); + createTransformer().transform(saxSource, new StreamResult(resultWriter)); + AssertJUnit.assertEquals("Identity transform of SAXSource", XML_DOCUMENT, resultWriter.toString()); - try { - InputStream in = new ByteArrayInputStream(xsl.getBytes()); - transformer = TransformerFactory.newInstance().newTransformer(new StreamSource(in)); + // test StreamSource + StreamSource streamSource = new StreamSource(new StringReader(XML_DOCUMENT)); + resultWriter = new StringWriter(); + createTransformer().transform(streamSource, new StreamResult(resultWriter)); + AssertJUnit.assertEquals("Identity transform of StreamSource", XML_DOCUMENT, resultWriter.toString()); + } - reponse = new DOMResult(); - transformer.transform(new StreamSource(new ByteArrayInputStream(sourceXml.getBytes())), reponse); - document = (Document) reponse.getNode(); - } catch (Exception e) { - String msg = "Exception in getTransformation: " + e; - System.err.println(msg); - Assert.fail(msg); - } + /* + * @bug 6505031 + * @summary Test transformer parses keys and their values coming from different xml documents. + */ + @Test + public final void testBug6505031() throws TransformerException { + Transformer transformer = createTransformerFromResource("transform.xsl"); + transformer.setParameter("config", getClass().getResource("config.xml").toString()); + transformer.setParameter("mapsFile", getClass().getResource("maps.xml").toString()); + String s = transformResourceToStringWriter(transformer, "template.xml").toString(); + Assert.assertTrue(s.contains("map1key1value") && s.contains("map2key1value")); + } - return (document); + /* + * @bug 8150704 + * @summary Test that XSL transformation with lots of temporary result trees will not run out of DTM IDs. + */ + @Test + public final void testBug8150704() throws TransformerException, IOException { + System.out.println("Testing transformation of Bug8150704-1.xml..."); + Transformer transformer = createTransformerFromResource("Bug8150704-1.xsl"); + StringWriter result = transformResourceToStringWriter(transformer, "Bug8150704-1.xml"); + String resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); + String reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-1.ref").getPath())); + Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-1.xml does not match reference"); + System.out.println("Passed."); + + System.out.println("Testing transformation of Bug8150704-2.xml..."); + transformer = createTransformerFromResource("Bug8150704-2.xsl"); + result = transformResourceToStringWriter(transformer, "Bug8150704-2.xml"); + resultstring = result.toString().replaceAll("\\r\\n", "\n").replaceAll("\\r", "\n"); + reference = getFileContentAsString(new File(getClass().getResource("Bug8150704-2.ref").getPath())); + Assert.assertEquals(resultstring, reference, "Output of transformation of Bug8150704-2.xml does not match reference"); + System.out.println("Passed."); } } diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd new file mode 100644 index 00000000000..872033f5d1a --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/Bug8149915.xsd @@ -0,0 +1,7 @@ + + + + Testapp for XSD annotation issue + This is an XSD annotation, just for the sake of it. + + diff --git a/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java new file mode 100644 index 00000000000..f8a5e62ac55 --- /dev/null +++ b/jaxp/test/javax/xml/jaxp/unittest/validation/SchemaTest.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package validation; + +import java.io.File; + +import javax.xml.XMLConstants; +import javax.xml.validation.SchemaFactory; + +import org.testng.annotations.Test; + +/* + * @summary Test Schema creation + * @bug 8149915 + */ +public class SchemaTest { + + /* + * @bug 8149915 + * Verifies that the annotation validator is initialized with the security manager for schema + * creation with http://apache.org/xml/features/validate-annotations=true. + */ + @Test + public void testValidation() throws Exception { + SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); + factory.setFeature("http://apache.org/xml/features/validate-annotations", true); + factory.newSchema(new File(getClass().getResource("Bug8149915.xsd").getFile())); + } +} diff --git a/jaxws/.hgtags b/jaxws/.hgtags index f7f802b6f6b..d02e1de4e0c 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -352,3 +352,6 @@ eb5e005a17e50d7d8340daaf21a5c3c5ae358d68 jdk-9+103 0f557aa096e2a5c9733d406d8cf0c2e6b1f8ca60 jdk-9+104 45a666c58e4c7d07638878684ad09decb3229dc9 jdk-9+105 c072c572d14948563ef5d86e1921699b3a2396ab jdk-9+106 +fafd694e801f0f5a7c737fb08630ced3ca8f772c jdk-9+107 +513eb2e432f64f85992442da9acdfcfbb36555d9 jdk-9+108 +4b0697e4ce8940b1599af274ff02296d7f59aded jdk-9+109 diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java index 0cbec252c26..8b658911397 100644 --- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java +++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/reflect/opt/Const.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,12 +29,12 @@ package com.sun.xml.internal.bind.v2.runtime.reflect.opt; * @author Kohsuke Kawaguchi */ public final class Const { - public static byte default_value_byte = 0; - public static boolean default_value_boolean = false; - public static char default_value_char = 0; - public static float default_value_float = 0; - public static double default_value_double = 0; - public static int default_value_int = 0; - public static long default_value_long = 0; - public static short default_value_short = 0; + public static final byte default_value_byte = 0; + public static final boolean default_value_boolean = false; + public static final char default_value_char = 0; + public static final float default_value_float = 0; + public static final double default_value_double = 0; + public static final int default_value_int = 0; + public static final long default_value_long = 0; + public static final short default_value_short = 0; } diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java index 0d4fa2647db..9becb9dd086 100644 --- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java +++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/runtime/unmarshaller/StructureLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,22 +231,11 @@ public final class StructureLoader extends Loader { @Override public void childElement(UnmarshallingContext.State state, TagName arg) throws SAXException { ChildLoader child = childUnmarshallers.get(arg.uri,arg.local); - if(child==null) { - if ((beanInfo != null) && (beanInfo.getTypeNames() != null)) { - Iterator typeNamesIt = beanInfo.getTypeNames().iterator(); - QName parentQName = null; - if ((typeNamesIt != null) && (typeNamesIt.hasNext()) && (catchAll == null)) { - parentQName = (QName) typeNamesIt.next(); - String parentUri = parentQName.getNamespaceURI(); - child = childUnmarshallers.get(parentUri, arg.local); - } - } - if (child == null) { - child = catchAll; - if(child==null) { - super.childElement(state,arg); - return; - } + if (child == null) { + child = catchAll; + if (child==null) { + super.childElement(state,arg); + return; } } diff --git a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java index b292e450fa8..42ef308e632 100644 --- a/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java +++ b/jaxws/src/java.xml.bind/share/classes/com/sun/xml/internal/bind/v2/schemagen/XmlSchemaGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -110,6 +110,7 @@ import com.sun.xml.internal.txw2.TypedXmlWriter; import com.sun.xml.internal.txw2.output.ResultFactory; import com.sun.xml.internal.txw2.output.XmlSerializer; import java.util.Collection; +import java.util.HashSet; import org.xml.sax.SAXParseException; /** @@ -436,7 +437,7 @@ public final class XmlSchemaGenerator { if(logger.isLoggable(Level.FINE)) { // debug logging to see what's going on. - logger.log(Level.FINE,"Wrigin XML Schema for "+toString(),new StackRecorder()); + logger.log(Level.FINE,"Writing XML Schema for "+toString(),new StackRecorder()); } // make it fool-proof @@ -465,6 +466,8 @@ public final class XmlSchemaGenerator { systemIds.put(n,output.getSystemId()); } } + //Clear the namespace specific set with already written classes + n.resetWritten(); } // then write'em all @@ -542,12 +545,24 @@ public final class XmlSchemaGenerator { */ private boolean useMimeNs; + /** + * Container for already processed classes + */ + private final Set written = new HashSet(); + public Namespace(String uri) { this.uri = uri; assert !XmlSchemaGenerator.this.namespaces.containsKey(uri); XmlSchemaGenerator.this.namespaces.put(uri,this); } + /** + * Clear out the set of already processed classes for this namespace + */ + void resetWritten() { + written.clear(); + } + /** * Process the given PropertyInfo looking for references to namespaces that * are foreign to the given namespace. Any foreign namespace references @@ -853,6 +868,10 @@ public final class XmlSchemaGenerator { * @param parent the writer of the parent element into which the type will be defined */ private void writeClass(ClassInfo c, TypeHost parent) { + if (written.contains(c)) { // to avoid cycles let's check if we haven't already processed the class + return; + } + written.add(c); // special handling for value properties if (containsValueProp(c)) { if (c.getProperties().size() == 1) { @@ -1080,9 +1099,13 @@ public final class XmlSchemaGenerator { } } } - if (cImpl != null) - e.ref(new QName(cImpl.getElementName().getNamespaceURI(), tn.getLocalPart())); - else + if (cImpl != null) { + if (tn.getNamespaceURI() != null && tn.getNamespaceURI().trim().length() != 0) { + e.ref(new QName(tn.getNamespaceURI(), tn.getLocalPart())); + } else { + e.ref(new QName(cImpl.getElementName().getNamespaceURI(), tn.getLocalPart())); + } + } else e.ref(new QName("", tn.getLocalPart())); } else e.ref(tn); diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java index 4a8bf2ad05c..4ff655a0051 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/client/p2p/HttpSOAPConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -512,13 +512,9 @@ class HttpSOAPConnection extends SOAPConnection { : httpConnection.getInputStream()); // If no reply message is returned, // content-Length header field value is expected to be zero. - // java SE 6 documentation says : - // available() : an estimate of the number of bytes that can be read - //(or skipped over) from this input stream without blocking - //or 0 when it reaches the end of the input stream. + // InputStream#available() can't be used here - it just says no data *YET*! if ((httpIn == null ) - || (httpConnection.getContentLength() == 0) - || (httpIn.available() == 0)) { + || (httpConnection.getContentLength() == 0)) { response = null; log.warning("SAAJ0014.p2p.content.zero"); } else { diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java index 38071ae07ed..bf39ee7540b 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/InternetHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -285,7 +285,7 @@ public final class InternetHeaders { * * @return Header objects */ - public FinalArrayList getAllHeaders() { + public List getAllHeaders() { return headers; // conceptually it should be read-only, but for performance reason I'm not wrapping it here } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java index 47077fa4393..6642dfa19ce 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/messaging/saaj/packaging/mime/internet/MimeBodyPart.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ package com.sun.xml.internal.messaging.saaj.packaging.mime.internet; +import com.sun.xml.internal.messaging.saaj.packaging.mime.Header; import com.sun.xml.internal.messaging.saaj.packaging.mime.MessagingException; import com.sun.xml.internal.messaging.saaj.packaging.mime.util.OutputUtil; import com.sun.xml.internal.messaging.saaj.util.ByteOutputStream; @@ -1041,7 +1042,7 @@ public final class MimeBodyPart { * Return all the headers from this Message as an Enumeration of * Header objects. */ - public FinalArrayList getAllHeaders() { + public List getAllHeaders() { return headers.getAllHeaders(); } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java index a29edc91cc2..25e0462c3bb 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/api/pipe/ThreadHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import java.util.concurrent.ThreadFactory; /** * Simple utility class to instantiate correct Thread instance - * depending on runtime context (jdk/non-jdk usage) and Java version. + * depending on Java version. * * @author miroslav.kos@oracle.com */ @@ -101,16 +101,16 @@ final class ThreadHelper { SunMiscThreadFactory(Constructor ctr) { this.ctr = ctr; } @Override public Thread newThread(Runnable r) { return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public Thread run() { - try { - return (Thread) ctr.newInstance(r); - } catch (Exception e) { - return new Thread(r); + new PrivilegedAction() { + @Override + public Thread run() { + try { + return (Thread) ctr.newInstance(r); + } catch (Exception e) { + return new Thread(r); + } } } - } ); } } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java index 4e52e928157..1548196df9e 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/transport/Headers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,5 +127,17 @@ public class Headers extends TreeMap> { l.add (value); put(key, l); } + /** + * Added to fix issue + * putAll() is easier to deal with as it doesn't return anything + */ + public void putAll(Map> map) { + for (String k : map.keySet()) { + List list = map.get(k); + for (String v : list) { + add(k,v); + } + } + } } diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java index bae830f73df..63f42c2c6be 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/ServiceFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -338,13 +338,13 @@ public final class ServiceFinder implements Iterable { int lc = 1; while ((lc = parseLine(service, u, r, lc, names, returned)) >= 0) ; } catch (IOException x) { - fail(service, ": " + x); + fail(service, ": " + x +";URL is :"+u.toString()); } finally { try { if (r != null) r.close(); if (in != null) in.close(); } catch (IOException y) { - fail(service, ": " + y); + fail(service, ": " + y +";URL is :"+u.toString()); } } return names.iterator(); diff --git a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties index 462e4882799..8d2adcadac9 100644 --- a/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties +++ b/jaxws/src/java.xml.ws/share/classes/com/sun/xml/internal/ws/util/version.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,4 +26,4 @@ build-id=2.3.0-SNAPSHOT build-version=JAX-WS RI 2.3.0-SNAPSHOT major-version=2.3.0 -svn-revision=ffaa49e66cc05e1bb2ddc103076a340dad5df997 +svn-revision=282759e2b822078de9ba78c743ed663541c16ead diff --git a/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java b/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java index 6dcb4b1f1aa..ef5500a0627 100644 --- a/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java +++ b/jaxws/src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -184,7 +184,7 @@ class FactoryFinder { private static String fromJDKProperties(String factoryId, String deprecatedFactoryId) { Path path = null; try { - String JAVA_HOME = System.getProperty("java.home"); + String JAVA_HOME = getSystemProperty("java.home"); path = Paths.get(JAVA_HOME, "conf", "jaxm.properties"); logger.log(Level.FINE, "Checking configuration in {0}", path); diff --git a/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java b/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java index 8c308b8d907..c7f4aab3b35 100644 --- a/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java +++ b/jaxws/src/java.xml.ws/share/classes/javax/xml/ws/spi/FactoryFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -137,7 +137,8 @@ class FactoryFinder { } catch (Exception ignored) { logger.log(Level.SEVERE, "Error reading JAX-WS configuration from [" + path + "] file. Check it is accessible and has correct format.", ignored); - } return null; + } + return null; } private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java index 6c024456b89..1af2c5d9a31 100644 --- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/codemodel/internal/JJavaName.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,7 +85,7 @@ public class JJavaName { * ("my_children","MyChildren","myChildren", and "MY-CHILDREN", "CODE003-children" respectively) *

* Although this method only works for English words, it handles non-English - * words gracefully (by just returning it as-is.) For example, 日本語 + * words gracefully (by just returning it as-is.) For example, "日本語" * will be returned as-is without modified, not "日本語s" *

* This method doesn't handle suffixes very well. For example, passing diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties new file mode 100644 index 00000000000..0cc3e21ee84 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle.properties @@ -0,0 +1,49 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = \ + Unexpected {0} appears at line {1} column {2} + +BASEDIR_DOESNT_EXIST = \ + Non-existent directory: {0} + +VERSION = \ + schemagen 2.3.0-SNAPSHOT + +FULLVERSION = \ + schemagen full version "2.3.0-SNAPSHOT" + +USAGE = \ +Usage: schemagen [-options ...] \n\ +Options: \n\ +\ \ \ \ -d : specify where to place processor and javac generated class files\n\ +\ \ \ \ -cp : specify where to find user specified files\n\ +\ \ \ \ -classpath : specify where to find user specified files\n\ +\ \ \ \ -encoding : specify encoding to be used for annotation processing/javac invocation \n\ +\ \ \ \ -episode : generate episode file for separate compilation\n\ +\ \ \ \ -disableXmlSecurity : disables XML security features for usage on xml parsing apis \n\ +\ \ \ \ -version : display version information\n\ +\ \ \ \ -fullversion : display full version information\n\ +\ \ \ \ -help : display this usage message diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties new file mode 100644 index 00000000000..3158ce32236 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_de.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = Nicht erkanntes {0} in Zeile {1} Spalte {2} + +BASEDIR_DOESNT_EXIST = Nicht vorhandenes Verzeichnis: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen vollst\u00E4ndige Version "2.3.0-SNAPSHOT" + +USAGE = Verwendung: schemagen [-options ...] \nOptionen: \n\\ \\ \\ \\ -d : Gibt an, wo die von Prozessor und javac generierten Klassendateien gespeichert werden sollen\n\\ \\ \\ \\ -cp : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -classpath : Gibt an, wo die vom Benutzer angegebenen Dateien gespeichert sind\n\\ \\ \\ \\ -encoding : Gibt die Codierung f\u00FCr die Annotationsverarbeitung/den javac-Aufruf an \n\\ \\ \\ \\ -episode : Generiert Episodendatei f\u00FCr separate Kompilierung\n\\ \\ \\ \\ -version : Zeigt Versionsinformation an\n\\ \\ \\ \\ -fullversion : Zeigt vollst\u00E4ndige Versionsinformationen an\n\\ \\ \\ \\ -help : Zeigt diese Verwendungsmeldung an diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties new file mode 100644 index 00000000000..81d9274dc3c --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_es.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = Aparece un {0} inesperado en la l\u00EDnea {1} y la columna {2} + +BASEDIR_DOESNT_EXIST = Directorio no existente: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = versi\u00F3n completa de schemagen "2.3.0-SNAPSHOT" + +USAGE = Sintaxis: schemagen [-options ...] \nOpciones: \n\\ \\ \\ \\ -d : especifique d\u00F3nde se colocan los archivos de clase generados por javac y el procesador\n\\ \\ \\ \\ -cp : especifique d\u00F3nde se encuentran los archivos especificados por el usuario\n\\ \\ \\ \\ -encoding : especifique la codificaci\u00F3n que se va a utilizar para el procesamiento de anotaciones/llamada de javac\n\\ \\ \\ \\ -episode : genera un archivo de episodio para una compilaci\u00F3n diferente\n\\ \\ \\ \\ -version : muestra la informaci\u00F3n de la versi\u00F3n\n\\ \\ \\ \\ -fullversion : muestra la informaci\u00F3n completa de la versi\u00F3n\n\\ \\ \\ \\ -help : muestra este mensaje de sintaxis diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties new file mode 100644 index 00000000000..597ce0e512b --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_fr.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = Un \u00E9l\u00E9ment {0} inattendu appara\u00EEt \u00E0 la ligne {1}, colonne {2} + +BASEDIR_DOESNT_EXIST = R\u00E9pertoire {0} inexistant + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = version compl\u00E8te de schemagen "2.3.0-SNAPSHOT" + +USAGE = Syntaxe : schemagen [-options ...] \nOptions : \n\ \ \ \ -d : indiquez o\u00F9 placer les fichiers de classe g\u00E9n\u00E9r\u00E9s par le processeur et le compilateur javac\n\ \ \ \ -cp : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -classpath : indiquez o\u00F9 trouver les fichiers sp\u00E9cifi\u00E9s par l'utilisateur\n\ \ \ \ -encoding : indiquez l'encodage \u00E0 utiliser pour l'appel de javac/traitement de l'annotation \n\ \ \ \ -episode : g\u00E9n\u00E9rez un fichier d'\u00E9pisode pour la compilation s\u00E9par\u00E9e\n\ \ \ \ -version : affichez les informations de version\n\ \ \ \ -fullversion : affichez les informations compl\u00E8tes de version\n\ \ \ \ -help : affichez ce message de syntaxe diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties new file mode 100644 index 00000000000..c7ef575e06e --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_it.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = {0} imprevisto visualizzato sulla riga {1} colonna {2} + +BASEDIR_DOESNT_EXIST = Directory non esistente: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = versione completa schemagen "2.3.0-SNAPSHOT" + +USAGE = Uso: schemagen [-options ...] \nOpzioni: \n\ \ \ \ -d : specifica dove posizionare il processore e i file della classe generata javac\n\ \ \ \ -cp : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -classpath : specifica dove trovare i file specificati dall'utente\n\ \ \ \ -encoding : specifica la codifica da usare per l'elaborazione dell'annotazione/richiamo javac \n\ \ \ \ -episode : genera il file di episodio per la compilazione separata\n\ \ \ \ -version : visualizza le informazioni sulla versione\n\ \ \ \ -fullversion : visualizza le informazioni sulla versione completa\n\ \ \ \ -help : visualizza questo messaggio sull'uso diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties new file mode 100644 index 00000000000..e07c234ff85 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ja.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = \u4E88\u671F\u3057\u306A\u3044{0}\u304C\u884C{1}\u3001\u5217{2}\u306B\u3042\u308A\u307E\u3059 + +BASEDIR_DOESNT_EXIST = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen\u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3"2.3.0-SNAPSHOT" + +USAGE = \u4F7F\u7528\u65B9\u6CD5: schemagen [-options ...] \n\u30AA\u30D7\u30B7\u30E7\u30F3: \n\ \ \ \ -d : \u30D7\u30ED\u30BB\u30C3\u30B5\u304A\u3088\u3073javac\u304C\u751F\u6210\u3057\u305F\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u7F6E\u304F\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -cp : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -classpath : \u30E6\u30FC\u30B6\u30FC\u304C\u6307\u5B9A\u3057\u305F\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u4F4D\u7F6E\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -encoding : \u6CE8\u91C8\u51E6\u7406/javac\u547C\u51FA\u3057\u306B\u4F7F\u7528\u3059\u308B\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u3092\u6307\u5B9A\u3057\u307E\u3059\n\ \ \ \ -episode : \u30B3\u30F3\u30D1\u30A4\u30EB\u3054\u3068\u306B\u30A8\u30D4\u30BD\u30FC\u30C9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3057\u307E\u3059\n\ \ \ \ -version : \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -fullversion : \u30D5\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3057\u307E\u3059\n\ \ \ \ -help : \u3053\u306E\u4F7F\u7528\u4F8B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u307E\u3059 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties new file mode 100644 index 00000000000..f4e5fa4d62e --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_ko.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = \uC608\uC0C1\uCE58 \uC54A\uC740 {0}\uC774(\uAC00) {1}\uD589 {2}\uC5F4\uC5D0 \uB098\uD0C0\uB0A9\uB2C8\uB2E4. + +BASEDIR_DOESNT_EXIST = \uC874\uC7AC\uD558\uC9C0 \uC54A\uB294 \uB514\uB809\uD1A0\uB9AC: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen \uC815\uC2DD \uBC84\uC804 "2.3.0-SNAPSHOT" + +USAGE = \uC0AC\uC6A9\uBC95: schemagen [-options ...] \n\uC635\uC158: \n\ \ \ \ -d : \uD504\uB85C\uC138\uC11C \uBC0F javac\uC5D0\uC11C \uC0DD\uC131\uD55C \uD074\uB798\uC2A4 \uD30C\uC77C\uC744 \uBC30\uCE58\uD560 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -cp : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -classpath : \uC0AC\uC6A9\uC790\uAC00 \uC9C0\uC815\uD55C \uD30C\uC77C\uC744 \uCC3E\uC744 \uC704\uCE58\uB97C \uC9C0\uC815\uD569\uB2C8\uB2E4.\n\ \ \ \ -encoding : \uC8FC\uC11D \uCC98\uB9AC/javac \uD638\uCD9C\uC5D0 \uC0AC\uC6A9\uD560 \uC778\uCF54\uB529\uC744 \uC9C0\uC815\uD569\uB2C8\uB2E4. \n\ \ \ \ -episode : \uBCC4\uB3C4 \uCEF4\uD30C\uC77C\uC744 \uC704\uD574 episode \uD30C\uC77C\uC744 \uC0DD\uC131\uD569\uB2C8\uB2E4.\n\ \ \ \ -version : \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -fullversion : \uC815\uC2DD \uBC84\uC804 \uC815\uBCF4\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4.\n\ \ \ \ -help : \uC774 \uC0AC\uC6A9\uBC95 \uBA54\uC2DC\uC9C0\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties new file mode 100644 index 00000000000..d56ca3894d5 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_pt_BR.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = {0} inesperado aparece na linha {1} coluna {2} + +BASEDIR_DOESNT_EXIST = Diret\u00F3rio n\u00E3o existente: {0} + +VERSION = gera\u00E7\u00E3o do esquema 2.3.0-SNAPSHOT + +FULLVERSION = vers\u00E3o completa da gera\u00E7\u00E3o do esquema "2.3.0-SNAPSHOT" + +USAGE = Uso: gera\u00E7\u00E3o do esquema [-options ...] \nOp\u00E7\u00F5es: \n\\ \\ \\ \\ -d : especificar onde colocar o processador e os arquivos da classe gerados por javac\n\\ \\ \\ \\ -cp : especificar onde localizar arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -classpath : especificar onde localizar os arquivos especificados pelo usu\u00E1rio\n\\ \\ \\ \\ -encoding : especificar codifica\u00E7\u00E3o a ser usada para processamento de anota\u00E7\u00E3o/chamada javac \n\\ \\ \\ \\ -episode : gerar arquivo do epis\u00F3dio para compila\u00E7\u00E3o separada\n\\ \\ \\ \\ -version : exibir informa\u00E7\u00F5es da vers\u00E3o\n\\ \\ \\ \\ -fullversion : exibir informa\u00E7\u00F5es da vers\u00E3o completa\n\\ \\ \\ \\ -help : exibir esta mensagem de uso diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties new file mode 100644 index 00000000000..c1be9f0f704 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_CN.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = \u5728\u7B2C {1} \u884C, \u7B2C {2} \u5217\u51FA\u73B0\u610F\u5916\u7684{0} + +BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u5F55: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-SNAPSHOT" + +USAGE = \u7528\u6CD5: schemagen [-options ...] \n\u9009\u9879: \n\ \ \ \ -d : \u6307\u5B9A\u653E\u7F6E\u5904\u7406\u7A0B\u5E8F\u548C javac \u751F\u6210\u7684\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -cp : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -classpath : \u6307\u5B9A\u67E5\u627E\u7528\u6237\u6307\u5B9A\u6587\u4EF6\u7684\u4F4D\u7F6E\n\ \ \ \ -encoding : \u6307\u5B9A\u7528\u4E8E\u6CE8\u91CA\u5904\u7406/javac \u8C03\u7528\u7684\u7F16\u7801\n\ \ \ \ -episode : \u751F\u6210\u7247\u6BB5\u6587\u4EF6\u4EE5\u4F9B\u5355\u72EC\u7F16\u8BD1\n\ \ \ \ -version : \u663E\u793A\u7248\u672C\u4FE1\u606F\n\ \ \ \ -fullversion : \u663E\u793A\u5B8C\u6574\u7684\u7248\u672C\u4FE1\u606F\n\ \ \ \ -help : \u663E\u793A\u6B64\u7528\u6CD5\u6D88\u606F diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties new file mode 100644 index 00000000000..dcd7976be7c --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/MessageBundle_zh_TW.properties @@ -0,0 +1,34 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +UNEXPECTED_NGCC_TOKEN = \u672A\u9810\u671F\u7684 {0} \u986F\u793A\u65BC\u884C {1} \u8CC7\u6599\u6B04 {2} + +BASEDIR_DOESNT_EXIST = \u4E0D\u5B58\u5728\u7684\u76EE\u9304: {0} + +VERSION = schemagen 2.3.0-SNAPSHOT + +FULLVERSION = schemagen \u5B8C\u6574\u7248\u672C "2.3.0-SNAPSHOT" + +USAGE = \u7528\u6CD5: schemagen [-options ...] \n\u9078\u9805: \n\\ \\ \\ \\ -d : \u6307\u5B9A\u8655\u7406\u5668\u4EE5\u53CA javac \u7522\u751F\u7684\u985E\u5225\u6A94\u6848\u653E\u7F6E\u4F4D\u7F6E\n\\ \\ \\ \\ -cp : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -classpath : \u6307\u5B9A\u8981\u5C0B\u627E\u4F7F\u7528\u8005\u6307\u5B9A\u6A94\u6848\u7684\u4F4D\u7F6E\n\\ \\ \\ \\ -encoding : \u6307\u5B9A\u8981\u7528\u65BC\u8A3B\u89E3\u8655\u7406/javac \u547C\u53EB\u7684\u7DE8\u78BC \n\\ \\ \\ \\ -episode : \u7522\u751F\u7368\u7ACB\u7DE8\u8B6F\u7684\u4E8B\u4EF6 (episode) \u6A94\u6848\n\\ \\ \\ \\ -version : \u986F\u793A\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -fullversion : \u986F\u793A\u5B8C\u6574\u7248\u672C\u8CC7\u8A0A\n\\ \\ \\ \\ -help : \u986F\u793A\u6B64\u7528\u6CD5\u8A0A\u606F diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties new file mode 100644 index 00000000000..d744da53d0d --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle.properties @@ -0,0 +1,33 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = \ + Directory "{0}" doesn't exist. + +UNRECOGNIZED_PARAMETER = \ + Unrecognized option {0} is not valid. + +OPERAND_MISSING = \ + Option "{0}" is missing an operand. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties new file mode 100644 index 00000000000..614b1664eaa --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_de.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = Verzeichnis "{0}" ist nicht vorhanden. + +UNRECOGNIZED_PARAMETER = Unbekannte Option {0} ist nicht g\u00FCltig. + +OPERAND_MISSING = In Option "{0}" fehlt ein Operand. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties new file mode 100644 index 00000000000..c32a9bd869f --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_es.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = El directorio "{0}" no existe. + +UNRECOGNIZED_PARAMETER = La opci\u00F3n no reconocida {0} no es v\u00E1lida. + +OPERAND_MISSING = A la opci\u00F3n "{0}" le falta un operando. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties new file mode 100644 index 00000000000..c7d0bf184bd --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_fr.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = Le r\u00E9pertoire "{0}" n''existe pas. + +UNRECOGNIZED_PARAMETER = L''option {0} non reconnue n''est pas valide. + +OPERAND_MISSING = Un op\u00E9rande est manquant dans l''option "{0}". diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties new file mode 100644 index 00000000000..7e78899f47d --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_it.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = La directory "{0}" non esiste. + +UNRECOGNIZED_PARAMETER = L''opzione non riconosciuta {0} non \u00E8 valida. + +OPERAND_MISSING = Operando mancante nell''opzione "{0}". diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties new file mode 100644 index 00000000000..490f37151ba --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ja.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = \u30C7\u30A3\u30EC\u30AF\u30C8\u30EA"{0}"\u304C\u5B58\u5728\u3057\u307E\u305B\u3093\u3002 + +UNRECOGNIZED_PARAMETER = \u8A8D\u8B58\u3055\u308C\u306A\u3044\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306F\u7121\u52B9\u3067\u3059\u3002 + +OPERAND_MISSING = \u30AA\u30D7\u30B7\u30E7\u30F3"{0}"\u306B\u30AA\u30DA\u30E9\u30F3\u30C9\u304C\u3042\u308A\u307E\u305B\u3093\u3002 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties new file mode 100644 index 00000000000..5a22607fbe7 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_ko.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = "{0}" \uB514\uB809\uD1A0\uB9AC\uAC00 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. + +UNRECOGNIZED_PARAMETER = \uC778\uC2DD\uD560 \uC218 \uC5C6\uB294 \uC635\uC158 {0}\uC740(\uB294) \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. + +OPERAND_MISSING = "{0}" \uC635\uC158\uC5D0 \uD53C\uC5F0\uC0B0\uC790\uAC00 \uB204\uB77D\uB418\uC5C8\uC2B5\uB2C8\uB2E4. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties new file mode 100644 index 00000000000..f6d654fe950 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_pt_BR.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = O diret\u00F3rio "{0}" n\u00E3o existe. + +UNRECOGNIZED_PARAMETER = A op\u00E7\u00E3o {0} n\u00E3o reconhecida \u00E9 inv\u00E1lida. + +OPERAND_MISSING = A op\u00E7\u00E3o "{0}" n\u00E3o encontrou um operando. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties new file mode 100644 index 00000000000..1300088afde --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_CN.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = \u76EE\u5F55 "{0}" \u4E0D\u5B58\u5728\u3002 + +UNRECOGNIZED_PARAMETER = \u65E0\u6CD5\u8BC6\u522B\u7684\u9009\u9879{0}, \u8BE5\u9009\u9879\u65E0\u6548\u3002 + +OPERAND_MISSING = \u9009\u9879 "{0}" \u7F3A\u5C11\u64CD\u4F5C\u6570\u3002 diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties new file mode 100644 index 00000000000..042c9816897 --- /dev/null +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/jxc/ap/MessageBundle_zh_TW.properties @@ -0,0 +1,30 @@ +# +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. 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. +# + +NON_EXISTENT_FILE = \u76EE\u9304 "{0}" \u4E0D\u5B58\u5728. + +UNRECOGNIZED_PARAMETER = \u7121\u6CD5\u8FA8\u8B58\u7684\u9078\u9805 {0} \u7121\u6548. + +OPERAND_MISSING = \u9078\u9805 "{0}" \u907A\u6F0F\u904B\u7B97\u5143. diff --git a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java index 396d88dc187..bc803684776 100644 --- a/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java +++ b/jaxws/src/jdk.xml.bind/share/classes/com/sun/tools/internal/xjc/model/CTypeRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,7 +68,6 @@ public final class CTypeRef implements TypeRef { public CTypeRef(CNonElement type, XSElementDecl decl) { this(type, BGMBuilder.getName(decl),getSimpleTypeName(decl), decl.isNillable(), decl.getDefaultValue() ); - } public QName getTypeName() { @@ -100,10 +99,15 @@ public final class CTypeRef implements TypeRef { */ private static QName resolveSimpleTypeName(XSType declType) { QName name = BGMBuilder.getName(declType); - if (name != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(name.getNamespaceURI())) - return resolveSimpleTypeName(declType.getBaseType()); - else - return name; + QName result = null; + if (name != null && !XMLConstants.W3C_XML_SCHEMA_NS_URI.equals(name.getNamespaceURI())) { + result = resolveSimpleTypeName(declType.getBaseType()); + } else { + if ( !"anySimpleType".equals(declType.getName()) ) { + result = name; + } + } + return result; } public CTypeRef(CNonElement type, QName elementName, QName typeName, boolean nillable, XmlString defaultValue) { diff --git a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties index 462e4882799..8d2adcadac9 100644 --- a/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties +++ b/jaxws/src/jdk.xml.ws/share/classes/com/sun/tools/internal/ws/version.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -26,4 +26,4 @@ build-id=2.3.0-SNAPSHOT build-version=JAX-WS RI 2.3.0-SNAPSHOT major-version=2.3.0 -svn-revision=ffaa49e66cc05e1bb2ddc103076a340dad5df997 +svn-revision=282759e2b822078de9ba78c743ed663541c16ead diff --git a/jdk/.hgtags b/jdk/.hgtags index 5b88bcd99f8..8d4f94f1f2c 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -349,3 +349,6 @@ eee1ced1d8e78293f2a004af818ca474387dbebf jdk-9+103 8faf1aec77a9517c69d2f4d8dd146429852ace7f jdk-9+104 55518739e399a1066c8613e19100d51b38d9f223 jdk-9+105 6e9ecae50b4e0d37483fb2719202eea5dca026a4 jdk-9+106 +8701b2bb1d2e1b9abc2a9be0933993c7150a9dbe jdk-9+107 +42794e648cfe9fd67461dcbe8b7594241a84bcff jdk-9+108 +1c7bad0798900fe58f4db01ae7ffdc84f5baee8c jdk-9+109 diff --git a/jdk/make/gendata/GendataHtml32dtd.gmk b/jdk/make/gendata/GendataHtml32dtd.gmk index 2bc0e708673..0c18d2a280c 100644 --- a/jdk/make/gendata/GendataHtml32dtd.gmk +++ b/jdk/make/gendata/GendataHtml32dtd.gmk @@ -30,6 +30,6 @@ $(HTML32DTD): $(BUILD_TOOLS_JDK) $(call LogInfo, Generating HTML DTD file) $(MKDIR) -p $(@D) $(RM) $@ - ($(TOOL_DTDBUILDER) $(LOG_INFO) html32 > $@) || exit 1 + ($(TOOL_DTDBUILDER) html32 > $@) || exit 1 TARGETS += $(HTML32DTD) diff --git a/jdk/make/gensrc/GensrcCLDR.gmk b/jdk/make/gensrc/GensrcCLDR.gmk index 45ccc349878..230dc3eb709 100644 --- a/jdk/make/gensrc/GensrcCLDR.gmk +++ b/jdk/make/gensrc/GensrcCLDR.gmk @@ -30,7 +30,7 @@ GENSRC_BASEDIR := $(SUPPORT_OUTPUTDIR)/gensrc/java.base GENSRC_DIR := $(SUPPORT_OUTPUTDIR)/gensrc/jdk.localedata CLDR_BASEMETAINFO_FILE := $(GENSRC_BASEDIR)/sun/util/cldr/CLDRBaseLocaleDataMetaInfo.java -CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo_jdk_localedata.java +CLDR_METAINFO_FILE := $(GENSRC_DIR)/sun/util/resources/cldr/provider/CLDRLocaleDataMetaInfo.java CLDR_BASE_LOCALES := "en-US" diff --git a/jdk/make/gensrc/GensrcMisc.gmk b/jdk/make/gensrc/GensrcMisc.gmk index bc70e0e01f0..a69c007cffb 100644 --- a/jdk/make/gensrc/GensrcMisc.gmk +++ b/jdk/make/gensrc/GensrcMisc.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,11 @@ ########################################################################################## # Install the launcher name, release version string, full version -# string and the runtime name into the Version.java file. +# string and the runtime name into the VersionProps.java file. $(eval $(call SetupTextFileProcessing, BUILD_VERSION_JAVA, \ - SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template, \ - OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java, \ + SOURCE_FILES := $(JDK_TOPDIR)/src/java.base/share/classes/java/lang/VersionProps.java.template, \ + OUTPUT_FILE := $(SUPPORT_OUTPUTDIR)/gensrc/java.base/java/lang/VersionProps.java, \ REPLACEMENTS := \ @@LAUNCHER_NAME@@ => $(LAUNCHER_NAME) ; \ @@RUNTIME_NAME@@ => $(RUNTIME_NAME) ; \ @@ -53,6 +53,8 @@ SOR_COPYRIGHT_YEARS = $(shell $(CAT) $(GENSRC_SOR_SRC)/$(GENSRC_SOR_SRC_FILE) | $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \ SRC := $(GENSRC_SOR_SRC), \ INCLUDE_FILES := $(GENSRC_SOR_SRC_FILE), \ + CFLAGS_windows := -nologo, \ + LDFLAGS_windows := -nologo, \ TOOLCHAIN := TOOLCHAIN_BUILD, \ OBJECT_DIR := $(GENSRC_SOR_BIN), \ OUTPUT_DIR := $(GENSRC_SOR_BIN), \ @@ -61,12 +63,12 @@ $(eval $(call SetupNativeCompilation, BUILD_GENSRC_SOR_EXE, \ SOR_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/ch/SocketOptionRegistry-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template ifeq ($(wildcard $(SOR_PREGEN_FILE)), ) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(BUILD_GENSRC_SOR_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOR_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_SOR_EXE) >> $@.tmp + $(BUILD_GENSRC_SOR_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ else $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/ch/SocketOptionRegistry.java: $(SOR_PREGEN_FILE) @@ -97,12 +99,12 @@ ifneq ($(OPENJDK_TARGET_OS), windows) UC_PREGEN_FILE := $(JDK_TOPDIR)/src/closed/java.base/$(OPENJDK_TARGET_OS)/classes/sun/nio/fs/UnixConstants-$(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH).java.template ifeq ($(wildcard $(UC_PREGEN_FILE)), ) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(BUILD_GENSRC_UC_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(UC_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_UC_EXE) >> $@.tmp + $(BUILD_GENSRC_UC_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ else $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/UnixConstants.java: $(UC_PREGEN_FILE) @@ -132,12 +134,12 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) OUTPUT_DIR := $(GENSRC_SOL_BIN), \ PROGRAM := genSolarisConstants)) - $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE) + $(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/nio/fs/SolarisConstants.java: $(BUILD_GENSRC_SOL_EXE_TARGET) $(MKDIR) -p $(@D) $(RM) $@ $@.tmp NAWK="$(NAWK)" SH="$(SH)" $(SH) -e \ $(JDK_TOPDIR)/make/scripts/addNotices.sh "$(SOL_COPYRIGHT_YEARS)" > $@.tmp - $(BUILD_GENSRC_SOL_EXE) >> $@.tmp + $(BUILD_GENSRC_SOL_EXE_TARGET) >> $@.tmp $(MV) $@.tmp $@ diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk index ad58edb2823..d6ba6443bf2 100644 --- a/jdk/make/lib/Awt2dLibraries.gmk +++ b/jdk/make/lib/Awt2dLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -593,8 +593,8 @@ ifeq ($(BUILD_HEADLESS), true) LDFLAGS_solaris := $(call SET_SHARED_LIBRARY_ORIGIN,/..), \ REORDER := $(LIBAWT_HEADLESS_REORDER), \ LIBS_unix := -lawt -ljvm -ljava, \ - LIBS_linux := -lm $(LIBDL), \ - LIBS_solaris := -lm $(LIBDL) $(LIBCXX) -lc, \ + LIBS_linux := $(LIBM) $(LIBDL), \ + LIBS_solaris := $(LIBM) $(LIBDL) $(LIBCXX) -lc, \ OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libawt_headless, \ )) diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk index ea7c7f3c991..9dcf06be11a 100644 --- a/jdk/make/lib/CoreLibraries.gmk +++ b/jdk/make/lib/CoreLibraries.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -137,12 +137,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) endif endif -ifeq ($(OPENJDK_TARGET_OS), linux) - ifeq ($(OPENJDK_TARGET_CPU), x86_64) - BUILD_LIBJAVA_Bits.c_CFLAGS := $(C_O_FLAG_NORM) - endif -endif - $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBRARY := java, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ @@ -163,7 +157,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \ LIBS_unix := -ljvm -lverify, \ LIBS_linux := $(LIBDL) $(BUILD_LIBFDLIBM), \ LIBS_solaris := -lsocket -lnsl -lscf $(LIBDL) $(BUILD_LIBFDLIBM) -lc, \ - LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) -lm,\ + LIBS_aix := $(LIBDL) $(BUILD_LIBFDLIBM) $(LIBM),\ LIBS_macosx := -lfdlibm \ -framework CoreFoundation \ -framework Foundation \ diff --git a/jdk/make/lib/Lib-java.desktop.gmk b/jdk/make/lib/Lib-java.desktop.gmk index c8bc8195854..5433fe96acb 100644 --- a/jdk/make/lib/Lib-java.desktop.gmk +++ b/jdk/make/lib/Lib-java.desktop.gmk @@ -29,6 +29,7 @@ include LibCommon.gmk $(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.desktop/*/native \ $(JDK_TOPDIR)/src/*/java.desktop/*/native))) +include LibosxLibraries.gmk include PlatformLibraries.gmk include Awt2dLibraries.gmk include SoundLibraries.gmk diff --git a/jdk/make/lib/Lib-java.instrument.gmk b/jdk/make/lib/Lib-java.instrument.gmk index 02df76073af..44ba88dad40 100644 --- a/jdk/make/lib/Lib-java.instrument.gmk +++ b/jdk/make/lib/Lib-java.instrument.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -67,7 +67,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBINSTRUMENT, \ -L$(call FindLibDirForModule, java.base)/jli, \ LDFLAGS_macosx := -Wl$(COMMA)-all_load, \ LDFLAGS_aix := -L$(SUPPORT_OUTPUTDIR)/native/java.base, \ - LDFLAGS_windows := -export:Agent_OnAttach, \ LIBS := $(JDKLIB_LIBS), \ LIBS_unix := -ljava $(LIBZ), \ LIBS_linux := -ljli $(LIBDL), \ diff --git a/jdk/make/lib/Lib-jdk.jdi.gmk b/jdk/make/lib/Lib-jdk.jdi.gmk index 8bed1f9abd1..f74b1c209a6 100644 --- a/jdk/make/lib/Lib-jdk.jdi.gmk +++ b/jdk/make/lib/Lib-jdk.jdi.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk index 198dc2c2433..fb5de3e1f24 100644 --- a/jdk/make/lib/Lib-jdk.jdwp.agent.gmk +++ b/jdk/make/lib/Lib-jdk.jdwp.agent.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it diff --git a/jdk/make/lib/Lib-jdk.deploy.osx.gmk b/jdk/make/lib/LibosxLibraries.gmk similarity index 94% rename from jdk/make/lib/Lib-jdk.deploy.osx.gmk rename to jdk/make/lib/LibosxLibraries.gmk index 881a387e14d..91ab6457cb4 100644 --- a/jdk/make/lib/Lib-jdk.deploy.osx.gmk +++ b/jdk/make/lib/LibosxLibraries.gmk @@ -23,18 +23,15 @@ # questions. # -include LibCommon.gmk - ifeq ($(OPENJDK_TARGET_OS), macosx) ################################################################################ - LIBOSX_DIRS := $(JDK_TOPDIR)/src/jdk.deploy.osx/macosx/native/libosx + LIBOSX_DIRS := $(JDK_TOPDIR)/src/java.desktop/macosx/native/libosx LIBOSX_CFLAGS := -I$(LIBOSX_DIRS) \ -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxapp \ $(LIBJAVA_HEADER_FLAGS) \ -I$(SUPPORT_OUTPUTDIR)/headers/java.desktop \ - -I$(SUPPORT_OUTPUTDIR)/headers/jdk.deploy.osx \ # $(eval $(call SetupNativeCompilation,BUILD_LIBOSX, \ diff --git a/jdk/make/mapfiles/libawt/mapfile-mawt-vers b/jdk/make/mapfiles/libawt/mapfile-mawt-vers index 8f9ee4135a5..247e29698e2 100644 --- a/jdk/make/mapfiles/libawt/mapfile-mawt-vers +++ b/jdk/make/mapfiles/libawt/mapfile-mawt-vers @@ -200,6 +200,7 @@ SUNWprivate_1.1 { Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff --git a/jdk/make/mapfiles/libawt_headless/mapfile-vers b/jdk/make/mapfiles/libawt_headless/mapfile-vers index 5ea1745e296..ac5101042a2 100644 --- a/jdk/make/mapfiles/libawt_headless/mapfile-vers +++ b/jdk/make/mapfiles/libawt_headless/mapfile-vers @@ -73,6 +73,7 @@ SUNWprivate_1.1 { Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff --git a/jdk/make/mapfiles/libawt_xawt/mapfile-vers b/jdk/make/mapfiles/libawt_xawt/mapfile-vers index 182ed0acfd7..42ef24d90a1 100644 --- a/jdk/make/mapfiles/libawt_xawt/mapfile-vers +++ b/jdk/make/mapfiles/libawt_xawt/mapfile-vers @@ -439,6 +439,7 @@ SUNWprivate_1.1 { Java_sun_print_CUPSPrinter_initIDs; Java_sun_print_CUPSPrinter_getCupsServer; Java_sun_print_CUPSPrinter_getCupsPort; + Java_sun_print_CUPSPrinter_getCupsDefaultPrinter; Java_sun_print_CUPSPrinter_canConnect; Java_sun_print_CUPSPrinter_getMedia; Java_sun_print_CUPSPrinter_getPageSizes; diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers index e6e6c6cfee8..ac21dd24890 100644 --- a/jdk/make/mapfiles/libjava/mapfile-vers +++ b/jdk/make/mapfiles/libjava/mapfile-vers @@ -229,12 +229,6 @@ SUNWprivate_1.1 { Java_java_lang_Throwable_fillInStackTrace; Java_java_lang_Throwable_getStackTraceDepth; Java_java_lang_Throwable_getStackTraceElement; - Java_java_nio_Bits_copyFromShortArray; - Java_java_nio_Bits_copyToShortArray; - Java_java_nio_Bits_copyFromIntArray; - Java_java_nio_Bits_copyToIntArray; - Java_java_nio_Bits_copyFromLongArray; - Java_java_nio_Bits_copyToLongArray; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedAction_2Ljava_security_AccessControlContext_2; Java_java_security_AccessController_doPrivileged__Ljava_security_PrivilegedExceptionAction_2; @@ -274,8 +268,6 @@ SUNWprivate_1.1 { Java_sun_reflect_Reflection_getCallerClass__; Java_sun_reflect_Reflection_getCallerClass__I; Java_sun_reflect_Reflection_getClassAccessFlags; - Java_sun_misc_Version_getJdkVersionInfo; - Java_sun_misc_Version_getJvmVersionInfo; Java_jdk_internal_misc_VM_latestUserDefinedLoader; Java_jdk_internal_misc_VM_getuid; Java_jdk_internal_misc_VM_geteuid; diff --git a/jdk/make/mapfiles/libjfr/mapfile-vers b/jdk/make/mapfiles/libjfr/mapfile-vers deleted file mode 100644 index 0bb2cbcb8bc..00000000000 --- a/jdk/make/mapfiles/libjfr/mapfile-vers +++ /dev/null @@ -1,45 +0,0 @@ -# -# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. -# ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. -# - -# Define library interface. - -SUNWprivate_1.1 { - global: - Java_oracle_jrockit_jfr_Process_getpid; - Java_oracle_jrockit_jfr_Timing_counterTime; - Java_oracle_jrockit_jfr_Timing_init; - Java_oracle_jrockit_jfr_Logger_output0; - Java_oracle_jrockit_jfr_JFR_isCommercialFeaturesUnlocked; - Java_oracle_jrockit_jfr_JFR_isStarted; - Java_oracle_jrockit_jfr_JFR_isSupportedInVM; - Java_oracle_jrockit_jfr_JFR_startFlightRecorder; - Java_oracle_jrockit_jfr_JFR_isDisabledOnCommandLine; - Java_oracle_jrockit_jfr_JFR_isEnabled; - Java_oracle_jrockit_jfr_VMJFR_options; - Java_oracle_jrockit_jfr_VMJFR_init; - Java_oracle_jrockit_jfr_VMJFR_addConstPool; - Java_oracle_jrockit_jfr_VMJFR_removeConstPool; - Java_oracle_jrockit_jfr_VMJFR_storeConstPool; - Java_oracle_jrockit_jfr_VMJFR_classID0; - Java_oracle_jrockit_jfr_VMJFR_stackTraceID; - Java_oracle_jrockit_jfr_VMJFR_threadID; - Java_oracle_jrockit_jfr_VMJFR_rotate; - Java_oracle_jrockit_jfr_VMJFR_shutdown; - Java_oracle_jrockit_jfr_VMJFR_start; - Java_oracle_jrockit_jfr_VMJFR_stop; - Java_oracle_jrockit_jfr_VMJFR_buffer; - Java_oracle_jrockit_jfr_VMJFR_flush; - Java_oracle_jrockit_jfr_VMJFR_write; - Java_oracle_jrockit_jfr_VMJFR_add; - Java_oracle_jrockit_jfr_VMJFR_remove; - Java_oracle_jrockit_jfr_VMJFR_setThreshold; - Java_oracle_jrockit_jfr_VMJFR_setPeriod; - Java_oracle_jrockit_jfr_VMJFR_getPeriod; - Java_oracle_jrockit_jfr_VMJFR_descriptors; - Java_oracle_jrockit_jfr_VMJFR_retransformClasses0; - JNI_OnLoad; - local: - *; -}; diff --git a/jdk/make/mapfiles/libnet/mapfile-vers b/jdk/make/mapfiles/libnet/mapfile-vers index a37668a8418..82247780181 100644 --- a/jdk/make/mapfiles/libnet/mapfile-vers +++ b/jdk/make/mapfiles/libnet/mapfile-vers @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -87,6 +87,9 @@ SUNWprivate_1.1 { Java_java_net_PlainSocketImpl_socketConnect; Java_java_net_PlainDatagramSocketImpl_getTimeToLive; Java_java_net_PlainDatagramSocketImpl_setTimeToLive; + Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0; + Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0; + Java_jdk_net_Sockets_isReusePortAvailable0; Java_sun_net_PortConfig_getUpper0; Java_sun_net_PortConfig_getLower0; Java_sun_net_dns_ResolverConfigurationImpl_localDomain0; @@ -112,6 +115,7 @@ SUNWprivate_1.1 { NET_EnableFastTcpLoopback; NET_ThrowNew; ipv6_available; + reuseport_available; initInetAddressIDs; local: diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux index b9b059a80c2..e4563b10c12 100644 --- a/jdk/make/mapfiles/libnio/mapfile-linux +++ b/jdk/make/mapfiles/libnio/mapfile-linux @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -109,6 +109,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_Net_setIntOption0; Java_sun_nio_ch_Net_initIDs; Java_sun_nio_ch_Net_isIPv6Available0; + Java_sun_nio_ch_Net_isReusePortAvailable0; Java_sun_nio_ch_Net_joinOrDrop4; Java_sun_nio_ch_Net_blockOrUnblock4; Java_sun_nio_ch_Net_joinOrDrop6; diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx index 6e4a7fb594c..daee0371e3c 100644 --- a/jdk/make/mapfiles/libnio/mapfile-macosx +++ b/jdk/make/mapfiles/libnio/mapfile-macosx @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -102,6 +102,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_Net_setIntOption0; Java_sun_nio_ch_Net_initIDs; Java_sun_nio_ch_Net_isIPv6Available0; + Java_sun_nio_ch_Net_isReusePortAvailable0; Java_sun_nio_ch_Net_joinOrDrop4; Java_sun_nio_ch_Net_blockOrUnblock4; Java_sun_nio_ch_Net_joinOrDrop6; diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris index 6834bd221d4..a1e0d99b0e6 100644 --- a/jdk/make/mapfiles/libnio/mapfile-solaris +++ b/jdk/make/mapfiles/libnio/mapfile-solaris @@ -1,5 +1,5 @@ # -# Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -97,6 +97,7 @@ SUNWprivate_1.1 { Java_sun_nio_ch_Net_setIntOption0; Java_sun_nio_ch_Net_initIDs; Java_sun_nio_ch_Net_isIPv6Available0; + Java_sun_nio_ch_Net_isReusePortAvailable0; Java_sun_nio_ch_Net_joinOrDrop4; Java_sun_nio_ch_Net_blockOrUnblock4; Java_sun_nio_ch_Net_joinOrDrop6; diff --git a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index c2f16e823cf..500cf2b10e4 100644 --- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -248,10 +248,7 @@ class ResourceBundleGenerator implements BundleGenerator { dir.mkdirs(); } String className = - (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : - "CLDRLocaleDataMetaInfo_" + - CLDRConverter.DESTINATION_DIR.substring(CLDRConverter.DESTINATION_DIR.lastIndexOf('/')+1) - .replaceAll("\\.", "_")); + (CLDRConverter.isBaseModule ? "CLDRBaseLocaleDataMetaInfo" : "CLDRLocaleDataMetaInfo"); File file = new File(dir, className + ".java"); if (!file.exists()) { file.createNewFile(); diff --git a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java index 0dee68e367f..8ef7cfe13b0 100644 --- a/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java +++ b/jdk/make/src/classes/build/tools/dtdbuilder/DTDParser.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -908,16 +908,12 @@ class DTDParser implements DTDConstants { this.dtd = dtd; this.in = new DTDInputStream(in, dtd); - long tm = System.currentTimeMillis(); ch = this.in.read(); parseSection(); if (ch != -1) { error("premature"); } - - tm = System.currentTimeMillis() - tm; - System.err.println("[Parsed DTD " + dtd + " in " + tm + "ms]"); } catch (IOException e) { error("ioexception"); } catch (Exception e) { diff --git a/jdk/make/src/classes/build/tools/module/boot.modules b/jdk/make/src/classes/build/tools/module/boot.modules index f7f21225a5d..0bf1c55fc5d 100644 --- a/jdk/make/src/classes/build/tools/module/boot.modules +++ b/jdk/make/src/classes/build/tools/module/boot.modules @@ -2,6 +2,7 @@ java.base java.compiler java.datatransfer java.desktop +java.httpclient java.instrument java.logging java.management @@ -18,14 +19,15 @@ java.xml java.xml.crypto jdk.charsets jdk.deploy -jdk.deploy.osx jdk.httpserver jdk.jfr +jdk.jsobject jdk.net jdk.vm.cds jdk.vm.ci jdk.management jdk.management.cmm +jdk.management.jfr jdk.management.resource jdk.naming.rmi jdk.sctp diff --git a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c index 41bd5484ab7..aab692f1f19 100644 --- a/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c +++ b/jdk/make/src/native/genconstants/ch/genSocketOptionRegistry.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,21 @@ #include #endif +/* Defines SO_REUSEPORT */ +#if !defined(SO_REUSEPORT) +#ifdef _WIN32 +#define SO_REUSEPORT 0 +#elif __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif + /** * Generates sun.nio.ch.SocketOptionRegistry, a class that maps Java-level * socket options to the platform specific level and option. @@ -102,6 +117,7 @@ int main(int argc, const char* argv[]) { emit_unspec("StandardSocketOptions.SO_SNDBUF", SOL_SOCKET, SO_SNDBUF); emit_unspec("StandardSocketOptions.SO_RCVBUF", SOL_SOCKET, SO_RCVBUF); emit_unspec("StandardSocketOptions.SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR); + emit_unspec("StandardSocketOptions.SO_REUSEPORT", SOL_SOCKET, SO_REUSEPORT); emit_unspec("StandardSocketOptions.TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY); emit_inet("StandardSocketOptions.IP_TOS", IPPROTO_IP, IP_TOS); diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java index d86feab3c2b..06a685b2482 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ import sun.security.provider.ParameterCache; *

  • By providing the size in bits of the prime modulus - * This will be used to create a prime modulus and base generator, which will * then be used to create the Diffie-Hellman key pair. The default size of the - * prime modulus is 1024 bits. + * prime modulus is 2048 bits. *
  • By providing a prime modulus and base generator * * @@ -68,7 +68,7 @@ public final class DHKeyPairGenerator extends KeyPairGeneratorSpi { public DHKeyPairGenerator() { super(); - initialize(1024, null); + initialize(2048, null); } /** diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java index 6f25b699a83..86c4cd900bb 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/DHParameterGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ import javax.crypto.spec.DHGenParameterSpec; * *

    The Diffie-Hellman parameter generation accepts the size in bits of the * prime modulus and the size in bits of the random exponent as input. - * The size of the prime modulus defaults to 1024 bits. + * The size of the prime modulus defaults to 2048 bits. * * @author Jan Luehe * @@ -50,7 +50,7 @@ public final class DHParameterGenerator extends AlgorithmParameterGeneratorSpi { // The size in bits of the prime modulus - private int primeSize = 1024; + private int primeSize = 2048; // The size in bits of the random exponent (private value) private int exponentSize = 0; diff --git a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java index a02aa4bd175..52a9e3e01ab 100644 --- a/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java +++ b/jdk/src/java.base/share/classes/com/sun/crypto/provider/PKCS12PBECipherCore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,6 +50,7 @@ final class PKCS12PBECipherCore { private CipherCore cipher; private int blockSize; private int keySize; + private int keyLength; // in bits private String algo = null; private String pbeAlgo = null; private byte[] salt = null; @@ -166,16 +167,18 @@ final class PKCS12PBECipherCore { throws NoSuchAlgorithmException { algo = symmCipherAlg; + keyLength = defKeySize * 8; if (algo.equals("RC4")) { - pbeAlgo = "PBEWithSHA1AndRC4_" + defKeySize * 8; + pbeAlgo = "PBEWithSHA1AndRC4_" + keyLength; } else { SymmetricCipher symmCipher = null; if (algo.equals("DESede")) { symmCipher = new DESedeCrypt(); pbeAlgo = "PBEWithSHA1AndDESede"; + keyLength = 112; // effective key length } else if (algo.equals("RC2")) { symmCipher = new RC2Crypt(); - pbeAlgo = "PBEWithSHA1AndRC2_" + defKeySize * 8; + pbeAlgo = "PBEWithSHA1AndRC2_" + keyLength; } else { throw new NoSuchAlgorithmException("No Cipher implementation " + "for PBEWithSHA1And" + algo); @@ -406,7 +409,7 @@ final class PKCS12PBECipherCore { } int implGetKeySize(Key key) throws InvalidKeyException { - return keySize; + return keyLength; } byte[] implWrap(Key key) throws IllegalBlockSizeException, diff --git a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java index f1691969666..2aa9ff36a7f 100644 --- a/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java +++ b/jdk/src/java.base/share/classes/java/lang/AbstractStringBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,39 +133,62 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence { } /** - * This method has the same contract as ensureCapacity, but is - * never synchronized. + * For positive values of {@code minimumCapacity}, this method + * behaves like {@code ensureCapacity}, however it is never + * synchronized. + * If {@code minimumCapacity} is non positive due to numeric + * overflow, this method throws {@code OutOfMemoryError}. */ private void ensureCapacityInternal(int minimumCapacity) { // overflow-conscious code - int capacity = value.length >> coder; - if (minimumCapacity - capacity > 0) { - expandCapacity(minimumCapacity); + int oldCapacity = value.length >> coder; + if (minimumCapacity - oldCapacity > 0) { + value = Arrays.copyOf(value, + newCapacity(minimumCapacity) << coder); } } /** - * This implements the expansion semantics of ensureCapacity with no - * size check or synchronization. + * The maximum size of array to allocate (unless necessary). + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit */ - private void expandCapacity(int minimumCapacity) { - int newCapacity = (value.length >> coder) * 2 + 2; - if (newCapacity - minimumCapacity < 0) { - newCapacity = minimumCapacity; + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + + /** + * Returns a capacity at least as large as the given minimum capacity. + * Returns the current capacity increased by the same amount + 2 if + * that suffices. + * Will not return a capacity greater than + * {@code (MAX_ARRAY_SIZE >> coder)} unless the given minimum capacity + * is greater than that. + * + * @param minCapacity the desired minimum capacity + * @throws OutOfMemoryError if minCapacity is less than zero or + * greater than (Integer.MAX_VALUE >> coder) + */ + private int newCapacity(int minCapacity) { + // overflow-conscious code + int oldCapacity = value.length >> coder; + int newCapacity = (oldCapacity << 1) + 2; + if (newCapacity - minCapacity < 0) { + newCapacity = minCapacity; } - if (newCapacity < 0) { - if (minimumCapacity < 0) {// overflow - throw new OutOfMemoryError(); - } - newCapacity = Integer.MAX_VALUE; + int SAFE_BOUND = MAX_ARRAY_SIZE >> coder; + return (newCapacity <= 0 || SAFE_BOUND - newCapacity < 0) + ? hugeCapacity(minCapacity) + : newCapacity; + } + + private int hugeCapacity(int minCapacity) { + int SAFE_BOUND = MAX_ARRAY_SIZE >> coder; + int UNSAFE_BOUND = Integer.MAX_VALUE >> coder; + if (UNSAFE_BOUND - minCapacity < 0) { // overflow + throw new OutOfMemoryError(); } - if (coder != LATIN1 && newCapacity > StringUTF16.MAX_LENGTH) { - if (minimumCapacity >= StringUTF16.MAX_LENGTH) { - throw new OutOfMemoryError(); - } - newCapacity = StringUTF16.MAX_LENGTH; - } - this.value = Arrays.copyOf(value, newCapacity << coder); + return (minCapacity > SAFE_BOUND) + ? minCapacity : SAFE_BOUND; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java index e5fcb94d1b9..91fa5623174 100644 --- a/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/ProcessHandleImpl.java @@ -81,9 +81,8 @@ final class ProcessHandleImpl implements ProcessHandle { ThreadGroup systemThreadGroup = tg; ThreadFactory threadFactory = grimReaper -> { - // Our thread stack requirement is quite modest. - Thread t = new Thread(systemThreadGroup, grimReaper, - "process reaper", 32768); + long stackSize = Boolean.getBoolean("jdk.lang.processReaperUseDefaultStackSize") ? 0 : 32768; + Thread t = new Thread(systemThreadGroup, grimReaper, "process reaper", stackSize); t.setDaemon(true); // A small attempt (probably futile) to avoid priority inversion t.setPriority(Thread.MAX_PRIORITY); diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index 86ec043d5b1..a609223d42f 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -42,6 +42,7 @@ import java.util.regex.PatternSyntaxException; import java.util.stream.IntStream; import java.util.stream.StreamSupport; import jdk.internal.HotSpotIntrinsicCandidate; +import jdk.internal.vm.annotation.Stable; /** * The {@code String} class represents character strings. All @@ -119,7 +120,18 @@ import jdk.internal.HotSpotIntrinsicCandidate; public final class String implements java.io.Serializable, Comparable, CharSequence { - /** The value is used for character storage. */ + /** + * The value is used for character storage. + * + * @implNote This field is trusted by the VM, and is a subject to + * constant folding if String instance is constant. Overwriting this + * field after construction will cause problems. + * + * Additionally, it is marked with {@link Stable} to trust the contents + * of the array. No other facility in JDK provides this functionality (yet). + * {@link Stable} is safe here, because value is never null. + */ + @Stable private final byte[] value; /** @@ -129,6 +141,9 @@ public final class String * LATIN1 * UTF16 * + * @implNote This field is trusted by the VM, and is a subject to + * constant folding if String instance is constant. Overwriting this + * field after construction will cause problems. */ private final byte coder; @@ -1222,30 +1237,12 @@ public final class String public int compare(String s1, String s2) { byte v1[] = s1.value; byte v2[] = s2.value; - int n1 = s1.length(); - int n2 = s2.length(); - boolean s1IsLatin1 = s1.isLatin1(); - boolean s2IsLatin1 = s2.isLatin1(); - int min = Math.min(n1, n2); - for (int i = 0; i < min; i++) { - char c1 = s1IsLatin1 ? StringLatin1.getChar(v1, i) - : StringUTF16.getChar(v1, i); - char c2 = s2IsLatin1 ? StringLatin1.getChar(v2, i) - : StringUTF16.getChar(v2, i); - if (c1 != c2) { - c1 = Character.toUpperCase(c1); - c2 = Character.toUpperCase(c2); - if (c1 != c2) { - c1 = Character.toLowerCase(c1); - c2 = Character.toLowerCase(c2); - if (c1 != c2) { - // No overflow because of numeric promotion - return c1 - c2; - } - } - } + if (s1.coder() == s2.coder()) { + return s1.isLatin1() ? StringLatin1.compareToCI(v1, v2) + : StringUTF16.compareToCI(v1, v2); } - return n1 - n2; + return s1.isLatin1() ? StringLatin1.compareToCI_UTF16(v1, v2) + : StringUTF16.compareToCI_Latin1(v1, v2); } /** Replaces the de-serialized object. */ diff --git a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java index 8e8016d833e..c491f4833e1 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringLatin1.java +++ b/jdk/src/java.base/share/classes/java/lang/StringLatin1.java @@ -128,6 +128,48 @@ final class StringLatin1 { return len1 - len2; } + public static int compareToCI(byte[] value, byte[] other) { + int len1 = value.length; + int len2 = other.length; + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + if (value[k] != other[k]) { + char c1 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(value, k)); + char c2 = (char) CharacterDataLatin1.instance.toUpperCase(getChar(other, k)); + if (c1 != c2) { + c1 = (char) CharacterDataLatin1.instance.toLowerCase(c1); + c2 = (char) CharacterDataLatin1.instance.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + + public static int compareToCI_UTF16(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = StringUTF16.length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = StringUTF16.getChar(other, k); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + c1 = Character.toLowerCase(c1); + c2 = Character.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + public static int hashCode(byte[] value) { int h = 0; for (byte v : value) { diff --git a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java index 937f642ce8d..fe0c964b290 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringUTF16.java +++ b/jdk/src/java.base/share/classes/java/lang/StringUTF16.java @@ -270,6 +270,50 @@ final class StringUTF16 { return len1 - len2; } + public static int compareToCI(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = getChar(other, k); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + c1 = Character.toLowerCase(c1); + c2 = Character.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + + public static int compareToCI_Latin1(byte[] value, byte[] other) { + int len1 = length(value); + int len2 = StringLatin1.length(other); + int lim = Math.min(len1, len2); + for (int k = 0; k < lim; k++) { + char c1 = getChar(value, k); + char c2 = StringLatin1.getChar(other, k); + if (c1 != c2) { + c1 = Character.toUpperCase(c1); + c2 = Character.toUpperCase(c2); + if (c1 != c2) { + c1 = Character.toLowerCase(c1); + c2 = Character.toLowerCase(c2); + if (c1 != c2) { + return c1 - c2; + } + } + } + } + return len1 - len2; + } + public static int hashCode(byte[] value) { int h = 0; int length = value.length >> 1; diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index 1919264ce52..c0c7c05156a 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1418,8 +1418,7 @@ public final class System { * for the given {@code caller}. * * @param name the name of the logger. - * @param caller the class for which the logger is being requested; - * can be {@code null}. + * @param caller the class for which the logger is being requested. * * @return a {@link Logger logger} suitable for the given caller's * use. @@ -1831,7 +1830,7 @@ public final class System { lineSeparator = props.getProperty("line.separator"); - sun.misc.Version.init(); + VersionProps.init(); FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); diff --git a/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template new file mode 100644 index 00000000000..dd0e038936d --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/VersionProps.java.template @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang; + +import java.io.PrintStream; + +class VersionProps { + + + private static final String launcher_name = + "@@LAUNCHER_NAME@@"; + + private static final String java_version = + "@@VERSION_SHORT@@"; + + private static final String java_runtime_name = + "@@RUNTIME_NAME@@"; + + private static final String java_runtime_version = + "@@VERSION_STRING@@"; + + static { + init(); + } + + public static void init() { + System.setProperty("java.version", java_version); + System.setProperty("java.runtime.version", java_runtime_version); + System.setProperty("java.runtime.name", java_runtime_name); + } + + /** + * In case you were wondering this method is called by java -version. + * Sad that it prints to stderr; would be nicer if default printed on + * stdout. + */ + public static void print() { + print(System.err); + } + + /** + * This is the same as print except that it adds an extra line-feed + * at the end, typically used by the -showversion in the launcher + */ + public static void println() { + print(System.err); + System.err.println(); + } + + /** + * Give a stream, it will print version info on it. + */ + public static void print(PrintStream ps) { + boolean isHeadless = false; + + /* Report that we're running headless if the property is true */ + String headless = System.getProperty("java.awt.headless"); + if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) { + isHeadless = true; + } + + /* First line: platform version. */ + ps.println(launcher_name + " version \"" + java_version + "\""); + + /* Second line: runtime version (ie, libraries). */ + + String jdk_debug_level = System.getProperty("jdk.debug", "release"); + /* Debug level is not printed for "release" builds */ + if ("release".equals(jdk_debug_level)) { + jdk_debug_level = ""; + } else { + jdk_debug_level = jdk_debug_level + " "; + } + + ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version); + + if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) { + // embedded builds report headless state + ps.print(", headless"); + } + ps.println(')'); + + /* Third line: JVM information. */ + String java_vm_name = System.getProperty("java.vm.name"); + String java_vm_version = System.getProperty("java.vm.version"); + String java_vm_info = System.getProperty("java.vm.info"); + ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " + + java_vm_info + ")"); + } + +} \ No newline at end of file diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index a3f6f47b00f..235ffe60f57 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1026,6 +1026,9 @@ MethodHandle longsToString = publicLookup() .asCollector(long[].class, 1); assertEquals("[123]", (String) longsToString.invokeExact((long)123)); * } + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument * @return a new method handle which collects some trailing argument @@ -1067,6 +1070,9 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1); assertEquals("BCPQRSZ", swr.toString()); * } + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param collectArgPos the zero-based position in the parameter list at which to start collecting. * @param arrayType often {@code Object[]}, the type of the array argument which will collect the arguments * @param arrayLength the number of arguments to collect into a new array argument @@ -1356,8 +1362,11 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); * The reference {@code x} must be convertible to the first parameter * type of the target. *

    - * (Note: Because method handles are immutable, the target method handle - * retains its original type and behavior.) + * Note: Because method handles are immutable, the target method handle + * retains its original type and behavior. + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param x the value to bind to the first argument of the target * @return a new method handle which prepends the given value to the incoming * argument list, before calling the original method handle diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index ebaf2a393ad..9b4029cc7b5 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -778,8 +778,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return (asTypeCache = wrapper); } + // Customize target if counting happens for too long. + private int invocations = CUSTOMIZE_THRESHOLD; + private void maybeCustomizeTarget() { + int c = invocations; + if (c >= 0) { + if (c == 1) { + target.customize(); + } + invocations = c - 1; + } + } + boolean countDown() { int c = count; + maybeCustomizeTarget(); if (c <= 1) { // Try to limit number of updates. MethodHandle.updateForm() doesn't guarantee LF update visibility. if (isCounting) { diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java index e9bb8046246..57ad668b903 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java @@ -30,7 +30,7 @@ import java.lang.reflect.Field; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; -import jdk.internal.ref.Cleaner; +import jdk.internal.ref.CleanerFactory; /** * The JVM interface for the method handles package is all here. @@ -68,10 +68,12 @@ class MethodHandleNatives { static CallSiteContext make(CallSite cs) { final CallSiteContext newContext = new CallSiteContext(); - // Cleaner is attached to CallSite instance and it clears native structures allocated for CallSite context. - // Though the CallSite can become unreachable, its Context is retained by the Cleaner instance (which is - // referenced from Cleaner class) until cleanup is performed. - Cleaner.create(cs, newContext); + // CallSite instance is tracked by a Cleanable which clears native + // structures allocated for CallSite context. Though the CallSite can + // become unreachable, its Context is retained by the Cleanable instance + // (which is referenced from Cleaner instance which is referenced from + // CleanerFactory class) until cleanup is performed. + CleanerFactory.cleaner().register(cs, newContext); return newContext; } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index fc9ac8e1518..70791273212 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -2139,7 +2139,7 @@ return invoker; * if its index does not appear in the array. * As in the case of {@link #dropArguments(MethodHandle,int,List) dropArguments}, * incoming arguments which are not mentioned in the reordering array - * are may be any type, as determined only by {@code newType}. + * may be of any type, as determined only by {@code newType}. *

    {@code
     import static java.lang.invoke.MethodHandles.*;
     import static java.lang.invoke.MethodType.*;
    @@ -2157,6 +2157,9 @@ MethodHandle twice = permuteArguments(add, intfn1, 0, 0);
     assert(twice.type().equals(intfn1));
     assert((int)twice.invokeExact(21) == 42);
          * }
    + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after arguments are reordered * @param newType the expected type of the new method handle * @param reorder an index array which controls the reordering @@ -2421,6 +2424,9 @@ assert((int)twice.invokeExact(21) == 42); * It may range between zero and N-L (inclusively), * where N is the arity of the target method handle * and L is the length of the values array. + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after the argument is inserted * @param pos where to insert the argument (zero for the first) * @param values the series of arguments to insert @@ -2639,14 +2645,25 @@ assertEquals("xY", (String) f1.invokeExact("x", "y")); // xY MethodHandle f2 = filterArguments(cat, 0, upcase, upcase); assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY * } - *

    Here is pseudocode for the resulting adapter: + *

    Here is pseudocode for the resulting adapter. In the code, {@code T} + * denotes the return type of both the {@code target} and resulting adapter. + * {@code P}/{@code p} and {@code B}/{@code b} represent the types and values + * of the parameters and arguments that precede and follow the filter position + * {@code pos}, respectively. {@code A[i]}/{@code a[i]} stand for the types and + * values of the filtered parameters and arguments; they also represent the + * return types of the {@code filter[i]} handles. The latter accept arguments + * {@code v[i]} of type {@code V[i]}, which also appear in the signature of + * the resulting adapter. *

    {@code
    -     * V target(P... p, A[i]... a[i], B... b);
    +     * T target(P... p, A[i]... a[i], B... b);
          * A[i] filter[i](V[i]);
          * T adapter(P... p, V[i]... v[i], B... b) {
    -     *   return target(p..., f[i](v[i])..., b...);
    +     *   return target(p..., filter[i](v[i])..., b...);
          * }
          * }
    + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after arguments are filtered * @param pos the position of the first argument to filter @@ -2753,7 +2770,17 @@ MethodHandle ts3_ts2_ts3 = collectArguments(ts3_ts2, 1, ts3); assertEquals("[top, [[up, down, strange], charm], bottom]", (String) ts3_ts2_ts3.invokeExact("top", "up", "down", "strange", "charm", "bottom")); * } - *

    Here is pseudocode for the resulting adapter: + *

    Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the return type of the {@code target} and resulting adapter. + * {@code V}/{@code v} stand for the return type and value of the + * {@code filter}, which are also found in the signature and arguments of + * the {@code target}, respectively, unless {@code V} is {@code void}. + * {@code A}/{@code a} and {@code C}/{@code c} represent the parameter types + * and values preceding and following the collection position, {@code pos}, + * in the {@code target}'s signature. They also turn up in the resulting + * adapter's signature and arguments, where they surround + * {@code B}/{@code b}, which represent the parameter types and arguments + * to the {@code filter} (if any). *

    {@code
          * T target(A...,V,C...);
          * V filter(B...);
    @@ -2771,7 +2798,7 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
          * // and if the filter has a void return:
          * T target3(A...,C...);
          * void filter3(B...);
    -     * void adapter3(A... a,B... b,C... c) {
    +     * T adapter3(A... a,B... b,C... c) {
          *   filter3(b...);
          *   return target3(a...,c...);
          * }
    @@ -2791,6 +2818,9 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
          * a non-void result, then {@code collectArguments(mh, N, coll)}
          * is equivalent to {@code filterArguments(mh, N, coll)}.
          * Other equivalences are possible but would require argument permutation.
    +     * 

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after filtering the subsequence of arguments * @param pos the position of the first adapter argument to pass to the filter, @@ -2864,29 +2894,36 @@ System.out.println((String) cat.invokeExact("x", "y")); // xy MethodHandle f0 = filterReturnValue(cat, length); System.out.println((int) f0.invokeExact("x", "y")); // 2 * }

    - *

    Here is pseudocode for the resulting adapter: + *

    Here is pseudocode for the resulting adapter. In the code, + * {@code T}/{@code t} represent the result type and value of the + * {@code target}; {@code V}, the result type of the {@code filter}; and + * {@code A}/{@code a}, the types and values of the parameters and arguments + * of the {@code target} as well as the resulting adapter. *

    {@code
    -     * V target(A...);
    -     * T filter(V);
    -     * T adapter(A... a) {
    -     *   V v = target(a...);
    -     *   return filter(v);
    +     * T target(A...);
    +     * V filter(T);
    +     * V adapter(A... a) {
    +     *   T t = target(a...);
    +     *   return filter(t);
          * }
          * // and if the target has a void return:
          * void target2(A...);
    -     * T filter2();
    -     * T adapter2(A... a) {
    +     * V filter2();
    +     * V adapter2(A... a) {
          *   target2(a...);
          *   return filter2();
          * }
          * // and if the filter has a void return:
    -     * V target3(A...);
    +     * T target3(A...);
          * void filter3(V);
          * void adapter3(A... a) {
    -     *   V v = target3(a...);
    -     *   filter3(v);
    +     *   T t = target3(a...);
    +     *   filter3(t);
          * }
          * }
    + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke before filtering the return value * @param filter method handle to call on the return value * @return method handle which incorporates the specified return value filtering logic @@ -2964,7 +3001,15 @@ MethodHandle catTrace = foldArguments(cat, trace); // also prints "boo": assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * } - *

    Here is pseudocode for the resulting adapter: + *

    Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the result type of the {@code target} and resulting adapter. + * {@code V}/{@code v} represent the type and value of the parameter and argument + * of {@code target} that precedes the folding position; {@code V} also is + * the result type of the {@code combiner}. {@code A}/{@code a} denote the + * types and values of the {@code N} parameters and arguments at the folding + * position. {@code B}/{@code b} represent the types and values of the + * {@code target} parameters and arguments that follow the folded parameters + * and arguments. *

    {@code
          * // there are N arguments in A...
          * T target(V, A[N]..., B...);
    @@ -2981,6 +3026,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          *   return target2(a..., b...);
          * }
          * }
    + *

    + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * @param target the method handle to invoke after arguments are combined * @param combiner method handle to call initially on the incoming arguments * @return method handle which incorporates the specified argument folding logic @@ -3022,7 +3070,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * argument and return types, except that the return type * of the test must be boolean, and the test is allowed * to have fewer arguments than the other two method handles. - *

    Here is pseudocode for the resulting adapter: + *

    + * Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the uniform result type of the three involved handles; + * {@code A}/{@code a}, the types and values of the {@code target} + * parameters and arguments that are consumed by the {@code test}; and + * {@code B}/{@code b}, those types and values of the {@code target} + * parameters and arguments that are not consumed by the {@code test}. *

    {@code
          * boolean test(A...);
          * T target(A...,B...);
    @@ -3084,7 +3138,13 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * argument and return types, except that handler may omit trailing arguments
          * (similarly to the predicate in {@link #guardWithTest guardWithTest}).
          * Also, the handler must have an extra leading parameter of {@code exType} or a supertype.
    -     * 

    Here is pseudocode for the resulting adapter: + *

    + * Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the return type of the {@code target} and {@code handler}, + * and correspondingly that of the resulting adapter; {@code A}/{@code a}, + * the types and values of arguments to the resulting handle consumed by + * {@code handler}; and {@code B}/{@code b}, those of arguments to the + * resulting handle discarded by {@code handler}. *

    {@code
          * T target(A..., B...);
          * T handler(ExType, A...);
    @@ -3208,12 +3268,17 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          * 
  • This list of types is called the "common prefix". * *

    - * Step 1B: Determine loop parameters.

      - *
    1. Examine init function parameter lists. - *
    2. Omitted init functions are deemed to have {@code null} parameter lists. - *
    3. All init function parameter lists must be effectively identical. - *
    4. The longest parameter list (which is necessarily unique) is called the "common suffix". + * Step 1B: Determine loop parameters.
        + *
      • If at least one init function is given,
          + *
        1. Examine init function parameter lists. + *
        2. Omitted init functions are deemed to have {@code null} parameter lists. + *
        3. All init function parameter lists must be effectively identical. + *
        4. The longest parameter list (which is necessarily unique) is called the "common suffix". *
        + *
      • If no init function is given,
          + *
        1. Examine the suffixes of the step, pred, and fini parameter lists, after removing the "common prefix". + *
        2. The longest of these suffixes is taken as the "common suffix". + *
      *

      * Step 1C: Determine loop return type.

        *
      1. Examine fini function return types, disregarding omitted fini functions. @@ -3226,9 +3291,6 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); *
      2. Every non-omitted pred function must have a {@code boolean} return type. *
      *

      - * (Implementation Note: Steps 1A, 1B, 1C, 1D are logically independent of each other, and may be performed in any - * order.) - *

      * Step 2: Determine parameter lists.

        *
      1. The parameter list for the resulting loop handle will be the "common suffix". *
      2. The parameter list for init functions will be adjusted to the "common suffix". (Note that their parameter @@ -3315,10 +3377,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); *
        {@code
              * // iterative implementation of the factorial function as a loop handle
              * static int one(int k) { return 1; }
        -     * int inc(int i, int acc, int k) { return i + 1; }
        -     * int mult(int i, int acc, int k) { return i * acc; }
        -     * boolean pred(int i, int acc, int k) { return i < k; }
        -     * int fin(int i, int acc, int k) { return acc; }
        +     * static int inc(int i, int acc, int k) { return i + 1; }
        +     * static int mult(int i, int acc, int k) { return i * acc; }
        +     * static boolean pred(int i, int acc, int k) { return i < k; }
        +     * static int fin(int i, int acc, int k) { return acc; }
              * // assume MH_one, MH_inc, MH_mult, MH_pred, and MH_fin are handles to the above methods
              * // null initializer for counter, should initialize to 0
              * MethodHandle[] counterClause = new MethodHandle[]{null, MH_inc};
        @@ -3376,9 +3438,7 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
                         collect(Collectors.toList());
         
                 // Step 1B: determine loop parameters.
        -        final List> empty = new ArrayList<>();
        -        final List> commonSuffix = init.stream().filter(Objects::nonNull).map(MethodHandle::type).
        -                map(MethodType::parameterList).reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty);
        +        final List> commonSuffix = buildCommonSuffix(init, step, pred, fini, commonPrefix.size());
                 checkLoop1b(init, commonSuffix);
         
                 // Step 1C: determine loop return type.
        @@ -3460,15 +3520,15 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
              * @apiNote Example:
              * 
        {@code
              * // implement the zip function for lists as a loop handle
        -     * List initZip(Iterator a, Iterator b) { return new ArrayList<>(); }
        -     * boolean zipPred(List zip, Iterator a, Iterator b) { return a.hasNext() && b.hasNext(); }
        -     * List zipStep(List zip, Iterator a, Iterator b) {
        +     * static List initZip(Iterator a, Iterator b) { return new ArrayList<>(); }
        +     * static boolean zipPred(List zip, Iterator a, Iterator b) { return a.hasNext() && b.hasNext(); }
        +     * static List zipStep(List zip, Iterator a, Iterator b) {
              *   zip.add(a.next());
              *   zip.add(b.next());
              *   return zip;
              * }
              * // assume MH_initZip, MH_zipPred, and MH_zipStep are handles to the above methods
        -     * MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred);
        +     * MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep);
              * List a = Arrays.asList("a", "b", "c", "d");
              * List b = Arrays.asList("e", "f", "g", "h");
              * List zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h");
        @@ -3534,9 +3594,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
              * @apiNote Example:
              * 
        {@code
              * // int i = 0; while (i < limit) { ++i; } return i; => limit
        -     * int zero(int limit) { return 0; }
        -     * int step(int i, int limit) { return i + 1; }
        -     * boolean pred(int i, int limit) { return i < limit; }
        +     * static int zero(int limit) { return 0; }
        +     * static int step(int i, int limit) { return i + 1; }
        +     * static boolean pred(int i, int limit) { return i < limit; }
              * // assume MH_zero, MH_step, and MH_pred are handles to the above methods
              * MethodHandle loop = MethodHandles.doWhileLoop(MH_zero, MH_step, MH_pred);
              * assertEquals(23, loop.invoke(23));
        @@ -3604,8 +3664,8 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
              * 
        {@code
              * // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s;
              * // => a variation on a well known theme
        -     * String start(String arg) { return arg; }
        -     * String step(int counter, String v, String arg) { return "na " + v; }
        +     * static String start(String arg) { return arg; }
        +     * static String step(int counter, String v, String arg) { return "na " + v; }
              * // assume MH_start and MH_step are handles to the two methods above
              * MethodHandle fit13 = MethodHandles.constant(int.class, 13);
              * MethodHandle loop = MethodHandles.countedLoop(fit13, MH_start, MH_step);
        @@ -3748,11 +3808,11 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
              * @apiNote Example:
              * 
        {@code
              * // reverse a list
        -     * List reverseStep(String e, List r, List l) {
        +     * static List reverseStep(String e, List r, List l) {
              *   r.add(0, e);
              *   return r;
              * }
        -     * List newArrayList(List l) { return new ArrayList<>(); }
        +     * static List newArrayList(List l) { return new ArrayList<>(); }
              * // assume MH_reverseStep, MH_newArrayList are handles to the above methods
              * MethodHandle loop = MethodHandles.iteratedLoop(null, MH_newArrayList, MH_reverseStep);
              * List list = Arrays.asList("a", "b", "c", "d", "e");
        @@ -3828,8 +3888,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
              * (Note that, except for argument type conversions, combinators represent {@code void} values in parameter lists
              * by omitting the corresponding paradoxical arguments, not by inserting {@code null} or zero values.)
              * 

        - * The {@code target} and {@code cleanup} handles' return types must be the same. Their parameter type lists also - * must be the same, but the {@code cleanup} handle must accept one or two more leading parameters:

          + * The {@code target} and {@code cleanup} handles must have the same corresponding argument and return types, except + * that the {@code cleanup} handle may omit trailing arguments. Also, the {@code cleanup} handle must have one or + * two extra leading parameters:
            *
          • a {@code Throwable}, which will carry the exception thrown by the {@code target} handle (if any); and *
          • a parameter of the same type as the return type of both {@code target} and {@code cleanup}, which will carry * the result from the execution of the {@code target} handle. @@ -3932,7 +3993,16 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); // also prints "jum": assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); * }
        - *

        Here is pseudocode for the resulting adapter: + *

        Here is pseudocode for the resulting adapter. In the code, {@code T} + * represents the result type of the {@code target} and resulting adapter. + * {@code V}/{@code v} represent the type and value of the parameter and argument + * of {@code target} that precedes the folding position; {@code V} also is + * the result type of the {@code combiner}. {@code A}/{@code a} denote the + * types and values of the {@code N} parameters and arguments at the folding + * position. {@code Z}/{@code z} and {@code B}/{@code b} represent the types + * and values of the {@code target} parameters and arguments that precede and + * follow the folded parameters and arguments starting at {@code pos}, + * respectively. *

        {@code
              * // there are N arguments in A...
              * T target(Z..., V, A[N]..., B...);
        @@ -3949,6 +4019,9 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
              *   return target2(z..., a..., b...);
              * }
              * }
        + *

        + * Note: The resulting adapter is never a {@linkplain MethodHandle#asVarargsCollector + * variable-arity method handle}, even if the original target method handle was. * * @param target the method handle to invoke after arguments are combined * @param pos the position at which to start folding and at which to insert the folding result; if this is {@code @@ -4011,6 +4084,21 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); } } + private static List> buildCommonSuffix(List init, List step, List pred, List fini, int cpSize) { + final List> empty = List.of(); + final List nonNullInits = init.stream().filter(Objects::nonNull).collect(Collectors.toList()); + if (nonNullInits.isEmpty()) { + final List> longest = Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull). + // take only those that can contribute to a common suffix because they are longer than the prefix + map(MethodHandle::type).filter(t -> t.parameterCount() > cpSize).map(MethodType::parameterList). + reduce((p, q) -> p.size() >= q.size() ? p : q).orElse(empty); + return longest.size() == 0 ? empty : longest.subList(cpSize, longest.size()); + } else { + return nonNullInits.stream().map(MethodHandle::type).map(MethodType::parameterList). + reduce((p, q) -> p.size() >= q.size() ? p : q).get(); + } + } + private static void checkLoop1b(List init, List> commonSuffix) { if (init.stream().filter(Objects::nonNull).map(MethodHandle::type).map(MethodType::parameterList). anyMatch(pl -> !pl.equals(commonSuffix.subList(0, pl.size())))) { @@ -4036,8 +4124,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); } private static void checkLoop2(List step, List pred, List fini, List> commonParameterSequence) { + final int cpSize = commonParameterSequence.size(); if (Stream.of(step, pred, fini).flatMap(List::stream).filter(Objects::nonNull).map(MethodHandle::type). - map(MethodType::parameterList).anyMatch(pl -> !pl.equals(commonParameterSequence.subList(0, pl.size())))) { + map(MethodType::parameterList). + anyMatch(pl -> pl.size() > cpSize || !pl.equals(commonParameterSequence.subList(0, pl.size())))) { throw newIllegalArgumentException("found non-effectively identical parameter type lists:\nstep: " + step + "\npred: " + pred + "\nfini: " + fini + " (common parameter sequence: " + commonParameterSequence + ")"); } @@ -4064,8 +4154,10 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); // The cleanup parameter list (minus the leading Throwable and result parameters) must be a sublist of the // target parameter list. int cleanupArgIndex = rtype == void.class ? 1 : 2; - if (!cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size()). - equals(target.type().parameterList().subList(0, cleanupParamTypes.size() - cleanupArgIndex))) { + List> cleanupArgSuffix = cleanupParamTypes.subList(cleanupArgIndex, cleanupParamTypes.size()); + List> targetParamTypes = target.type().parameterList(); + if (targetParamTypes.size() < cleanupArgSuffix.size() || + !cleanupArgSuffix.equals(targetParamTypes.subList(0, cleanupParamTypes.size() - cleanupArgIndex))) { throw misMatchedTypes("cleanup parameters after (Throwable,result) and target parameter list prefix", cleanup.type(), target.type()); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java index 5fb5277e798..9a4cecdc561 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/StringConcatFactory.java @@ -91,7 +91,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; * can call with more than 255 slots. This limits the number of static and * dynamic arguments one can pass to bootstrap method. Since there are potential * concatenation strategies that use {@code MethodHandle} combinators, we need - * to reserve a few empty slots on the parameter lists to to capture the + * to reserve a few empty slots on the parameter lists to capture the * temporal results. This is why bootstrap methods in this factory do not accept * more than 200 argument slots. Users requiring more than 200 argument slots in * concatenation are expected to split the large concatenation in smaller diff --git a/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java b/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java index bee049ec8fe..63bd43c53c1 100644 --- a/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java +++ b/jdk/src/java.base/share/classes/java/lang/ref/Cleaner.java @@ -25,10 +25,11 @@ package java.lang.ref; +import jdk.internal.ref.CleanerImpl; + import java.util.Objects; import java.util.concurrent.ThreadFactory; - -import jdk.internal.ref.CleanerImpl; +import java.util.function.Function; /** * {@code Cleaner} manages a set of object references and corresponding cleaning actions. @@ -135,7 +136,12 @@ public final class Cleaner { final CleanerImpl impl; static { - CleanerImpl.setCleanerImplAccess((Cleaner c) -> c.impl); + CleanerImpl.setCleanerImplAccess(new Function() { + @Override + public CleanerImpl apply(Cleaner cleaner) { + return cleaner.impl; + } + }); } /** diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java index 1f9eba1300e..7a9b7fc17ed 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,9 @@ import java.io.FileDescriptor; import java.io.IOException; import java.security.AccessController; import sun.net.ResourceManager; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; /** * Abstract datagram and multicast socket implementation base class. @@ -70,6 +73,45 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl }); } + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; + + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + + private static volatile Set> socketOptions; + + /** + * Returns a set of SocketOptions supported by this impl + * and by this impl's socket (Socket or ServerSocket) + * + * @return a Set of SocketOptions + */ + @Override + protected Set> supportedOptions() { + Set> options = socketOptions; + if (options == null) { + if (isReusePortAvailable()) { + options = new HashSet<>(); + options.addAll(super.supportedOptions()); + options.add(StandardSocketOptions.SO_REUSEPORT); + options = Collections.unmodifiableSet(options); + } else { + options = super.supportedOptions(); + } + socketOptions = options; + } + return options; + } + /** * Creates a datagram socket */ @@ -303,6 +345,14 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl if (o == null || !(o instanceof Boolean)) throw new SocketException("bad argument for IP_MULTICAST_LOOP"); break; + case SO_REUSEPORT: + if (o == null || !(o instanceof Boolean)) { + throw new SocketException("bad argument for SO_REUSEPORT"); + } + if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } + break; default: throw new SocketException("invalid option: " + optID); } @@ -343,6 +393,13 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl result = socketGetOption(optID); break; + case SO_REUSEPORT: + if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } + result = socketGetOption(optID); + break; + default: throw new SocketException("invalid option: " + optID); } @@ -364,4 +421,5 @@ abstract class AbstractPlainDatagramSocketImpl extends DatagramSocketImpl } abstract int dataAvailable(); + private static native boolean isReusePortAvailable0(); } diff --git a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java index 8841e4fe724..c9afa2657a2 100644 --- a/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/AbstractPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,9 @@ import java.io.FileDescriptor; import sun.net.ConnectionResetException; import sun.net.NetHooks; import sun.net.ResourceManager; +import java.util.Set; +import java.util.HashSet; +import java.util.Collections; /** * Default Socket Implementation. This implementation does @@ -87,6 +90,45 @@ abstract class AbstractPlainSocketImpl extends SocketImpl }); } + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; + + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + + private static volatile Set> socketOptions; + + /** + * Returns a set of SocketOptions supported by this impl + * and by this impl's socket (Socket or ServerSocket) + * + * @return a Set of SocketOptions + */ + @Override + protected Set> supportedOptions() { + Set> options = socketOptions; + if (options == null) { + if (isReusePortAvailable()) { + options = new HashSet<>(); + options.addAll(super.supportedOptions()); + options.add(StandardSocketOptions.SO_REUSEPORT); + options = Collections.unmodifiableSet(options); + } else { + options = super.supportedOptions(); + } + socketOptions = options; + } + return options; + } + /** * Creates a socket with a boolean that specifies whether this * is a stream socket (true) or an unconnected UDP socket (false). @@ -269,6 +311,13 @@ abstract class AbstractPlainSocketImpl extends SocketImpl throw new SocketException("bad parameter for SO_REUSEADDR"); on = ((Boolean)val).booleanValue(); break; + case SO_REUSEPORT: + if (val == null || !(val instanceof Boolean)) + throw new SocketException("bad parameter for SO_REUSEPORT"); + if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) + throw new UnsupportedOperationException("unsupported option"); + on = ((Boolean)val).booleanValue(); + break; default: throw new SocketException("unrecognized TCP option: " + opt); } @@ -326,6 +375,12 @@ abstract class AbstractPlainSocketImpl extends SocketImpl case SO_KEEPALIVE: ret = socketGetOption(opt, null); return Boolean.valueOf(ret != -1); + case SO_REUSEPORT: + if (!supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } + ret = socketGetOption(opt, null); + return Boolean.valueOf(ret != -1); // should never get here default: return null; @@ -723,4 +778,6 @@ abstract class AbstractPlainSocketImpl extends SocketImpl public static final int SHUT_RD = 0; public static final int SHUT_WR = 1; + + private static native boolean isReusePortAvailable0(); } diff --git a/jdk/src/java.base/share/classes/java/net/Authenticator.java b/jdk/src/java.base/share/classes/java/net/Authenticator.java index e62e169099c..8b59db010f3 100644 --- a/jdk/src/java.base/share/classes/java/net/Authenticator.java +++ b/jdk/src/java.base/share/classes/java/net/Authenticator.java @@ -319,6 +319,48 @@ class Authenticator { } } + /** + * Ask this authenticator for a password. + * + * @param host The hostname of the site requesting authentication. + * @param addr The InetAddress of the site requesting authorization, + * or null if not known. + * @param port the port for the requested connection + * @param protocol The protocol that's requesting the connection + * ({@link java.net.Authenticator#getRequestingProtocol()}) + * @param prompt A prompt string for the user + * @param scheme The authentication scheme + * @param url The requesting URL that caused the authentication + * @param reqType The type (server or proxy) of the entity requesting + * authentication. + * + * @return The username/password, or null if one can't be gotten + * + * @since 9 + */ + public PasswordAuthentication + requestPasswordAuthenticationInstance(String host, + InetAddress addr, + int port, + String protocol, + String prompt, + String scheme, + URL url, + RequestorType reqType) { + synchronized (this) { + this.reset(); + this.requestingHost = host; + this.requestingSite = addr; + this.requestingPort = port; + this.requestingProtocol = protocol; + this.requestingPrompt = prompt; + this.requestingScheme = scheme; + this.requestingURL = url; + this.requestingAuthType = reqType; + return this.getPasswordAuthentication(); + } + } + /** * Gets the {@code hostname} of the * site or proxy requesting authentication, or {@code null} diff --git a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java index 97526bc3712..98f06833f9c 100644 --- a/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/DatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,7 @@ package java.net; import java.io.FileDescriptor; import java.io.IOException; -import java.io.InterruptedIOException; import java.util.Set; -import java.util.HashSet; /** * Abstract datagram and multicast socket implementation base class. @@ -287,6 +285,9 @@ public abstract class DatagramSocketImpl implements SocketOptions { setOption(SocketOptions.SO_RCVBUF, value); } else if (name == StandardSocketOptions.SO_REUSEADDR) { setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + setOption(SocketOptions.SO_REUSEPORT, value); } else if (name == StandardSocketOptions.IP_TOS) { setOption(SocketOptions.IP_TOS, value); } else if (name == StandardSocketOptions.IP_MULTICAST_IF && @@ -329,6 +330,9 @@ public abstract class DatagramSocketImpl implements SocketOptions { return (T) getOption(SocketOptions.SO_RCVBUF); } else if (name == StandardSocketOptions.SO_REUSEADDR) { return (T) getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + return (T) getOption(SocketOptions.SO_REUSEPORT); } else if (name == StandardSocketOptions.IP_TOS) { return (T) getOption(SocketOptions.IP_TOS); } else if (name == StandardSocketOptions.IP_MULTICAST_IF && @@ -346,32 +350,32 @@ public abstract class DatagramSocketImpl implements SocketOptions { } } - private static final Set> dgSocketOptions = - new HashSet<>(); + private static final Set> dgSocketOptions; - private static final Set> mcSocketOptions = - new HashSet<>(); + private static final Set> mcSocketOptions; static { - dgSocketOptions.add(StandardSocketOptions.SO_SNDBUF); - dgSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - dgSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - dgSocketOptions.add(StandardSocketOptions.IP_TOS); + dgSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS); - mcSocketOptions.add(StandardSocketOptions.SO_SNDBUF); - mcSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - mcSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - mcSocketOptions.add(StandardSocketOptions.IP_TOS); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_IF); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_TTL); - mcSocketOptions.add(StandardSocketOptions.IP_MULTICAST_LOOP); - }; + mcSocketOptions = Set.of(StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS, + StandardSocketOptions.IP_MULTICAST_IF, + StandardSocketOptions.IP_MULTICAST_TTL, + StandardSocketOptions.IP_MULTICAST_LOOP); + } /** * Returns a set of SocketOptions supported by this impl * and by this impl's socket (DatagramSocket or MulticastSocket) * * @return a Set of SocketOptions + * + * @since 9 */ protected Set> supportedOptions() { if (getDatagramSocket() instanceof MulticastSocket) { diff --git a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java index 70dedec795e..4c7e0ab6f94 100644 --- a/jdk/src/java.base/share/classes/java/net/JarURLConnection.java +++ b/jdk/src/java.base/share/classes/java/net/JarURLConnection.java @@ -173,6 +173,14 @@ public abstract class JarURLConnection extends URLConnection { } jarFileURL = new URL(spec.substring(0, separator++)); + /* + * The url argument may have had a runtime fragment appended, so + * we need to add a runtime fragment to the jarFileURL to enable + * runtime versioning when the underlying jar file is opened. + */ + if ("runtime".equals(url.getRef())) { + jarFileURL = new URL(jarFileURL, "#runtime"); + } entryName = null; /* if ! is the last letter of the innerURL, entryName is null */ diff --git a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java index 77c6e198ab0..365092b1e07 100644 --- a/jdk/src/java.base/share/classes/java/net/MulticastSocket.java +++ b/jdk/src/java.base/share/classes/java/net/MulticastSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -98,7 +98,11 @@ class MulticastSocket extends DatagramSocket { *

        * When the socket is created the * {@link DatagramSocket#setReuseAddress(boolean)} method is - * called to enable the SO_REUSEADDR socket option. + * called to enable the SO_REUSEADDR socket option. When + * {@link StandardSocketOptions#SO_REUSEPORT SO_REUSEPORT} is + * supported then + * {@link DatagramSocketImpl#setOption(SocketOption, Object)} + * is called to enable the socket option. * * @exception IOException if an I/O exception occurs * while creating the MulticastSocket @@ -106,6 +110,7 @@ class MulticastSocket extends DatagramSocket { * {@code checkListen} method doesn't allow the operation. * @see SecurityManager#checkListen * @see java.net.DatagramSocket#setReuseAddress(boolean) + * @see java.net.DatagramSocketImpl#setOption(SocketOption, Object) */ public MulticastSocket() throws IOException { this(new InetSocketAddress(0)); @@ -167,6 +172,11 @@ class MulticastSocket extends DatagramSocket { // Enable SO_REUSEADDR before binding setReuseAddress(true); + // Enable SO_REUSEPORT if supported before binding + if (supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + this.setOption(StandardSocketOptions.SO_REUSEPORT, true); + } + if (bindaddr != null) { try { bind(bindaddr); diff --git a/jdk/src/java.base/share/classes/java/net/ProxySelector.java b/jdk/src/java.base/share/classes/java/net/ProxySelector.java index d6bb53656fd..04c675cedc8 100644 --- a/jdk/src/java.base/share/classes/java/net/ProxySelector.java +++ b/jdk/src/java.base/share/classes/java/net/ProxySelector.java @@ -162,4 +162,49 @@ public abstract class ProxySelector { * @throws IllegalArgumentException if either argument is null */ public abstract void connectFailed(URI uri, SocketAddress sa, IOException ioe); + + /** + * Returns a ProxySelector which uses the given proxy address for all HTTP + * and HTTPS requests. If proxy is {@code null} then proxying is disabled. + * + * @param proxyAddress + * The address of the proxy + * + * @return a ProxySelector + * + * @since 9 + */ + public static ProxySelector of(InetSocketAddress proxyAddress) { + return new StaticProxySelector(proxyAddress); + } + + static class StaticProxySelector extends ProxySelector { + private static final List NO_PROXY_LIST = List.of(Proxy.NO_PROXY); + final List list; + + StaticProxySelector(InetSocketAddress address){ + Proxy p; + if (address == null) { + p = Proxy.NO_PROXY; + } else { + p = new Proxy(Proxy.Type.HTTP, address); + } + list = List.of(p); + } + + @Override + public void connectFailed(URI uri, SocketAddress sa, IOException e) { + /* ignore */ + } + + @Override + public synchronized List select(URI uri) { + String scheme = uri.getScheme().toLowerCase(); + if (scheme.equals("http") || scheme.equals("https")) { + return list; + } else { + return NO_PROXY_LIST; + } + } + } } diff --git a/jdk/src/java.base/share/classes/java/net/SocketImpl.java b/jdk/src/java.base/share/classes/java/net/SocketImpl.java index eef92f30b6e..60fe083445a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketImpl.java +++ b/jdk/src/java.base/share/classes/java/net/SocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.FileDescriptor; import java.util.Set; -import java.util.HashSet; -import java.util.Collections; /** * The abstract class {@code SocketImpl} is a common superclass @@ -386,6 +384,9 @@ public abstract class SocketImpl implements SocketOptions { setOption(SocketOptions.SO_RCVBUF, value); } else if (name == StandardSocketOptions.SO_REUSEADDR) { setOption(SocketOptions.SO_REUSEADDR, value); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + setOption(SocketOptions.SO_REUSEPORT, value); } else if (name == StandardSocketOptions.SO_LINGER && (getSocket() != null)) { setOption(SocketOptions.SO_LINGER, value); @@ -426,6 +427,9 @@ public abstract class SocketImpl implements SocketOptions { return (T)getOption(SocketOptions.SO_RCVBUF); } else if (name == StandardSocketOptions.SO_REUSEADDR) { return (T)getOption(SocketOptions.SO_REUSEADDR); + } else if (name == StandardSocketOptions.SO_REUSEPORT && + supportedOptions().contains(name)) { + return (T)getOption(SocketOptions.SO_REUSEPORT); } else if (name == StandardSocketOptions.SO_LINGER && (getSocket() != null)) { return (T)getOption(SocketOptions.SO_LINGER); @@ -439,31 +443,31 @@ public abstract class SocketImpl implements SocketOptions { } } - private static final Set> socketOptions = - new HashSet<>(); + private static final Set> socketOptions; - private static final Set> serverSocketOptions = - new HashSet<>(); + private static final Set> serverSocketOptions; static { - socketOptions.add(StandardSocketOptions.SO_KEEPALIVE); - socketOptions.add(StandardSocketOptions.SO_SNDBUF); - socketOptions.add(StandardSocketOptions.SO_RCVBUF); - socketOptions.add(StandardSocketOptions.SO_REUSEADDR); - socketOptions.add(StandardSocketOptions.SO_LINGER); - socketOptions.add(StandardSocketOptions.IP_TOS); - socketOptions.add(StandardSocketOptions.TCP_NODELAY); + socketOptions = Set.of(StandardSocketOptions.SO_KEEPALIVE, + StandardSocketOptions.SO_SNDBUF, + StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.SO_LINGER, + StandardSocketOptions.IP_TOS, + StandardSocketOptions.TCP_NODELAY); - serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF); - serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR); - serverSocketOptions.add(StandardSocketOptions.IP_TOS); - }; + serverSocketOptions = Set.of(StandardSocketOptions.SO_RCVBUF, + StandardSocketOptions.SO_REUSEADDR, + StandardSocketOptions.IP_TOS); + } /** * Returns a set of SocketOptions supported by this impl * and by this impl's socket (Socket or ServerSocket) * * @return a Set of SocketOptions + * + * @since 9 */ protected Set> supportedOptions() { if (getSocket() != null) { diff --git a/jdk/src/java.base/share/classes/java/net/SocketOptions.java b/jdk/src/java.base/share/classes/java/net/SocketOptions.java index c846bbb9b12..fbfb81eca1a 100644 --- a/jdk/src/java.base/share/classes/java/net/SocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/SocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,6 +170,17 @@ public interface SocketOptions { @Native public static final int SO_REUSEADDR = 0x04; + /** Sets SO_REUSEPORT for a socket. This option enables and disables + * the ability to have multiple sockets listen to the same address + * and port. + *

        + * Valid for: SocketImpl, DatagramSocketImpl + * + * @since 9 + * @see StandardSocketOptions#SO_REUSEPORT + */ + @Native public static final int SO_REUSEPORT = 0x0E; + /** * Sets SO_BROADCAST for a socket. This option enables and disables * the ability of the process to send broadcast messages. It is supported diff --git a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java index 7fdd5f075d6..ae47845fae3 100644 --- a/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java +++ b/jdk/src/java.base/share/classes/java/net/StandardSocketOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -186,6 +186,29 @@ public final class StandardSocketOptions { public static final SocketOption SO_REUSEADDR = new StdSocketOption("SO_REUSEADDR", Boolean.class); + /** + * Re-use port. + * + *

        The value of this socket option is a {@code Boolean} that represents + * whether the option is enabled or disabled. The exact semantics of this + * socket option are socket type and system dependent. + * + *

        In the case of stream-oriented sockets, this socket option usually allows + * multiple listening sockets to be bound to both same address + * and same port. + * + *

        For datagram-oriented sockets the socket option usually allows + * multiple UDP sockets to be bound to the same address and port. + * + *

        An implementation allows this socket option to be set before the + * socket is bound or connected. Changing the value of this socket option + * after the socket is bound has no effect. + * + * @since 9 + */ + public static final SocketOption SO_REUSEPORT = + new StdSocketOption("SO_REUSEPORT", Boolean.class); + /** * Linger on close if data is present. * diff --git a/jdk/src/java.base/share/classes/java/net/package-info.java b/jdk/src/java.base/share/classes/java/net/package-info.java index 2279cca479f..37a4ea69de1 100644 --- a/jdk/src/java.base/share/classes/java/net/package-info.java +++ b/jdk/src/java.base/share/classes/java/net/package-info.java @@ -121,7 +121,8 @@ * underlying protocol handlers like http or https.

      3. *
      4. {@link java.net.HttpURLConnection} is a subclass of URLConnection * and provides some additional functionalities specific to the - * HTTP protocol.
      5. + * HTTP protocol. This API has been superceded by the newer + HTTP client API described in the previous section. * *

        The recommended usage is to use {@link java.net.URI} to identify * resources, then convert it into a {@link java.net.URL} when it is time to diff --git a/jdk/src/java.base/share/classes/java/nio/Bits.java b/jdk/src/java.base/share/classes/java/nio/Bits.java index 09623eab845..2b8e8baa49c 100644 --- a/jdk/src/java.base/share/classes/java/nio/Bits.java +++ b/jdk/src/java.base/share/classes/java/nio/Bits.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -736,102 +736,9 @@ class Bits { // package-private }); } - // -- Bulk get/put acceleration -- - // These numbers represent the point at which we have empirically // determined that the average cost of a JNI call exceeds the expense // of an element by element copy. These numbers may change over time. static final int JNI_COPY_TO_ARRAY_THRESHOLD = 6; static final int JNI_COPY_FROM_ARRAY_THRESHOLD = 6; - - // This number limits the number of bytes to copy per call to Unsafe's - // copyMemory method. A limit is imposed to allow for safepoint polling - // during a large copy - static final long UNSAFE_COPY_THRESHOLD = 1024L * 1024L; - - // These methods do no bounds checking. Verification that the copy will not - // result in memory corruption should be done prior to invocation. - // All positions and lengths are specified in bytes. - - /** - * Copy from given source array to destination address. - * - * @param src - * source array - * @param srcBaseOffset - * offset of first element of storage in source array - * @param srcPos - * offset within source array of the first element to read - * @param dstAddr - * destination address - * @param length - * number of bytes to copy - */ - static void copyFromArray(Object src, long srcBaseOffset, long srcPos, - long dstAddr, long length) - { - long offset = srcBaseOffset + srcPos; - while (length > 0) { - long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; - unsafe.copyMemory(src, offset, null, dstAddr, size); - length -= size; - offset += size; - dstAddr += size; - } - } - - /** - * Copy from source address into given destination array. - * - * @param srcAddr - * source address - * @param dst - * destination array - * @param dstBaseOffset - * offset of first element of storage in destination array - * @param dstPos - * offset within destination array of the first element to write - * @param length - * number of bytes to copy - */ - static void copyToArray(long srcAddr, Object dst, long dstBaseOffset, long dstPos, - long length) - { - long offset = dstBaseOffset + dstPos; - while (length > 0) { - long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length; - unsafe.copyMemory(null, srcAddr, dst, offset, size); - length -= size; - srcAddr += size; - offset += size; - } - } - - static void copyFromCharArray(Object src, long srcPos, long dstAddr, - long length) - { - copyFromShortArray(src, srcPos, dstAddr, length); - } - - static void copyToCharArray(long srcAddr, Object dst, long dstPos, - long length) - { - copyToShortArray(srcAddr, dst, dstPos, length); - } - - static native void copyFromShortArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToShortArray(long srcAddr, Object dst, long dstPos, - long length); - - static native void copyFromIntArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToIntArray(long srcAddr, Object dst, long dstPos, - long length); - - static native void copyFromLongArray(Object src, long srcPos, long dstAddr, - long length); - static native void copyToLongArray(long srcAddr, Object dst, long dstPos, - long length); - } diff --git a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 76aa4a9c61b..40a39eb0ed9 100644 --- a/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/jdk/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -270,16 +270,22 @@ class Direct$Type$Buffer$RW$$BO$ if (length > rem) throw new BufferUnderflowException(); + long dstOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$); #if[!byte] if (order() != ByteOrder.nativeOrder()) - Bits.copyTo$Memtype$Array(ix(pos), dst, - (long)offset << $LG_BYTES_PER_VALUE$, - (long)length << $LG_BYTES_PER_VALUE$); + unsafe.copySwapMemory(null, + ix(pos), + dst, + dstOffset, + (long)length << $LG_BYTES_PER_VALUE$, + (long)1 << $LG_BYTES_PER_VALUE$); else #end[!byte] - Bits.copyToArray(ix(pos), dst, arrayBaseOffset, - (long)offset << $LG_BYTES_PER_VALUE$, - (long)length << $LG_BYTES_PER_VALUE$); + unsafe.copyMemory(null, + ix(pos), + dst, + dstOffset, + (long)length << $LG_BYTES_PER_VALUE$); position(pos + length); } else { super.get(dst, offset, length); @@ -362,18 +368,22 @@ class Direct$Type$Buffer$RW$$BO$ if (length > rem) throw new BufferOverflowException(); + long srcOffset = arrayBaseOffset + ((long)offset << $LG_BYTES_PER_VALUE$); #if[!byte] if (order() != ByteOrder.nativeOrder()) - Bits.copyFrom$Memtype$Array(src, - (long)offset << $LG_BYTES_PER_VALUE$, - ix(pos), - (long)length << $LG_BYTES_PER_VALUE$); + unsafe.copySwapMemory(src, + srcOffset, + null, + ix(pos), + (long)length << $LG_BYTES_PER_VALUE$, + (long)1 << $LG_BYTES_PER_VALUE$); else #end[!byte] - Bits.copyFromArray(src, arrayBaseOffset, - (long)offset << $LG_BYTES_PER_VALUE$, - ix(pos), - (long)length << $LG_BYTES_PER_VALUE$); + unsafe.copyMemory(src, + srcOffset, + null, + ix(pos), + (long)length << $LG_BYTES_PER_VALUE$); position(pos + length); } else { super.put(src, offset, length); diff --git a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java index de85b2f525c..78ee33e764a 100644 --- a/jdk/src/java.base/share/classes/java/nio/charset/Charset.java +++ b/jdk/src/java.base/share/classes/java/nio/charset/Charset.java @@ -44,7 +44,6 @@ import java.util.ServiceConfigurationError; import java.util.SortedMap; import java.util.TreeMap; import jdk.internal.misc.VM; -import sun.misc.ASCIICaseInsensitiveComparator; import sun.nio.cs.StandardCharsets; import sun.nio.cs.ThreadLocalCoders; import sun.security.action.GetPropertyAction; @@ -579,7 +578,7 @@ public abstract class Charset public SortedMap run() { TreeMap m = new TreeMap<>( - ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + String.CASE_INSENSITIVE_ORDER); put(standardProvider.charsets(), m); CharsetProvider[] ecps = ExtendedProviderHolder.extendedProviders; for (CharsetProvider ecp :ecps) { diff --git a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java index 246f140b435..285e19a1639 100644 --- a/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java +++ b/jdk/src/java.base/share/classes/java/security/KeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ import sun.security.util.Debug; * associated with each of the keys. * *

        If the algorithm is the DSA algorithm, and the keysize (modulus - * size) is 512, 768, or 1024, then the Sun provider uses a set of + * size) is 512, 768, 1024, or 2048, then the Sun provider uses a set of * precomputed values for the {@code p}, {@code q}, and * {@code g} parameters. If the modulus size is not one of the above * values, the Sun provider creates a new set of parameters. Other @@ -96,7 +96,7 @@ import sun.security.util.Debug; * (via a call to an {@code initialize} method), each provider must * supply (and document) a default initialization. * For example, the Sun provider uses a default modulus size (keysize) - * of 1024 bits. + * of 1024 bits for DSA key pairs. * *

        Note that this class is abstract and extends from * {@code KeyPairGeneratorSpi} for historical reasons. diff --git a/jdk/src/java.base/share/classes/java/util/Collections.java b/jdk/src/java.base/share/classes/java/util/Collections.java index 73047bff5d1..0eb9da0f644 100644 --- a/jdk/src/java.base/share/classes/java/util/Collections.java +++ b/jdk/src/java.base/share/classes/java/util/Collections.java @@ -2728,7 +2728,7 @@ public class Collections { * Set s2 = m2.keySet(); // Needn't be in synchronized block * ... * synchronized (m) { // Synchronizing on m, not m2 or s2! - * Iterator i = s.iterator(); // Must be in synchronized block + * Iterator i = s2.iterator(); // Must be in synchronized block * while (i.hasNext()) * foo(i.next()); * } diff --git a/jdk/src/java.base/share/classes/java/util/Currency.java b/jdk/src/java.base/share/classes/java/util/Currency.java index 74c7b4bb3fc..8648147bcfe 100644 --- a/jdk/src/java.base/share/classes/java/util/Currency.java +++ b/jdk/src/java.base/share/classes/java/util/Currency.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -92,7 +92,12 @@ import sun.util.logging.PlatformLogger; * and the remainder of entries in file are processed. For instances where duplicate * country code entries exist, the behavior of the Currency information for that * {@code Currency} is undefined and the remainder of entries in file are processed. + *

        + * It is recommended to use {@link java.math.BigDecimal} class while dealing + * with {@code Currency} or monetary values as it provides better handling of floating + * point numbers and their operations. * + * @see java.math.BigDecimal * @since 1.4 */ public final class Currency implements Serializable { @@ -516,14 +521,16 @@ public final class Currency implements Serializable { } /** - * Gets the default number of fraction digits used with this currency. - * For example, the default number of fraction digits for the Euro is 2, - * while for the Japanese Yen it's 0. - * In the case of pseudo-currencies, such as IMF Special Drawing Rights, - * -1 is returned. - * - * @return the default number of fraction digits used with this currency - */ + * Gets the default number of fraction digits used with this currency. + * Note that the number of fraction digits is the same as ISO 4217's + * minor unit for the currency. + * For example, the default number of fraction digits for the Euro is 2, + * while for the Japanese Yen it's 0. + * In the case of pseudo-currencies, such as IMF Special Drawing Rights, + * -1 is returned. + * + * @return the default number of fraction digits used with this currency + */ public int getDefaultFractionDigits() { return defaultFractionDigits; } diff --git a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java index f54b3d931b2..579102a2bc7 100644 --- a/jdk/src/java.base/share/classes/java/util/SplittableRandom.java +++ b/jdk/src/java.base/share/classes/java/util/SplittableRandom.java @@ -219,12 +219,20 @@ public final class SplittableRandom { return seed += gamma; } + // IllegalArgumentException messages + static final String BAD_BOUND = "bound must be positive"; + static final String BAD_RANGE = "bound must be greater than origin"; + static final String BAD_SIZE = "size must be non-negative"; + /** * The seed generator for default constructors. */ - private static final AtomicLong defaultGen = new AtomicLong(initialSeed()); + private static final AtomicLong defaultGen + = new AtomicLong(mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime())); - private static long initialSeed() { + // at end of to survive static initialization circularity + static { if (java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Boolean run() { @@ -234,17 +242,10 @@ public final class SplittableRandom { long s = (long)seedBytes[0] & 0xffL; for (int i = 1; i < 8; ++i) s = (s << 8) | ((long)seedBytes[i] & 0xffL); - return s; + defaultGen.set(s); } - return (mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); } - // IllegalArgumentException messages - static final String BAD_BOUND = "bound must be positive"; - static final String BAD_RANGE = "bound must be greater than origin"; - static final String BAD_SIZE = "size must be non-negative"; - /* * Internal versions of nextX methods used by streams, as well as * the public nextX(origin, bound) methods. These exist mainly to diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 3e50171cf20..69ecc46cf6d 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -125,53 +125,6 @@ public class ThreadLocalRandom extends Random { * but we provide identical statistical properties. */ - /** Generates per-thread initialization/probe field */ - private static final AtomicInteger probeGenerator = new AtomicInteger(); - - /** - * The next seed for default constructors. - */ - private static final AtomicLong seeder = new AtomicLong(initialSeed()); - - private static long initialSeed() { - if (java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Boolean run() { - return Boolean.getBoolean("java.util.secureRandomSeed"); - }})) { - byte[] seedBytes = java.security.SecureRandom.getSeed(8); - long s = (long)seedBytes[0] & 0xffL; - for (int i = 1; i < 8; ++i) - s = (s << 8) | ((long)seedBytes[i] & 0xffL); - return s; - } - return (mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); - } - - /** - * The seed increment. - */ - private static final long GAMMA = 0x9e3779b97f4a7c15L; - - /** - * The increment for generating probe values. - */ - private static final int PROBE_INCREMENT = 0x9e3779b9; - - /** - * The increment of seeder per new instance. - */ - private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL; - - // Constants from SplittableRandom - private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53) - private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24) - - /** Rarely-used holder for the second of a pair of Gaussians */ - private static final ThreadLocal nextLocalGaussian = - new ThreadLocal<>(); - private static long mix64(long z) { z = (z ^ (z >>> 33)) * 0xff51afd7ed558ccdL; z = (z ^ (z >>> 33)) * 0xc4ceb9fe1a85ec53L; @@ -194,9 +147,6 @@ public class ThreadLocalRandom extends Random { initialized = true; // false during super() call } - /** The common ThreadLocalRandom */ - static final ThreadLocalRandom instance = new ThreadLocalRandom(); - /** * Initialize Thread fields for the current thread. Called only * when Thread.threadLocalRandomProbe is zero, indicating that a @@ -248,11 +198,6 @@ public class ThreadLocalRandom extends Random { return (int)(mix64(nextSeed()) >>> (64 - bits)); } - // IllegalArgumentException messages - static final String BAD_BOUND = "bound must be positive"; - static final String BAD_RANGE = "bound must be greater than origin"; - static final String BAD_SIZE = "size must be non-negative"; - /** * The form of nextLong used by LongStream Spliterators. If * origin is greater than bound, acts as unbounded form of @@ -1050,6 +995,32 @@ public class ThreadLocalRandom extends Random { return current(); } + // Static initialization + + /** + * The seed increment. + */ + private static final long GAMMA = 0x9e3779b97f4a7c15L; + + /** + * The increment for generating probe values. + */ + private static final int PROBE_INCREMENT = 0x9e3779b9; + + /** + * The increment of seeder per new instance. + */ + private static final long SEEDER_INCREMENT = 0xbb67ae8584caa73bL; + + // Constants from SplittableRandom + private static final double DOUBLE_UNIT = 0x1.0p-53; // 1.0 / (1L << 53) + private static final float FLOAT_UNIT = 0x1.0p-24f; // 1.0f / (1 << 24) + + // IllegalArgumentException messages + static final String BAD_BOUND = "bound must be positive"; + static final String BAD_RANGE = "bound must be greater than origin"; + static final String BAD_SIZE = "size must be non-negative"; + // Unsafe mechanics private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long SEED; @@ -1067,4 +1038,36 @@ public class ThreadLocalRandom extends Random { throw new Error(e); } } + + /** Rarely-used holder for the second of a pair of Gaussians */ + private static final ThreadLocal nextLocalGaussian = + new ThreadLocal<>(); + + /** Generates per-thread initialization/probe field */ + private static final AtomicInteger probeGenerator = new AtomicInteger(); + + /** The common ThreadLocalRandom */ + static final ThreadLocalRandom instance = new ThreadLocalRandom(); + + /** + * The next seed for default constructors. + */ + private static final AtomicLong seeder + = new AtomicLong(mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime())); + + // at end of to survive static initialization circularity + static { + if (java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public Boolean run() { + return Boolean.getBoolean("java.util.secureRandomSeed"); + }})) { + byte[] seedBytes = java.security.SecureRandom.getSeed(8); + long s = (long)seedBytes[0] & 0xffL; + for (int i = 1; i < 8; ++i) + s = (s << 8) | ((long)seedBytes[i] & 0xffL); + seeder.set(s); + } + } } diff --git a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java index f2a01acbdba..342c85ea2fd 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/jdk/src/java.base/share/classes/java/util/jar/Attributes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,9 @@ import java.util.Set; import java.util.Collection; import java.util.AbstractSet; import java.util.Iterator; +import java.util.Locale; import sun.util.logging.PlatformLogger; import java.util.Comparator; -import sun.misc.ASCIICaseInsensitiveComparator; /** * The Attributes class maps Manifest attribute names to associated string @@ -501,7 +501,7 @@ public class Attributes implements Map, Cloneable { */ public boolean equals(Object o) { if (o instanceof Name) { - Comparator c = ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER; + Comparator c = String.CASE_INSENSITIVE_ORDER; return c.compare(name, ((Name)o).name) == 0; } else { return false; @@ -513,7 +513,7 @@ public class Attributes implements Map, Cloneable { */ public int hashCode() { if (hashCode == -1) { - hashCode = ASCIICaseInsensitiveComparator.lowerCaseHashCode(name); + hashCode = name.toLowerCase(Locale.ROOT).hashCode(); } return hashCode; } @@ -646,5 +646,13 @@ public class Attributes implements Map, Cloneable { * manifest attribute used for package versioning. */ public static final Name SPECIFICATION_VENDOR = new Name("Specification-Vendor"); + + /** + * {@code Name} object for {@code Multi-Release} + * manifest attribute that indicates this is a multi-release JAR file. + * + * @since 9 + */ + public static final Name MULTI_RELEASE = new Name("Multi-Release"); } } diff --git a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java index 62734ceefbd..b3bbced134c 100644 --- a/jdk/src/java.base/share/classes/java/util/jar/JarFile.java +++ b/jdk/src/java.base/share/classes/java/util/jar/JarFile.java @@ -28,6 +28,7 @@ package java.util.jar; import java.io.*; import java.lang.ref.SoftReference; import java.net.URL; +import java.security.PrivilegedAction; import java.util.*; import java.util.stream.Stream; import java.util.stream.StreamSupport; @@ -37,28 +38,91 @@ import java.security.cert.Certificate; import java.security.AccessController; import java.security.CodeSource; import jdk.internal.misc.SharedSecrets; -import sun.security.action.GetPropertyAction; import sun.security.util.ManifestEntryVerifier; import sun.security.util.SignatureFileVerifier; +import static java.util.jar.Attributes.Name.MULTI_RELEASE; + /** * The {@code JarFile} class is used to read the contents of a jar file * from any file that can be opened with {@code java.io.RandomAccessFile}. * It extends the class {@code java.util.zip.ZipFile} with support - * for reading an optional {@code Manifest} entry. The - * {@code Manifest} can be used to specify meta-information about the - * jar file and its entries. + * for reading an optional {@code Manifest} entry, and support for + * processing multi-release jar files. The {@code Manifest} can be used + * to specify meta-information about the jar file and its entries. + * + *

        A multi-release jar file is a jar file that contains + * a manifest with a main attribute named "Multi-Release", + * a set of "base" entries, some of which are public classes with public + * or protected methods that comprise the public interface of the jar file, + * and a set of "versioned" entries contained in subdirectories of the + * "META-INF/versions" directory. The versioned entries are partitioned by the + * major version of the Java platform. A versioned entry, with a version + * {@code n}, {@code 8 < n}, in the "META-INF/versions/{n}" directory overrides + * the base entry as well as any entry with a version number {@code i} where + * {@code 8 < i < n}. + * + *

        By default, a {@code JarFile} for a multi-release jar file is configured + * to process the multi-release jar file as if it were a plain (unversioned) jar + * file, and as such an entry name is associated with at most one base entry. + * The {@code JarFile} may be configured to process a multi-release jar file by + * creating the {@code JarFile} with the + * {@link JarFile#JarFile(File, boolean, int, Release)} constructor. The + * {@code Release} object sets a maximum version used when searching for + * versioned entries. When so configured, an entry name + * can correspond with at most one base entry and zero or more versioned + * entries. A search is required to associate the entry name with the latest + * versioned entry whose version is less than or equal to the maximum version + * (see {@link #getEntry(String)}). + * + *

        Class loaders that utilize {@code JarFile} to load classes from the + * contents of {@code JarFile} entries should construct the {@code JarFile} + * by invoking the {@link JarFile#JarFile(File, boolean, int, Release)} + * constructor with the value {@code Release.RUNTIME} assigned to the last + * argument. This assures that classes compatible with the major + * version of the running JVM are loaded from multi-release jar files. + * + *

        If the verify flag is on when opening a signed jar file, the content of + * the file is verified against its signature embedded inside the file. Please + * note that the verification process does not include validating the signer's + * certificate. A caller should inspect the return value of + * {@link JarEntry#getCodeSigners()} to further determine if the signature + * can be trusted. * *

        Unless otherwise noted, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be * thrown. * - * If the verify flag is on when opening a signed jar file, the content of the - * file is verified against its signature embedded inside the file. Please note - * that the verification process does not include validating the signer's - * certificate. A caller should inspect the return value of - * {@link JarEntry#getCodeSigners()} to further determine if the signature - * can be trusted. + * @implNote + *

        + * If the API can not be used to configure a {@code JarFile} (e.g. to override + * the configuration of a compiled application or library), two {@code System} + * properties are available. + *
          + *
        • + * {@code jdk.util.jar.version} can be assigned a value that is the + * {@code String} representation of a non-negative integer + * {@code <= Version.current().major()}. The value is used to set the effective + * runtime version to something other than the default value obtained by + * evaluating {@code Version.current().major()}. The effective runtime version + * is the version that the {@link JarFile#JarFile(File, boolean, int, Release)} + * constructor uses when the value of the last argument is + * {@code Release.RUNTIME}. + *
        • + *
        • + * {@code jdk.util.jar.enableMultiRelease} can be assigned one of the three + * {@code String} values true, false, or force. The + * value true, the default value, enables multi-release jar file + * processing. The value false disables multi-release jar processing, + * ignoring the "Multi-Release" manifest attribute, and the versioned + * directories in a multi-release jar file if they exist. Furthermore, + * the method {@link JarFile#isMultiRelease()} returns false. The value + * force causes the {@code JarFile} to be initialized to runtime + * versioning after construction. It effectively does the same as this code: + * {@code (new JarFile(File, boolean, int, Release.RUNTIME)}. + *
        • + *
        + *
        * * @author David Connelly * @see Manifest @@ -68,26 +132,126 @@ import sun.security.util.SignatureFileVerifier; */ public class JarFile extends ZipFile { + private final static int BASE_VERSION; + private final static int RUNTIME_VERSION; + private final static boolean MULTI_RELEASE_ENABLED; + private final static boolean MULTI_RELEASE_FORCED; private SoftReference manRef; private JarEntry manEntry; private JarVerifier jv; private boolean jvInitialized; private boolean verify; + private final int version; + private boolean notVersioned; + private final boolean runtimeVersioned; // indicates if Class-Path attribute present (only valid if hasCheckedSpecialAttributes true) private boolean hasClassPathAttribute; // true if manifest checked for special attributes private volatile boolean hasCheckedSpecialAttributes; - // Set up JavaUtilJarAccess in SharedSecrets static { + // Set up JavaUtilJarAccess in SharedSecrets SharedSecrets.setJavaUtilJarAccess(new JavaUtilJarAccessImpl()); + + BASE_VERSION = 8; // one less than lowest version for versioned entries + RUNTIME_VERSION = AccessController.doPrivileged( + new PrivilegedAction() { + public Integer run() { + Integer v = jdk.Version.current().major(); + Integer i = Integer.getInteger("jdk.util.jar.version", v); + i = i < 0 ? 0 : i; + return i > v ? v : i; + } + } + ); + String multi_release = AccessController.doPrivileged( + new PrivilegedAction() { + public String run() { + return System.getProperty("jdk.util.jar.enableMultiRelease", "true"); + } + } + ); + switch (multi_release) { + case "true": + default: + MULTI_RELEASE_ENABLED = true; + MULTI_RELEASE_FORCED = false; + break; + case "false": + MULTI_RELEASE_ENABLED = false; + MULTI_RELEASE_FORCED = false; + break; + case "force": + MULTI_RELEASE_ENABLED = true; + MULTI_RELEASE_FORCED = true; + break; + } } + /** + * A set of constants that represent the entries in either the base directory + * or one of the versioned directories in a multi-release jar file. It's + * possible for a multi-release jar file to contain versioned directories + * that are not represented by the constants of the {@code Release} enum. + * In those cases, the entries will not be located by this {@code JarFile} + * through the aliasing mechanism, but they can be directly accessed by + * specifying the full path name of the entry. + * + * @since 9 + */ + public enum Release { + /** + * Represents unversioned entries, or entries in "regular", as opposed + * to multi-release jar files. + */ + BASE(BASE_VERSION), + + /** + * Represents entries found in the META-INF/versions/9 directory of a + * multi-release jar file. + */ + VERSION_9(9), + + // fill in the "blanks" for future releases + + /** + * Represents entries found in the META-INF/versions/{n} directory of a + * multi-release jar file, where {@code n} is the effective runtime + * version of the jar file. + * + * @implNote + *
        + * The effective runtime version is determined + * by evaluating {@code Version.current().major()} or by using the value + * of the {@code jdk.util.jar.version} System property if it exists. + *
        + */ + RUNTIME(RUNTIME_VERSION); + + Release(int version) { + this.version = version; + } + + private static Release valueOf(int version) { + return version <= BASE.value() ? BASE : valueOf("VERSION_" + version); + } + + private final int version; + + private int value() { + return this.version; + } + } + + private static final String META_INF = "META-INF/"; + + private static final String META_INF_VERSIONS = META_INF + "versions/"; + /** * The JAR manifest file name. */ - public static final String MANIFEST_NAME = "META-INF/MANIFEST.MF"; + public static final String MANIFEST_NAME = META_INF + "MANIFEST.MF"; /** * Creates a new {@code JarFile} to read from the specified @@ -129,7 +293,6 @@ class JarFile extends ZipFile { this(file, true, ZipFile.OPEN_READ); } - /** * Creates a new {@code JarFile} to read from the specified * {@code File} object. @@ -144,7 +307,6 @@ class JarFile extends ZipFile { this(file, verify, ZipFile.OPEN_READ); } - /** * Creates a new {@code JarFile} to read from the specified * {@code File} object in the specified mode. The mode argument @@ -162,10 +324,104 @@ class JarFile extends ZipFile { * @since 1.3 */ public JarFile(File file, boolean verify, int mode) throws IOException { - super(file, mode); - this.verify = verify; + this(file, verify, mode, Release.BASE); + this.notVersioned = true; } + /** + * Creates a new {@code JarFile} to read from the specified + * {@code File} object in the specified mode. The mode argument + * must be either {@code OPEN_READ} or {@code OPEN_READ | OPEN_DELETE}. + * The version argument configures the {@code JarFile} for processing + * multi-release jar files. + * + * @param file the jar file to be opened for reading + * @param verify whether or not to verify the jar file if + * it is signed. + * @param mode the mode in which the file is to be opened + * @param version specifies the release version for a multi-release jar file + * @throws IOException if an I/O error has occurred + * @throws IllegalArgumentException + * if the {@code mode} argument is invalid + * @throws SecurityException if access to the file is denied + * by the SecurityManager + * @throws NullPointerException if {@code version} is {@code null} + * @since 9 + */ + public JarFile(File file, boolean verify, int mode, Release version) throws IOException { + super(file, mode); + Objects.requireNonNull(version); + this.verify = verify; + // version applies to multi-release jar files, ignored for regular jar files + this.version = MULTI_RELEASE_FORCED ? RUNTIME_VERSION : version.value(); + this.runtimeVersioned = version == Release.RUNTIME; + assert runtimeVersionExists(); + } + + private boolean runtimeVersionExists() { + int version = jdk.Version.current().major(); + try { + Release.valueOf(version); + return true; + } catch (IllegalArgumentException x) { + System.err.println("No JarFile.Release object for release " + version); + return false; + } + } + + /** + * Returns the maximum version used when searching for versioned entries. + * + * @return the maximum version, or {@code Release.BASE} if this jar file is + * processed as if it is an unversioned jar file or is not a + * multi-release jar file + * @since 9 + */ + public final Release getVersion() { + if (isMultiRelease()) { + return runtimeVersioned ? Release.RUNTIME : Release.valueOf(version); + } else { + return Release.BASE; + } + } + + /** + * Indicates whether or not this jar file is a multi-release jar file. + * + * @return true if this JarFile is a multi-release jar file + * @since 9 + */ + public final boolean isMultiRelease() { + // do not call this code in a constructor because some subclasses use + // lazy loading of manifest so it won't be available at construction time + if (MULTI_RELEASE_ENABLED) { + // Doubled-checked locking pattern + Boolean result = isMultiRelease; + if (result == null) { + synchronized (this) { + result = isMultiRelease; + if (result == null) { + Manifest man = null; + try { + man = getManifest(); + } catch (IOException e) { + //Ignored, manifest cannot be read + } + isMultiRelease = result = (man != null) + && man.getMainAttributes().containsKey(MULTI_RELEASE) + ? Boolean.TRUE : Boolean.FALSE; + } + } + } + return result == Boolean.TRUE; + } else { + return false; + } + } + // the following field, isMultiRelease, should only be used in the method + // isMultiRelease(), like a static local + private volatile Boolean isMultiRelease; // is jar multi-release? + /** * Returns the jar file manifest, or {@code null} if none. * @@ -209,40 +465,87 @@ class JarFile extends ZipFile { } /** - * Returns the {@code JarEntry} for the given entry name or + * Returns the {@code JarEntry} for the given base entry name or * {@code null} if not found. * + *

        If this {@code JarFile} is a multi-release jar file and is configured + * to be processed as such, then a search is performed to find and return + * a {@code JarEntry} that is the latest versioned entry associated with the + * given entry name. The returned {@code JarEntry} is the versioned entry + * corresponding to the given base entry name prefixed with the string + * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for + * which an entry exists. If such a versioned entry does not exist, then + * the {@code JarEntry} for the base entry is returned, otherwise + * {@code null} is returned if no entries are found. The initial value for + * the version {@code n} is the maximum version as returned by the method + * {@link JarFile#getVersion()}. + * * @param name the jar file entry name - * @return the {@code JarEntry} for the given entry name or - * {@code null} if not found. + * @return the {@code JarEntry} for the given entry name, or + * the versioned entry name, or {@code null} if not found * * @throws IllegalStateException * may be thrown if the jar file has been closed * * @see java.util.jar.JarEntry + * + * @implSpec + *

        + * This implementation invokes {@link JarFile#getEntry(String)}. + *
        */ public JarEntry getJarEntry(String name) { return (JarEntry)getEntry(name); } /** - * Returns the {@code ZipEntry} for the given entry name or + * Returns the {@code ZipEntry} for the given base entry name or * {@code null} if not found. * + *

        If this {@code JarFile} is a multi-release jar file and is configured + * to be processed as such, then a search is performed to find and return + * a {@code ZipEntry} that is the latest versioned entry associated with the + * given entry name. The returned {@code ZipEntry} is the versioned entry + * corresponding to the given base entry name prefixed with the string + * {@code "META-INF/versions/{n}/"}, for the largest value of {@code n} for + * which an entry exists. If such a versioned entry does not exist, then + * the {@code ZipEntry} for the base entry is returned, otherwise + * {@code null} is returned if no entries are found. The initial value for + * the version {@code n} is the maximum version as returned by the method + * {@link JarFile#getVersion()}. + * * @param name the jar file entry name * @return the {@code ZipEntry} for the given entry name or - * {@code null} if not found + * the versioned entry name or {@code null} if not found * * @throws IllegalStateException * may be thrown if the jar file has been closed * * @see java.util.zip.ZipEntry + * + * @implSpec + *

        + * This implementation may return a versioned entry for the requested name + * even if there is not a corresponding base entry. This can occur + * if there is a private or package-private versioned entry that matches. + * If a subclass overrides this method, assure that the override method + * invokes {@code super.getEntry(name)} to obtain all versioned entries. + *
        */ public ZipEntry getEntry(String name) { ZipEntry ze = super.getEntry(name); if (ze != null) { return new JarFileEntry(ze); } + // no matching base entry, but maybe there is a versioned entry, + // like a new private class + if (isMultiRelease()) { + ze = new ZipEntry(name); + ZipEntry vze = getVersionedEntry(ze); + if (ze != vze) { + return new JarFileEntry(name, vze); + } + } return null; } @@ -250,14 +553,42 @@ class JarFile extends ZipFile { Iterator { final Enumeration e = JarFile.super.entries(); + ZipEntry ze; public boolean hasNext() { - return e.hasMoreElements(); + if (notVersioned) { + return e.hasMoreElements(); + } + if (ze != null) { + return true; + } + return findNext(); + } + + private boolean findNext() { + while (e.hasMoreElements()) { + ZipEntry ze2 = e.nextElement(); + if (!ze2.getName().startsWith(META_INF_VERSIONS)) { + ze = ze2; + return true; + } + } + return false; } public JarEntry next() { - ZipEntry ze = e.nextElement(); - return new JarFileEntry(ze); + ZipEntry ze2; + + if (notVersioned) { + ze2 = e.nextElement(); + return new JarFileEntry(ze2.getName(), ze2); + } + if (ze != null || findNext()) { + ze2 = ze; + ze = null; + return new JarFileEntry(ze2); + } + throw new NoSuchElementException(); } public boolean hasMoreElements() { @@ -274,7 +605,19 @@ class JarFile extends ZipFile { } /** - * Returns an enumeration of the jar file entries. + * Returns an enumeration of the jar file entries. The set of entries + * returned depends on whether or not the jar file is a multi-release jar + * file, and on the constructor used to create the {@code JarFile}. If the + * jar file is not a multi-release jar file, all entries are returned, + * regardless of how the {@code JarFile} is created. If the constructor + * does not take a {@code Release} argument, all entries are returned. + * If the jar file is a multi-release jar file and the constructor takes a + * {@code Release} argument, then the set of entries returned is equivalent + * to the set of entries that would be returned if the set was built by + * invoking {@link JarFile#getEntry(String)} or + * {@link JarFile#getJarEntry(String)} with the name of each base entry in + * the jar file. A base entry is an entry whose path name does not start + * with "META-INF/versions/". * * @return an enumeration of the jar file entries * @throws IllegalStateException @@ -285,10 +628,21 @@ class JarFile extends ZipFile { } /** - * Returns an ordered {@code Stream} over the jar file entries. + * Returns an ordered {@code Stream} over all the jar file entries. * Entries appear in the {@code Stream} in the order they appear in - * the central directory of the jar file. - * + * the central directory of the jar file. The set of entries + * returned depends on whether or not the jar file is a multi-release jar + * file, and on the constructor used to create the {@code JarFile}. If the + * jar file is not a multi-release jar file, all entries are returned, + * regardless of how the {@code JarFile} is created. If the constructor + * does not take a {@code Release} argument, all entries are returned. + * If the jar file is a multi-release jar file and the constructor takes a + * {@code Release} argument, then the set of entries returned is equivalent + * to the set of entries that would be returned if the set was built by + * invoking {@link JarFile#getEntry(String)} or + * {@link JarFile#getJarEntry(String)} with the name of each base entry in + * the jar file. A base entry is an entry whose path name does not start + * with "META-INF/versions/". * @return an ordered {@code Stream} of entries in this jar file * @throws IllegalStateException if the jar file has been closed * @since 1.8 @@ -300,14 +654,44 @@ class JarFile extends ZipFile { Spliterator.IMMUTABLE | Spliterator.NONNULL), false); } + private ZipEntry searchForVersionedEntry(final int version, String name) { + ZipEntry vze = null; + String sname = "/" + name; + int i = version; + while (i > BASE_VERSION) { + vze = super.getEntry(META_INF_VERSIONS + i + sname); + if (vze != null) break; + i--; + } + return vze; + } + + private ZipEntry getVersionedEntry(ZipEntry ze) { + ZipEntry vze = null; + if (version > BASE_VERSION && !ze.isDirectory()) { + String name = ze.getName(); + if (!name.startsWith(META_INF)) { + vze = searchForVersionedEntry(version, name); + } + } + return vze == null ? ze : vze; + } + private class JarFileEntry extends JarEntry { + final private String name; + JarFileEntry(ZipEntry ze) { - super(ze); + super(isMultiRelease() ? getVersionedEntry(ze) : ze); + this.name = ze.getName(); + } + JarFileEntry(String name, ZipEntry vze) { + super(vze); + this.name = name; } public Attributes getAttributes() throws IOException { Manifest man = JarFile.this.getManifest(); if (man != null) { - return man.getAttributes(getName()); + return man.getAttributes(super.getName()); } else { return null; } @@ -319,7 +703,7 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (certs == null && jv != null) { - certs = jv.getCerts(JarFile.this, this); + certs = jv.getCerts(JarFile.this, reifiedEntry()); } return certs == null ? null : certs.clone(); } @@ -330,10 +714,22 @@ class JarFile extends ZipFile { throw new RuntimeException(e); } if (signers == null && jv != null) { - signers = jv.getCodeSigners(JarFile.this, this); + signers = jv.getCodeSigners(JarFile.this, reifiedEntry()); } return signers == null ? null : signers.clone(); } + JarFileEntry reifiedEntry() { + if (isMultiRelease()) { + String entryName = super.getName(); + return entryName.equals(this.name) ? this : new JarFileEntry(entryName, this); + } + return this; + } + + @Override + public String getName() { + return name; + } } /* @@ -491,12 +887,23 @@ class JarFile extends ZipFile { // wrap a verifier stream around the real stream return new JarVerifier.VerifierStream( getManifestFromReference(), - ze instanceof JarFileEntry ? - (JarEntry) ze : getJarEntry(ze.getName()), + verifiableEntry(ze), super.getInputStream(ze), jv); } + private JarEntry verifiableEntry(ZipEntry ze) { + if (ze instanceof JarFileEntry) { + // assure the name and entry match for verification + return ((JarFileEntry)ze).reifiedEntry(); + } + ze = getJarEntry(ze.getName()); + if (ze instanceof JarFileEntry) { + return ((JarFileEntry)ze).reifiedEntry(); + } + return (JarEntry)ze; + } + // Statics for hand-coded Boyer-Moore search private static final char[] CLASSPATH_CHARS = {'c','l','a','s','s','-','p','a','t','h'}; // The bad character shift for "class-path" @@ -523,7 +930,7 @@ class JarFile extends ZipFile { private JarEntry getManEntry() { if (manEntry == null) { // First look up manifest entry using standard name - manEntry = getJarEntry(MANIFEST_NAME); + ZipEntry manEntry = super.getEntry(MANIFEST_NAME); if (manEntry == null) { // If not found, then iterate through all the "META-INF/" // entries to find a match. @@ -531,12 +938,15 @@ class JarFile extends ZipFile { if (names != null) { for (String name : names) { if (MANIFEST_NAME.equals(name.toUpperCase(Locale.ENGLISH))) { - manEntry = getJarEntry(name); + manEntry = super.getEntry(name); break; } } } } + this.manEntry = (manEntry == null) + ? null + : new JarFileEntry(manEntry.getName(), manEntry); } return manEntry; } diff --git a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java index 84199462c80..a313b64589d 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java +++ b/jdk/src/java.base/share/classes/java/util/stream/AbstractPipeline.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -327,6 +327,8 @@ abstract class AbstractPipeline> @Override @SuppressWarnings("unchecked") public S onClose(Runnable closeHandler) { + if (linkedOrConsumed) + throw new IllegalStateException(MSG_STREAM_LINKED); Objects.requireNonNull(closeHandler); Runnable existingHandler = sourceStage.sourceCloseAction; sourceStage.sourceCloseAction = diff --git a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java index 574e4f17fc7..9d25d902bb4 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/DoubleStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -949,24 +949,100 @@ public interface DoubleStream extends BaseStream { */ public static DoubleStream iterate(final double seed, final DoubleUnaryOperator f) { Objects.requireNonNull(f); - final PrimitiveIterator.OfDouble iterator = new PrimitiveIterator.OfDouble() { - double t = seed; + Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + double prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(DoubleConsumer action) { + Objects.requireNonNull(action); + double t; + if (started) + t = f.applyAsDouble(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.doubleStream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code DoubleStream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

        + * {@code DoubleStream.iterate} should produce the same sequence of + * elements as produced by the corresponding for-loop: + *

        {@code
        +     *     for (double index=seed; predicate.test(index); index = f.apply(index)) {
        +     *         ...
        +     *     }
        +     * }
        + * + *

        + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code DoubleStream} + * @since 9 + */ + public static DoubleStream iterate(double seed, DoublePredicate predicate, DoubleUnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator.OfDouble spliterator = new Spliterators.AbstractDoubleSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + double prev; + boolean started, finished; + + @Override + public boolean tryAdvance(DoubleConsumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + double t; + if (started) + t = f.applyAsDouble(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public double nextDouble() { - double v = t; - t = f.applyAsDouble(t); - return v; + public void forEachRemaining(DoubleConsumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + double t = started ? f.applyAsDouble(prev) : seed; + while (predicate.test(t)) { + action.accept(t); + t = f.applyAsDouble(t); + } } }; - return StreamSupport.doubleStream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false); + return StreamSupport.doubleStream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java index 91ddad2b2a8..115a782937f 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/IntStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/IntStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -885,28 +885,104 @@ public interface IntStream extends BaseStream { * @param seed the initial element * @param f a function to be applied to the previous element to produce * a new element - * @return A new sequential {@code IntStream} + * @return a new sequential {@code IntStream} */ public static IntStream iterate(final int seed, final IntUnaryOperator f) { Objects.requireNonNull(f); - final PrimitiveIterator.OfInt iterator = new PrimitiveIterator.OfInt() { - int t = seed; + Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + int prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(IntConsumer action) { + Objects.requireNonNull(action); + int t; + if (started) + t = f.applyAsInt(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.intStream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code IntStream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

        + * {@code IntStream.iterate} should produce the same sequence of elements + * as produced by the corresponding for-loop: + *

        {@code
        +     *     for (int index=seed; predicate.test(index); index = f.apply(index)) {
        +     *         ...
        +     *     }
        +     * }
        + * + *

        + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code IntStream} + * @since 9 + */ + public static IntStream iterate(int seed, IntPredicate predicate, IntUnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator.OfInt spliterator = new Spliterators.AbstractIntSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + int prev; + boolean started, finished; + + @Override + public boolean tryAdvance(IntConsumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + int t; + if (started) + t = f.applyAsInt(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public int nextInt() { - int v = t; - t = f.applyAsInt(t); - return v; + public void forEachRemaining(IntConsumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + int t = started ? f.applyAsInt(prev) : seed; + while (predicate.test(t)) { + action.accept(t); + t = f.applyAsInt(t); + } } }; - return StreamSupport.intStream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false); + return StreamSupport.intStream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java index c1a89eb4b76..f987820c5a8 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/LongStream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/LongStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -879,24 +879,100 @@ public interface LongStream extends BaseStream { */ public static LongStream iterate(final long seed, final LongUnaryOperator f) { Objects.requireNonNull(f); - final PrimitiveIterator.OfLong iterator = new PrimitiveIterator.OfLong() { - long t = seed; + Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + long prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(LongConsumer action) { + Objects.requireNonNull(action); + long t; + if (started) + t = f.applyAsLong(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.longStream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code LongStream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

        + * {@code LongStream.iterate} should produce the same sequence of elements + * as produced by the corresponding for-loop: + *

        {@code
        +     *     for (long index=seed; predicate.test(index); index = f.apply(index)) {
        +     *         ...
        +     *     }
        +     * }
        + * + *

        + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code LongStream} + * @since 9 + */ + public static LongStream iterate(long seed, LongPredicate predicate, LongUnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator.OfLong spliterator = new Spliterators.AbstractLongSpliterator(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL) { + long prev; + boolean started, finished; + + @Override + public boolean tryAdvance(LongConsumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + long t; + if (started) + t = f.applyAsLong(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public long nextLong() { - long v = t; - t = f.applyAsLong(t); - return v; + public void forEachRemaining(LongConsumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + long t = started ? f.applyAsLong(prev) : seed; + while (predicate.test(t)) { + action.accept(t); + t = f.applyAsLong(t); + } } }; - return StreamSupport.longStream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE | Spliterator.NONNULL), false); + return StreamSupport.longStream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/Stream.java b/jdk/src/java.base/share/classes/java/util/stream/Stream.java index aef2581d0eb..1dd1d43f91d 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Stream.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Stream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,6 @@ import java.nio.file.Path; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; -import java.util.Iterator; import java.util.Objects; import java.util.Optional; import java.util.Spliterator; @@ -1185,23 +1184,103 @@ public interface Stream extends BaseStream> { */ public static Stream iterate(final T seed, final UnaryOperator f) { Objects.requireNonNull(f); - final Iterator iterator = new Iterator() { - @SuppressWarnings("unchecked") - T t = (T) Streams.NONE; + Spliterator spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE) { + T prev; + boolean started; @Override - public boolean hasNext() { + public boolean tryAdvance(Consumer action) { + Objects.requireNonNull(action); + T t; + if (started) + t = f.apply(prev); + else { + t = seed; + started = true; + } + action.accept(prev = t); + return true; + } + }; + return StreamSupport.stream(spliterator, false); + } + + /** + * Returns a sequential ordered {@code Stream} produced by iterative + * application of a function to an initial element, conditioned on + * satisfying the supplied predicate. The stream terminates as soon as + * the predicate returns false. + * + *

        + * {@code Stream.iterate} should produce the same sequence of elements as + * produced by the corresponding for-loop: + *

        {@code
        +     *     for (T index=seed; predicate.test(index); index = f.apply(index)) {
        +     *         ...
        +     *     }
        +     * }
        + * + *

        + * The resulting sequence may be empty if the predicate does not hold on + * the seed value. Otherwise the first element will be the supplied seed + * value, the next element (if present) will be the result of applying the + * function f to the seed value, and so on iteratively until the predicate + * indicates that the stream should terminate. + * + * @param the type of stream elements + * @param seed the initial element + * @param predicate a predicate to apply to elements to determine when the + * stream must terminate. + * @param f a function to be applied to the previous element to produce + * a new element + * @return a new sequential {@code Stream} + * @since 9 + */ + public static Stream iterate(T seed, Predicate predicate, UnaryOperator f) { + Objects.requireNonNull(f); + Objects.requireNonNull(predicate); + Spliterator spliterator = new Spliterators.AbstractSpliterator<>(Long.MAX_VALUE, + Spliterator.ORDERED | Spliterator.IMMUTABLE) { + T prev; + boolean started, finished; + + @Override + public boolean tryAdvance(Consumer action) { + Objects.requireNonNull(action); + if (finished) + return false; + T t; + if (started) + t = f.apply(prev); + else { + t = seed; + started = true; + } + if (!predicate.test(t)) { + prev = null; + finished = true; + return false; + } + action.accept(prev = t); return true; } @Override - public T next() { - return t = (t == Streams.NONE) ? seed : f.apply(t); + public void forEachRemaining(Consumer action) { + Objects.requireNonNull(action); + if (finished) + return; + finished = true; + T t = started ? f.apply(prev) : seed; + prev = null; + while (predicate.test(t)) { + action.accept(t); + t = f.apply(t); + } } }; - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - iterator, - Spliterator.ORDERED | Spliterator.IMMUTABLE), false); + return StreamSupport.stream(spliterator, false); } /** diff --git a/jdk/src/java.base/share/classes/java/util/stream/Streams.java b/jdk/src/java.base/share/classes/java/util/stream/Streams.java index 4023a3ea0cc..0d2c23051ff 100644 --- a/jdk/src/java.base/share/classes/java/util/stream/Streams.java +++ b/jdk/src/java.base/share/classes/java/util/stream/Streams.java @@ -48,14 +48,6 @@ final class Streams { throw new Error("no instances"); } - /** - * An object instance representing no value, that cannot be an actual - * data element of a stream. Used when processing streams that can contain - * {@code null} elements to distinguish between a {@code null} value and no - * value. - */ - static final Object NONE = new Object(); - /** * An {@code int} range spliterator. */ diff --git a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java index fa674888824..338aa12eafc 100644 --- a/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java +++ b/jdk/src/java.base/share/classes/javax/crypto/JceSecurity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,8 +64,7 @@ final class JceSecurity { private static final Map verifyingProviders = new IdentityHashMap<>(); - // Set the default value. May be changed in the static initializer. - private static boolean isRestricted = true; + private static final boolean isRestricted; /* * Don't let anyone instantiate this. diff --git a/jdk/src/java.base/share/classes/jdk/Version.java b/jdk/src/java.base/share/classes/jdk/Version.java index 9ce9ec9314d..75c6b35c444 100644 --- a/jdk/src/java.base/share/classes/jdk/Version.java +++ b/jdk/src/java.base/share/classes/jdk/Version.java @@ -28,10 +28,10 @@ package jdk; import java.math.BigInteger; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.stream.Collectors; -import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; @@ -208,11 +208,10 @@ public final class Version + s + "'"); // $VNUM is a dot-separated list of integers of arbitrary length - version - = Collections.unmodifiableList( - Arrays.stream(m.group(VNUM_GROUP).split("\\.")) - .map(Integer::parseInt) - .collect(Collectors.toList())); + List list = new ArrayList<>(); + for (String i : m.group(VNUM_GROUP).split("\\.")) + list.add(Integer.parseInt(i)); + version = Collections.unmodifiableList(list); pre = Optional.ofNullable(m.group(PRE_GROUP)); diff --git a/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java index 0a560dc11e5..88cd1feaf8f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java +++ b/jdk/src/java.base/share/classes/jdk/internal/math/FormattedFloatingDecimal.java @@ -106,10 +106,28 @@ public class FormattedFloatingDecimal{ return decExponentRounded - 1; } + /** + * Returns the mantissa as a {@code char[]}. Note that the returned value + * is a reference to the internal {@code char[]} containing the mantissa, + * therefore code invoking this method should not pass the return value to + * external code but should in that case make a copy. + * + * @return a reference to the internal {@code char[]} representing the + * mantissa. + */ public char[] getMantissa(){ return mantissa; } + /** + * Returns the exponent as a {@code char[]}. Note that the returned value + * is a reference to the internal {@code char[]} containing the exponent, + * therefore code invoking this method should not pass the return value to + * external code but should in that case make a copy. + * + * @return a reference to the internal {@code char[]} representing the + * exponent. + */ public char[] getExponent(){ return exponent; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java b/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java index 8c5b8833834..0891f2a125f 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/InnocuousThread.java @@ -128,8 +128,12 @@ public final class InnocuousThread extends Thread { } final ThreadGroup root = group; INNOCUOUSTHREADGROUP = AccessController.doPrivileged( - (PrivilegedAction) () -> - { return new ThreadGroup(root, "InnocuousThreadGroup"); }); + new PrivilegedAction() { + @Override + public ThreadGroup run() { + return new ThreadGroup(root, "InnocuousThreadGroup"); + } + }); } catch (Exception e) { throw new Error(e); } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java index 541c4962bab..307989eed96 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/SharedSecrets.java @@ -118,6 +118,8 @@ public class SharedSecrets { } public static JavaNetInetAddressAccess getJavaNetInetAddressAccess() { + if (javaNetInetAddressAccess == null) + unsafe.ensureClassInitialized(java.net.InetAddress.class); return javaNetInetAddressAccess; } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java index 92adbbe295e..0002fdcde93 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Signal.java @@ -279,6 +279,11 @@ public final class Signal { public void handle(Signal sig) { throw new UnsupportedOperationException("invoking native signal handle not supported"); } + + public String toString() { + return this == SIG_DFL ? "SIG_DFL" : + (this == SIG_IGN ? "SIG_IGN" : super.toString()); + } } } diff --git a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java index f130d383a84..8905977111b 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java +++ b/jdk/src/java.base/share/classes/jdk/internal/misc/Unsafe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -458,6 +458,78 @@ public final class Unsafe { copyMemory(null, srcAddress, null, destAddress, bytes); } + private boolean isPrimitiveArray(Class c) { + Class componentType = c.getComponentType(); + return componentType != null && componentType.isPrimitive(); + } + + private native void copySwapMemory0(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize); + + /** + * Copies all elements from one block of memory to another block, + * *unconditionally* byte swapping the elements on the fly. + * + *

        This method determines each block's base address by means of two parameters, + * and so it provides (in effect) a double-register addressing mode, + * as discussed in {@link #getInt(Object,long)}. When the object reference is null, + * the offset supplies an absolute base address. + * + * @since 9 + */ + public void copySwapMemory(Object srcBase, long srcOffset, + Object destBase, long destOffset, + long bytes, long elemSize) { + if (bytes < 0) { + throw new IllegalArgumentException(); + } + if (elemSize != 2 && elemSize != 4 && elemSize != 8) { + throw new IllegalArgumentException(); + } + if (bytes % elemSize != 0) { + throw new IllegalArgumentException(); + } + if ((srcBase == null && srcOffset == 0) || + (destBase == null && destOffset == 0)) { + throw new NullPointerException(); + } + + // Must be off-heap, or primitive heap arrays + if (srcBase != null && (srcOffset < 0 || !isPrimitiveArray(srcBase.getClass()))) { + throw new IllegalArgumentException(); + } + if (destBase != null && (destOffset < 0 || !isPrimitiveArray(destBase.getClass()))) { + throw new IllegalArgumentException(); + } + + // Sanity check size and offsets on 32-bit platforms. Most + // significant 32 bits must be zero. + if (ADDRESS_SIZE == 4 && + (bytes >>> 32 != 0 || srcOffset >>> 32 != 0 || destOffset >>> 32 != 0)) { + throw new IllegalArgumentException(); + } + + if (bytes == 0) { + return; + } + + copySwapMemory0(srcBase, srcOffset, destBase, destOffset, bytes, elemSize); + } + + /** + * Copies all elements from one block of memory to another block, byte swapping the + * elements on the fly. + * + * This provides a single-register addressing mode, as + * discussed in {@link #getInt(Object,long)}. + * + * Equivalent to {@code copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize)}. + */ + public void copySwapMemory(long srcAddress, long destAddress, long bytes, long elemSize) { + copySwapMemory(null, srcAddress, null, destAddress, bytes, elemSize); + } + /** * Disposes of a block of native memory, as obtained from {@link * #allocateMemory} or {@link #reallocateMemory}. The address passed to @@ -710,6 +782,46 @@ public final class Unsafe { Object expected, Object x); + @HotSpotIntrinsicCandidate + public final native Object compareAndExchangeObjectVolatile(Object o, long offset, + Object expected, + Object x); + + @HotSpotIntrinsicCandidate + public final Object compareAndExchangeObjectAcquire(Object o, long offset, + Object expected, + Object x) { + return compareAndExchangeObjectVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final Object compareAndExchangeObjectRelease(Object o, long offset, + Object expected, + Object x) { + return compareAndExchangeObjectVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObject(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObjectAcquire(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapObjectRelease(Object o, long offset, + Object expected, + Object x) { + return compareAndSwapObject(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -724,6 +836,46 @@ public final class Unsafe { int expected, int x); + @HotSpotIntrinsicCandidate + public final native int compareAndExchangeIntVolatile(Object o, long offset, + int expected, + int x); + + @HotSpotIntrinsicCandidate + public final int compareAndExchangeIntAcquire(Object o, long offset, + int expected, + int x) { + return compareAndExchangeIntVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final int compareAndExchangeIntRelease(Object o, long offset, + int expected, + int x) { + return compareAndExchangeIntVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapInt(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapIntAcquire(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapIntRelease(Object o, long offset, + int expected, + int x) { + return compareAndSwapInt(o, offset, expected, x); + } + /** * Atomically updates Java variable to {@code x} if it is currently * holding {@code expected}. @@ -738,6 +890,46 @@ public final class Unsafe { long expected, long x); + @HotSpotIntrinsicCandidate + public final native long compareAndExchangeLongVolatile(Object o, long offset, + long expected, + long x); + + @HotSpotIntrinsicCandidate + public final long compareAndExchangeLongAcquire(Object o, long offset, + long expected, + long x) { + return compareAndExchangeLongVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final long compareAndExchangeLongRelease(Object o, long offset, + long expected, + long x) { + return compareAndExchangeLongVolatile(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLong(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLongAcquire(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + + @HotSpotIntrinsicCandidate + public final boolean weakCompareAndSwapLongRelease(Object o, long offset, + long expected, + long x) { + return compareAndSwapLong(o, offset, expected, x); + } + /** * Fetches a reference value from a given Java variable, with volatile * load semantics. Otherwise identical to {@link #getObject(Object, long)} @@ -836,6 +1028,224 @@ public final class Unsafe { @HotSpotIntrinsicCandidate public native void putOrderedLong(Object o, long offset, long x); + /** Acquire version of {@link #getObjectVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final Object getObjectAcquire(Object o, long offset) { + return getObjectVolatile(o, offset); + } + + /** Acquire version of {@link #getBooleanVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final boolean getBooleanAcquire(Object o, long offset) { + return getBooleanVolatile(o, offset); + } + + /** Acquire version of {@link #getByteVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final byte getByteAcquire(Object o, long offset) { + return getByteVolatile(o, offset); + } + + /** Acquire version of {@link #getShortVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final short getShortAcquire(Object o, long offset) { + return getShortVolatile(o, offset); + } + + /** Acquire version of {@link #getCharVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final char getCharAcquire(Object o, long offset) { + return getCharVolatile(o, offset); + } + + /** Acquire version of {@link #getIntVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final int getIntAcquire(Object o, long offset) { + return getIntVolatile(o, offset); + } + + /** Acquire version of {@link #getFloatVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final float getFloatAcquire(Object o, long offset) { + return getFloatVolatile(o, offset); + } + + /** Acquire version of {@link #getLongVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final long getLongAcquire(Object o, long offset) { + return getLongVolatile(o, offset); + } + + /** Acquire version of {@link #getDoubleVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final double getDoubleAcquire(Object o, long offset) { + return getDoubleVolatile(o, offset); + } + + /** Release version of {@link #putObjectVolatile(Object, long, Object)} */ + @HotSpotIntrinsicCandidate + public final void putObjectRelease(Object o, long offset, Object x) { + putObjectVolatile(o, offset, x); + } + + /** Release version of {@link #putBooleanVolatile(Object, long, boolean)} */ + @HotSpotIntrinsicCandidate + public final void putBooleanRelease(Object o, long offset, boolean x) { + putBooleanVolatile(o, offset, x); + } + + /** Release version of {@link #putByteVolatile(Object, long, byte)} */ + @HotSpotIntrinsicCandidate + public final void putByteRelease(Object o, long offset, byte x) { + putByteVolatile(o, offset, x); + } + + /** Release version of {@link #putShortVolatile(Object, long, short)} */ + @HotSpotIntrinsicCandidate + public final void putShortRelease(Object o, long offset, short x) { + putShortVolatile(o, offset, x); + } + + /** Release version of {@link #putCharVolatile(Object, long, char)} */ + @HotSpotIntrinsicCandidate + public final void putCharRelease(Object o, long offset, char x) { + putCharVolatile(o, offset, x); + } + + /** Release version of {@link #putIntVolatile(Object, long, int)} */ + @HotSpotIntrinsicCandidate + public final void putIntRelease(Object o, long offset, int x) { + putIntVolatile(o, offset, x); + } + + /** Release version of {@link #putFloatVolatile(Object, long, float)} */ + @HotSpotIntrinsicCandidate + public final void putFloatRelease(Object o, long offset, float x) { + putFloatVolatile(o, offset, x); + } + + /** Release version of {@link #putLongVolatile(Object, long, long)} */ + @HotSpotIntrinsicCandidate + public final void putLongRelease(Object o, long offset, long x) { + putLongVolatile(o, offset, x); + } + + /** Release version of {@link #putDoubleVolatile(Object, long, double)} */ + @HotSpotIntrinsicCandidate + public final void putDoubleRelease(Object o, long offset, double x) { + putDoubleVolatile(o, offset, x); + } + + // ------------------------------ Opaque -------------------------------------- + + /** Opaque version of {@link #getObjectVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final Object getObjectOpaque(Object o, long offset) { + return getObjectVolatile(o, offset); + } + + /** Opaque version of {@link #getBooleanVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final boolean getBooleanOpaque(Object o, long offset) { + return getBooleanVolatile(o, offset); + } + + /** Opaque version of {@link #getByteVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final byte getByteOpaque(Object o, long offset) { + return getByteVolatile(o, offset); + } + + /** Opaque version of {@link #getShortVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final short getShortOpaque(Object o, long offset) { + return getShortVolatile(o, offset); + } + + /** Opaque version of {@link #getCharVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final char getCharOpaque(Object o, long offset) { + return getCharVolatile(o, offset); + } + + /** Opaque version of {@link #getIntVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final int getIntOpaque(Object o, long offset) { + return getIntVolatile(o, offset); + } + + /** Opaque version of {@link #getFloatVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final float getFloatOpaque(Object o, long offset) { + return getFloatVolatile(o, offset); + } + + /** Opaque version of {@link #getLongVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final long getLongOpaque(Object o, long offset) { + return getLongVolatile(o, offset); + } + + /** Opaque version of {@link #getDoubleVolatile(Object, long)} */ + @HotSpotIntrinsicCandidate + public final double getDoubleOpaque(Object o, long offset) { + return getDoubleVolatile(o, offset); + } + + /** Opaque version of {@link #putObjectVolatile(Object, long, Object)} */ + @HotSpotIntrinsicCandidate + public final void putObjectOpaque(Object o, long offset, Object x) { + putObjectVolatile(o, offset, x); + } + + /** Opaque version of {@link #putBooleanVolatile(Object, long, boolean)} */ + @HotSpotIntrinsicCandidate + public final void putBooleanOpaque(Object o, long offset, boolean x) { + putBooleanVolatile(o, offset, x); + } + + /** Opaque version of {@link #putByteVolatile(Object, long, byte)} */ + @HotSpotIntrinsicCandidate + public final void putByteOpaque(Object o, long offset, byte x) { + putByteVolatile(o, offset, x); + } + + /** Opaque version of {@link #putShortVolatile(Object, long, short)} */ + @HotSpotIntrinsicCandidate + public final void putShortOpaque(Object o, long offset, short x) { + putShortVolatile(o, offset, x); + } + + /** Opaque version of {@link #putCharVolatile(Object, long, char)} */ + @HotSpotIntrinsicCandidate + public final void putCharOpaque(Object o, long offset, char x) { + putCharVolatile(o, offset, x); + } + + /** Opaque version of {@link #putIntVolatile(Object, long, int)} */ + @HotSpotIntrinsicCandidate + public final void putIntOpaque(Object o, long offset, int x) { + putIntVolatile(o, offset, x); + } + + /** Opaque version of {@link #putFloatVolatile(Object, long, float)} */ + @HotSpotIntrinsicCandidate + public final void putFloatOpaque(Object o, long offset, float x) { + putFloatVolatile(o, offset, x); + } + + /** Opaque version of {@link #putLongVolatile(Object, long, long)} */ + @HotSpotIntrinsicCandidate + public final void putLongOpaque(Object o, long offset, long x) { + putLongVolatile(o, offset, x); + } + + /** Opaque version of {@link #putDoubleVolatile(Object, long, double)} */ + @HotSpotIntrinsicCandidate + public final void putDoubleOpaque(Object o, long offset, double x) { + putDoubleVolatile(o, offset, x); + } + /** * Unblocks the given thread blocked on {@code park}, or, if it is * not blocked, causes the subsequent call to {@code park} not to @@ -1028,6 +1438,23 @@ public final class Unsafe { @HotSpotIntrinsicCandidate public native void fullFence(); + /** + * Ensures that loads before the fence will not be reordered with + * loads after the fence. + */ + public final void loadLoadFence() { + loadFence(); + } + + /** + * Ensures that stores before the fence will not be reordered with + * stores after the fence. + */ + public final void storeStoreFence() { + storeFence(); + } + + /** * Throws IllegalAccessError; for use by the VM for access control * error support. @@ -1159,7 +1586,12 @@ public final class Unsafe { /** @see #getLongUnaligned(Object, long) */ @HotSpotIntrinsicCandidate public final char getCharUnaligned(Object o, long offset) { - return (char)getShortUnaligned(o, offset); + if ((offset & 1) == 0) { + return getChar(o, offset); + } else { + return (char)makeShort(getByte(o, offset), + getByte(o, offset + 1)); + } } /** @see #getLongUnaligned(Object, long, boolean) */ diff --git a/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java b/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java index 6d99648eac2..787382326f7 100644 --- a/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java +++ b/jdk/src/java.base/share/classes/jdk/internal/ref/CleanerImpl.java @@ -31,6 +31,7 @@ import java.lang.ref.ReferenceQueue; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Function; import jdk.internal.misc.InnocuousThread; @@ -39,7 +40,7 @@ import jdk.internal.misc.InnocuousThread; * CleanerImpl manages a set of object references and corresponding cleaning actions. * CleanerImpl provides the functionality of {@link java.lang.ref.Cleaner}. */ -public final class CleanerImpl { +public final class CleanerImpl implements Runnable { /** * An object to access the CleanerImpl from a Cleaner; set by Cleaner init. @@ -103,7 +104,7 @@ public final class CleanerImpl { } // schedule a nop cleaning action for the cleaner, so the associated thread // will continue to run at least until the cleaner is reclaimable. - new PhantomCleanableRef(cleaner, cleaner, () -> {}); + new CleanerCleanable(cleaner); if (threadFactory == null) { threadFactory = CleanerImpl.InnocuousThreadFactory.factory(); @@ -112,7 +113,7 @@ public final class CleanerImpl { // now that there's at least one cleaning action, for the cleaner, // we can start the associated thread, which runs until // all cleaning actions have been run. - Thread thread = threadFactory.newThread(this::run); + Thread thread = threadFactory.newThread(this); thread.setDaemon(true); thread.start(); } @@ -128,7 +129,8 @@ public final class CleanerImpl { * If the thread is a ManagedLocalsThread, the threadlocals * are erased before each cleanup */ - private void run() { + @Override + public void run() { Thread t = Thread.currentThread(); InnocuousThread mlThread = (t instanceof InnocuousThread) ? (InnocuousThread) t @@ -147,10 +149,9 @@ public final class CleanerImpl { if (ref != null) { ref.clean(); } - } catch (InterruptedException i) { - continue; // ignore the interruption } catch (Throwable e) { // ignore exceptions from the cleanup action + // (including interruption of cleanup thread) } } } @@ -320,14 +321,32 @@ public final class CleanerImpl { return factory; } + final AtomicInteger cleanerThreadNumber = new AtomicInteger(); + public Thread newThread(Runnable r) { - return AccessController.doPrivileged((PrivilegedAction) () -> { - Thread t = new InnocuousThread(r); - t.setPriority(Thread.MAX_PRIORITY - 2); - t.setName("Cleaner-" + t.getId()); - return t; + return AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Thread run() { + Thread t = new InnocuousThread(r); + t.setPriority(Thread.MAX_PRIORITY - 2); + t.setName("Cleaner-" + cleanerThreadNumber.getAndIncrement()); + return t; + } }); } } + /** + * A PhantomCleanable implementation for tracking the Cleaner itself. + */ + static final class CleanerCleanable extends PhantomCleanable { + CleanerCleanable(Cleaner cleaner) { + super(cleaner, cleaner); + } + + @Override + protected void performCleanup() { + // no action + } + } } diff --git a/jdk/src/java.base/share/classes/jdk/net/Sockets.java b/jdk/src/java.base/share/classes/jdk/net/Sockets.java index 1ba53f29a15..a8b78b044d8 100644 --- a/jdk/src/java.base/share/classes/jdk/net/Sockets.java +++ b/jdk/src/java.base/share/classes/jdk/net/Sockets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -251,9 +251,23 @@ public class Sockets { } } + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; + + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + private static void initOptionSets() { boolean flowsupported = ExtendedOptionsImpl.flowSupported(); - + boolean reuseportsupported = isReusePortAvailable(); // Socket Set> set = new HashSet<>(); @@ -261,6 +275,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.TCP_NODELAY); @@ -275,6 +292,9 @@ public class Sockets { set = new HashSet<>(); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); set = Collections.unmodifiableSet(set); options.put(ServerSocket.class, set); @@ -285,6 +305,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); if (flowsupported) { set.add(ExtendedSocketOptions.SO_FLOW_SLA); @@ -298,6 +321,9 @@ public class Sockets { set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (reuseportsupported) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); set.add(StandardSocketOptions.IP_MULTICAST_TTL); @@ -308,4 +334,6 @@ public class Sockets { set = Collections.unmodifiableSet(set); options.put(MulticastSocket.class, set); } + + private static native boolean isReusePortAvailable0(); } diff --git a/jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java b/jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java deleted file mode 100644 index 9fdc6b53b54..00000000000 --- a/jdk/src/java.base/share/classes/sun/misc/ASCIICaseInsensitiveComparator.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.misc; - -import java.util.Comparator; - -/** Implements a locale and case insensitive comparator suitable for - strings that are known to only contain ASCII characters. Some - tables internal to the JDK contain only ASCII data and are using - the "generalized" java.lang.String case-insensitive comparator - which converts each character to both upper and lower case. */ - -public class ASCIICaseInsensitiveComparator implements Comparator { - public static final Comparator CASE_INSENSITIVE_ORDER = - new ASCIICaseInsensitiveComparator(); - - public int compare(String s1, String s2) { - int n1=s1.length(), n2=s2.length(); - int minLen = n1 < n2 ? n1 : n2; - for (int i=0; i < minLen; i++) { - char c1 = s1.charAt(i); - char c2 = s2.charAt(i); - assert c1 <= '\u007F' && c2 <= '\u007F'; - if (c1 != c2) { - c1 = (char)toLower(c1); - c2 = (char)toLower(c2); - if (c1 != c2) { - return c1 - c2; - } - } - } - return n1 - n2; - } - - /** - * A case insensitive hash code method to go with the case insensitive - * compare() method. - * - * Returns a hash code for this ASCII string as if it were lower case. - * - * returns same answer as:

        - * s.toLowerCase(Locale.US).hashCode();

        - * but does not allocate memory (it does NOT have the special - * case Turkish rules). - * - * @param s a String to compute the hashcode on. - * @return a hash code value for this object. - */ - public static int lowerCaseHashCode(String s) { - int h = 0; - int len = s.length(); - - for (int i = 0; i < len; i++) { - h = 31*h + toLower(s.charAt(i)); - } - - return h; - } - - /* If java.util.regex.ASCII ever becomes public or sun.*, use its code instead:*/ - static boolean isLower(int ch) { - return ((ch-'a')|('z'-ch)) >= 0; - } - - static boolean isUpper(int ch) { - return ((ch-'A')|('Z'-ch)) >= 0; - } - - static int toLower(int ch) { - return isUpper(ch) ? (ch + 0x20) : ch; - } - - static int toUpper(int ch) { - return isLower(ch) ? (ch - 0x20) : ch; - } -} diff --git a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java index 1ad9a2776b6..ac86bdc5756 100644 --- a/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java +++ b/jdk/src/java.base/share/classes/sun/misc/URLClassPath.java @@ -63,6 +63,7 @@ import java.util.jar.JarEntry; import java.util.jar.Manifest; import java.util.jar.Attributes; import java.util.jar.Attributes.Name; +import java.util.zip.ZipFile; import jdk.internal.jimage.ImageLocation; import jdk.internal.jimage.ImageReader; @@ -727,9 +728,10 @@ public class URLClassPath { if (!p.exists()) { throw new FileNotFoundException(p.getPath()); } - return checkJar(new JarFile(p.getPath())); + return checkJar(new JarFile(new File(p.getPath()), true, ZipFile.OPEN_READ, + JarFile.Release.RUNTIME)); } - URLConnection uc = getBaseURL().openConnection(); + URLConnection uc = (new URL(getBaseURL(), "#runtime")).openConnection(); uc.setRequestProperty(USER_AGENT_JAVA_VERSION, JAVA_VERSION); JarFile jarFile = ((JarURLConnection)uc).getJarFile(); return checkJar(jarFile); @@ -756,7 +758,13 @@ public class URLClassPath { final URL url; try { - url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + if (jar.isMultiRelease()) { + // add #runtime fragment to tell JarURLConnection to use + // runtime versioning if the underlying jar file is multi-release + url = new URL(getBaseURL(), ParseUtil.encodePath(name, false) + "#runtime"); + } else { + url = new URL(getBaseURL(), ParseUtil.encodePath(name, false)); + } if (check) { URLClassPath.check(url); } diff --git a/jdk/src/java.base/share/classes/sun/misc/Version.java.template b/jdk/src/java.base/share/classes/sun/misc/Version.java.template deleted file mode 100644 index 51b306a0cc4..00000000000 --- a/jdk/src/java.base/share/classes/sun/misc/Version.java.template +++ /dev/null @@ -1,268 +0,0 @@ -/* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.misc; -import java.io.PrintStream; - -public class Version { - - - private static final String launcher_name = - "@@LAUNCHER_NAME@@"; - - private static final String java_version = - "@@VERSION_SHORT@@"; - - private static final String java_runtime_name = - "@@RUNTIME_NAME@@"; - - private static final String java_runtime_version = - "@@VERSION_STRING@@"; - - static { - init(); - } - - public static void init() { - System.setProperty("java.version", java_version); - System.setProperty("java.runtime.version", java_runtime_version); - System.setProperty("java.runtime.name", java_runtime_name); - } - - private static boolean versionsInitialized = false; - private static int jvm_major_version = 0; - private static int jvm_minor_version = 0; - private static int jvm_security_version = 0; - private static int jvm_patch_version = 0; - private static int jvm_build_number = 0; - private static int jdk_major_version = 0; - private static int jdk_minor_version = 0; - private static int jdk_security_version = 0; - private static int jdk_patch_version = 0; - private static int jdk_build_number = 0; - - /** - * In case you were wondering this method is called by java -version. - * Sad that it prints to stderr; would be nicer if default printed on - * stdout. - */ - public static void print() { - print(System.err); - } - - /** - * This is the same as print except that it adds an extra line-feed - * at the end, typically used by the -showversion in the launcher - */ - public static void println() { - print(System.err); - System.err.println(); - } - - /** - * Give a stream, it will print version info on it. - */ - public static void print(PrintStream ps) { - boolean isHeadless = false; - - /* Report that we're running headless if the property is true */ - String headless = System.getProperty("java.awt.headless"); - if ( (headless != null) && (headless.equalsIgnoreCase("true")) ) { - isHeadless = true; - } - - /* First line: platform version. */ - ps.println(launcher_name + " version \"" + java_version + "\""); - - /* Second line: runtime version (ie, libraries). */ - - String jdk_debug_level = System.getProperty("jdk.debug", "release"); - /* Debug level is not printed for "release" builds */ - if ("release".equals(jdk_debug_level)) { - jdk_debug_level = ""; - } else { - jdk_debug_level = jdk_debug_level + " "; - } - - ps.print(java_runtime_name + " (" + jdk_debug_level + "build " + java_runtime_version); - - if (java_runtime_name.indexOf("Embedded") != -1 && isHeadless) { - // embedded builds report headless state - ps.print(", headless"); - } - ps.println(')'); - - /* Third line: JVM information. */ - String java_vm_name = System.getProperty("java.vm.name"); - String java_vm_version = System.getProperty("java.vm.version"); - String java_vm_info = System.getProperty("java.vm.info"); - ps.println(java_vm_name + " (" + jdk_debug_level + "build " + java_vm_version + ", " + - java_vm_info + ")"); - } - - - /** - * Returns the major version of the running JVM. - * @return the major version of the running JVM - * @since 1.6 - */ - public static synchronized int jvmMajorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_major_version; - } - - /** - * Returns the minor version of the running JVM. - * @return the minor version of the running JVM - * @since 1.6 - */ - public static synchronized int jvmMinorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_minor_version; - } - - - /** - * Returns the security version of the running JVM. - * @return the security version of the running JVM - * @since 9 - */ - public static synchronized int jvmSecurityVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_security_version; - } - - /** - * Returns the patch release version of the running JVM. - * @return the patch release version of the running JVM - * @since 9 - */ - public static synchronized int jvmPatchVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_patch_version; - } - - /** - * Returns the build number of the running JVM. - * @return the build number of the running JVM - * @since 1.6 - */ - public static synchronized int jvmBuildNumber() { - if (!versionsInitialized) { - initVersions(); - } - return jvm_build_number; - } - - /** - * Returns the major version of the running JDK. - * @return the major version of the running JDK - * @since 1.6 - */ - public static synchronized int jdkMajorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_major_version; - } - - /** - * Returns the minor version of the running JDK. - * @return the minor version of the running JDK - * @since 1.6 - */ - public static synchronized int jdkMinorVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_minor_version; - } - - /** - * Returns the security version of the running JDK. - * @return the security version of the running JDK - * @since 9 - */ - public static synchronized int jdkSecurityVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_security_version; - } - - /** - * Returns the patch release version of the running JDK. - * @return the patch release version of the running JDK - * @since 9 - */ - public static synchronized int jdkPatchVersion() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_patch_version; - } - - /** - * Returns the build number of the running JDK. - * @return the build number of the running JDK - * @since 1.6 - */ - public static synchronized int jdkBuildNumber() { - if (!versionsInitialized) { - initVersions(); - } - return jdk_build_number; - } - - private static synchronized void initVersions() { - if (versionsInitialized) { - return; - } - if (!getJvmVersionInfo()) { - throw new InternalError("Unable to obtain JVM version info"); - } - getJdkVersionInfo(); - versionsInitialized = true; - } - - // Gets the JVM version info if available and sets the jvm_*_version fields - // and its capabilities. - private static native boolean getJvmVersionInfo(); - private static native void getJdkVersionInfo(); -} - -// Help Emacs a little because this file doesn't end in .java. -// -// Local Variables: *** -// mode: java *** -// End: *** diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java index 1e8697ba237..fe1a1f3c8f2 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/jar/URLJarFile.java @@ -65,9 +65,10 @@ public class URLJarFile extends JarFile { } static JarFile getJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - if (isFileURL(url)) - return new URLJarFile(url, closeController); - else { + if (isFileURL(url)) { + Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE; + return new URLJarFile(url, closeController, version); + } else { return retrieve(url, closeController); } } @@ -89,8 +90,13 @@ public class URLJarFile extends JarFile { this.closeController = closeController; } - private URLJarFile(URL url, URLJarFileCloseController closeController) throws IOException { - super(ParseUtil.decode(url.getFile())); + private URLJarFile(File file, URLJarFileCloseController closeController, Release version) throws IOException { + super(file, true, ZipFile.OPEN_READ | ZipFile.OPEN_DELETE, version); + this.closeController = closeController; + } + + private URLJarFile(URL url, URLJarFileCloseController closeController, Release version) throws IOException { + super(new File(ParseUtil.decode(url.getFile())), true, ZipFile.OPEN_READ, version); this.closeController = closeController; } @@ -175,14 +181,6 @@ public class URLJarFile extends JarFile { return false; } - /** - * Given a URL, retrieves a JAR file, caches it to disk, and creates a - * cached JAR file object. - */ - private static JarFile retrieve(final URL url) throws IOException { - return retrieve(url, null); - } - /** * Given a URL, retrieves a JAR file, caches it to disk, and creates a * cached JAR file object. @@ -202,6 +200,7 @@ public class URLJarFile extends JarFile { { JarFile result = null; + Release version = "runtime".equals(url.getRef()) ? Release.RUNTIME : Release.BASE; /* get the stream before asserting privileges */ try (final InputStream in = url.openConnection().getInputStream()) { @@ -211,7 +210,7 @@ public class URLJarFile extends JarFile { Path tmpFile = Files.createTempFile("jar_cache", null); try { Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING); - JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController); + JarFile jarFile = new URLJarFile(tmpFile.toFile(), closeController, version); tmpFile.toFile().deleteOnExit(); return jarFile; } catch (Throwable thr) { diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java index 8ed2c9f1317..39b19b42204 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,6 +231,9 @@ abstract class AsynchronousServerSocketChannelImpl HashSet> set = new HashSet<>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } return Collections.unmodifiableSet(set); } } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java index 3122b96a29f..36b3c1b7ab9 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/AsynchronousSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -508,6 +508,9 @@ abstract class AsynchronousSocketChannelImpl set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.TCP_NODELAY); if (ExtendedOptionsImpl.flowSupported()) { set.add(jdk.net.ExtendedSocketOptions.SO_FLOW_SLA); diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index 7eb987991c9..77d14619222 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -298,6 +298,9 @@ class DatagramChannelImpl set.add(StandardSocketOptions.SO_SNDBUF); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_BROADCAST); set.add(StandardSocketOptions.IP_TOS); set.add(StandardSocketOptions.IP_MULTICAST_IF); diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java b/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java index d2c03a34fea..3c43c5a6777 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/IOVecWrapper.java @@ -26,7 +26,7 @@ package sun.nio.ch; import java.nio.ByteBuffer; -import jdk.internal.ref.Cleaner; +import jdk.internal.ref.CleanerFactory; /** @@ -101,7 +101,7 @@ class IOVecWrapper { } if (wrapper == null) { wrapper = new IOVecWrapper(size); - Cleaner.create(wrapper, new Deallocator(wrapper.vecArray)); + CleanerFactory.cleaner().register(wrapper, new Deallocator(wrapper.vecArray)); cached.set(wrapper); } return wrapper; diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java index 27c46a9ca2c..062ce35468e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Net.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Net.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,6 +56,8 @@ public class Net { private static volatile boolean checkedIPv6; private static volatile boolean isIPv6Available; + private static volatile boolean checkedReusePort; + private static volatile boolean isReusePortAvailable; /** * Tells whether dual-IPv4/IPv6 sockets should be used. @@ -68,6 +70,17 @@ public class Net { return isIPv6Available; } + /** + * Tells whether SO_REUSEPORT is supported. + */ + static boolean isReusePortAvailable() { + if (!checkedReusePort) { + isReusePortAvailable = isReusePortAvailable0(); + checkedReusePort = true; + } + return isReusePortAvailable; + } + /** * Returns true if exclusive binding is on */ @@ -389,6 +402,8 @@ public class Net { private static native boolean isIPv6Available0(); + private static native boolean isReusePortAvailable0(); + /* * Returns 1 for Windows and -1 for Solaris/Linux/Mac OS */ diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java index 2a427f1a352..9cfe7c43c4d 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/ServerSocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,6 @@ import java.nio.channels.spi.*; import java.util.*; import sun.net.NetHooks; - /** * An implementation of ServerSocketChannels */ @@ -185,6 +184,9 @@ class ServerSocketChannelImpl HashSet> set = new HashSet<>(2); set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.IP_TOS); return Collections.unmodifiableSet(set); } diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index c4965e1111b..c4644920c3e 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -234,6 +234,9 @@ class SocketChannelImpl set.add(StandardSocketOptions.SO_RCVBUF); set.add(StandardSocketOptions.SO_KEEPALIVE); set.add(StandardSocketOptions.SO_REUSEADDR); + if (Net.isReusePortAvailable()) { + set.add(StandardSocketOptions.SO_REUSEPORT); + } set.add(StandardSocketOptions.SO_LINGER); set.add(StandardSocketOptions.TCP_NODELAY); // additional options required by socket adaptor diff --git a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java index a580b82c4d0..af89eca4544 100644 --- a/jdk/src/java.base/share/classes/sun/nio/ch/Util.java +++ b/jdk/src/java.base/share/classes/sun/nio/ch/Util.java @@ -33,7 +33,6 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.util.*; import jdk.internal.misc.Unsafe; -import jdk.internal.ref.Cleaner; import sun.security.action.GetPropertyAction; diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java index 91efac348e8..1a215d11bf1 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffer.java @@ -71,8 +71,8 @@ class NativeBuffer { return size; } - Cleaner cleaner() { - return cleaner; + void free() { + cleaner.clean(); } // not synchronized; only safe for use by thread-local caches diff --git a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java index 728d96eb2b3..4f0aa5c9071 100644 --- a/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java +++ b/jdk/src/java.base/share/classes/sun/nio/fs/NativeBuffers.java @@ -107,14 +107,14 @@ class NativeBuffers { for (int i=0; i responses) throws SSLException { + Map responses) { statusType = type; encodedResponsesLen = 0; encodedResponses = new ArrayList<>(chain.length); @@ -715,7 +715,7 @@ static final class CertificateStatus extends HandshakeMessage encodedResponses.add(respDER); encodedResponsesLen = 3 + respDER.length; } else { - throw new SSLHandshakeException("Zero-length or null " + + throw new IllegalArgumentException("Zero-length or null " + "OCSP Response"); } } else if (statusType == StatusRequestType.OCSP_MULTI) { @@ -732,8 +732,8 @@ static final class CertificateStatus extends HandshakeMessage } } } else { - throw new SSLHandshakeException("Unsupported StatusResponseType: " + - statusType); + throw new IllegalArgumentException( + "Unsupported StatusResponseType: " + statusType); } } diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java index 15b420da172..903f6fb376a 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/SSLContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -55,7 +55,11 @@ public abstract class SSLContextImpl extends SSLContextSpi { // DTLS cookie exchange manager private volatile HelloCookieManager helloCookieManager; - private StatusResponseManager statusResponseManager; + private final boolean clientEnableStapling = Debug.getBooleanProperty( + "jdk.tls.client.enableStatusRequestExtension", true); + private final boolean serverEnableStapling = Debug.getBooleanProperty( + "jdk.tls.server.enableStatusRequestExtension", false); + private volatile StatusResponseManager statusResponseManager; SSLContextImpl() { ephemeralKeyManager = new EphemeralKeyManager(); @@ -80,7 +84,6 @@ public abstract class SSLContextImpl extends SSLContextSpi { } } trustManager = chooseTrustManager(tm); - statusResponseManager = new StatusResponseManager(); if (sr == null) { secureRandom = JsseJce.getSecureRandom(); @@ -258,6 +261,18 @@ public abstract class SSLContextImpl extends SSLContextSpi { } StatusResponseManager getStatusResponseManager() { + if (serverEnableStapling && statusResponseManager == null) { + synchronized (this) { + if (statusResponseManager == null) { + if (debug != null && Debug.isOn("sslctx")) { + System.out.println( + "Initializing StatusResponseManager"); + } + statusResponseManager = new StatusResponseManager(); + } + } + } + return statusResponseManager; } @@ -309,6 +324,18 @@ public abstract class SSLContextImpl extends SSLContextSpi { (cipherSuites == getClientDefaultCipherSuiteList()); } + /** + * Return whether client or server side stapling has been enabled + * for this SSLContextImpl + * @param isClient true if the caller is operating in a client side role, + * false if acting as a server. + * @return true if stapling has been enabled for the specified role, false + * otherwise. + */ + boolean isStaplingEnabled(boolean isClient) { + return isClient ? clientEnableStapling : serverEnableStapling; + } + /* * Return the list of all available CipherSuites with a priority of * minPriority or above. diff --git a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java index 0b8072ff679..a4c119faf25 100644 --- a/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java +++ b/jdk/src/java.base/share/classes/sun/security/ssl/ServerHandshaker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ import java.security.spec.ECParameterSpec; import java.math.BigInteger; import javax.crypto.SecretKey; -import javax.crypto.spec.SecretKeySpec; import javax.net.ssl.*; import sun.security.action.GetLongAction; @@ -67,7 +66,6 @@ final class ServerHandshaker extends Handshaker { // our authentication info private X509Certificate[] certs; - private Map responseMap; private PrivateKey privateKey; private Object serviceCreds; @@ -118,11 +116,6 @@ final class ServerHandshaker extends Handshaker { LegacyAlgorithmConstraints.PROPERTY_TLS_LEGACY_ALGS, new SSLAlgorithmDecomposer()); - // To switch off the status_request[_v2] extensions - private static final boolean enableStatusRequestExtension = - Debug.getBooleanProperty( - "jdk.tls.server.enableStatusRequestExtension", false); - private boolean staplingActive = false; private long statusRespTimeout; static { @@ -582,16 +575,6 @@ final class ServerHandshaker extends Handshaker { } } - // Check if the client has asserted the status_request[_v2] extension(s) - CertStatusReqExtension statReqExt = (CertStatusReqExtension) - mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST); - CertStatusReqListV2Extension statReqExtV2 = - (CertStatusReqListV2Extension)mesg.extensions.get( - ExtensionType.EXT_STATUS_REQUEST_V2); - // Keep stapling active if at least one of the extensions has been set - staplingActive = enableStatusRequestExtension && - (statReqExt != null || statReqExtV2 != null); - /* * FIRST, construct the ServerHello using the options and priorities * from the ClientHello. Update the (pending) cipher spec as we do @@ -887,66 +870,17 @@ final class ServerHandshaker extends Handshaker { m1.extensions.add(maxFragLenExt); } - StatusRequestType statReqType = null; - StatusRequest statReqData = null; - if (staplingActive && !resumingSession) { - ExtensionType statusRespExt = ExtensionType.EXT_STATUS_REQUEST; - - // Determine which type of stapling we are doing and assert the - // proper extension in the server hello. - // Favor status_request_v2 over status_request and ocsp_multi - // over ocsp. - // If multiple ocsp or ocsp_multi types exist, select the first - // instance of a given type - if (statReqExtV2 != null) { // RFC 6961 stapling - statusRespExt = ExtensionType.EXT_STATUS_REQUEST_V2; - List reqItems = - statReqExtV2.getRequestItems(); - int ocspIdx = -1; - int ocspMultiIdx = -1; - for (int pos = 0; pos < reqItems.size(); pos++) { - CertStatusReqItemV2 item = reqItems.get(pos); - if (ocspIdx < 0 && item.getType() == - StatusRequestType.OCSP) { - ocspIdx = pos; - } else if (ocspMultiIdx < 0 && item.getType() == - StatusRequestType.OCSP_MULTI) { - ocspMultiIdx = pos; - } - } - if (ocspMultiIdx >= 0) { - statReqType = reqItems.get(ocspMultiIdx).getType(); - statReqData = reqItems.get(ocspMultiIdx).getRequest(); - } else if (ocspIdx >= 0) { - statReqType = reqItems.get(ocspIdx).getType(); - statReqData = reqItems.get(ocspIdx).getRequest(); - } else { - // Some unknown type. We will not do stapling for - // this connection since we cannot understand the - // requested type. - staplingActive = false; - } - } else { // RFC 6066 stapling - statReqType = StatusRequestType.OCSP; - statReqData = statReqExt.getRequest(); - } - - if (statReqType != null && statReqData != null) { - // Next, attempt to obtain status responses - StatusResponseManager statRespMgr = - sslContext.getStatusResponseManager(); - responseMap = statRespMgr.get(statReqType, statReqData, certs, - statusRespTimeout, TimeUnit.MILLISECONDS); - if (!responseMap.isEmpty()) { - // We now can safely assert status_request[_v2] in our - // ServerHello, and know for certain that we can provide - // responses back to this client for this connection. - if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST) { - m1.extensions.add(new CertStatusReqExtension()); - } else if (statusRespExt == ExtensionType.EXT_STATUS_REQUEST_V2) { - m1.extensions.add(new CertStatusReqListV2Extension()); - } - } + StaplingParameters staplingParams = processStapling(mesg); + if (staplingParams != null) { + // We now can safely assert status_request[_v2] in our + // ServerHello, and know for certain that we can provide + // responses back to this client for this connection. + if (staplingParams.statusRespExt == + ExtensionType.EXT_STATUS_REQUEST) { + m1.extensions.add(new CertStatusReqExtension()); + } else if (staplingParams.statusRespExt == + ExtensionType.EXT_STATUS_REQUEST_V2) { + m1.extensions.add(new CertStatusReqListV2Extension()); } } @@ -1022,24 +956,15 @@ final class ServerHandshaker extends Handshaker { * supports status stapling and there is at least one response to * return to the client. */ - if (staplingActive && !responseMap.isEmpty()) { - try { - CertificateStatus csMsg = new CertificateStatus(statReqType, - certs, responseMap); - if (debug != null && Debug.isOn("handshake")) { - csMsg.print(System.out); - } - csMsg.write(output); - handshakeState.update(csMsg, resumingSession); - responseMap = null; - } catch (SSLException ssle) { - // We don't want the exception to be fatal, we just won't - // send the message if we fail on construction. - if (debug != null && Debug.isOn("handshake")) { - System.out.println("Failed during CertificateStatus " + - "construction: " + ssle); - } + if (staplingParams != null) { + CertificateStatus csMsg = new CertificateStatus( + staplingParams.statReqType, certs, + staplingParams.responseMap); + if (debug != null && Debug.isOn("handshake")) { + csMsg.print(System.out); } + csMsg.write(output); + handshakeState.update(csMsg, resumingSession); } /* @@ -2069,4 +1994,121 @@ final class ServerHandshaker extends Handshaker { session.setPeerCertificates(peerCerts); } + + private StaplingParameters processStapling(ClientHello mesg) { + StaplingParameters params = null; + ExtensionType ext; + StatusRequestType type = null; + StatusRequest req = null; + Map responses; + + // If this feature has not been enabled, then no more processing + // is necessary. Also we will only staple if we're doing a full + // handshake. + if (!sslContext.isStaplingEnabled(false) || resumingSession) { + return null; + } + + // Check if the client has asserted the status_request[_v2] extension(s) + CertStatusReqExtension statReqExt = (CertStatusReqExtension) + mesg.extensions.get(ExtensionType.EXT_STATUS_REQUEST); + CertStatusReqListV2Extension statReqExtV2 = + (CertStatusReqListV2Extension)mesg.extensions.get( + ExtensionType.EXT_STATUS_REQUEST_V2); + // Keep processing only if either status_request or status_request_v2 + // has been sent in the ClientHello. + if (statReqExt == null && statReqExtV2 == null) { + return null; + } + + // Determine which type of stapling we are doing and assert the + // proper extension in the server hello. + // Favor status_request_v2 over status_request and ocsp_multi + // over ocsp. + // If multiple ocsp or ocsp_multi types exist, select the first + // instance of a given type + ext = ExtensionType.EXT_STATUS_REQUEST; + if (statReqExtV2 != null) { // RFC 6961 stapling + ext = ExtensionType.EXT_STATUS_REQUEST_V2; + List reqItems = + statReqExtV2.getRequestItems(); + int ocspIdx = -1; + int ocspMultiIdx = -1; + for (int pos = 0; pos < reqItems.size(); pos++) { + CertStatusReqItemV2 item = reqItems.get(pos); + if (ocspIdx < 0 && item.getType() == + StatusRequestType.OCSP) { + ocspIdx = pos; + } else if (ocspMultiIdx < 0 && item.getType() == + StatusRequestType.OCSP_MULTI) { + ocspMultiIdx = pos; + } + } + if (ocspMultiIdx >= 0) { + type = reqItems.get(ocspMultiIdx).getType(); + req = reqItems.get(ocspMultiIdx).getRequest(); + } else if (ocspIdx >= 0) { + type = reqItems.get(ocspIdx).getType(); + req = reqItems.get(ocspIdx).getRequest(); + } + } else { // RFC 6066 stapling + type = StatusRequestType.OCSP; + req = statReqExt.getRequest(); + } + + // If, after walking through the extensions we were unable to + // find a suitable StatusRequest, then stapling is disabled. + // Both statReqType and statReqData must have been set to continue. + if (type == null || req == null) { + return null; + } + + // Get the OCSP responses from the StatusResponseManager + StatusResponseManager statRespMgr = + sslContext.getStatusResponseManager(); + if (statRespMgr != null) { + responses = statRespMgr.get(type, req, certs, statusRespTimeout, + TimeUnit.MILLISECONDS); + if (!responses.isEmpty()) { + // If this RFC 6066-style stapling (SSL cert only) then the + // response cannot be zero length + if (type == StatusRequestType.OCSP) { + byte[] respDER = responses.get(certs[0]); + if (respDER == null || respDER.length <= 0) { + return null; + } + } + params = new StaplingParameters(ext, type, req, responses); + } + } else { + // This should not happen, but if lazy initialization of the + // StatusResponseManager doesn't occur we should turn off stapling. + if (debug != null && Debug.isOn("handshake")) { + System.out.println("Warning: lazy initialization " + + "of the StatusResponseManager failed. " + + "Stapling has been disabled."); + } + } + + return params; + } + + /** + * Inner class used to hold stapling parameters needed by the handshaker + * when stapling is active. + */ + private class StaplingParameters { + private final ExtensionType statusRespExt; + private final StatusRequestType statReqType; + private final StatusRequest statReqData; + private final Map responseMap; + + StaplingParameters(ExtensionType ext, StatusRequestType type, + StatusRequest req, Map responses) { + statusRespExt = ext; + statReqType = type; + statReqData = req; + responseMap = responses; + } + } } diff --git a/jdk/src/java.base/share/conf/security/java.security b/jdk/src/java.base/share/conf/security/java.security index 157fa3c7fc7..fdcfe2be25c 100644 --- a/jdk/src/java.base/share/conf/security/java.security +++ b/jdk/src/java.base/share/conf/security/java.security @@ -578,7 +578,7 @@ jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # # Example: # jdk.tls.disabledAlgorithms=MD5, SSLv3, DSA, RSA keySize < 2048 -jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 768 +jdk.tls.disabledAlgorithms=SSLv3, RC4, MD5withRSA, DH keySize < 1024 # Legacy algorithms for Secure Socket Layer/Transport Layer Security (SSL/TLS) # processing in JSSE implementation. diff --git a/jdk/src/java.base/share/native/include/jni.h b/jdk/src/java.base/share/native/include/jni.h index 2e83cb7e06e..c09658a1fa7 100644 --- a/jdk/src/java.base/share/native/include/jni.h +++ b/jdk/src/java.base/share/native/include/jni.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1952,6 +1952,7 @@ JNI_OnUnload(JavaVM *vm, void *reserved); #define JNI_VERSION_1_4 0x00010004 #define JNI_VERSION_1_6 0x00010006 #define JNI_VERSION_1_8 0x00010008 +#define JNI_VERSION_9 0x00090000 #ifdef __cplusplus } /* extern "C" */ diff --git a/jdk/src/java.base/share/native/libjava/Bits.c b/jdk/src/java.base/share/native/libjava/Bits.c deleted file mode 100644 index f3780199718..00000000000 --- a/jdk/src/java.base/share/native/libjava/Bits.c +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - */ - -#include "jni.h" -#include "jni_util.h" -#include "jlong.h" -#include - -#define MBYTE 1048576 - -#define GETCRITICAL_OR_RETURN(bytes, env, obj) { \ - bytes = (*env)->GetPrimitiveArrayCritical(env, obj, NULL); \ - if (bytes == NULL) { \ - if ((*env)->ExceptionOccurred(env) == NULL) \ - JNU_ThrowInternalError(env, "Unable to get array"); \ - return; \ - } \ -} - -#define RELEASECRITICAL(bytes, env, obj, mode) { \ - (*env)->ReleasePrimitiveArrayCritical(env, obj, bytes, mode); \ -} - -#define SWAPSHORT(x) ((jshort)(((x) << 8) | (((x) >> 8) & 0xff))) -#define SWAPINT(x) ((jint)((SWAPSHORT((jshort)(x)) << 16) | \ - (SWAPSHORT((jshort)((x) >> 16)) & 0xffff))) -#define SWAPLONG(x) ((jlong)(((jlong)SWAPINT((jint)(x)) << 32) | \ - ((jlong)SWAPINT((jint)((x) >> 32)) & 0xffffffff))) - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromShortArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jshort *srcShort, *dstShort, *endShort; - jshort tmpShort; - - dstShort = (jshort *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcShort = (jshort *)(bytes + srcPos); - endShort = srcShort + (size / sizeof(jshort)); - while (srcShort < endShort) { - tmpShort = *srcShort++; - *dstShort++ = SWAPSHORT(tmpShort); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToShortArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jshort *srcShort, *dstShort, *endShort; - jshort tmpShort; - - srcShort = (jshort *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstShort = (jshort *)(bytes + dstPos); - endShort = srcShort + (size / sizeof(jshort)); - while (srcShort < endShort) { - tmpShort = *srcShort++; - *dstShort++ = SWAPSHORT(tmpShort); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromIntArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jint *srcInt, *dstInt, *endInt; - jint tmpInt; - - dstInt = (jint *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcInt = (jint *)(bytes + srcPos); - endInt = srcInt + (size / sizeof(jint)); - while (srcInt < endInt) { - tmpInt = *srcInt++; - *dstInt++ = SWAPINT(tmpInt); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToIntArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jint *srcInt, *dstInt, *endInt; - jint tmpInt; - - srcInt = (jint *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstInt = (jint *)(bytes + dstPos); - endInt = srcInt + (size / sizeof(jint)); - while (srcInt < endInt) { - tmpInt = *srcInt++; - *dstInt++ = SWAPINT(tmpInt); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyFromLongArray(JNIEnv *env, jclass clazz, jobject src, - jlong srcPos, jlong dstAddr, jlong length) -{ - jbyte *bytes; - size_t size; - jlong *srcLong, *dstLong, *endLong; - jlong tmpLong; - - dstLong = (jlong *)jlong_to_ptr(dstAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, src); - - srcLong = (jlong *)(bytes + srcPos); - endLong = srcLong + (size / sizeof(jlong)); - while (srcLong < endLong) { - tmpLong = *srcLong++; - *dstLong++ = SWAPLONG(tmpLong); - } - - RELEASECRITICAL(bytes, env, src, JNI_ABORT); - - length -= size; - srcPos += size; - } -} - -JNIEXPORT void JNICALL -Java_java_nio_Bits_copyToLongArray(JNIEnv *env, jclass clazz, jlong srcAddr, - jobject dst, jlong dstPos, jlong length) -{ - jbyte *bytes; - size_t size; - jlong *srcLong, *dstLong, *endLong; - jlong tmpLong; - - srcLong = (jlong *)jlong_to_ptr(srcAddr); - - while (length > 0) { - size = (length < MBYTE) ? (size_t)length : (size_t)MBYTE; - - GETCRITICAL_OR_RETURN(bytes, env, dst); - - dstLong = (jlong *)(bytes + dstPos); - endLong = srcLong + (size / sizeof(jlong)); - while (srcLong < endLong) { - tmpLong = *srcLong++; - *dstLong++ = SWAPLONG(tmpLong); - } - - RELEASECRITICAL(bytes, env, dst, 0); - - length -= size; - dstPos += size; - } -} diff --git a/jdk/src/java.base/share/native/libjava/Version.c b/jdk/src/java.base/share/native/libjava/Version.c deleted file mode 100644 index a58e1bb3f3b..00000000000 --- a/jdk/src/java.base/share/native/libjava/Version.c +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jvm.h" -#include "jdk_util.h" - -#include "sun_misc_Version.h" - -static void setStaticIntField(JNIEnv* env, jclass cls, const char* name, jint value) -{ - jfieldID fid; - fid = (*env)->GetStaticFieldID(env, cls, name, "I"); - if (fid != 0) { - (*env)->SetStaticIntField(env, cls, fid, value); - } -} - -typedef void (JNICALL *GetJvmVersionInfo_fp)(JNIEnv*, jvm_version_info*, size_t); - -JNIEXPORT jboolean JNICALL -Java_sun_misc_Version_getJvmVersionInfo(JNIEnv *env, jclass cls) -{ - jvm_version_info info; - GetJvmVersionInfo_fp func_p; - - if (!JDK_InitJvmHandle()) { - JNU_ThrowInternalError(env, "Handle for JVM not found for symbol lookup"); - return JNI_FALSE; - } - func_p = (GetJvmVersionInfo_fp) JDK_FindJvmEntry("JVM_GetVersionInfo"); - if (func_p == NULL) { - return JNI_FALSE; - } - - (*func_p)(env, &info, sizeof(info)); - setStaticIntField(env, cls, "jvm_major_version", JVM_VERSION_MAJOR(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_minor_version", JVM_VERSION_MINOR(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_security_version", JVM_VERSION_SECURITY(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_build_number", JVM_VERSION_BUILD(info.jvm_version)); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - setStaticIntField(env, cls, "jvm_patch_version", info.patch_version); - JNU_CHECK_EXCEPTION_RETURN(env, JNI_FALSE); - - return JNI_TRUE; -} - -JNIEXPORT void JNICALL -Java_sun_misc_Version_getJdkVersionInfo(JNIEnv *env, jclass cls) -{ - jdk_version_info info; - - JDK_GetVersionInfo0(&info, sizeof(info)); - setStaticIntField(env, cls, "jdk_major_version", JDK_VERSION_MAJOR(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_minor_version", JDK_VERSION_MINOR(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_security_version", JDK_VERSION_SECURITY(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_build_number", JDK_VERSION_BUILD(info.jdk_version)); - JNU_CHECK_EXCEPTION(env); - setStaticIntField(env, cls, "jdk_patch_version", info.patch_version); - JNU_CHECK_EXCEPTION(env); -} diff --git a/jdk/src/java.base/share/native/libjli/java.c b/jdk/src/java.base/share/native/libjli/java.c index 9c7b27052ac..41e0e21f14b 100644 --- a/jdk/src/java.base/share/native/libjli/java.c +++ b/jdk/src/java.base/share/native/libjli/java.c @@ -1470,7 +1470,7 @@ PrintJavaVersion(JNIEnv *env, jboolean extraLF) jclass ver; jmethodID print; - NULL_CHECK(ver = FindBootStrapClass(env, "sun/misc/Version")); + NULL_CHECK(ver = FindBootStrapClass(env, "java/lang/VersionProps")); NULL_CHECK(print = (*env)->GetStaticMethodID(env, ver, (extraLF == JNI_TRUE) ? "println" : "print", diff --git a/jdk/src/java.base/share/native/libnet/net_util.c b/jdk/src/java.base/share/native/libnet/net_util.c index e94903fd720..c2d4b002b04 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.c +++ b/jdk/src/java.base/share/native/libnet/net_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,14 +29,21 @@ #include "net_util.h" int IPv6_supported() ; +int reuseport_supported() ; static int IPv6_available; +static int REUSEPORT_available; JNIEXPORT jint JNICALL ipv6_available() { return IPv6_available ; } +JNIEXPORT jint JNICALL reuseport_available() +{ + return REUSEPORT_available; +} + JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { @@ -45,7 +52,6 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) jmethodID mid; jstring s; jint preferIPv4Stack; - if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) { return JNI_EVERSION; /* JNI version not supported */ } @@ -64,6 +70,9 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) supporting socket APIs are available */ IPv6_available = IPv6_supported() & (!preferIPv4Stack); + + /* check if SO_REUSEPORT is supported on this platform */ + REUSEPORT_available = reuseport_supported(); platformInit(); parseExclusiveBindProperty(env); diff --git a/jdk/src/java.base/share/native/libnet/net_util.h b/jdk/src/java.base/share/native/libnet/net_util.h index f6b29297ecf..1d7b2a2c51e 100644 --- a/jdk/src/java.base/share/native/libnet/net_util.h +++ b/jdk/src/java.base/share/native/libnet/net_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,6 +131,8 @@ jfieldID NET_GetFileDescriptorID(JNIEnv *env); JNIEXPORT jint JNICALL ipv6_available() ; +JNIEXPORT jint JNICALL reuseport_available() ; + void NET_AllocSockaddr(struct sockaddr **him, int *len); diff --git a/jdk/src/java.base/share/native/libzip/CRC32.c b/jdk/src/java.base/share/native/libzip/CRC32.c index 5d1a5c34d95..e29207b7764 100644 --- a/jdk/src/java.base/share/native/libzip/CRC32.c +++ b/jdk/src/java.base/share/native/libzip/CRC32.c @@ -54,7 +54,7 @@ Java_java_util_zip_CRC32_updateBytes0(JNIEnv *env, jclass cls, jint crc, return crc; } -JNIEXPORT jint JNICALL +jint JNICALL ZIP_CRC32(jint crc, const jbyte *buf, jint len) { return crc32(crc, (Bytef*)buf, len); diff --git a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java index 31715d40c82..f7c65931613 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,15 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl protected void setOption(SocketOption name, T value) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + super.setOption(name, value); + } else { + if (supportedOptions().contains(name)) { + super.setOption(name, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } else { if (!flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -62,7 +70,15 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + return super.getOption(name); + } else { + if (supportedOptions().contains(name)) { + return super.getOption(name); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } if (!flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -87,6 +103,9 @@ class PlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } protected void socketSetOption(int opt, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } try { socketSetOption0(opt, val); } catch (SocketException se) { diff --git a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java index 272130bd6b9..2ec573ea5a9 100644 --- a/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/unix/classes/java/net/PlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,7 +59,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl protected void setOption(SocketOption name, T value) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - super.setOption(name, value); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + super.setOption(name, value); + } else { + if (supportedOptions().contains(name)) { + super.setOption(name, value); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } else { if (getSocket() == null || !flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -76,7 +84,15 @@ class PlainSocketImpl extends AbstractPlainSocketImpl @SuppressWarnings("unchecked") protected T getOption(SocketOption name) throws IOException { if (!name.equals(ExtendedSocketOptions.SO_FLOW_SLA)) { - return super.getOption(name); + if (!name.equals(StandardSocketOptions.SO_REUSEPORT)) { + return super.getOption(name); + } else { + if (supportedOptions().contains(name)) { + return super.getOption(name); + } else { + throw new UnsupportedOperationException("unsupported option"); + } + } } if (getSocket() == null || !flowSupported()) { throw new UnsupportedOperationException("unsupported option"); @@ -101,6 +117,9 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } protected void socketSetOption(int opt, boolean b, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT && !supportedOptions().contains(StandardSocketOptions.SO_REUSEPORT)) { + throw new UnsupportedOperationException("unsupported option"); + } try { socketSetOption0(opt, b, val); } catch (SocketException se) { diff --git a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java index 559fda4144f..2001c382324 100644 --- a/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/java.base/unix/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -85,7 +85,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(URLUtil.urlNoFragString(url), local_result); + fileCache.put(urlKey(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -113,13 +113,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { URL urlRemoved = urlCache.remove(jarFile); if (urlRemoved != null) - fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + fileCache.remove(urlKey(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + JarFile result = fileCache.get(urlKey(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { @@ -149,6 +149,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return result; } + private String urlKey(URL url) { + String urlstr = URLUtil.urlNoFragString(url); + if ("runtime".equals(url.getRef())) urlstr += "#runtime"; + return urlstr; + } + private Permission getPermission(JarFile jarFile) { try { URLConnection uc = getConnection(jarFile); diff --git a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c index e6f18428769..034040baf83 100644 --- a/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c +++ b/jdk/src/java.base/unix/native/libnet/PlainDatagramSocketImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1392,6 +1392,7 @@ Java_java_net_PlainDatagramSocketImpl_socketSetOption0(JNIEnv *env, } case java_net_SocketOptions_SO_REUSEADDR: + case java_net_SocketOptions_SO_REUSEPORT: case java_net_SocketOptions_SO_BROADCAST: { jclass cls; @@ -1769,6 +1770,9 @@ Java_java_net_PlainDatagramSocketImpl_socketGetOption(JNIEnv *env, jobject this, case java_net_SocketOptions_SO_REUSEADDR: return createBoolean(env, optval.i); + case java_net_SocketOptions_SO_REUSEPORT: + return createBoolean(env, optval.i); + case java_net_SocketOptions_SO_SNDBUF: case java_net_SocketOptions_SO_RCVBUF: case java_net_SocketOptions_IP_TOS: diff --git a/jdk/src/java.base/unix/native/libnet/SdpSupport.c b/jdk/src/java.base/unix/native/libnet/SdpSupport.c index be8c46464fa..1fe5353fcd6 100644 --- a/jdk/src/java.base/unix/native/libnet/SdpSupport.c +++ b/jdk/src/java.base/unix/native/libnet/SdpSupport.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -108,6 +108,11 @@ Java_sun_net_sdp_SdpSupport_convert0(JNIEnv *env, jclass cls, int fd) len = sizeof(arg); if (getsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, &len) == 0) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char*)&arg, len); +#ifdef SO_REUSEPORT + len = sizeof(arg); + if (getsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, &len) == 0) + setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (char*)&arg, len); +#endif len = sizeof(arg); if (getsockopt(fd, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, &len) == 0) setsockopt(s, SOL_SOCKET, SO_OOBINLINE, (char*)&arg, len); diff --git a/jdk/src/java.base/unix/native/libnet/SocketImpl.c b/jdk/src/java.base/unix/native/libnet/SocketImpl.c new file mode 100644 index 00000000000..3427b0ef405 --- /dev/null +++ b/jdk/src/java.base/unix/native/libnet/SocketImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include +#include + +#include "net_util.h" + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.c b/jdk/src/java.base/unix/native/libnet/net_util_md.c index f5645699d29..abad413e39c 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.c +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -439,6 +439,25 @@ jint IPv6_supported() } #endif /* DONT_ENABLE_IPV6 */ +jint reuseport_supported() +{ + /* Do a simple dummy call, and try to figure out from that */ + int one = 1; + int rv, s; + s = socket(PF_INET, SOCK_STREAM, 0); + if (s < 0) { + return JNI_FALSE; + } + rv = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, (void *)&one, sizeof(one)); + if (rv != 0) { + rv = JNI_FALSE; + } else { + rv = JNI_TRUE; + } + close(s); + return rv; +} + void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, const char* hostname, int gai_error) @@ -1014,6 +1033,7 @@ NET_MapSocketOption(jint cmd, int *level, int *optname) { { java_net_SocketOptions_SO_RCVBUF, SOL_SOCKET, SO_RCVBUF }, { java_net_SocketOptions_SO_KEEPALIVE, SOL_SOCKET, SO_KEEPALIVE }, { java_net_SocketOptions_SO_REUSEADDR, SOL_SOCKET, SO_REUSEADDR }, + { java_net_SocketOptions_SO_REUSEPORT, SOL_SOCKET, SO_REUSEPORT }, { java_net_SocketOptions_SO_BROADCAST, SOL_SOCKET, SO_BROADCAST }, { java_net_SocketOptions_IP_TOS, IPPROTO_IP, IP_TOS }, { java_net_SocketOptions_IP_MULTICAST_IF, IPPROTO_IP, IP_MULTICAST_IF }, diff --git a/jdk/src/java.base/unix/native/libnet/net_util_md.h b/jdk/src/java.base/unix/native/libnet/net_util_md.h index 31ed3f808eb..f440bd8ae6a 100644 --- a/jdk/src/java.base/unix/native/libnet/net_util_md.h +++ b/jdk/src/java.base/unix/native/libnet/net_util_md.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -60,6 +60,19 @@ void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, #define NET_WAIT_WRITE 0x02 #define NET_WAIT_CONNECT 0x04 +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif + jint NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout); /************************************************************************ diff --git a/jdk/src/java.base/unix/native/libnio/ch/Net.c b/jdk/src/java.base/unix/native/libnio/ch/Net.c index 1010355bb76..a4032d69652 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/Net.c +++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -161,6 +161,12 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return (ipv6_available()) ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + return (reuseport_available()) ? JNI_TRUE : JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return -1; diff --git a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h index 441ea20cc7c..c769dfbd49c 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/nio_util.h +++ b/jdk/src/java.base/unix/native/libnio/ch/nio_util.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,18 @@ } while((_result == -1) && (errno == EINTR)); \ } while(0) +/* Defines SO_REUSEPORT */ +#ifndef SO_REUSEPORT +#ifdef __linux__ +#define SO_REUSEPORT 15 +#elif __solaris__ +#define SO_REUSEPORT 0x100e +#elif defined(AIX) || defined(MACOSX) +#define SO_REUSEPORT 0x0200 +#else +#define SO_REUSEPORT 0 +#endif +#endif /* NIO utility procedures */ diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java index 88a7ddcfdb0..8f464ddfd07 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -167,6 +167,11 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl int optionValue = 0; + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } + switch(opt) { case IP_TOS : case SO_RCVBUF : @@ -200,6 +205,9 @@ class DualStackPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl } if (opt == SO_REUSEADDR && reuseAddressEmulated) return isReuseAddress; + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) + throw new UnsupportedOperationException("unsupported option"); int value = socketGetIntOption(nativefd, opt); Object returnValue = null; diff --git a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java index 6792a411842..3d681db1dd6 100644 --- a/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/DualStackPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -181,6 +181,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl if (opt == SO_TIMEOUT) { // timeout implemented through select. return; } + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } int optionValue = 0; @@ -224,6 +228,10 @@ class DualStackPlainSocketImpl extends AbstractPlainSocketImpl localAddress(nativefd, (InetAddressContainer)iaContainerObj); return 0; // return value doesn't matter. } + // SO_REUSEPORT is not supported on Windows. + if (opt == SO_REUSEPORT) { + throw new UnsupportedOperationException("unsupported option"); + } // SO_REUSEADDR emulated when using exclusive bind if (opt == SO_REUSEADDR && exclusiveBind) diff --git a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java index 938d995593b..259a39ac195 100644 --- a/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/PlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -173,10 +173,18 @@ class PlainSocketImpl extends AbstractPlainSocketImpl } public void setOption(int opt, Object val) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } impl.setOption(opt, val); } public Object getOption(int opt) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } return impl.getOption(opt); } @@ -332,14 +340,27 @@ class PlainSocketImpl extends AbstractPlainSocketImpl void socketSetOption(int cmd, boolean on, Object value) throws SocketException { + if (cmd == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } impl.socketSetOption(cmd, on, value); } int socketGetOption(int opt, Object iaContainerObj) throws SocketException { + if (opt == SocketOptions.SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } return impl.socketGetOption(opt, iaContainerObj); } void socketSendUrgentData(int data) throws IOException { impl.socketSendUrgentData(data); } + + static boolean isReusePortAvailable() { + // SO_REUSEPORT is not supported on Windows. + return false; + } } diff --git a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java index 9bdb8d5c6e1..7198b49671e 100644 --- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainDatagramSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -130,6 +130,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl return socketLocalAddress(family); } else if (optID == SO_REUSEADDR && reuseAddressEmulated) { return isReuseAddress; + } else if (optID == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else { return super.getOption(optID); } @@ -142,6 +145,9 @@ class TwoStacksPlainDatagramSocketImpl extends AbstractPlainDatagramSocketImpl // socket already bound, emulate reuseAddressEmulated = true; isReuseAddress = (Boolean)val; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else { socketNativeSetOption(opt, val); } diff --git a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java index a8be4000d93..4f0b132520e 100644 --- a/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java +++ b/jdk/src/java.base/windows/classes/java/net/TwoStacksPlainSocketImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -128,6 +128,9 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl } else if (opt == SO_REUSEADDR && exclusiveBind) { // SO_REUSEADDR emulated when using exclusive bind return isReuseAddress; + } else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); } else return super.getOption(opt); } @@ -144,6 +147,10 @@ class TwoStacksPlainSocketImpl extends AbstractPlainSocketImpl // SO_REUSEADDR emulated when using exclusive bind if (opt == SO_REUSEADDR && exclusiveBind) isReuseAddress = on; + else if (opt == SO_REUSEPORT) { + // SO_REUSEPORT is not supported on Windows. + throw new UnsupportedOperationException("unsupported option"); + } else socketNativeSetOption(opt, on, value); } diff --git a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java index 07db32fc079..91bf5388460 100644 --- a/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java +++ b/jdk/src/java.base/windows/classes/sun/net/www/protocol/jar/JarFileFactory.java @@ -95,7 +95,7 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { result = getCachedJarFile(url); if (result == null) { - fileCache.put(URLUtil.urlNoFragString(url), local_result); + fileCache.put(urlKey(url), local_result); urlCache.put(local_result, url); result = local_result; } else { @@ -123,13 +123,13 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { synchronized (instance) { URL urlRemoved = urlCache.remove(jarFile); if (urlRemoved != null) - fileCache.remove(URLUtil.urlNoFragString(urlRemoved)); + fileCache.remove(urlKey(urlRemoved)); } } private JarFile getCachedJarFile(URL url) { assert Thread.holdsLock(instance); - JarFile result = fileCache.get(URLUtil.urlNoFragString(url)); + JarFile result = fileCache.get(urlKey(url)); /* if the JAR file is cached, the permission will always be there */ if (result != null) { @@ -159,6 +159,12 @@ class JarFileFactory implements URLJarFile.URLJarFileCloseController { return result; } + private String urlKey(URL url) { + String urlstr = URLUtil.urlNoFragString(url); + if ("runtime".equals(url.getRef())) urlstr += "#runtime"; + return urlstr; + } + private Permission getPermission(JarFile jarFile) { try { URLConnection uc = getConnection(jarFile); diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java index 8e28e8471ac..63b2112aca1 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -463,7 +463,7 @@ class WindowsWatchService } CloseHandle(key.handle()); closeAttachedEvent(key.overlappedAddress()); - key.buffer().cleaner().clean(); + key.buffer().free(); } /** diff --git a/jdk/src/java.base/windows/native/libjava/java_props_md.c b/jdk/src/java.base/windows/native/libjava/java_props_md.c index 135976483b6..382a35a571e 100644 --- a/jdk/src/java.base/windows/native/libjava/java_props_md.c +++ b/jdk/src/java.base/windows/native/libjava/java_props_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -469,7 +469,9 @@ GetJavaProperties(JNIEnv* env) * Windows Server 2008 R2 6 1 (!VER_NT_WORKSTATION) * Windows 8 6 2 (VER_NT_WORKSTATION) * Windows Server 2012 6 2 (!VER_NT_WORKSTATION) + * Windows Server 2012 R2 6 3 (!VER_NT_WORKSTATION) * Windows 10 10 0 (VER_NT_WORKSTATION) + * Windows Server 2016 10 0 (!VER_NT_WORKSTATION) * * This mapping will presumably be augmented as new Windows * versions are released. @@ -543,6 +545,7 @@ GetJavaProperties(JNIEnv* env) } } else { switch (minorVersion) { + case 0: sprops.os_name = "Windows Server 2016"; break; default: sprops.os_name = "Windows NT (unknown)"; } } diff --git a/jdk/src/java.base/windows/native/libnet/SocketImpl.c b/jdk/src/java.base/windows/native/libnet/SocketImpl.c new file mode 100644 index 00000000000..8e5745de8d3 --- /dev/null +++ b/jdk/src/java.base/windows/native/libnet/SocketImpl.c @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_java_net_AbstractPlainDatagramSocketImpl_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_jdk_net_Sockets_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c index 8a0f5c15275..4868201c1f3 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.c +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -242,6 +242,11 @@ jint IPv6_supported() return JNI_TRUE; } +jint reuseport_supported() +{ + /* SO_REUSEPORT is not supported onn Windows */ + return JNI_FALSE; +} /* * Return the default TOS value */ diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.h b/jdk/src/java.base/windows/native/libnet/net_util_md.h index db6971616bf..5ac48046f3b 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.h +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.h @@ -54,6 +54,9 @@ #else +/*SO_REUSEPORT is not supported on Windows, define it to 0*/ +#define SO_REUSEPORT 0 + /* Retain this code a little longer to support building in * old environments. _MSC_VER is defined as: * 1200 for MSVC++ 6.0 @@ -353,3 +356,4 @@ JNIEXPORT jint JNICALL Java_java_net_NetworkInterface_getMTU0_XP JNIEXPORT jboolean JNICALL Java_java_net_NetworkInterface_isLoopback0_XP (JNIEnv *env, jclass cls, jstring name, jint index); + diff --git a/jdk/src/java.base/windows/native/libnio/ch/Net.c b/jdk/src/java.base/windows/native/libnio/ch/Net.c index 12f3c190c49..c7702006d27 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/Net.c +++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,6 +93,13 @@ Java_sun_nio_ch_Net_isIPv6Available0(JNIEnv* env, jclass cl) return ipv6_available() ? JNI_TRUE : JNI_FALSE; } +JNIEXPORT jboolean JNICALL +Java_sun_nio_ch_Net_isReusePortAvailable0(JNIEnv* env, jclass c1) +{ + // SO_REUSEPORT is not supported on Windows + return JNI_FALSE; +} + JNIEXPORT jint JNICALL Java_sun_nio_ch_Net_isExclusiveBindAvailable(JNIEnv *env, jclass clazz) { return 1; diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java index ef5ca43cf23..4a72d0fd371 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameBorder.java @@ -40,6 +40,7 @@ import apple.laf.JRSUIState.TitleBarHeightState; import com.apple.laf.AquaUtils.RecyclableSingleton; import com.apple.laf.AquaInternalFrameBorderMetrics; +import java.awt.geom.AffineTransform; public class AquaInternalFrameBorder implements Border, UIResource { private static final int kCloseButton = 0; @@ -309,18 +310,40 @@ public class AquaInternalFrameBorder implements Border, UIResource { return isInsideYButtonArea(i, y) && x >= startX && x <= endX; } - protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, final int x, final int y) { - Icon icon = frame.getFrameIcon(); - if (icon == null) icon = UIManager.getIcon("InternalFrame.icon"); - if (icon == null) return; + protected void paintTitleIcon(final Graphics g, final JInternalFrame frame, + final int x, final int y) { - // Resize to 16x16 if necessary. - if (icon instanceof ImageIcon && (icon.getIconWidth() > sMaxIconWidth || icon.getIconHeight() > sMaxIconHeight)) { - final Image img = ((ImageIcon)icon).getImage(); - ((ImageIcon)icon).setImage(img.getScaledInstance(sMaxIconWidth, sMaxIconHeight, Image.SCALE_SMOOTH)); + Icon icon = frame.getFrameIcon(); + if (icon == null) { + icon = UIManager.getIcon("InternalFrame.icon"); } - icon.paintIcon(frame, g, x, y); + if (icon == null) { + return; + } + + if (icon.getIconWidth() > sMaxIconWidth + || icon.getIconHeight() > sMaxIconHeight) { + final Graphics2D g2 = (Graphics2D) g; + final AffineTransform savedAT = g2.getTransform(); + double xScaleFactor = (double) sMaxIconWidth / icon.getIconWidth(); + double yScaleFactor = (double) sMaxIconHeight / icon.getIconHeight(); + + //Coordinates are after a translation hence relative origin shifts + g2.translate(x, y); + + //scaling factor is needed to scale while maintaining aspect ratio + double scaleMaintainAspectRatio = Math.min(xScaleFactor, yScaleFactor); + + //minimum value is taken to set to a maximum Icon Dimension + g2.scale(scaleMaintainAspectRatio, scaleMaintainAspectRatio); + + icon.paintIcon(frame, g2, 0, 0); + g2.setTransform(savedAT); + + } else { + icon.paintIcon(frame, g, x, y); + } } protected int getIconWidth(final JInternalFrame frame) { @@ -330,9 +353,7 @@ public class AquaInternalFrameBorder implements Border, UIResource { if (icon == null) { icon = UIManager.getIcon("InternalFrame.icon"); } - - if (icon != null && icon instanceof ImageIcon) { - // Resize to 16x16 if necessary. + if (icon != null) { width = Math.min(icon.getIconWidth(), sMaxIconWidth); } @@ -346,9 +367,7 @@ public class AquaInternalFrameBorder implements Border, UIResource { if (icon == null) { icon = UIManager.getIcon("InternalFrame.icon"); } - - if (icon != null && icon instanceof ImageIcon) { - // Resize to 16x16 if necessary. + if (icon != null) { height = Math.min(icon.getIconHeight(), sMaxIconHeight); } diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java index 2dec5c895eb..35b87aac27e 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTableHeaderUI.java @@ -128,14 +128,17 @@ public class AquaTableHeaderUI extends BasicTableHeaderUI { // Modify the table "border" to draw smaller, and with the titles in the right position // and sort indicators, just like an NSSave/Open panel. final AquaTableHeaderBorder cellBorder = AquaTableHeaderBorder.getListHeaderBorder(); - final boolean thisColumnSelected = localTable.getColumnModel().getColumn(column).getModelIndex() == sortColumn; + cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE); - cellBorder.setSelected(thisColumnSelected); - if (thisColumnSelected) { - cellBorder.setSortOrder(sortOrder); - } else { - cellBorder.setSortOrder(AquaTableHeaderBorder.SORT_NONE); + if (localTable != null) { + final boolean thisColumnSelected = localTable.getColumnModel().getColumn(column).getModelIndex() == sortColumn; + + cellBorder.setSelected(thisColumnSelected); + if (thisColumnSelected) { + cellBorder.setSortOrder(sortOrder); + } } + setBorder(cellBorder); return this; } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m index 07bb7fab938..9b8e370a938 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTEvent.m @@ -134,7 +134,7 @@ const keyTable[] = {0x3D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x3E, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x3F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, // the 'fn' key on PowerBooks - {0x40, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x40, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F17}, {0x41, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_DECIMAL}, {0x42, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x43, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_MULTIPLY}, @@ -149,8 +149,8 @@ const keyTable[] = {0x4C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_ENTER}, {0x4D, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, {0x4E, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_SUBTRACT}, - {0x4F, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, - {0x50, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x4F, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F18}, + {0x50, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F19}, {0x51, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_EQUALS}, {0x52, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD0}, {0x53, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD1}, @@ -160,7 +160,7 @@ const keyTable[] = {0x57, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD5}, {0x58, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD6}, {0x59, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD7}, - {0x5A, NO, KL_UNKNOWN, java_awt_event_KeyEvent_VK_UNDEFINED}, + {0x5A, NO, KL_STANDARD, java_awt_event_KeyEvent_VK_F20}, {0x5B, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD8}, {0x5C, YES, KL_NUMPAD, java_awt_event_KeyEvent_VK_NUMPAD9}, {0x5D, YES, KL_STANDARD, java_awt_event_KeyEvent_VK_BACK_SLASH}, // This is a combo yen/backslash on JIS keyboards. diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m index 805596cc118..8070995baa6 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/AWTView.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -624,7 +624,8 @@ AWT_ASSERT_APPKIT_THREAD; { NSString *selectedText = [self accessibleSelectedText]; NSAttributedString *styledText = [[NSAttributedString alloc] initWithString:selectedText]; - NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) documentAttributes:nil]; + NSData *rtfdData = [styledText RTFDFromRange:NSMakeRange(0, [styledText length]) + documentAttributes:@{NSDocumentTypeDocumentAttribute: NSRTFTextDocumentType}]; [styledText release]; return rtfdData; } @@ -681,7 +682,7 @@ AWT_ASSERT_APPKIT_THREAD; if ([[pboard types] containsObject:NSRTFDPboardType]) { NSData *rtfdData = [pboard dataForType:NSRTFDPboardType]; - NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:nil]; + NSAttributedString *styledText = [[NSAttributedString alloc] initWithRTFD:rtfdData documentAttributes:NULL]; NSString *text = [styledText string]; [styledText release]; diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m index 8f1e269de8f..9d8326ade6d 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/awt/LWCToolkit.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -743,9 +743,10 @@ Java_sun_lwawt_macosx_LWCToolkit_initAppkit JNIEXPORT jint JNICALL DEF_JNI_OnLoad(JavaVM *vm, void *reserved) { OSXAPP_SetJavaVM(vm); - // We need to let Foundation know that this is a multithreaded application, if it isn't already. + // We need to let Foundation know that this is a multithreaded application, + // if it isn't already. if (![NSThread isMultiThreaded]) { - [NSThread detachNewThreadSelector:nil toTarget:nil withObject:nil]; + [[[[NSThread alloc] init] autorelease] start]; } return JNI_VERSION_1_4; diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m b/jdk/src/java.desktop/macosx/native/libosx/CFileManager.m similarity index 91% rename from jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m rename to jdk/src/java.desktop/macosx/native/libosx/CFileManager.m index f5e676ad490..52ca5f8eccf 100644 --- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/CFileManager.m +++ b/jdk/src/java.desktop/macosx/native/libosx/CFileManager.m @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -213,25 +213,23 @@ JNF_COCOA_EXIT(env); */ JNIEXPORT jboolean JNICALL Java_com_apple_eio_FileManager__1moveToTrash -(JNIEnv *env, jclass clz, jstring url) +(JNIEnv *env, jclass clz, jstring fileName) { - __block jboolean returnValue = JNI_FALSE; + __block BOOL returnValue = NO; JNF_COCOA_ENTER(env); - NSString *path = JNFNormalizedNSStringForPath(env, url); + NSString * path = JNFNormalizedNSStringForPath(env, fileName); + NSURL *url = [NSURL fileURLWithPath:path]; [JNFRunLoop performOnMainThreadWaiting:YES withBlock:^(){ - NSInteger res = 0; - [[NSWorkspace sharedWorkspace] performFileOperation:NSWorkspaceRecycleOperation - source:[path stringByDeletingLastPathComponent] - destination:nil - files:[NSArray arrayWithObject:[path lastPathComponent]] - tag:&res]; - returnValue = (res == 0); + + returnValue = [[NSFileManager defaultManager] trashItemAtURL:url + resultingItemURL:nil + error:nil]; }]; JNF_COCOA_EXIT(env); - return returnValue; + return returnValue ? JNI_TRUE: JNI_FALSE; } /* diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java index 5bb49a5bef7..46185618913 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFBaseJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -86,16 +86,16 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { /** * Whether to write abbreviated JPEG streams (default == false). - * A subclass which sets this to true should also + * A subclass which sets this to {@code true} should also * initialized {@link #JPEGStreamMetadata}. */ protected boolean writeAbbreviatedStream = false; /** * Stream metadata equivalent to a tables-only stream such as in - * the JPEGTables. Default value is null. + * the {@code JPEGTables}. Default value is {@code null}. * This should be set by any subclass which sets - * {@link writeAbbreviatedStream} to true. + * {@link writeAbbreviatedStream} to {@code true}. */ protected IIOMetadata JPEGStreamMetadata = null; @@ -108,15 +108,15 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { /** * Removes nonessential nodes from a JPEG native image metadata tree. * All nodes derived from JPEG marker segments other than DHT, DQT, - * SOF, SOS segments are removed unless pruneTables is - * true in which case the nodes derived from the DHT and + * SOF, SOS segments are removed unless {@code pruneTables} is + * {@code true} in which case the nodes derived from the DHT and * DQT marker segments are also removed. * * @param tree A javax_imageio_jpeg_image_1.0 tree. * @param pruneTables Whether to prune Huffman and quantization tables. - * @throws NullPointerException if tree is - * null. - * @throws IllegalArgumentException if tree is not the root + * @throws NullPointerException if {@code tree} is + * {@code null}. + * @throws IllegalArgumentException if {@code tree} is not the root * of a JPEG native image metadata tree. */ private static void pruneNodes(Node tree, boolean pruneTables) { @@ -182,8 +182,8 @@ public abstract class TIFFBaseJPEGCompressor extends TIFFCompressor { } /** - * A ByteArrayOutputStream which allows writing to an - * ImageOutputStream. + * A {@code ByteArrayOutputStream} which allows writing to an + * {@code ImageOutputStream}. */ private static class IIOByteArrayOutputStream extends ByteArrayOutputStream { IIOByteArrayOutputStream() { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java index 3138974ad00..14aa2540acb 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFColorConverter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,39 +31,39 @@ package com.sun.imageio.plugins.tiff; public abstract class TIFFColorConverter { /** - * Constructs an instance of a TIFFColorConverter. + * Constructs an instance of a {@code TIFFColorConverter}. */ public TIFFColorConverter() {} /** * Converts an RGB triple into the native color space of this * TIFFColorConverter, and stores the result in the first three - * entries of the result array. + * entries of the {@code result} array. * * @param r the red value. * @param g the green value. * @param b the blue value. - * @param result an array of floats containing three elements. - * @throws NullPointerException if result is - * null. + * @param result an array of {@code float}s containing three elements. + * @throws NullPointerException if {@code result} is + * {@code null}. * @throws ArrayIndexOutOfBoundsException if - * result.length < 3. + * {@code result.length < 3}. */ public abstract void fromRGB(float r, float g, float b, float[] result); /** * Converts a triple in the native color space of this * TIFFColorConverter into an RGB triple, and stores the result in - * the first three entries of the rgb array. + * the first three entries of the {@code rgb} array. * * @param x0 the value of channel 0. * @param x1 the value of channel 1. * @param x2 the value of channel 2. - * @param rgb an array of floats containing three elements. - * @throws NullPointerException if rgb is - * null. + * @param rgb an array of {@code float}s containing three elements. + * @throws NullPointerException if {@code rgb} is + * {@code null}. * @throws ArrayIndexOutOfBoundsException if - * rgb.length < 3. + * {@code rgb.length < 3}. */ public abstract void toRGB(float x0, float x1, float x2, float[] rgb); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java index cc72f85cea8..ce1b2a58fa1 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,13 +35,13 @@ import javax.imageio.stream.ImageOutputStream; public abstract class TIFFCompressor { /** - * The ImageWriter calling this - * TIFFCompressor. + * The {@code ImageWriter} calling this + * {@code TIFFCompressor}. */ protected ImageWriter writer; /** - * The IIOMetadata object containing metadata for the + * The {@code IIOMetadata} object containing metadata for the * current image. */ protected IIOMetadata metadata; @@ -63,7 +63,7 @@ public abstract class TIFFCompressor { protected boolean isCompressionLossless; /** - * The ImageOutputStream to be written. + * The {@code ImageOutputStream} to be written. */ protected ImageOutputStream stream; @@ -75,26 +75,26 @@ public abstract class TIFFCompressor { * to provide the implementation of the compression algorithm of an * unsupported compression type. * - *

        The parameters compressionTagValue and - * isCompressionLossless are provided to accomodate + *

        The parameters {@code compressionTagValue} and + * {@code isCompressionLossless} are provided to accomodate * compression types which are unknown. A compression type is * "known" if it is either among those already supported by the * TIFF writer (see {@link TIFFImageWriteParam}), or is listed in * the TIFF 6.0 specification but not supported. If the compression - * type is unknown, the compressionTagValue and - * isCompressionLossless parameters are ignored.

        + * type is unknown, the {@code compressionTagValue} and + * {@code isCompressionLossless} parameters are ignored.

        * * @param compressionType The name of the compression type. * @param compressionTagValue The value to be assigned to the TIFF * Compression tag in the TIFF image metadata; ignored if - * compressionType is a known type. + * {@code compressionType} is a known type. * @param isCompressionLossless Whether the compression is lossless; - * ignored if compressionType is a known type. + * ignored if {@code compressionType} is a known type. * - * @throws NullPointerException if compressionType is - * null. - * @throws IllegalArgumentException if compressionTagValue is - * less 1. + * @throws NullPointerException if {@code compressionType} is + * {@code null}. + * @throws IllegalArgumentException if {@code compressionTagValue} is + * less {@code 1}. */ public TIFFCompressor(String compressionType, int compressionTagValue, @@ -163,9 +163,9 @@ public abstract class TIFFCompressor { } /** - * Sets the ImageOutputStream to be written. + * Sets the {@code ImageOutputStream} to be written. * - * @param stream an ImageOutputStream to be written. + * @param stream an {@code ImageOutputStream} to be written. * * @see #getStream */ @@ -174,9 +174,9 @@ public abstract class TIFFCompressor { } /** - * Returns the ImageOutputStream that will be written. + * Returns the {@code ImageOutputStream} that will be written. * - * @return an ImageOutputStream. + * @return an {@code ImageOutputStream}. * * @see #setStream(ImageOutputStream) */ @@ -185,9 +185,9 @@ public abstract class TIFFCompressor { } /** - * Sets the value of the writer field. + * Sets the value of the {@code writer} field. * - * @param writer the current ImageWriter. + * @param writer the current {@code ImageWriter}. * * @see #getWriter() */ @@ -196,9 +196,9 @@ public abstract class TIFFCompressor { } /** - * Returns the current ImageWriter. + * Returns the current {@code ImageWriter}. * - * @return an ImageWriter. + * @return an {@code ImageWriter}. * * @see #setWriter(ImageWriter) */ @@ -207,9 +207,9 @@ public abstract class TIFFCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -219,9 +219,9 @@ public abstract class TIFFCompressor { } /** - * Returns the current IIOMetadata object. + * Returns the current {@code IIOMetadata} object. * - * @return the IIOMetadata object for the image being + * @return the {@code IIOMetadata} object for the image being * written. * * @see #setMetadata(IIOMetadata) @@ -232,15 +232,15 @@ public abstract class TIFFCompressor { /** * Encodes the supplied image data, writing to the currently set - * ImageOutputStream. + * {@code ImageOutputStream}. * - * @param b an array of bytes containing the packed + * @param b an array of {@code byte}s containing the packed * but uncompressed image data. * @param off the starting offset of the data to be written in the - * array b. + * array {@code b}. * @param width the width of the rectangle of pixels to be written. * @param height the height of the rectangle of pixels to be written. - * @param bitsPerSample an array of ints indicting + * @param bitsPerSample an array of {@code int}s indicting * the number of bits used to represent each image sample within * a pixel. * @param scanlineStride the number of bytes separating each @@ -249,7 +249,7 @@ public abstract class TIFFCompressor { * @return the number of bytes written. * * @throws IOException if the supplied data cannot be encoded by - * this TIFFCompressor, or if any I/O error occurs + * this {@code TIFFCompressor}, or if any I/O error occurs * during writing. */ public abstract int encode(byte[] b, int off, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java index fdc29f26016..bdd31218e03 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,7 @@ import com.sun.imageio.plugins.common.SimpleCMYKColorSpace; * *

        Decompressors may be written with various levels of complexity. * The most complex decompressors will override the - * decode method, and will perform all the work of + * {@code decode} method, and will perform all the work of * decoding, subsampling, offsetting, clipping, and format conversion. * This approach may be the most efficient, since it is possible to * avoid the use of extra image buffers, and it may be possible to @@ -89,35 +89,35 @@ import com.sun.imageio.plugins.common.SimpleCMYKColorSpace; * the destination. * *

        Less ambitious decompressors may override the - * decodeRaw method, which is responsible for + * {@code decodeRaw} method, which is responsible for * decompressing the entire tile or strip into a byte array (or other * appropriate datatype). The default implementation of - * decode will perform all necessary setup of buffers, - * call decodeRaw to perform the actual decoding, perform + * {@code decode} will perform all necessary setup of buffers, + * call {@code decodeRaw} to perform the actual decoding, perform * subsampling, and copy the results into the final destination image. * Where possible, it will pass the real image buffer to - * decodeRaw in order to avoid making an extra copy. + * {@code decodeRaw} in order to avoid making an extra copy. * *

        Slightly more ambitious decompressors may override - * decodeRaw, but avoid writing pixels that will be + * {@code decodeRaw}, but avoid writing pixels that will be * discarded in the subsampling phase. */ public abstract class TIFFDecompressor { /** - * The ImageReader calling this - * TIFFDecompressor. + * The {@code ImageReader} calling this + * {@code TIFFDecompressor}. */ protected ImageReader reader; /** - * The IIOMetadata object containing metadata for the + * The {@code IIOMetadata} object containing metadata for the * current image. */ protected IIOMetadata metadata; /** - * The value of the PhotometricInterpretation tag. + * The value of the {@code PhotometricInterpretation} tag. * Legal values are {@link * BaselineTIFFTagSet#PHOTOMETRIC_INTERPRETATION_WHITE_IS_ZERO }, * {@link @@ -135,7 +135,7 @@ public abstract class TIFFDecompressor { protected int photometricInterpretation; /** - * The value of the Compression tag. Legal values are + * The value of the {@code Compression} tag. Legal values are * {@link BaselineTIFFTagSet#COMPRESSION_NONE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_RLE}, {@link * BaselineTIFFTagSet#COMPRESSION_CCITT_T_4}, {@link @@ -151,23 +151,23 @@ public abstract class TIFFDecompressor { protected int compression; /** - * true if the image is encoded using separate planes. + * {@code true} if the image is encoded using separate planes. */ protected boolean planar; /** - * The value of the SamplesPerPixel tag. + * The value of the {@code SamplesPerPixel} tag. */ protected int samplesPerPixel; /** - * The value of the BitsPerSample tag. + * The value of the {@code BitsPerSample} tag. * */ protected int[] bitsPerSample; /** - * The value of the SampleFormat tag. Legal values + * The value of the {@code SampleFormat} tag. Legal values * are {@link BaselineTIFFTagSet#SAMPLE_FORMAT_UNSIGNED_INTEGER}, * {@link BaselineTIFFTagSet#SAMPLE_FORMAT_SIGNED_INTEGER}, {@link * BaselineTIFFTagSet#SAMPLE_FORMAT_FLOATING_POINT}, {@link @@ -178,7 +178,7 @@ public abstract class TIFFDecompressor { new int[] {BaselineTIFFTagSet.SAMPLE_FORMAT_UNSIGNED_INTEGER}; /** - * The value of the ExtraSamples tag. Legal values + * The value of the {@code ExtraSamples} tag. Legal values * are {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNSPECIFIED}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_ASSOCIATED_ALPHA}, * {@link BaselineTIFFTagSet#EXTRA_SAMPLES_UNASSOCIATED_ALPHA}, @@ -187,7 +187,7 @@ public abstract class TIFFDecompressor { protected int[] extraSamples; /** - * The value of the ColorMap tag. + * The value of the {@code ColorMap} tag. * */ protected char[] colorMap; @@ -195,20 +195,20 @@ public abstract class TIFFDecompressor { // Region of input stream containing the data /** - * The ImageInputStream containing the TIFF source + * The {@code ImageInputStream} containing the TIFF source * data. */ protected ImageInputStream stream; /** - * The offset in the source ImageInputStream of the + * The offset in the source {@code ImageInputStream} of the * start of the data to be decompressed. */ protected long offset; /** * The number of bytes of data from the source - * ImageInputStream to be decompressed. + * {@code ImageInputStream} to be decompressed. */ protected int byteCount; @@ -244,15 +244,15 @@ public abstract class TIFFDecompressor { // Subsampling to be performed /** - * The source X offset used, along with dstXOffset - * and subsampleX, to map between horizontal source + * The source X offset used, along with {@code dstXOffset} + * and {@code subsampleX}, to map between horizontal source * and destination pixel coordinates. */ protected int sourceXOffset; /** * The horizontal destination offset used, along with - * sourceXOffset and subsampleX, to map + * {@code sourceXOffset} and {@code subsampleX}, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceXOffset sourceXOffset} for * the mapping equations. @@ -260,15 +260,15 @@ public abstract class TIFFDecompressor { protected int dstXOffset; /** - * The source Y offset used, along with dstYOffset - * and subsampleY, to map between vertical source and + * The source Y offset used, along with {@code dstYOffset} + * and {@code subsampleY}, to map between vertical source and * destination pixel coordinates. */ protected int sourceYOffset; /** * The vertical destination offset used, along with - * sourceYOffset and subsampleY, to map + * {@code sourceYOffset} and {@code subsampleY}, to map * between horizontal source and destination pixel coordinates. * See the comment for {@link #sourceYOffset sourceYOffset} for * the mapping equations. @@ -305,7 +305,7 @@ public abstract class TIFFDecompressor { // Destination for decodeRaw /** - * A BufferedImage for the decodeRaw + * A {@code BufferedImage} for the {@code decodeRaw} * method to write into. */ protected BufferedImage rawImage; @@ -345,15 +345,15 @@ public abstract class TIFFDecompressor { * The X coordinate of the upper-left source pixel that will * actually be copied into the destination image, taking into * account all subsampling, offsetting, and clipping. That is, - * the pixel at (activeSrcMinX, - * activeSrcMinY) is to be copied into the - * destination pixel at (dstMinX, - * dstMinY). + * the pixel at ({@code activeSrcMinX}, + * {@code activeSrcMinY}) is to be copied into the + * destination pixel at ({@code dstMinX}, + * {@code dstMinY}). * *

        The pixels in the source region to be copied are - * those with X coordinates of the form activeSrcMinX + - * k*subsampleX, where k is an integer such - * that 0 ≤ k < dstWidth. + * those with X coordinates of the form {@code activeSrcMinX + + * k*subsampleX}, where {@code k} is an integer such + * that {@code 0 ≤ k < dstWidth}. */ protected int activeSrcMinX; @@ -363,9 +363,9 @@ public abstract class TIFFDecompressor { * all subsampling, offsetting, and clipping. * *

        The pixels in the source region to be copied are - * those with Y coordinates of the form activeSrcMinY + - * k*subsampleY, where k is an integer such - * that 0 ≤ k < dstHeight. + * those with Y coordinates of the form {@code activeSrcMinY + + * k*subsampleY}, where {@code k} is an integer such + * that {@code 0 ≤ k < dstHeight}. */ protected int activeSrcMinY; @@ -375,7 +375,7 @@ public abstract class TIFFDecompressor { * susbampling, offsetting, and clipping. * *

        The active source width will always be equal to - * (dstWidth - 1)*subsampleX + 1. + * {@code (dstWidth - 1)*subsampleX + 1}. */ protected int activeSrcWidth; @@ -385,13 +385,13 @@ public abstract class TIFFDecompressor { * susbampling, offsetting, and clipping. * *

        The active source height will always be equal to - * (dstHeight - 1)*subsampleY + 1. + * {@code (dstHeight - 1)*subsampleY + 1}. */ protected int activeSrcHeight; /** - * A TIFFColorConverter object describing the color space of - * the encoded pixel data, or null. + * A {@code TIFFColorConverter} object describing the color space of + * the encoded pixel data, or {@code null}. */ protected TIFFColorConverter colorConverter; @@ -420,13 +420,13 @@ public abstract class TIFFDecompressor { // to exactly those dest pixels that are present in the source region. /** - * Create a PixelInterleavedSampleModel for use in creating - * an ImageTypeSpecifier. Its dimensions will be 1x1 and + * Create a {@code PixelInterleavedSampleModel} for use in creating + * an {@code ImageTypeSpecifier}. Its dimensions will be 1x1 and * it will have ascending band offsets as {0, 1, 2, ..., numBands}. * * @param dataType The data type (DataBuffer.TYPE_*). * @param numBands The number of bands. - * @return A PixelInterleavedSampleModel. + * @return A {@code PixelInterleavedSampleModel}. */ static SampleModel createInterleavedSM(int dataType, int numBands) { @@ -443,8 +443,8 @@ public abstract class TIFFDecompressor { } /** - * Create a ComponentColorModel for use in creating - * an ImageTypeSpecifier. + * Create a {@code ComponentColorModel} for use in creating + * an {@code ImageTypeSpecifier}. */ // This code was copied from javax.imageio.ImageTypeSpecifier. static ColorModel createComponentCM(ColorSpace colorSpace, @@ -518,8 +518,8 @@ public abstract class TIFFDecompressor { } /** - * Return the number of bits occupied by dataType - * which must be one of the DataBuffer TYPEs. + * Return the number of bits occupied by {@code dataType} + * which must be one of the {@code DataBuffer} {@code TYPE}s. */ private static int getDataTypeSize(int dataType) throws IIOException { int dataTypeSize = 0; @@ -578,7 +578,7 @@ public abstract class TIFFDecompressor { } /** - * Determines whether the DataBuffer is filled without + * Determines whether the {@code DataBuffer} is filled without * any interspersed padding bits. */ private static boolean isDataBufferBitContiguous(SampleModel sm) @@ -678,8 +678,8 @@ public abstract class TIFFDecompressor { } /** - * Reformats bit-discontiguous data into the DataBuffer - * of the supplied WritableRaster. + * Reformats bit-discontiguous data into the {@code DataBuffer} + * of the supplied {@code WritableRaster}. */ private static void reformatDiscontiguousData(byte[] buf, int stride, @@ -715,21 +715,21 @@ public abstract class TIFFDecompressor { /** * A utility method that returns an - * ImageTypeSpecifier suitable for decoding an image + * {@code ImageTypeSpecifier} suitable for decoding an image * with the given parameters. * * @param photometricInterpretation the value of the - * PhotometricInterpretation field. - * @param compression the value of the Compression field. + * {@code PhotometricInterpretation} field. + * @param compression the value of the {@code Compression} field. * @param samplesPerPixel the value of the - * SamplesPerPixel field. - * @param bitsPerSample the value of the BitsPerSample field. - * @param sampleFormat the value of the SampleFormat field. - * @param extraSamples the value of the ExtraSamples field. - * @param colorMap the value of the ColorMap field. + * {@code SamplesPerPixel} field. + * @param bitsPerSample the value of the {@code BitsPerSample} field. + * @param sampleFormat the value of the {@code SampleFormat} field. + * @param extraSamples the value of the {@code ExtraSamples} field. + * @param colorMap the value of the {@code ColorMap} field. * - * @return a suitable ImageTypeSpecifier, or - * null if it is not possible to create one. + * @return a suitable {@code ImageTypeSpecifier}, or + * {@code null} if it is not possible to create one. */ public static ImageTypeSpecifier getRawImageTypeSpecifier(int photometricInterpretation, @@ -1216,26 +1216,26 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the reader field. + * Sets the value of the {@code reader} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param reader the current ImageReader. + * @param reader the current {@code ImageReader}. */ public void setReader(ImageReader reader) { this.reader = reader; } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being read. */ public void setMetadata(IIOMetadata metadata) { @@ -1243,10 +1243,10 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the photometricInterpretation + * Sets the value of the {@code photometricInterpretation} * field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1258,9 +1258,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the compression field. + * Sets the value of the {@code compression} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1271,13 +1271,13 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the planar field. + * Sets the value of the {@code planar} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param planar true if the image to be decoded is + * @param planar {@code true} if the image to be decoded is * stored in planar format. */ public void setPlanar(boolean planar) { @@ -1285,9 +1285,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the samplesPerPixel field. + * Sets the value of the {@code samplesPerPixel} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1299,9 +1299,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the bitsPerSample field. + * Sets the value of the {@code bitsPerSample} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1314,9 +1314,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the sampleFormat field. + * Sets the value of the {@code sampleFormat} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1330,9 +1330,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the extraSamples field. + * Sets the value of the {@code extraSamples} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1346,14 +1346,14 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the colorMap field. + * Sets the value of the {@code colorMap} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param colorMap the color map to apply to the source data, - * as an array of chars. + * as an array of {@code char}s. */ public void setColorMap(char[] colorMap) { this.colorMap = colorMap == null ? @@ -1361,22 +1361,22 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the stream field. + * Sets the value of the {@code stream} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param stream the ImageInputStream to be read. + * @param stream the {@code ImageInputStream} to be read. */ public void setStream(ImageInputStream stream) { this.stream = stream; } /** - * Sets the value of the offset field. + * Sets the value of the {@code offset} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1388,9 +1388,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the byteCount field. + * Sets the value of the {@code byteCount} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1403,9 +1403,9 @@ public abstract class TIFFDecompressor { // Region of the file image represented in the stream /** - * Sets the value of the srcMinX field. + * Sets the value of the {@code srcMinX} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1418,9 +1418,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the srcMinY field. + * Sets the value of the {@code srcMinY} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1433,9 +1433,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the srcWidth field. + * Sets the value of the {@code srcWidth} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1447,9 +1447,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the srcHeight field. + * Sets the value of the {@code srcHeight} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1463,9 +1463,9 @@ public abstract class TIFFDecompressor { // First source pixel to be read /** - * Sets the value of the sourceXOffset field. + * Sets the value of the {@code sourceXOffset} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1477,9 +1477,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstXOffset field. + * Sets the value of the {@code dstXOffset} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1491,9 +1491,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the sourceYOffset. + * Sets the value of the {@code sourceYOffset}. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1505,9 +1505,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstYOffset field. + * Sets the value of the {@code dstYOffset} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1521,15 +1521,15 @@ public abstract class TIFFDecompressor { // Subsampling to be performed /** - * Sets the value of the subsampleX field. + * Sets the value of the {@code subsampleX} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param subsampleX the horizontal subsampling factor. * - * @throws IllegalArgumentException if subsampleX is + * @throws IllegalArgumentException if {@code subsampleX} is * less than or equal to 0. */ public void setSubsampleX(int subsampleX) { @@ -1540,15 +1540,15 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the subsampleY field. + * Sets the value of the {@code subsampleY} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * * @param subsampleY the vertical subsampling factor. * - * @throws IllegalArgumentException if subsampleY is + * @throws IllegalArgumentException if {@code subsampleY} is * less than or equal to 0. */ public void setSubsampleY(int subsampleY) { @@ -1561,13 +1561,13 @@ public abstract class TIFFDecompressor { // Band subsetting/rearrangement /** - * Sets the value of the sourceBands field. + * Sets the value of the {@code sourceBands} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param sourceBands an array of ints + * @param sourceBands an array of {@code int}s * specifying the source bands to be read. */ public void setSourceBands(int[] sourceBands) { @@ -1576,13 +1576,13 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the destinationBands field. + * Sets the value of the {@code destinationBands} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param destinationBands an array of ints + * @param destinationBands an array of {@code int}s * specifying the destination bands to be written. */ public void setDestinationBands(int[] destinationBands) { @@ -1593,22 +1593,22 @@ public abstract class TIFFDecompressor { // Destination image and region /** - * Sets the value of the image field. + * Sets the value of the {@code image} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * - * @param image the destination BufferedImage. + * @param image the destination {@code BufferedImage}. */ public void setImage(BufferedImage image) { this.image = image; } /** - * Sets the value of the dstMinX field. + * Sets the value of the {@code dstMinX} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1620,9 +1620,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstMinY field. + * Sets the value of the {@code dstMinY} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1634,9 +1634,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstWidth field. + * Sets the value of the {@code dstWidth} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1647,9 +1647,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the dstHeight field. + * Sets the value of the {@code dstHeight} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1662,9 +1662,9 @@ public abstract class TIFFDecompressor { // Active source region /** - * Sets the value of the activeSrcMinX field. + * Sets the value of the {@code activeSrcMinX} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1676,9 +1676,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the activeSrcMinY field. + * Sets the value of the {@code activeSrcMinY} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1690,9 +1690,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the activeSrcWidth field. + * Sets the value of the {@code activeSrcWidth} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1703,9 +1703,9 @@ public abstract class TIFFDecompressor { } /** - * Sets the value of the activeSrcHeight field. + * Sets the value of the {@code activeSrcHeight} field. * - *

        If this method is called, the beginDecoding + *

        If this method is called, the {@code beginDecoding} * method must be called prior to calling any of the decode * methods. * @@ -1716,23 +1716,23 @@ public abstract class TIFFDecompressor { } /** - * Sets the TIFFColorConverter object describing the color + * Sets the {@code TIFFColorConverter} object describing the color * space of the encoded data in the input stream. If no - * TIFFColorConverter is set, no conversion will be performed. + * {@code TIFFColorConverter} is set, no conversion will be performed. * - * @param colorConverter a TIFFColorConverter object, or - * null. + * @param colorConverter a {@code TIFFColorConverter} object, or + * {@code null}. */ public void setColorConverter(TIFFColorConverter colorConverter) { this.colorConverter = colorConverter; } /** - * Returns an ImageTypeSpecifier describing an image + * Returns an {@code ImageTypeSpecifier} describing an image * whose underlying data array has the same format as the raw * source pixel data. * - * @return an ImageTypeSpecifier. + * @return an {@code ImageTypeSpecifier}. */ public ImageTypeSpecifier getRawImageType() { ImageTypeSpecifier its = @@ -1747,18 +1747,18 @@ public abstract class TIFFDecompressor { } /** - * Creates a BufferedImage whose underlying data + * Creates a {@code BufferedImage} whose underlying data * array will be suitable for holding the raw decoded output of - * the decodeRaw method. + * the {@code decodeRaw} method. * *

        The default implementation calls - * getRawImageType, and calls the resulting - * ImageTypeSpecifier's - * createBufferedImage method. + * {@code getRawImageType}, and calls the resulting + * {@code ImageTypeSpecifier}'s + * {@code createBufferedImage} method. * - * @return a BufferedImage whose underlying data + * @return a {@code BufferedImage} whose underlying data * array has the same format as the raw source pixel data, or - * null if it is not possible to create such an + * {@code null} if it is not possible to create such an * image. */ public BufferedImage createRawImage() { @@ -1811,22 +1811,22 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided byte - * array b, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * bytes. + * Decodes the source data into the provided {@code byte} + * array {@code b}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code byte}s. * - * @param b a byte array to be written. - * @param dstOffset the starting offset in b to be + * @param b a {@code byte} array to be written. + * @param dstOffset the starting offset in {@code b} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of bytes to + * @param scanlineStride the number of {@code byte}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public abstract void decodeRaw(byte[] b, int dstOffset, @@ -1834,25 +1834,25 @@ public abstract class TIFFDecompressor { int scanlineStride) throws IOException; /** - * Decodes the source data into the provided short - * array s, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * shorts + * Decodes the source data into the provided {@code short} + * array {@code s}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code short}s * - *

        The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into s. + *

        The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code s}. * - * @param s a short array to be written. - * @param dstOffset the starting offset in s to be + * @param s a {@code short} array to be written. + * @param dstOffset the starting offset in {@code s} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of shorts to + * @param scanlineStride the number of {@code short}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(short[] s, int dstOffset, @@ -1891,25 +1891,25 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided int - * array i, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * ints. + * Decodes the source data into the provided {@code int} + * array {@code i}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code int}s. * - *

        The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into i. + *

        The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code i}. * - * @param i an int array to be written. - * @param dstOffset the starting offset in i to be + * @param i an {@code int} array to be written. + * @param dstOffset the starting offset in {@code i} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of ints to + * @param scanlineStride the number of {@code int}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(int[] i, int dstOffset, @@ -1953,25 +1953,25 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided float - * array f, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * floats. + * Decodes the source data into the provided {@code float} + * array {@code f}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code float}s. * - *

        The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into f. + *

        The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code f}. * - * @param f a float array to be written. - * @param dstOffset the starting offset in f to be + * @param f a {@code float} array to be written. + * @param dstOffset the starting offset in {@code f} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of floats to + * @param scanlineStride the number of {@code float}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(float[] f, int dstOffset, @@ -2017,25 +2017,25 @@ public abstract class TIFFDecompressor { } /** - * Decodes the source data into the provided double - * array f, starting at the offset given by - * dstOffset. Each pixel occupies - * bitsPerPixel bits, with no padding between pixels. - * Scanlines are separated by scanlineStride - * doubles. + * Decodes the source data into the provided {@code double} + * array {@code f}, starting at the offset given by + * {@code dstOffset}. Each pixel occupies + * {@code bitsPerPixel} bits, with no padding between pixels. + * Scanlines are separated by {@code scanlineStride} + * {@code double}s. * - *

        The default implementation calls decodeRaw(byte[] b, - * ...) and copies the resulting data into f. + *

        The default implementation calls {@code decodeRaw(byte[] b, + * ...)} and copies the resulting data into {@code f}. * - * @param f a double array to be written. - * @param dstOffset the starting offset in f to be + * @param f a {@code double} array to be written. + * @param dstOffset the starting offset in {@code f} to be * written. * @param bitsPerPixel the number of bits for each pixel. - * @param scanlineStride the number of doubles to + * @param scanlineStride the number of {@code double}s to * advance between that starting pixels of each scanline. * * @throws IOException if an error occurs reading from the source - * ImageInputStream. + * {@code ImageInputStream}. */ public void decodeRaw(double[] d, int dstOffset, @@ -2104,16 +2104,16 @@ public abstract class TIFFDecompressor { /** * This routine is called prior to a sequence of calls to the - * decode method, in order to allow any necessary + * {@code decode} method, in order to allow any necessary * tables or other structures to be initialized based on metadata * values. This routine is guaranteed to be called any time the * metadata values have changed. * *

        The default implementation computes tables used by the - * decode method to rescale components to different + * {@code decode} method to rescale components to different * bit depths. Thus, if this method is overridden, it is - * important for the subclass method to call super(), - * unless it overrides decode as well. + * important for the subclass method to call {@code super()}, + * unless it overrides {@code decode} as well. */ public void beginDecoding() { // Note: This method assumes that sourceBands, destinationBands, @@ -2242,35 +2242,35 @@ public abstract class TIFFDecompressor { /** * Decodes the input bit stream (located in the - * ImageInputStream stream, at offset - * offset, and continuing for byteCount - * bytes) into the output BufferedImage - * image. + * {@code ImageInputStream} {@code stream}, at offset + * {@code offset}, and continuing for {@code byteCount} + * bytes) into the output {@code BufferedImage} + * {@code image}. * *

        The default implementation analyzes the destination image * to determine if it is suitable as the destination for the - * decodeRaw method. If not, a suitable image is - * created. Next, decodeRaw is called to perform the + * {@code decodeRaw} method. If not, a suitable image is + * created. Next, {@code decodeRaw} is called to perform the * actual decoding, and the results are copied into the * destination image if necessary. Subsampling and offsetting are * performed automatically. * *

        The precise responsibilities of this routine are as * follows. The input bit stream is defined by the instance - * variables stream, offset, and - * byteCount. These bits contain the data for the - * region of the source image defined by srcMinX, - * srcMinY, srcWidth, and - * srcHeight. + * variables {@code stream}, {@code offset}, and + * {@code byteCount}. These bits contain the data for the + * region of the source image defined by {@code srcMinX}, + * {@code srcMinY}, {@code srcWidth}, and + * {@code srcHeight}. * *

        The source data is required to be subsampling, starting at - * the sourceXOffsetth column and including - * every subsampleXth pixel thereafter (and similarly - * for sourceYOffset and - * subsampleY). + * the {@code sourceXOffset}th column and including + * every {@code subsampleX}th pixel thereafter (and similarly + * for {@code sourceYOffset} and + * {@code subsampleY}). * *

        Pixels are copied into the destination with an addition shift of - * (dstXOffset, dstYOffset). The complete + * ({@code dstXOffset}, {@code dstYOffset}). The complete * set of formulas relating the source and destination coordinate spaces * are: * @@ -2279,9 +2279,9 @@ public abstract class TIFFDecompressor { * dy = (sy - sourceYOffset)/subsampleY + dstYOffset; *

  • * - * Only source pixels such that (sx - sourceXOffset) % - * subsampleX == 0 and (sy - sourceYOffset) % - * subsampleY == 0 are copied. + * Only source pixels such that {@code (sx - sourceXOffset) % + * subsampleX == 0} and {@code (sy - sourceYOffset) % + * subsampleY == 0} are copied. * *

    The inverse mapping, from destination to source coordinates, * is one-to-one: @@ -2292,9 +2292,9 @@ public abstract class TIFFDecompressor { *

    * *

    The region of the destination image to be updated is given - * by the instance variables dstMinX, - * dstMinY, dstWidth, and - * dstHeight. + * by the instance variables {@code dstMinX}, + * {@code dstMinY}, {@code dstWidth}, and + * {@code dstHeight}. * *

    It is possible that not all of the source data being read * will contribute to the destination image. For example, the @@ -2303,32 +2303,32 @@ public abstract class TIFFDecompressor { * convenience, the bounds of the active source region (that is, * the region of the strip or tile being read that actually * contributes to the destination image, taking clipping into - * account) are available as activeSrcMinX, - * activeSrcMinY, activeSrcWidth and - * activeSrcHeight. Thus, the source pixel at - * (activeSrcMinX, activeSrcMinY) will - * map to the destination pixel (dstMinX, - * dstMinY). + * account) are available as {@code activeSrcMinX}, + * {@code activeSrcMinY}, {@code activeSrcWidth} and + * {@code activeSrcHeight}. Thus, the source pixel at + * ({@code activeSrcMinX}, {@code activeSrcMinY}) will + * map to the destination pixel ({@code dstMinX}, + * {@code dstMinY}). * *

    The sequence of source bands given by - * sourceBands are to be copied into the sequence of + * {@code sourceBands} are to be copied into the sequence of * bands in the destination given by - * destinationBands. + * {@code destinationBands}. * *

    Some standard tag information is provided the instance - * variables photometricInterpretation, - * compression, samplesPerPixel, - * bitsPerSample, sampleFormat, - * extraSamples, and colorMap. + * variables {@code photometricInterpretation}, + * {@code compression}, {@code samplesPerPixel}, + * {@code bitsPerSample}, {@code sampleFormat}, + * {@code extraSamples}, and {@code colorMap}. * *

    In practice, unless there is a significant performance * advantage to be gained by overriding this routine, most users * will prefer to use the default implementation of this routine, - * and instead override the decodeRaw and/or - * getRawImageType methods. + * and instead override the {@code decodeRaw} and/or + * {@code getRawImageType} methods. * * @exception IOException if an error occurs in - * decodeRaw. + * {@code decodeRaw}. */ public void decode() throws IOException { byte[] byteData = null; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java index b3e202cb2cd..3541ce110db 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFExifJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,7 +29,7 @@ import javax.imageio.metadata.IIOMetadata; import javax.imageio.plugins.tiff.BaselineTIFFTagSet; /** - * A TIFFCompressor for the JPEG variant of Exif. + * A {@code TIFFCompressor} for the JPEG variant of Exif. */ public class TIFFExifJPEGCompressor extends TIFFBaseJPEGCompressor { public TIFFExifJPEGCompressor(ImageWriteParam param) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java index 9cbf49eb84b..5c126acab53 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFaxCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -232,12 +232,12 @@ abstract class TIFFFaxCompressor extends TIFFCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

    The implementation in this class also sets local options * from the FILL_ORDER field if it exists.

    * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -253,8 +253,8 @@ abstract class TIFFFaxCompressor extends TIFFCompressor { } /** - * Return min of maxOffset or offset of first pixel - * different from pixel at bitOffset. + * Return min of {@code maxOffset} or offset of first pixel + * different from pixel at {@code bitOffset}. */ public int nextState(byte[] data, int base, diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java index ced248f9d7e..994d10d7810 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFFieldNode.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,12 +34,12 @@ import javax.imageio.plugins.tiff.TIFFTag; import javax.imageio.plugins.tiff.TIFFTagSet; /** - * The Node representation of a TIFFField + * The {@code Node} representation of a {@code TIFFField} * wherein the child node is procedural rather than buffered. */ public class TIFFFieldNode extends IIOMetadataNode { private static String getNodeName(TIFFField f) { - return f.getData() instanceof TIFFDirectory ? + return (f.hasDirectory() || f.getData() instanceof TIFFDirectory) ? "TIFFIFD" : "TIFFField"; } @@ -52,7 +52,8 @@ public class TIFFFieldNode extends IIOMetadataNode { public TIFFFieldNode(TIFFField field) { super(getNodeName(field)); - isIFD = field.getData() instanceof TIFFDirectory; + isIFD = field.hasDirectory() || + field.getData() instanceof TIFFDirectory; this.field = field; @@ -68,7 +69,8 @@ public class TIFFFieldNode extends IIOMetadataNode { setAttribute("parentTagName", tagName); } - TIFFDirectory dir = (TIFFDirectory)field.getData(); + TIFFDirectory dir = field.hasDirectory() ? + field.getDirectory() : (TIFFDirectory)field.getData(); TIFFTagSet[] tagSets = dir.getTagSets(); if(tagSets != null) { StringBuilder tagSetNames = new StringBuilder(); @@ -90,7 +92,8 @@ public class TIFFFieldNode extends IIOMetadataNode { if(isInitialized) return; if(isIFD) { - TIFFDirectory dir = (TIFFDirectory)field.getData(); + TIFFDirectory dir = field.hasDirectory() ? + field.getDirectory() : (TIFFDirectory)field.getData(); TIFFField[] fields = dir.getTIFFFields(); if(fields != null) { TIFFTagSet[] tagSets = dir.getTagSets(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java index c60a98c793b..46d1419ee4c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFIFD.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -153,7 +153,7 @@ public class TIFFIFD extends TIFFDirectory { } /** - * Returns an Iterator over the TIFF fields. The + * Returns an {@code Iterator} over the TIFF fields. The * traversal is in the order of increasing tag number. */ // Note: the sort is guaranteed for low fields by the use of an @@ -164,7 +164,7 @@ public class TIFFIFD extends TIFFDirectory { } /** - * Read the value of a field. The data parameter should be + * Read the value of a field. The {@code data} parameter should be * an array of length 1 of Object. * * @param stream the input stream @@ -762,8 +762,8 @@ public class TIFFIFD extends TIFFDirectory { } /** - * Returns a TIFFIFD wherein all fields from the - * BaselineTIFFTagSet are copied by value and all other + * Returns a {@code TIFFIFD} wherein all fields from the + * {@code BaselineTIFFTagSet} are copied by value and all other * fields copied by reference. */ public TIFFIFD getShallowClone() { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java index decebe16f0c..933c2da5a6c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -1620,8 +1620,8 @@ public class TIFFImageMetadata extends IIOMetadata { } /** - * Returns a TIFFImageMetadata wherein all fields in the - * root IFD from the BaselineTIFFTagSet are copied by value + * Returns a {@code TIFFImageMetadata} wherein all fields in the + * root IFD from the {@code BaselineTIFFTagSet} are copied by value * and all other fields copied by reference. */ public TIFFImageMetadata getShallowClone() { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java index 47356e0d6a2..317027351fc 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,7 +83,7 @@ public class TIFFImageReader extends ImageReader { // Metadata for image at 'currIndex', or null. private TIFFImageMetadata imageMetadata = null; - // A List of Longs indicating the stream + // A {@code List} of {@code Long}s indicating the stream // positions of the start of the IFD for each image. Entries // are added as needed. private List imageStartPosition = new ArrayList(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java index 21dc5cb7eb4..c30f7ec70f9 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriteParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -122,11 +122,11 @@ import javax.imageio.ImageWriteParam; * quality value is passed directly to the JPEG writer plug-in which * interprets it in the usual way.

    * - *

    The canWriteTiles and - * canWriteCompressed methods will return - * true; the canOffsetTiles and - * canWriteProgressive methods will return - * false.

    + *

    The {@code canWriteTiles} and + * {@code canWriteCompressed} methods will return + * {@code true}; the {@code canOffsetTiles} and + * {@code canWriteProgressive} methods will return + * {@code false}.

    * *

    If tiles are being written, then each of their dimensions will be * rounded to the nearest multiple of 16 per the TIFF specification. If @@ -140,10 +140,10 @@ import javax.imageio.ImageWriteParam; public class TIFFImageWriteParam extends ImageWriteParam { /** - * Constructs a TIFFImageWriteParam instance - * for a given Locale. + * Constructs a {@code TIFFImageWriteParam} instance + * for a given {@code Locale}. * - * @param locale the Locale for which messages + * @param locale the {@code Locale} for which messages * should be localized. */ public TIFFImageWriteParam(Locale locale) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java index ea819e9e968..d0d5c3e5ce0 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFImageWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -221,11 +221,11 @@ public class TIFFImageWriter extends ImageWriter { * relative to a given tile grid layout specified by its X offset * and tile width. * - *

    If tileWidth < 0, the results of this method - * are undefined. If tileWidth == 0, an - * ArithmeticException will be thrown. + *

    If {@code tileWidth < 0}, the results of this method + * are undefined. If {@code tileWidth == 0}, an + * {@code ArithmeticException} will be thrown. * - * @throws ArithmeticException If tileWidth == 0. + * @throws ArithmeticException If {@code tileWidth == 0}. */ public static int XToTileX(int x, int tileGridXOffset, int tileWidth) { x -= tileGridXOffset; @@ -240,11 +240,11 @@ public class TIFFImageWriter extends ImageWriter { * relative to a given tile grid layout specified by its Y offset * and tile height. * - *

    If tileHeight < 0, the results of this method - * are undefined. If tileHeight == 0, an - * ArithmeticException will be thrown. + *

    If {@code tileHeight < 0}, the results of this method + * are undefined. If {@code tileHeight == 0}, an + * {@code ArithmeticException} will be thrown. * - * @throws ArithmeticException If tileHeight == 0. + * @throws ArithmeticException If {@code tileHeight == 0}. */ public static int YToTileY(int y, int tileGridYOffset, int tileHeight) { y -= tileGridYOffset; @@ -424,17 +424,17 @@ public class TIFFImageWriter extends ImageWriter { } /** - * Converts a standard javax_imageio_1.0 tree to a - * TIFFImageMetadata object. + * Converts a standard {@code javax_imageio_1.0} tree to a + * {@code TIFFImageMetadata} object. * * @param inData The metadata object. - * @return a TIFFImageMetadata or null if - * the standard tree derived from the input object is null. - * @throws IllegalArgumentException if inData is - * null. - * @throws IllegalArgumentException if inData does not support + * @return a {@code TIFFImageMetadata} or {@code null} if + * the standard tree derived from the input object is {@code null}. + * @throws IllegalArgumentException if {@code inData} is + * {@code null}. + * @throws IllegalArgumentException if {@code inData} does not support * the standard metadata format. - * @throws IIOInvalidTreeException if inData generates an + * @throws IIOInvalidTreeException if {@code inData} generates an * invalid standard metadata tree. */ private TIFFImageMetadata convertStandardImageMetadata(IIOMetadata inData) @@ -463,15 +463,15 @@ public class TIFFImageWriter extends ImageWriter { /** * Converts a native - * javax_imageio_tiff_image_1.0 tree to a - * TIFFImageMetadata object. + * {@code javax_imageio_tiff_image_1.0} tree to a + * {@code TIFFImageMetadata} object. * * @param inData The metadata object. - * @return a TIFFImageMetadata or null if - * the native tree derived from the input object is null. - * @throws IllegalArgumentException if inData is - * null or does not support the native metadata format. - * @throws IIOInvalidTreeException if inData generates an + * @return a {@code TIFFImageMetadata} or {@code null} if + * the native tree derived from the input object is {@code null}. + * @throws IllegalArgumentException if {@code inData} is + * {@code null} or does not support the native metadata format. + * @throws IIOInvalidTreeException if {@code inData} generates an * invalid native metadata tree. */ private TIFFImageMetadata convertNativeImageMetadata(IIOMetadata inData) @@ -504,8 +504,8 @@ public class TIFFImageWriter extends ImageWriter { * as needed. The destination image dimensions are provided as parameters * because these might differ from those of the source due to subsampling. * - * @param cm The ColorModel of the image being written. - * @param sm The SampleModel of the image being written. + * @param cm The {@code ColorModel} of the image being written. + * @param sm The {@code SampleModel} of the image being written. * @param destWidth The width of the written image after subsampling. * @param destHeight The height of the written image after subsampling. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java index a631a3a926c..7b6cfcf5b28 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFJPEGCompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,14 +102,14 @@ public class TIFFJPEGCompressor extends TIFFBaseJPEGCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

    The implementation in this class also adds the TIFF fields * JPEGTables, YCbCrSubSampling, YCbCrPositioning, and * ReferenceBlackWhite superseding any prior settings of those * fields.

    * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java index d53a275955f..cbf3b504f63 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -245,7 +245,7 @@ class TIFFLZWDecompressor extends TIFFDecompressor { } /** - * Append newString to the end of oldString. + * Append {@code newString} to the end of {@code oldString}. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java index 92656697d2c..2a61535cff3 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFLZWUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -188,7 +188,7 @@ class TIFFLZWUtil { } /** - * Append newString to the end of oldString. + * Append {@code newString} to the end of {@code oldString}. */ public byte[] composeString(byte oldString[], byte newString) { int length = oldString.length; diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java index 657bd28861b..6ffc1f0acb7 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFNullDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,16 +34,16 @@ public class TIFFNullDecompressor extends TIFFDecompressor { */ private boolean isReadActiveOnly = false; - /** The original value of srcMinX. */ + /** The original value of {@code srcMinX}. */ private int originalSrcMinX; - /** The original value of srcMinY. */ + /** The original value of {@code srcMinY}. */ private int originalSrcMinY; - /** The original value of srcWidth. */ + /** The original value of {@code srcWidth}. */ private int originalSrcWidth; - /** The original value of srcHeight. */ + /** The original value of {@code srcHeight}. */ private int originalSrcHeight; public TIFFNullDecompressor() {} diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java index 264657ddb2a..2837754ddb2 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFOldJPEGDecompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ import javax.imageio.plugins.tiff.BaselineTIFFTagSet; import javax.imageio.plugins.tiff.TIFFField; /** - * TIFFDecompressor for "Old JPEG" compression. + * {@code TIFFDecompressor} for "Old JPEG" compression. */ public class TIFFOldJPEGDecompressor extends TIFFJPEGDecompressor { diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java index cebfdfb2221..523f9eaa574 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRLECompressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,8 +42,8 @@ public class TIFFRLECompressor extends TIFFFaxCompressor { * CCITT RLE (Run Lenth Encoding). * * @param data The row of data to compress. - * @param rowOffset Starting index in data. - * @param colOffset Bit offset within first data[rowOffset]. + * @param rowOffset Starting index in {@code data}. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param rowLength Number of bits in the row. * @param compData The compressed data. * diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java index 98a336f8c8f..77e0c9a109c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFRenderedImage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -85,15 +85,15 @@ public class TIFFRenderedImage implements RenderedImage { } /** - * Creates a copy of param. The source subsampling and + * Creates a copy of {@code param}. The source subsampling and * and bands settings and the destination bands and offset settings - * are copied. If param is a TIFFImageReadParam - * then the TIFFDecompressor and - * TIFFColorConverter settings are also copied; otherwise - * they are explicitly set to null. + * are copied. If {@code param} is a {@code TIFFImageReadParam} + * then the {@code TIFFDecompressor} and + * {@code TIFFColorConverter} settings are also copied; otherwise + * they are explicitly set to {@code null}. * * @param param the parameters to be copied. - * @param copyTagSets whether the TIFFTagSet settings + * @param copyTagSets whether the {@code TIFFTagSet} settings * should be copied if set. * @return copied parameters. */ diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java index fa2652ef902..55088e34dfe 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT4Compressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,13 +41,13 @@ public class TIFFT4Compressor extends TIFFFaxCompressor { } /** - * Sets the value of the metadata field. + * Sets the value of the {@code metadata} field. * *

    The implementation in this class also sets local options * from the T4_OPTIONS field if it exists, and if it doesn't, adds * it with default values.

    * - * @param metadata the IIOMetadata object for the + * @param metadata the {@code IIOMetadata} object for the * image being written. * * @see #getMetadata() @@ -86,7 +86,7 @@ public class TIFFT4Compressor extends TIFFFaxCompressor { * @param isEOLAligned Whether EOL bit sequences should be padded. * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. - * @param colOffset Bit offset within first data[rowOffset]. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. diff --git a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java index 964bba05032..517c23bde54 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java +++ b/jdk/src/java.desktop/share/classes/com/sun/imageio/plugins/tiff/TIFFT6Compressor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,7 +42,7 @@ public class TIFFT6Compressor extends TIFFFaxCompressor { * * @param data The row of data to compress. * @param lineStride Byte step between the same sample in different rows. - * @param colOffset Bit offset within first data[rowOffset]. + * @param colOffset Bit offset within first {@code data[rowOffset]}. * @param width Number of bits in the row. * @param height Number of rows in the buffer. * @param compData The compressed data. diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java index 8c9dc3c78be..c0ac8bf6d40 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,11 @@ package com.sun.media.sound; import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.io.InputStream; import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioSystem; import javax.sound.sampled.UnsupportedAudioFileException; @@ -49,11 +49,6 @@ public final class AiffFileReader extends SunFileReader { throws UnsupportedAudioFileException, IOException { DataInputStream dis = new DataInputStream(stream); - // assumes a stream at the beginning of the file which has already - // passed the magic number test... - // leaves the input stream at the beginning of the audio data - int fileRead = 0; - int dataLength = 0; AudioFormat format = null; // Read the magic number @@ -65,9 +60,9 @@ public final class AiffFileReader extends SunFileReader { throw new UnsupportedAudioFileException("not an AIFF file"); } + int frameLength = 0; int length = dis.readInt(); int iffType = dis.readInt(); - fileRead += 12; int totallength; if(length <= 0 ) { @@ -91,7 +86,6 @@ public final class AiffFileReader extends SunFileReader { // Read the chunk name int chunkName = dis.readInt(); int chunkLen = dis.readInt(); - fileRead += 8; int chunkRead = 0; @@ -112,7 +106,13 @@ public final class AiffFileReader extends SunFileReader { if (channels <= 0) { throw new UnsupportedAudioFileException("Invalid number of channels"); } - dis.readInt(); // numSampleFrames + frameLength = dis.readInt(); // numSampleFrames + if (frameLength < 0) { + // AiffFileFormat uses int, unlike AIS which uses long + //TODO this (negative) value should be passed as long to AIS + frameLength = AudioSystem.NOT_SPECIFIED; + } + int sampleSizeInBits = dis.readUnsignedShort(); if (sampleSizeInBits < 1 || sampleSizeInBits > 32) { throw new UnsupportedAudioFileException("Invalid AIFF/COMM sampleSize"); @@ -149,38 +149,17 @@ public final class AiffFileReader extends SunFileReader { break; case AiffFileFormat.SSND_MAGIC: // Data chunk. - // we are getting *weird* numbers for chunkLen sometimes; - // this really should be the size of the data chunk.... - int dataOffset = dis.readInt(); - int blocksize = dis.readInt(); + int dataOffset = dis.readInt(); // for now unused in javasound + int blocksize = dis.readInt(); // for now unused in javasound chunkRead += 8; - - // okay, now we are done reading the header. we need to set the size - // of the data segment. we know that sometimes the value we get for - // the chunksize is absurd. this is the best i can think of:if the - // value seems okay, use it. otherwise, we get our value of - // length by assuming that everything left is the data segment; - // its length should be our original length (for all AIFF data chunks) - // minus what we've read so far. - // $$kk: we should be able to get length for the data chunk right after - // we find "SSND." however, some aiff files give *weird* numbers. what - // is going on?? - - if (chunkLen < length) { - dataLength = chunkLen - chunkRead; - } else { - // $$kk: 11.03.98: this seems dangerous! - dataLength = length - (fileRead + chunkRead); - } ssndFound = true; break; } // switch - fileRead += chunkRead; // skip the remainder of this chunk if (!ssndFound) { int toSkip = chunkLen - chunkRead; if (toSkip > 0) { - fileRead += dis.skipBytes(toSkip); + dis.skipBytes(toSkip); } } } // while @@ -188,36 +167,12 @@ public final class AiffFileReader extends SunFileReader { if (format == null) { throw new UnsupportedAudioFileException("missing COMM chunk"); } - AudioFileFormat.Type type = aifc?AudioFileFormat.Type.AIFC:AudioFileFormat.Type.AIFF; + Type type = aifc ? Type.AIFC : Type.AIFF; - return new AiffFileFormat(type, totallength, format, dataLength / format.getFrameSize()); + return new AiffFileFormat(type, totallength, format, frameLength); } // HELPER METHODS - /** write_ieee_extended(DataOutputStream dos, double f) throws IOException { - * Extended precision IEEE floating-point conversion routine. - * @argument DataOutputStream - * @argument double - * @return void - * @exception IOException - */ - private void write_ieee_extended(DataOutputStream dos, double f) throws IOException { - - int exponent = 16398; - double highMantissa = f; - - // For now write the integer portion of f - // $$jb: 03.30.99: stay in synch with JMF on this!!!! - while (highMantissa < 44000) { - highMantissa *= 2; - exponent--; - } - dos.writeShort(exponent); - dos.writeInt( ((int) highMantissa) << 16); - dos.writeInt(0); // low Mantissa - } - - /** * read_ieee_extended * Extended precision IEEE floating-point conversion routine. diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java index 0a4788df804..9b5ebac2f6b 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/AiffFileWriter.java @@ -59,7 +59,6 @@ public final class AiffFileWriter extends SunFileWriter { super(new AudioFileFormat.Type[]{AudioFileFormat.Type.AIFF}); } - // METHODS TO IMPLEMENT AudioFileWriter @Override @@ -83,7 +82,6 @@ public final class AiffFileWriter extends SunFileWriter { return new AudioFileFormat.Type[0]; } - @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, OutputStream out) throws IOException { Objects.requireNonNull(stream); @@ -102,11 +100,9 @@ public final class AiffFileWriter extends SunFileWriter { throw new IOException("stream length not specified"); } - int bytesWritten = writeAiffFile(stream, aiffFileFormat, out); - return bytesWritten; + return writeAiffFile(stream, aiffFileFormat, out); } - @Override public int write(AudioInputStream stream, AudioFileFormat.Type fileType, File out) throws IOException { Objects.requireNonNull(stream); @@ -129,12 +125,15 @@ public final class AiffFileWriter extends SunFileWriter { // $$kk: 10.22.99: jan: please either implement this or throw an exception! // $$fb: 2001-07-13: done. Fixes Bug 4479981 - int ssndBlockSize = (aiffFileFormat.getFormat().getChannels() * aiffFileFormat.getFormat().getSampleSizeInBits()); + int channels = aiffFileFormat.getFormat().getChannels(); + int sampleSize = aiffFileFormat.getFormat().getSampleSizeInBits(); + int ssndBlockSize = channels * ((sampleSize + 7) / 8); int aiffLength=bytesWritten; int ssndChunkSize=aiffLength-aiffFileFormat.getHeaderSize()+16; long dataSize=ssndChunkSize-16; - int numFrames=(int) (dataSize*8/ssndBlockSize); + //TODO possibly incorrect round + int numFrames = (int) (dataSize / ssndBlockSize); RandomAccessFile raf=new RandomAccessFile(out, "rw"); // skip FORM magic @@ -173,12 +172,7 @@ public final class AiffFileWriter extends SunFileWriter { AudioFormat streamFormat = stream.getFormat(); AudioFormat.Encoding streamEncoding = streamFormat.getEncoding(); - - float sampleRate; int sampleSizeInBits; - int channels; - int frameSize; - float frameRate; int fileSize; boolean convert8to16 = false; @@ -235,7 +229,6 @@ public final class AiffFileWriter extends SunFileWriter { return fileFormat; } - private int writeAiffFile(InputStream in, AiffFileFormat aiffFileFormat, OutputStream out) throws IOException { int bytesRead = 0; @@ -275,25 +268,20 @@ public final class AiffFileWriter extends SunFileWriter { AudioFormat.Encoding encoding = null; //$$fb a little bit nicer handling of constants - - //int headerSize = 54; int headerSize = aiffFileFormat.getHeaderSize(); - //int fverChunkSize = 0; int fverChunkSize = aiffFileFormat.getFverChunkSize(); - //int commChunkSize = 26; int commChunkSize = aiffFileFormat.getCommChunkSize(); int aiffLength = -1; int ssndChunkSize = -1; - //int ssndOffset = headerSize - 16; int ssndOffset = aiffFileFormat.getSsndChunkOffset(); short channels = (short) format.getChannels(); short sampleSize = (short) format.getSampleSizeInBits(); - int ssndBlockSize = (channels * sampleSize); - int numFrames = aiffFileFormat.getFrameLength(); - long dataSize = -1; + int ssndBlockSize = channels * ((sampleSize + 7) / 8); + int numFrames = aiffFileFormat.getFrameLength(); + long dataSize = -1; if( numFrames != AudioSystem.NOT_SPECIFIED) { - dataSize = (long) numFrames * ssndBlockSize / 8; + dataSize = (long) numFrames * ssndBlockSize; ssndChunkSize = (int)dataSize + 16; aiffLength = (int)dataSize+headerSize; } @@ -403,9 +391,6 @@ public final class AiffFileWriter extends SunFileWriter { } - - - // HELPER METHODS private static final int DOUBLE_MANTISSA_LENGTH = 52; @@ -452,6 +437,4 @@ public final class AiffFileWriter extends SunFileWriter { dos.writeShort(extendedBits79To64); dos.writeLong(extendedBits63To0); } - - } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java index 240c6d27c58..9085c58b530 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveExtensibleFileReader.java @@ -255,16 +255,17 @@ public final class WaveExtensibleFileReader extends SunFileReader { public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { - AudioFileFormat format = getAudioFileFormat(stream); + final AudioFileFormat format = getAudioFileFormat(stream); // we've got everything, the stream is supported and it is at the // beginning of the header, so find the data chunk again and return an // AudioInputStream - RIFFReader riffiterator = new RIFFReader(stream); + final RIFFReader riffiterator = new RIFFReader(stream); while (riffiterator.hasNextChunk()) { RIFFReader chunk = riffiterator.nextChunk(); if (chunk.getFormat().equals("data")) { - return new AudioInputStream(chunk, format.getFormat(), chunk - .getSize()); + final AudioFormat af = format.getFormat(); + final long length = chunk.getSize() / af.getFrameSize(); + return new AudioInputStream(chunk, af, length); } } throw new UnsupportedAudioFileException(); diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java index afecd0e34be..6639cf040e8 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/WaveFloatFileReader.java @@ -95,16 +95,17 @@ public final class WaveFloatFileReader extends SunFileReader { public AudioInputStream getAudioInputStream(final InputStream stream) throws UnsupportedAudioFileException, IOException { - AudioFileFormat format = getAudioFileFormat(stream); + final AudioFileFormat format = getAudioFileFormat(stream); // we've got everything, the stream is supported and it is at the // beginning of the header, so find the data chunk again and return an // AudioInputStream - RIFFReader riffiterator = new RIFFReader(stream); + final RIFFReader riffiterator = new RIFFReader(stream); while (riffiterator.hasNextChunk()) { RIFFReader chunk = riffiterator.nextChunk(); if (chunk.getFormat().equals("data")) { - return new AudioInputStream(chunk, format.getFormat(), - chunk.getSize()); + final AudioFormat af = format.getFormat(); + final long length = chunk.getSize() / af.getFrameSize(); + return new AudioInputStream(chunk, af, length); } } throw new UnsupportedAudioFileException(); diff --git a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java index d23e672779c..9b04496f65b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java +++ b/jdk/src/java.desktop/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java @@ -231,7 +231,9 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy // Before all the checks below we first see if it's an FTP provider or a focus cycle root. // If it's the case just go down cycle (if it's set to "implicit"). Component comp = getComponentDownCycle(aComponent, FORWARD_TRAVERSAL); - if (comp != null) { + // Check if aComponent is focus-cycle-root's default Component, i.e. + // focus cycle root & focus-cycle-root's default Component is same. + if (comp != null && comp != aComponent) { return comp; } diff --git a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java index 6f1427fe54a..1ab720f7555 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java +++ b/jdk/src/java.desktop/share/classes/java/beans/EventHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -526,8 +526,11 @@ public class EventHandler implements InvocationHandler { * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see #create(Class, Object, String, String) + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action) @@ -584,8 +587,11 @@ public class EventHandler implements InvocationHandler { * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see #create(Class, Object, String, String, String) + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action, @@ -675,8 +681,11 @@ public class EventHandler implements InvocationHandler { * @throws NullPointerException if {@code listenerInterface} is null * @throws NullPointerException if {@code target} is null * @throws NullPointerException if {@code action} is null - * + * @throws IllegalArgumentException if creating a Proxy for + * {@code listenerInterface} fails for any of the restrictions + * specified by {@link Proxy#newProxyInstance} * @see EventHandler + * @see Proxy#newProxyInstance */ public static T create(Class listenerInterface, Object target, String action, diff --git a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java index ddef0cffad5..ba2cbcd2dc9 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java +++ b/jdk/src/java.desktop/share/classes/java/beans/SimpleBeanInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,8 @@ package java.beans; import java.awt.Image; import java.awt.Toolkit; -import java.io.InputStream; +import java.awt.image.ImageProducer; +import java.net.URL; import java.security.AccessController; import java.security.PrivilegedAction; @@ -171,19 +172,24 @@ public class SimpleBeanInfo implements BeanInfo { } /** - * This is a utility method to help in loading icon images. - * It takes the name of a resource file associated with the - * current object's class file and loads an image object - * from that file. Typically images will be GIFs. + * This is a utility method to help in loading icon images. It takes the + * name of a resource file associated with the current object's class file + * and loads an image object from that file. Typically images will be GIFs. * - * @param resourceName A pathname relative to the directory - * holding the class file of the current class. For example, - * "wombat.gif". - * @return an image object. May be null if the load failed. + * @param resourceName A pathname relative to the directory holding the + * class file of the current class. For example, "wombat.gif". + * @return an image object or null if the resource is not found or the + * resource could not be loaded as an Image */ public Image loadImage(final String resourceName) { - try (InputStream in = getClass().getResourceAsStream(resourceName)) { - return Toolkit.getDefaultToolkit().createImage(in.readAllBytes()); + try { + final URL url = getClass().getResource(resourceName); + if (url != null) { + final ImageProducer ip = (ImageProducer) url.getContent(); + if (ip != null) { + return Toolkit.getDefaultToolkit().createImage(ip); + } + } } catch (final Exception ignored) { } return null; diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java index d434acf8ab3..d1dbd3cf4fb 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/BaselineTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -2175,9 +2175,9 @@ public class BaselineTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of a BaselineTIFFTagSet. + * Returns a shared instance of a {@code BaselineTIFFTagSet}. * - * @return a BaselineTIFFTagSet instance. + * @return a {@code BaselineTIFFTagSet} instance. */ public synchronized static BaselineTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java index d37a1330d12..03198c45c51 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifGPSTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ public class ExifGPSTagSet extends TIFFTagSet { /** * A value to be used with the "GPSVersionID" tag to indicate GPS version * 2.2. The value equals the US-ASCII encoding of the byte array - * {'2', '2', '0', '0'}. + * {@code {'2', '2', '0', '0'}}. * * @see #TAG_GPS_VERSION_ID */ @@ -711,9 +711,9 @@ public class ExifGPSTagSet extends TIFFTagSet { } /** - * Returns a shared instance of an ExifGPSTagSet. + * Returns a shared instance of an {@code ExifGPSTagSet}. * - * @return an ExifGPSTagSet instance. + * @return an {@code ExifGPSTagSet} instance. */ public synchronized static ExifGPSTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java index b2a52790f0b..7089c653fbe 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifInteroperabilityTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -88,9 +88,9 @@ public class ExifInteroperabilityTagSet extends TIFFTagSet { /** * Returns the shared instance of - * ExifInteroperabilityTagSet. + * {@code ExifInteroperabilityTagSet}. * - * @return the ExifInteroperabilityTagSet instance. + * @return the {@code ExifInteroperabilityTagSet} instance. */ public synchronized static ExifInteroperabilityTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java index 29647711fc4..108e1a16852 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifParentTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,9 +80,9 @@ public class ExifParentTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of an ExifParentTIFFTagSet. + * Returns a shared instance of an {@code ExifParentTIFFTagSet}. * - * @return an ExifParentTIFFTagSet instance. + * @return an {@code ExifParentTIFFTagSet} instance. */ public synchronized static ExifParentTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java index 5867a0ffef5..c5be97c88c2 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/ExifTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import java.util.List; * standard for annotating images used by most digital camera * manufacturers. The Exif specification may be found at * - * http://www.exif.org/Exif2-2.PDF + * {@code http://www.exif.org/Exif2-2.PDF} * . * *

    The definitions of the data types referenced by the field @@ -67,7 +67,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { /** * A value to be used with the "ExifVersion" tag to indicate Exif version * 2.1. The value equals the US-ASCII encoding of the byte array - * {'0', '2', '1', '0'}. + * {@code {'0', '2', '1', '0'}}. * * @see #TAG_EXIF_VERSION */ @@ -78,7 +78,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { /** * A value to be used with the "ExifVersion" tag to indicate Exif version * 2.2. The value equals the US-ASCII encoding of the byte array - * {'0', '2', '2', '0'}. + * {@code {'0', '2', '2', '0'}}. * * @see #TAG_EXIF_VERSION */ @@ -94,7 +94,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { /** * A tag indicating the color space information (type SHORT). The - * legal values are given by the COLOR_SPACE_* + * legal values are given by the {@code COLOR_SPACE_*} * constants. * * @see #COLOR_SPACE_SRGB @@ -1256,7 +1256,7 @@ public class ExifTIFFTagSet extends TIFFTagSet { static class ExifVersion extends TIFFTag { public ExifVersion() { - super("Exifversion", + super("ExifVersion", TAG_EXIF_VERSION, 1 << TIFFTag.TIFF_UNDEFINED, 4); @@ -1992,9 +1992,9 @@ public class ExifTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of an ExifTIFFTagSet. + * Returns a shared instance of an {@code ExifTIFFTagSet}. * - * @return an ExifTIFFTagSet instance. + * @return an {@code ExifTIFFTagSet} instance. */ public synchronized static ExifTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java index fa9733cd3f0..8a3043da122 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/FaxTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -131,9 +131,9 @@ public class FaxTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of a FaxTIFFTagSet. + * Returns a shared instance of a {@code FaxTIFFTagSet}. * - * @return a FaxTIFFTagSet instance. + * @return a {@code FaxTIFFTagSet} instance. */ public synchronized static FaxTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java index c478f7c03e7..28ee56abd3c 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/GeoTIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,7 +32,7 @@ import java.util.List; * standard for annotating georeferenced or geocoded raster imagery. * The GeoTIFF specification may be found at - * http://www.remotesensing.org/geotiff/spec/geotiffhome.html + * {@code http://www.remotesensing.org/geotiff/spec/geotiffhome.html} * . This class does not handle the GeoKeys referenced * from a GeoKeyDirectoryTag as those are not TIFF tags per se. * @@ -63,7 +63,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { /** A tag used to store the GeoKey directory. */ public static final int TAG_GEO_KEY_DIRECTORY = 34735; - /** A tag used to store all double-values GeoKeys. */ + /** A tag used to store all {@code double}-values GeoKeys. */ public static final int TAG_GEO_DOUBLE_PARAMS = 34736; /** A tag used to store all ASCII-values GeoKeys. */ @@ -97,7 +97,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { static class GeoKeyDirectory extends TIFFTag { public GeoKeyDirectory() { - super("GeoKeyDirectory", + super("GeoKeyDirectoryTag", TAG_GEO_KEY_DIRECTORY, 1 << TIFFTag.TIFF_SHORT); } @@ -105,7 +105,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { static class GeoDoubleParams extends TIFFTag { public GeoDoubleParams() { - super("GeoDoubleParams", + super("GeoDoubleParamsTag", TAG_GEO_DOUBLE_PARAMS, 1 << TIFFTag.TIFF_DOUBLE); } @@ -113,7 +113,7 @@ public class GeoTIFFTagSet extends TIFFTagSet { static class GeoAsciiParams extends TIFFTag { public GeoAsciiParams() { - super("GeoAsciiParams", + super("GeoAsciiParamsTag", TAG_GEO_ASCII_PARAMS, 1 << TIFFTag.TIFF_ASCII); } @@ -137,9 +137,9 @@ public class GeoTIFFTagSet extends TIFFTagSet { } /** - * Returns a shared instance of a GeoTIFFTagSet. + * Returns a shared instance of a {@code GeoTIFFTagSet}. * - * @return a GeoTIFFTagSet instance. + * @return a {@code GeoTIFFTagSet} instance. */ public synchronized static GeoTIFFTagSet getInstance() { if (theInstance == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java index ea13664767c..f3e5577716a 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFDirectory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,58 +41,58 @@ import com.sun.imageio.plugins.tiff.TIFFImageMetadata; * image metadata. A TIFF image metadata tree represents an Image File * Directory (IFD) from a TIFF 6.0 stream. An IFD consists of a number of * IFD Entries each of which associates an identifying tag number with - * a compatible value. A TIFFDirectory instance corresponds + * a compatible value. A {@code TIFFDirectory} instance corresponds * to an IFD and contains a set of {@link TIFFField}s each of which * corresponds to an IFD Entry in the IFD. * - *

    When reading, a TIFFDirectory may be created by passing + *

    When reading, a {@code TIFFDirectory} may be created by passing * the value returned by {@link javax.imageio.ImageReader#getImageMetadata * ImageReader.getImageMetadata()} to {@link #createFromMetadata * createFromMetadata()}. The {@link TIFFField}s in the directory may then * be obtained using the accessor methods provided in this class.

    * *

    When writing, an {@link IIOMetadata} object for use by one of the - * write() methods of {@link javax.imageio.ImageWriter} may be - * created from a TIFFDirectory by {@link #getAsMetadata()}. - * The TIFFDirectory itself may be created by construction or - * from the IIOMetadata object returned by + * {@code write()} methods of {@link javax.imageio.ImageWriter} may be + * created from a {@code TIFFDirectory} by {@link #getAsMetadata()}. + * The {@code TIFFDirectory} itself may be created by construction or + * from the {@code IIOMetadata} object returned by * {@link javax.imageio.ImageWriter#getDefaultImageMetadata - * ImageWriter.getDefaultImageMetadata()}. The TIFFFields in the + * ImageWriter.getDefaultImageMetadata()}. The {@code TIFFField}s in the * directory may be set using the mutator methods provided in this class.

    * - *

    A TIFFDirectory is aware of the tag numbers in the + *

    A {@code TIFFDirectory} is aware of the tag numbers in the * group of {@link TIFFTagSet}s associated with it. When - * a TIFFDirectory is created from a native image metadata + * a {@code TIFFDirectory} is created from a native image metadata * object, these tag sets are derived from the tagSets attribute * of the TIFFIFD node.

    * - *

    A TIFFDirectory might also have a parent {@link TIFFTag}. + *

    A {@code TIFFDirectory} might also have a parent {@link TIFFTag}. * This will occur if the directory represents an IFD other than the root * IFD of the image. The parent tag is the tag of the IFD Entry which is a - * pointer to the IFD represented by this TIFFDirectory. The - * {@link TIFFTag#isIFDPointer} method of this parent TIFFTag - * must return true. When a TIFFDirectory is + * pointer to the IFD represented by this {@code TIFFDirectory}. The + * {@link TIFFTag#isIFDPointer} method of this parent {@code TIFFTag} + * must return {@code true}. When a {@code TIFFDirectory} is * created from a native image metadata object, the parent tag set is set * from the parentTagName attribute of the corresponding - * TIFFIFD node. Note that a TIFFDirectory instance - * which has a non-null parent tag will be contained in the - * data field of a TIFFField instance which has a tag field + * TIFFIFD node. Note that a {@code TIFFDirectory} instance + * which has a non-{@code null} parent tag will be contained in the + * data field of a {@code TIFFField} instance which has a tag field * equal to the contained directory's parent tag.

    * - *

    As an example consider an Exif image. The TIFFDirectory + *

    As an example consider an Exif image. The {@code TIFFDirectory} * instance corresponding to the Exif IFD in the Exif stream would have parent * tag {@link ExifParentTIFFTagSet#TAG_EXIF_IFD_POINTER TAG_EXIF_IFD_POINTER} * and would include {@link ExifTIFFTagSet} in its group of known tag sets. - * The TIFFDirectory corresponding to this Exif IFD will be - * contained in the data field of a TIFFField which will in turn - * be contained in the TIFFDirectory corresponding to the primary - * IFD of the Exif image which will itself have a null-valued + * The {@code TIFFDirectory} corresponding to this Exif IFD will be + * contained in the data field of a {@code TIFFField} which will in turn + * be contained in the {@code TIFFDirectory} corresponding to the primary + * IFD of the Exif image which will itself have a {@code null}-valued * parent tag.

    * *

    Note that this implementation is not synchronized. If multiple - * threads use a TIFFDirectory instance concurrently, and at + * threads use a {@code TIFFDirectory} instance concurrently, and at * least one of the threads modifies the directory, for example, by adding - * or removing TIFFFields or TIFFTagSets, it + * or removing {@code TIFFField}s or {@code TIFFTagSet}s, it * must be synchronized externally.

    * * @since 9 @@ -107,10 +107,10 @@ public class TIFFDirectory implements Cloneable { private static final int MAX_LOW_FIELD_TAG_NUM = BaselineTIFFTagSet.TAG_REFERENCE_BLACK_WHITE; - /** The TIFFTagSets associated with this directory. */ + /** The {@code TIFFTagSets} associated with this directory. */ private List tagSets; - /** The parent TIFFTag of this directory. */ + /** The parent {@code TIFFTag} of this directory. */ private TIFFTag parentTag; /** @@ -123,13 +123,13 @@ public class TIFFDirectory implements Cloneable { private int numLowFields = 0; /** - * A mapping of Integer tag numbers to TIFFFields + * A mapping of {@code Integer} tag numbers to {@code TIFFField}s * for fields which are not low tag numbered. */ private Map highFields = new TreeMap(); /** - * Creates a TIFFDirectory instance from the contents of + * Creates a {@code TIFFDirectory} instance from the contents of * an image metadata object. The supplied object must support an image * metadata format supported by the TIFF {@link javax.imageio.ImageWriter} * plug-in. This will usually be either the TIFF native image metadata @@ -139,12 +139,12 @@ public class TIFFDirectory implements Cloneable { * @param tiffImageMetadata A metadata object which supports a compatible * image metadata format. * - * @return A TIFFDirectory populated from the contents of + * @return A {@code TIFFDirectory} populated from the contents of * the supplied metadata object. * - * @throws NullPointerException if tiffImageMetadata - * is null. - * @throws IllegalArgumentException if tiffImageMetadata + * @throws NullPointerException if {@code tiffImageMetadata} + * is {@code null}. + * @throws IllegalArgumentException if {@code tiffImageMetadata} * does not support a compatible image metadata format. * @throws IIOInvalidTreeException if the supplied metadata object * cannot be parsed. @@ -204,7 +204,7 @@ public class TIFFDirectory implements Cloneable { } /** - * Converts a TIFFDirectory to a TIFFIFD. + * Converts a {@code TIFFDirectory} to a {@code TIFFIFD}. */ private static TIFFIFD getDirectoryAsIFD(TIFFDirectory dir) { if(dir instanceof TIFFIFD) { @@ -219,27 +219,39 @@ public class TIFFDirectory implements Cloneable { TIFFField f = fields[i]; TIFFTag tag = f.getTag(); if(tag.isIFDPointer()) { - TIFFDirectory subIFD = - getDirectoryAsIFD((TIFFDirectory)f.getData()); - f = new TIFFField(tag, f.getType(), (long)f.getCount(), subIFD); + TIFFDirectory subDir = null; + if (f.hasDirectory()) { + subDir = f.getDirectory(); + } else if (f.getData() instanceof TIFFDirectory) { + subDir = (TIFFDirectory)f.getData(); + } + if (subDir != null) { + TIFFDirectory subIFD = getDirectoryAsIFD(subDir); + f = new TIFFField(tag, f.getType(), (long)f.getCount(), + subIFD); + } else { + f = null; + } + } + if (f != null) { + ifd.addTIFFField(f); } - ifd.addTIFFField(f); } return ifd; } /** - * Constructs a TIFFDirectory which is aware of a given + * Constructs a {@code TIFFDirectory} which is aware of a given * group of {@link TIFFTagSet}s. An optional parent {@link TIFFTag} * may also be specified. * - * @param tagSets The TIFFTagSets associated with this + * @param tagSets The {@code TIFFTagSets} associated with this * directory. - * @param parentTag The parent TIFFTag of this directory; - * may be null. - * @throws NullPointerException if tagSets is - * null. + * @param parentTag The parent {@code TIFFTag} of this directory; + * may be {@code null}. + * @throws NullPointerException if {@code tagSets} is + * {@code null}. */ public TIFFDirectory(TIFFTagSet[] tagSets, TIFFTag parentTag) { if(tagSets == null) { @@ -256,8 +268,8 @@ public class TIFFDirectory implements Cloneable { /** * Returns the {@link TIFFTagSet}s of which this directory is aware. * - * @return The TIFFTagSets associated with this - * TIFFDirectory. + * @return The {@code TIFFTagSet}s associated with this + * {@code TIFFDirectory}. */ public TIFFTagSet[] getTagSets() { return tagSets.toArray(new TIFFTagSet[tagSets.size()]); @@ -267,9 +279,9 @@ public class TIFFDirectory implements Cloneable { * Adds an element to the group of {@link TIFFTagSet}s of which this * directory is aware. * - * @param tagSet The TIFFTagSet to add. - * @throws NullPointerException if tagSet is - * null. + * @param tagSet The {@code TIFFTagSet} to add. + * @throws NullPointerException if {@code tagSet} is + * {@code null}. */ public void addTagSet(TIFFTagSet tagSet) { if(tagSet == null) { @@ -285,9 +297,9 @@ public class TIFFDirectory implements Cloneable { * Removes an element from the group of {@link TIFFTagSet}s of which this * directory is aware. * - * @param tagSet The TIFFTagSet to remove. - * @throws NullPointerException if tagSet is - * null. + * @param tagSet The {@code TIFFTagSet} to remove. + * @throws NullPointerException if {@code tagSet} is + * {@code null}. */ public void removeTagSet(TIFFTagSet tagSet) { if(tagSet == null) { @@ -301,10 +313,10 @@ public class TIFFDirectory implements Cloneable { /** * Returns the parent {@link TIFFTag} of this directory if one - * has been defined or null otherwise. + * has been defined or {@code null} otherwise. * - * @return The parent TIFFTag of this - * TIFFDiectory or null. + * @return The parent {@code TIFFTag} of this + * {@code TIFFDiectory} or {@code null}. */ public TIFFTag getParentTag() { return parentTag; @@ -312,12 +324,12 @@ public class TIFFDirectory implements Cloneable { /** * Returns the {@link TIFFTag} which has tag number equal to - * tagNumber or null if no such tag + * {@code tagNumber} or {@code null} if no such tag * exists in the {@link TIFFTagSet}s associated with this * directory. * * @param tagNumber The tag number of interest. - * @return The corresponding TIFFTag or null. + * @return The corresponding {@code TIFFTag} or {@code null}. */ public TIFFTag getTag(int tagNumber) { return TIFFIFD.getTag(tagNumber, tagSets); @@ -326,8 +338,8 @@ public class TIFFDirectory implements Cloneable { /** * Returns the number of {@link TIFFField}s in this directory. * - * @return The number of TIFFFields in this - * TIFFDirectory. + * @return The number of {@code TIFFField}s in this + * {@code TIFFDirectory}. */ public int getNumTIFFFields() { return numLowFields + highFields.size(); @@ -339,7 +351,7 @@ public class TIFFDirectory implements Cloneable { * * @param tagNumber The tag number. * @return Whether a {@link TIFFTag} with tag number equal to - * tagNumber is present in this TIFFDirectory. + * {@code tagNumber} is present in this {@code TIFFDirectory}. */ public boolean containsTIFFField(int tagNumber) { return (tagNumber >= 0 && tagNumber <= MAX_LOW_FIELD_TAG_NUM && @@ -351,7 +363,7 @@ public class TIFFDirectory implements Cloneable { * Adds a TIFF field to the directory. * * @param f The field to add. - * @throws NullPointerException if f is null. + * @throws NullPointerException if {@code f} is {@code null}. */ public void addTIFFField(TIFFField f) { if(f == null) { @@ -372,8 +384,8 @@ public class TIFFDirectory implements Cloneable { * Retrieves a TIFF field from the directory. * * @param tagNumber The tag number of the tag associated with the field. - * @return A TIFFField with the requested tag number of - * null if no such field is present. + * @return A {@code TIFFField} with the requested tag number of + * {@code null} if no such field is present. */ public TIFFField getTIFFField(int tagNumber) { TIFFField f; @@ -444,7 +456,7 @@ public class TIFFDirectory implements Cloneable { * Converts the directory to a metadata object. * * @return A metadata instance initialized from the contents of this - * TIFFDirectory. + * {@code TIFFDirectory}. */ public IIOMetadata getAsMetadata() { return new TIFFImageMetadata(getDirectoryAsIFD(this)); @@ -453,7 +465,7 @@ public class TIFFDirectory implements Cloneable { /** * Clones the directory and all the fields contained therein. * - * @return A clone of this TIFFDirectory. + * @return A clone of this {@code TIFFDirectory}. * @throws CloneNotSupportedException if the instance cannot be cloned. */ @Override diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java index 7afc44520f9..336f81550b7 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * *

    A field in a TIFF Image File Directory (IFD) is defined as a * tag number accompanied by a sequence of values of identical data type. - * TIFF 6.0 defines 12 data types; a 13th type IFD is + * TIFF 6.0 defines 12 data types; a 13th type {@code IFD} is * defined in TIFF Tech Note 1 of TIFF Specification Supplement 1. These * TIFF data types are referred to by Java constants and mapped internally * onto Java language data types and type names as follows: @@ -68,10 +68,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_BYTE} * * - * byte + * {@code byte} * * - * "Byte" + * {@code "Byte"} * * * @@ -83,10 +83,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_ASCII} * * - * String + * {@code String} * * - * "Ascii" + * {@code "Ascii"} * * * @@ -98,10 +98,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SHORT} * * - * char + * {@code char} * * - * "Short" + * {@code "Short"} * * * @@ -113,10 +113,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_LONG} * * - * long + * {@code long} * * - * "Long" + * {@code "Long"} * * * @@ -128,10 +128,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_RATIONAL} * * - * long[2] {numerator, denominator} + * {@code long[2]} {numerator, denominator} * * - * "Rational" + * {@code "Rational"} * * * @@ -143,10 +143,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SBYTE} * * - * byte + * {@code byte} * * - * "SByte" + * {@code "SByte"} * * * @@ -158,10 +158,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_UNDEFINED} * * - * byte + * {@code byte} * * - * "Undefined" + * {@code "Undefined"} * * * @@ -173,10 +173,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SSHORT} * * - * short + * {@code short} * * - * "SShort" + * {@code "SShort"} * * * @@ -188,10 +188,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SLONG} * * - * int + * {@code int} * * - * "SLong" + * {@code "SLong"} * * * @@ -203,10 +203,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_SRATIONAL} * * - * int[2] {numerator, denominator} + * {@code int[2]} {numerator, denominator} * * - * "SRational" + * {@code "SRational"} * * * @@ -218,10 +218,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_FLOAT} * * - * float + * {@code float} * * - * "Float" + * {@code "Float"} * * * @@ -233,10 +233,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_DOUBLE} * * - * double + * {@code double} * * - * "Double" + * {@code "Double"} * * * @@ -248,10 +248,10 @@ import com.sun.imageio.plugins.tiff.TIFFIFD; * {@link TIFFTag#TIFF_IFD_POINTER} * * - * long + * {@code long} * * - * "IFDPointer" + * {@code "IFDPointer"} * * * @@ -411,19 +411,19 @@ public class TIFFField implements Cloneable { } /** - * Creates a TIFFField from a TIFF native image + * Creates a {@code TIFFField} from a TIFF native image * metadata node. If the value of the "tagNumber" attribute - * of the node is not found in tagSet then a new - * TIFFTag with name TIFFTag.UNKNOWN_TAG_NAME + * of the node is not found in {@code tagSet} then a new + * {@code TIFFTag} with name {@code TIFFTag.UNKNOWN_TAG_NAME} * will be created and assigned to the field. * - * @param tagSet The TIFFTagSet to which the - * TIFFTag of the field belongs. - * @param node A native TIFF image metadata TIFFField node. - * @throws NullPointerException if node is - * null. + * @param tagSet The {@code TIFFTagSet} to which the + * {@code TIFFTag} of the field belongs. + * @param node A native TIFF image metadata {@code TIFFField} node. + * @throws NullPointerException if {@code node} is + * {@code null}. * @throws IllegalArgumentException if the name of the node is not - * "TIFFField". + * {@code "TIFFField"}. * @return A new {@code TIFFField}. */ public static TIFFField createFromMetadataNode(TIFFTagSet tagSet, @@ -487,14 +487,14 @@ public class TIFFField implements Cloneable { } /** - * Constructs a TIFFField with arbitrary data. The - * type parameter must be a value for which + * Constructs a {@code TIFFField} with arbitrary data. The + * {@code type} parameter must be a value for which * {@link TIFFTag#isDataTypeOK tag.isDataTypeOK()} - * returns true. The data parameter must + * returns {@code true}. The {@code data} parameter must * be an array of a Java type appropriate for the type of the TIFF * field. * - *

    Note that the value (data) of the TIFFField + *

    Note that the value (data) of the {@code TIFFField} * will always be the actual field value regardless of the number of * bytes required for that value. This is the case despite the fact * that the TIFF IFD Entry corresponding to the field may @@ -503,24 +503,29 @@ public class TIFFField implements Cloneable { * value fits into 4 bytes). In other words, the value of the * field will already have been read from the TIFF stream. (An exception * to this case may occur when the field represents the contents of a - * non-baseline IFD. In that case the data will be a long[] - * containing the offset to the IFD and the TIFFDirectory + * non-baseline IFD. In that case the data will be a {@code long[]} + * containing the offset to the IFD and the {@code TIFFDirectory} * returned by {@link #getDirectory()} will be its contents.) * * @param tag The tag to associated with this field. - * @param type One of the TIFFTag.TIFF_* constants + * @param type One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. * @param data The actual data content of the field. * - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if count < 0. - * @throws NullPointerException if data == null. - * @throws IllegalArgumentException if data is an instance of + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code count < 0}. + * @throws IllegalArgumentException if {@code count < 1} + * and {@code type} is {@code TIFF_RATIONAL} or + * {@code TIFF_SRATIONAL}. + * @throws IllegalArgumentException if {@code count ≠ 1} + * and {@code type} is {@code TIFF_IFD_POINTER}. + * @throws NullPointerException if {@code data == null}. + * @throws IllegalArgumentException if {@code data} is an instance of * a class incompatible with the specified type. * @throws IllegalArgumentException if the size of the data array is wrong. */ @@ -534,6 +539,14 @@ public class TIFFField implements Cloneable { + " for " + tag.getName() + " tag"); } else if(count < 0) { throw new IllegalArgumentException("count < 0!"); + } else if((type == TIFFTag.TIFF_RATIONAL + || type == TIFFTag.TIFF_SRATIONAL) + && count < 1) { + throw new IllegalArgumentException + ("Type is TIFF_RATIONAL or TIFF_SRATIONAL and count < 1"); + } else if (type == TIFFTag.TIFF_IFD_POINTER && count != 1) { + throw new IllegalArgumentException + ("Type is TIFF_IFD_POINTER count != 1"); } else if(data == null) { throw new NullPointerException("data == null!"); } @@ -612,15 +625,15 @@ public class TIFFField implements Cloneable { * parameters and the created array. * * @param tag The tag to associated with this field. - * @param type One of the TIFFTag.TIFF_* constants + * @param type One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @param count The number of data values. - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if count < 0. + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code count < 0}. * @see #TIFFField(TIFFTag,int,int,Object) */ public TIFFField(TIFFTag tag, int type, int count) { @@ -628,20 +641,20 @@ public class TIFFField implements Cloneable { } /** - * Constructs a TIFFField with a single non-negative integral + * Constructs a {@code TIFFField} with a single non-negative integral * value. * The field will have type * {@link TIFFTag#TIFF_SHORT TIFF_SHORT} if - * val < 65536 and type + * {@code val < 65536} and type * {@link TIFFTag#TIFF_LONG TIFF_LONG} otherwise. The count * of the field will be unity. * * @param tag The tag to associate with this field. * @param value The value to associate with this field. - * @throws NullPointerException if tag == null. + * @throws NullPointerException if {@code tag == null}. * @throws IllegalArgumentException if the derived type is unacceptable - * for the supplied TIFFTag. - * @throws IllegalArgumentException if value < 0. + * for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code value < 0}. */ public TIFFField(TIFFTag tag, int value) { if(tag == null) { @@ -677,24 +690,24 @@ public class TIFFField implements Cloneable { } /** - * Constructs a TIFFField with an IFD offset and contents. + * Constructs a {@code TIFFField} with an IFD offset and contents. * The offset will be stored as the data of this field as - * long[] {offset}. The directory will not be cloned. The count + * {@code long[] {offset}}. The directory will not be cloned. The count * of the field will be unity. * * @param tag The tag to associated with this field. - * @param type One of the constants TIFFTag.TIFF_LONG or - * TIFFTag.TIFF_IFD_POINTER. + * @param type One of the constants {@code TIFFTag.TIFF_LONG} or + * {@code TIFFTag.TIFF_IFD_POINTER}. * @param offset The IFD offset. * @param dir The directory. * - * @throws NullPointerException if tag == null. - * @throws IllegalArgumentException if type is neither - * TIFFTag.TIFF_LONG nor TIFFTag.TIFF_IFD_POINTER. - * @throws IllegalArgumentException if type is an unacceptable - * data type for the supplied TIFFTag. - * @throws IllegalArgumentException if offset is non-positive. - * @throws NullPointerException if dir == null. + * @throws NullPointerException if {@code tag == null}. + * @throws IllegalArgumentException if {@code type} is neither + * {@code TIFFTag.TIFF_LONG} nor {@code TIFFTag.TIFF_IFD_POINTER}. + * @throws IllegalArgumentException if {@code type} is an unacceptable + * data type for the supplied {@code TIFFTag}. + * @throws IllegalArgumentException if {@code offset} is non-positive. + * @throws NullPointerException if {@code dir == null}. * * @see #TIFFField(TIFFTag,int,int,Object) */ @@ -715,14 +728,14 @@ public class TIFFField implements Cloneable { /** * Retrieves the tag associated with this field. * - * @return The associated TIFFTag. + * @return The associated {@code TIFFTag}. */ public TIFFTag getTag() { return tag; } /** - * Retrieves the tag number in the range [0, 65535]. + * Retrieves the tag number in the range {@code [0, 65535]}. * * @return The tag number. */ @@ -732,7 +745,7 @@ public class TIFFField implements Cloneable { /** * Returns the type of the data stored in the field. For a TIFF 6.0 - * stream, the value will equal one of the TIFFTag.TIFF_* + * stream, the value will equal one of the {@code TIFFTag.TIFF_*} * constants. For future revisions of TIFF, higher values are possible. * * @return The data type of the field value. @@ -744,11 +757,11 @@ public class TIFFField implements Cloneable { /** * Returns the name of the supplied data type constant. * - * @param dataType One of the TIFFTag.TIFF_* constants + * @param dataType One of the {@code TIFFTag.TIFF_*} constants * indicating the data type of the field as written to the TIFF stream. * @return The type name corresponding to the supplied type constant. - * @throws IllegalArgumentException if dataType is not - * one of the TIFFTag.TIFF_* data type constants. + * @throws IllegalArgumentException if {@code dataType} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. */ public static String getTypeName(int dataType) { if (dataType < TIFFTag.MIN_DATATYPE || @@ -761,11 +774,11 @@ public class TIFFField implements Cloneable { /** * Returns the data type constant corresponding to the supplied data - * type name. If the name is unknown -1 will be returned. + * type name. If the name is unknown {@code -1} will be returned. * * @param typeName The type name. - * @return One of the TIFFTag.TIFF_* constants or - * -1 if the name is not recognized. + * @return One of the {@code TIFFTag.TIFF_*} constants or + * {@code -1} if the name is not recognized. */ public static int getTypeByName(String typeName) { for (int i = TIFFTag.MIN_DATATYPE; i <= TIFFTag.MAX_DATATYPE; i++) { @@ -780,14 +793,14 @@ public class TIFFField implements Cloneable { /** * Creates an array appropriate for the indicated data type. * - * @param dataType One of the TIFFTag.TIFF_* data type + * @param dataType One of the {@code TIFFTag.TIFF_*} data type * constants. * @param count The number of values in the array. * @return An array appropriate for the specified data type. * - * @throws IllegalArgumentException if dataType is not - * one of the TIFFTag.TIFF_* data type constants. - * @throws IllegalArgumentException if count < 0. + * @throws IllegalArgumentException if {@code dataType} is not + * one of the {@code TIFFTag.TIFF_*} data type constants. + * @throws IllegalArgumentException if {@code count < 0}. */ public static Object createArrayForType(int dataType, int count) { if(count < 0) { @@ -823,15 +836,15 @@ public class TIFFField implements Cloneable { } /** - * Returns the TIFFField as a node named either + * Returns the {@code TIFFField} as a node named either * "TIFFField" or "TIFFIFD" as described in the * TIFF native image metadata specification. The node will be named * "TIFFIFD" if and only if the field's data object is an * instance of {@link TIFFDirectory} or equivalently * {@link TIFFTag#isIFDPointer getTag.isIFDPointer()} returns - * true. + * {@code true}. * - * @return a Node named "TIFFField" or + * @return a {@code Node} named "TIFFField" or * "TIFFIFD". */ public Node getAsNativeNode() { @@ -850,8 +863,8 @@ public class TIFFField implements Cloneable { /** * Returns the number of data items present in the field. For - * TIFFTag.TIFF_ASCII fields, the value returned is the - * number of Strings, not the total length of the + * {@code TIFFTag.TIFF_ASCII} fields, the value returned is the + * number of {@code String}s, not the total length of the * data as in the file representation. * * @return The number of data items present in the field. @@ -871,17 +884,17 @@ public class TIFFField implements Cloneable { /** * Returns the data as an uninterpreted array of - * bytes. The type of the field must be one of - * TIFFTag.TIFF_BYTE, TIFF_SBYTE, or - * TIFF_UNDEFINED. + * {@code byte}s. The type of the field must be one of + * {@code TIFFTag.TIFF_BYTE}, {@code TIFF_SBYTE}, or + * {@code TIFF_UNDEFINED}. * - *

    For data in TIFFTag.TIFF_BYTE format, the application + *

    For data in {@code TIFFTag.TIFF_BYTE} format, the application * must take care when promoting the data to longer integral types * to avoid sign extension. * * @throws ClassCastException if the field is not of type - * TIFF_BYTE, TIFF_SBYTE, or - * TIFF_UNDEFINED. + * {@code TIFF_BYTE}, {@code TIFF_SBYTE}, or + * {@code TIFF_UNDEFINED}. * @return The data as an uninterpreted array of bytes. */ public byte[] getAsBytes() { @@ -889,11 +902,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SHORT data as an array of - * chars (unsigned 16-bit integers). + * Returns {@code TIFFTag.TIFF_SHORT} data as an array of + * {@code char}s (unsigned 16-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SHORT. + * {@code TIFF_SHORT}. * @return The data as an array of {@code char}s. */ public char[] getAsChars() { @@ -901,11 +914,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SSHORT data as an array of - * shorts (signed 16-bit integers). + * Returns {@code TIFFTag.TIFF_SSHORT} data as an array of + * {@code short}s (signed 16-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SSHORT. + * {@code TIFF_SSHORT}. * @return The data as an array of {@code short}s. */ public short[] getAsShorts() { @@ -913,12 +926,12 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SLONG data as an array of - * ints (signed 32-bit integers). + * Returns {@code TIFFTag.TIFF_SLONG} data as an array of + * {@code int}s (signed 32-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_SHORT, TIFF_SSHORT, or - * TIFF_SLONG. + * {@code TIFF_SHORT}, {@code TIFF_SSHORT}, or + * {@code TIFF_SLONG}. * @return The data as an array of {@code int}s. */ public int[] getAsInts() { @@ -944,12 +957,12 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_LONG or - * TIFF_IFD_POINTER data as an array of - * longs (signed 64-bit integers). + * Returns {@code TIFFTag.TIFF_LONG} or + * {@code TIFF_IFD_POINTER} data as an array of + * {@code long}s (signed 64-bit integers). * * @throws ClassCastException if the field is not of type - * TIFF_LONG or TIFF_IFD_POINTER. + * {@code TIFF_LONG} or {@code TIFF_IFD_POINTER}. * @return The data as an array of {@code long}s. */ public long[] getAsLongs() { @@ -957,11 +970,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_FLOAT data as an array of - * floats (32-bit floating-point values). + * Returns {@code TIFFTag.TIFF_FLOAT} data as an array of + * {@code float}s (32-bit floating-point values). * * @throws ClassCastException if the field is not of type - * TIFF_FLOAT. + * {@code TIFF_FLOAT}. * @return The data as an array of {@code float}s. */ public float[] getAsFloats() { @@ -969,11 +982,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_DOUBLE data as an array of - * doubles (64-bit floating-point values). + * Returns {@code TIFFTag.TIFF_DOUBLE} data as an array of + * {@code double}s (64-bit floating-point values). * * @throws ClassCastException if the field is not of type - * TIFF_DOUBLE. + * {@code TIFF_DOUBLE}. * @return The data as an array of {@code double}s. */ public double[] getAsDoubles() { @@ -981,11 +994,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_SRATIONAL data as an array of - * 2-element arrays of ints. + * Returns {@code TIFFTag.TIFF_SRATIONAL} data as an array of + * 2-element arrays of {@code int}s. * * @throws ClassCastException if the field is not of type - * TIFF_SRATIONAL. + * {@code TIFF_SRATIONAL}. * @return The data as an array of signed rationals. */ public int[][] getAsSRationals() { @@ -993,11 +1006,11 @@ public class TIFFField implements Cloneable { } /** - * Returns TIFFTag.TIFF_RATIONAL data as an array of - * 2-element arrays of longs. + * Returns {@code TIFFTag.TIFF_RATIONAL} data as an array of + * 2-element arrays of {@code long}s. * * @throws ClassCastException if the field is not of type - * TIFF_RATIONAL. + * {@code TIFF_RATIONAL}. * @return The data as an array of unsigned rationals. */ public long[][] getAsRationals() { @@ -1005,30 +1018,30 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as an int. + * Returns data in any format as an {@code int}. * - *

    TIFFTag.TIFF_BYTE values are treated as unsigned; that + *

    {@code TIFFTag.TIFF_BYTE} values are treated as unsigned; that * is, no sign extension will take place and the returned value - * will be in the range [0, 255]. TIFF_SBYTE data + * will be in the range [0, 255]. {@code TIFF_SBYTE} data * will be returned in the range [-128, 127]. * - *

    A TIFF_UNDEFINED value is treated as though - * it were a TIFF_BYTE. + *

    A {@code TIFF_UNDEFINED} value is treated as though + * it were a {@code TIFF_BYTE}. * - *

    Data in TIFF_SLONG, TIFF_LONG, - * TIFF_FLOAT, TIFF_DOUBLE or - * TIFF_IFD_POINTER format are simply cast to - * int and may suffer from truncation. + *

    Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, + * {@code TIFF_FLOAT}, {@code TIFF_DOUBLE} or + * {@code TIFF_IFD_POINTER} format are simply cast to + * {@code int} and may suffer from truncation. * - *

    Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

    Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision - * arithmetic and then casting to int. Loss of + * arithmetic and then casting to {@code int}. Loss of * precision and truncation may occur. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * case to int. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * case to {@code int}. * * @param index The index of the data. * @return The data at the given index as an {@code int}. @@ -1068,17 +1081,17 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as a long. + * Returns data in any format as a {@code long}. * - *

    TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

    {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * cast to long. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * cast to {@code long}. * * @param index The index of the data. * @return The data at the given index as a {@code long}. @@ -1114,27 +1127,27 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as a float. + * Returns data in any format as a {@code float}. * - *

    TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

    {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

    Data in TIFF_SLONG, TIFF_LONG, - * TIFF_DOUBLE, or TIFF_IFD_POINTER format are - * simply cast to float and may suffer from + *

    Data in {@code TIFF_SLONG}, {@code TIFF_LONG}, + * {@code TIFF_DOUBLE}, or {@code TIFF_IFD_POINTER} format are + * simply cast to {@code float} and may suffer from * truncation. * - *

    Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

    Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision - * arithmetic and then casting to float. + * arithmetic and then casting to {@code float}. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method, with the result - * cast to float. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method, with the result + * cast to {@code float}. * * @param index The index of the data. * @return The data at the given index as a {@code float}. @@ -1174,21 +1187,21 @@ public class TIFFField implements Cloneable { } /** - * Returns data in any format as a double. + * Returns data in any format as a {@code double}. * - *

    TIFFTag.TIFF_BYTE and TIFF_UNDEFINED data + *

    {@code TIFFTag.TIFF_BYTE} and {@code TIFF_UNDEFINED} data * are treated as unsigned; that is, no sign extension will take * place and the returned value will be in the range [0, 255]. - * TIFF_SBYTE data will be returned in the range + * {@code TIFF_SBYTE} data will be returned in the range * [-128, 127]. * - *

    Data in TIFF_SRATIONAL or - * TIFF_RATIONAL format are evaluated by dividing the + *

    Data in {@code TIFF_SRATIONAL} or + * {@code TIFF_RATIONAL} format are evaluated by dividing the * numerator into the denominator using double-precision * arithmetic. * - *

    Data in TIFF_ASCII format will be parsed as by - * the Double.parseDouble method. + *

    Data in {@code TIFF_ASCII} format will be parsed as by + * the {@code Double.parseDouble} method. * * @param index The index of the data. * @return The data at the given index as a {@code double}. @@ -1228,11 +1241,11 @@ public class TIFFField implements Cloneable { } /** - * Returns a TIFFTag.TIFF_ASCII value as a - * String. + * Returns a {@code TIFFTag.TIFF_ASCII} value as a + * {@code String}. * * @throws ClassCastException if the field is not of type - * TIFF_ASCII. + * {@code TIFF_ASCII}. * * @param index The index of the data. * @return The data at the given index as a {@code String}. @@ -1242,13 +1255,13 @@ public class TIFFField implements Cloneable { } /** - * Returns a TIFFTag.TIFF_SRATIONAL data item as a - * two-element array of ints. + * Returns a {@code TIFFTag.TIFF_SRATIONAL} data item as a + * two-element array of {@code int}s. * * @param index The index of the data. * @return The data at the given index as a signed rational. * @throws ClassCastException if the field is not of type - * TIFF_SRATIONAL. + * {@code TIFF_SRATIONAL}. */ public int[] getAsSRational(int index) { return ((int[][])data)[index]; @@ -1261,7 +1274,7 @@ public class TIFFField implements Cloneable { * @param index The index of the data. * @return The data at the given index as an unsigned rational. * @throws ClassCastException if the field is not of type - * TIFF_RATIONAL. + * {@code TIFF_RATIONAL}. */ public long[] getAsRational(int index) { return ((long[][])data)[index]; @@ -1269,11 +1282,11 @@ public class TIFFField implements Cloneable { /** - * Returns a String containing a human-readable + * Returns a {@code String} containing a human-readable * version of the data item. Data of type - * TIFFTag.TIFF_RATIONAL or TIFF_SRATIONAL are + * {@code TIFFTag.TIFF_RATIONAL} or {@code TIFF_SRATIONAL} are * represented as a pair of integers separated by a - * '/' character. + * {@code '/'} character. * * @param index The index of the data. * @return The data at the given index as a {@code String}. @@ -1342,7 +1355,7 @@ public class TIFFField implements Cloneable { } /** - * Returns whether the field has a TIFFDirectory. + * Returns whether the field has a {@code TIFFDirectory}. * * @return true if and only if getDirectory() returns non-null. */ @@ -1351,8 +1364,8 @@ public class TIFFField implements Cloneable { } /** - * Returns the associated TIFFDirectory, if available. If no - * directory is set, then null will be returned. + * Returns the associated {@code TIFFDirectory}, if available. If no + * directory is set, then {@code null} will be returned. * * @return the TIFFDirectory instance or null. */ @@ -1363,7 +1376,7 @@ public class TIFFField implements Cloneable { /** * Clones the field and all the information contained therein. * - * @return A clone of this TIFFField. + * @return A clone of this {@code TIFFField}. * @throws CloneNotSupportedException if the instance cannot be cloned. */ @Override diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java index 27f633c7cfd..9c120d094ef 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFImageReadParam.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,11 +39,11 @@ import javax.imageio.ImageReadParam; * be provided by this interface. * *

    Additional TIFF tags must be organized into - * TIFFTagSets. A TIFFTagSet may be + * {@code TIFFTagSet}s. A {@code TIFFTagSet} may be * provided to the reader by means of the - * addAllowedTagSet method. By default, the tag sets - * BaselineTIFFTagSet, FaxTIFFTagSet, - * ExifParentTIFFTagSet, and GeoTIFFTagSet + * {@code addAllowedTagSet} method. By default, the tag sets + * {@code BaselineTIFFTagSet}, {@code FaxTIFFTagSet}, + * {@code ExifParentTIFFTagSet}, and {@code GeoTIFFTagSet} * are included. * * @since 9 @@ -53,10 +53,10 @@ public class TIFFImageReadParam extends ImageReadParam { private List allowedTagSets = new ArrayList(4); /** - * Constructs a TIFFImageReadParam. Tags defined by - * the TIFFTagSets BaselineTIFFTagSet, - * FaxTIFFTagSet, ExifParentTIFFTagSet, and - * GeoTIFFTagSet will be supported. + * Constructs a {@code TIFFImageReadParam}. Tags defined by + * the {@code TIFFTagSet}s {@code BaselineTIFFTagSet}, + * {@code FaxTIFFTagSet}, {@code ExifParentTIFFTagSet}, and + * {@code GeoTIFFTagSet} will be supported. * * @see BaselineTIFFTagSet * @see FaxTIFFTagSet @@ -71,13 +71,13 @@ public class TIFFImageReadParam extends ImageReadParam { } /** - * Adds a TIFFTagSet object to the list of allowed + * Adds a {@code TIFFTagSet} object to the list of allowed * tag sets. * - * @param tagSet a TIFFTagSet. + * @param tagSet a {@code TIFFTagSet}. * - * @throws IllegalArgumentException if tagSet is - * null. + * @throws IllegalArgumentException if {@code tagSet} is + * {@code null}. */ public void addAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { @@ -87,15 +87,15 @@ public class TIFFImageReadParam extends ImageReadParam { } /** - * Removes a TIFFTagSet object from the list of - * allowed tag sets. Removal is based on the equals - * method of the TIFFTagSet, which is normally + * Removes a {@code TIFFTagSet} object from the list of + * allowed tag sets. Removal is based on the {@code equals} + * method of the {@code TIFFTagSet}, which is normally * defined as reference equality. * - * @param tagSet a TIFFTagSet. + * @param tagSet a {@code TIFFTagSet}. * - * @throws IllegalArgumentException if tagSet is - * null. + * @throws IllegalArgumentException if {@code tagSet} is + * {@code null}. */ public void removeAllowedTagSet(TIFFTagSet tagSet) { if (tagSet == null) { @@ -105,10 +105,10 @@ public class TIFFImageReadParam extends ImageReadParam { } /** - * Returns a List containing the allowed - * TIFFTagSet objects. + * Returns a {@code List} containing the allowed + * {@code TIFFTagSet} objects. * - * @return a List of TIFFTagSets. + * @return a {@code List} of {@code TIFFTagSet}s. */ public List getAllowedTagSets() { return allowedTagSets; diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java index 68542c4078d..c312bd55419 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,7 +105,7 @@ public class TIFFTag { * The name assigned to a tag with an unknown tag number. Such * a tag may be created for example when reading an IFD and a * tag number is encountered which is not in any of the - * TIFFTagSets known to the reader. + * {@code TIFFTagSet}s known to the reader. */ public static final String UNKNOWN_TAG_NAME = "UnknownTag"; @@ -141,12 +141,12 @@ public class TIFFTag { private SortedMap valueNames = null; /** - * Constructs a TIFFTag with a given name, tag number, set + * Constructs a {@code TIFFTag} with a given name, tag number, set * of legal data types, and value count. A negative value count signifies * that either an arbitrary number of values is legal or the required count * is determined by the values of other fields in the IFD. A non-negative * count specifies the number of values which an associated field must - * contain. The tag will have no associated TIFFTagSet. + * contain. The tag will have no associated {@code TIFFTagSet}. * *

    If there are mnemonic names to be associated with the legal * data values for the tag, {@link #addValueName(int, String) @@ -183,18 +183,18 @@ public class TIFFTag { } /** - * Constructs a TIFFTag with a given name, tag number and - * TIFFTagSet to which it refers. The legal data types are + * Constructs a {@code TIFFTag} with a given name, tag number and + * {@code TIFFTagSet} to which it refers. The legal data types are * set to include {@link #TIFF_LONG} and {@link #TIFF_IFD_POINTER} and the - * value count is unity. The TIFFTagSet will - * represent the set of TIFFTags which appear in the IFD - * pointed to. A TIFFTag represents an IFD pointer if and - * only if tagSet is non-null or the data - * type TIFF_IFD_POINTER is legal. + * value count is unity. The {@code TIFFTagSet} will + * represent the set of {@code TIFFTag}s which appear in the IFD + * pointed to. A {@code TIFFTag} represents an IFD pointer if and + * only if {@code tagSet} is non-{@code null} or the data + * type {@code TIFF_IFD_POINTER} is legal. * * @param name the name of the tag. * @param number the number used to represent the tag. - * @param tagSet the TIFFTagSet to which this tag belongs. + * @param tagSet the {@code TIFFTagSet} to which this tag belongs. * @throws NullPointerException if name or tagSet is null. * @throws IllegalArgumentException if number is negative. * @@ -210,9 +210,9 @@ public class TIFFTag { } /** - * Constructs a TIFFTag with a given name, tag number, + * Constructs a {@code TIFFTag} with a given name, tag number, * and set of legal data types. The value count of the tag will be - * undefined and it will have no associated TIFFTagSet. + * undefined and it will have no associated {@code TIFFTagSet}. * * @param name the name of the tag. * @param number the number used to represent the tag. @@ -236,9 +236,9 @@ public class TIFFTag { * * @return the number of bytes used to store the given data type. * - * @throws IllegalArgumentException if datatype is - * less than MIN_DATATYPE or greater than - * MAX_DATATYPE. + * @throws IllegalArgumentException if {@code datatype} is + * less than {@code MIN_DATATYPE} or greater than + * {@code MAX_DATATYPE}. */ public static int getSizeOfType(int dataType) { if (dataType < MIN_DATATYPE ||dataType > MAX_DATATYPE) { @@ -251,7 +251,7 @@ public class TIFFTag { /** * Returns the name of the tag, as it will appear in image metadata. * - * @return the tag name, as a String. + * @return the tag name, as a {@code String}. */ public String getName() { return name; @@ -260,7 +260,7 @@ public class TIFFTag { /** * Returns the integer used to represent the tag. * - * @return the tag number, as an int. + * @return the tag number, as an {@code int}. */ public int getNumber() { return number; @@ -276,7 +276,7 @@ public class TIFFTag { * (1 << TIFFTag.TIFF_SHORT) | (1 << TIFFTag.TIFF_LONG) * * - * @return an int containing a bitmask encoding the + * @return an {@code int} containing a bitmask encoding the * set of valid data types. */ public int getDataTypes() { @@ -285,11 +285,11 @@ public class TIFFTag { /** * Returns the value count of this tag. If this value is positive, it - * represents the required number of values for a TIFFField + * represents the required number of values for a {@code TIFFField} * which has this tag. If the value is negative, the count is undefined. * In the latter case the count may be derived, e.g., the number of values - * of the BitsPerSample field is SamplesPerPixel, - * or it may be variable as in the case of most US-ASCII + * of the {@code BitsPerSample} field is {@code SamplesPerPixel}, + * or it may be variable as in the case of most {@code US-ASCII} * fields. * * @return the value count of this tag. @@ -299,18 +299,18 @@ public class TIFFTag { } /** - * Returns true if the given data type + * Returns {@code true} if the given data type * may be used for the data associated with this tag. * * @param dataType the data type to be queried, one of - * TIFF_BYTE, TIFF_SHORT, etc. + * {@code TIFF_BYTE}, {@code TIFF_SHORT}, etc. * - * @return a boolean indicating whether the given + * @return a {@code boolean} indicating whether the given * data type may be used with this tag. * - * @throws IllegalArgumentException if datatype is - * less than MIN_DATATYPE or greater than - * MAX_DATATYPE. + * @throws IllegalArgumentException if {@code datatype} is + * less than {@code MIN_DATATYPE} or greater than + * {@code MAX_DATATYPE}. */ public boolean isDataTypeOK(int dataType) { if (dataType < MIN_DATATYPE || dataType > MAX_DATATYPE) { @@ -320,38 +320,38 @@ public class TIFFTag { } /** - * Returns the TIFFTagSet of which this tag is a part. + * Returns the {@code TIFFTagSet} of which this tag is a part. * - * @return the containing TIFFTagSet. + * @return the containing {@code TIFFTagSet}. */ public TIFFTagSet getTagSet() { return tagSet; } /** - * Returns true if this tag is used to point to an IFD - * structure containing additional tags. A TIFFTag represents - * an IFD pointer if and only if its TIFFTagSet is - * non-null or the data type TIFF_IFD_POINTER is + * Returns {@code true} if this tag is used to point to an IFD + * structure containing additional tags. A {@code TIFFTag} represents + * an IFD pointer if and only if its {@code TIFFTagSet} is + * non-{@code null} or the data type {@code TIFF_IFD_POINTER} is * legal. This condition will be satisfied if and only if either - * getTagSet() != null or - * isDataTypeOK(TIFF_IFD_POINTER) == true. + * {@code getTagSet() != null} or + * {@code isDataTypeOK(TIFF_IFD_POINTER) == true}. * *

    Many TIFF extensions use the IFD mechanism in order to limit the * number of new tags that may appear in the root IFD.

    * - * @return true if this tag points to an IFD. + * @return {@code true} if this tag points to an IFD. */ public boolean isIFDPointer() { return tagSet != null || isDataTypeOK(TIFF_IFD_POINTER); } /** - * Returns true if there are mnemonic names associated with + * Returns {@code true} if there are mnemonic names associated with * the set of legal values for the data associated with this tag. Mnemonic * names apply only to tags which have integral data type. * - * @return true if mnemonic value names are available. + * @return {@code true} if mnemonic value names are available. */ public boolean hasValueNames() { return valueNames != null; @@ -373,14 +373,14 @@ public class TIFFTag { /** * Returns the mnemonic name associated with a particular value - * that this tag's data may take on, or null if + * that this tag's data may take on, or {@code null} if * no name is present. Mnemonic names apply only to tags which have * integral data type. * * @param value the data value. * * @return the mnemonic name associated with the value, as a - * String. + * {@code String}. */ public String getValueName(int value) { if (valueNames == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java index 8082fba86b8..793bafce1b7 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/plugins/tiff/TIFFTagSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,7 +39,7 @@ import java.util.TreeSet; * specification itself). * *

    This class and its subclasses are responsible for mapping - * between raw tag numbers and TIFFTag objects, which + * between raw tag numbers and {@code TIFFTag} objects, which * contain additional information about each tag, such as the tag's * name, legal data types, and mnemonic names for some or all of ts * data values. @@ -59,15 +59,15 @@ public class TIFFTagSet { private TIFFTagSet() {} /** - * Constructs a TIFFTagSet, given a List - * of TIFFTag objects. + * Constructs a {@code TIFFTagSet}, given a {@code List} + * of {@code TIFFTag} objects. * - * @param tags a List object containing - * TIFFTag objects to be added to this tag set. + * @param tags a {@code List} object containing + * {@code TIFFTag} objects to be added to this tag set. * - * @throws IllegalArgumentException if tags is - * null, or contains objects that are not instances - * of the TIFFTag class. + * @throws IllegalArgumentException if {@code tags} is + * {@code null}, or contains objects that are not instances + * of the {@code TIFFTag} class. */ public TIFFTagSet(List tags) { if (tags == null) { @@ -88,29 +88,29 @@ public class TIFFTagSet { } /** - * Returns the TIFFTag from this set that is - * associated with the given tag number, or null if + * Returns the {@code TIFFTag} from this set that is + * associated with the given tag number, or {@code null} if * no tag exists for that number. * * @param tagNumber the number of the tag to be retrieved. * - * @return the numbered TIFFTag, or null. + * @return the numbered {@code TIFFTag}, or {@code null}. */ public TIFFTag getTag(int tagNumber) { return allowedTagsByNumber.get(Integer.valueOf(tagNumber)); } /** - * Returns the TIFFTag having the given tag name, or - * null if the named tag does not belong to this tag set. + * Returns the {@code TIFFTag} having the given tag name, or + * {@code null} if the named tag does not belong to this tag set. * * @param tagName the name of the tag to be retrieved, as a - * String. + * {@code String}. * - * @return the named TIFFTag, or null. + * @return the named {@code TIFFTag}, or {@code null}. * - * @throws IllegalArgumentException if tagName is - * null. + * @throws IllegalArgumentException if {@code tagName} is + * {@code null}. */ public TIFFTag getTag(String tagName) { if (tagName == null) { @@ -123,7 +123,7 @@ public class TIFFTagSet { * Retrieves an unmodifiable numerically increasing set of tag numbers. * *

    The returned object is unmodifiable and contains the tag - * numbers of all TIFFTags in this TIFFTagSet + * numbers of all {@code TIFFTag}s in this {@code TIFFTagSet} * sorted into ascending order according to * {@link Integer#compareTo(Object)}.

    * @@ -145,7 +145,7 @@ public class TIFFTagSet { * Retrieves an unmodifiable lexicographically increasing set of tag names. * *

    The returned object is unmodifiable and contains the tag - * names of all TIFFTags in this TIFFTagSet + * names of all {@code TIFFTag}s in this {@code TIFFTagSet} * sorted into ascending order according to * {@link String#compareTo(Object)}.

    * diff --git a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java index 520d508c3b5..fede6e1b85c 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java +++ b/jdk/src/java.desktop/share/classes/javax/print/ServiceUI.java @@ -193,36 +193,48 @@ public class ServiceUI { getLocalGraphicsEnvironment().getDefaultScreenDevice(). getDefaultConfiguration().getBounds() : gc.getBounds(); + x += gcBounds.x; + y += gcBounds.y; ServiceDialog dialog; if (owner instanceof Frame) { dialog = new ServiceDialog(gc, - x + gcBounds.x, - y + gcBounds.y, + x, + y, services, defaultIndex, flavor, attributes, (Frame)owner); } else { dialog = new ServiceDialog(gc, - x + gcBounds.x, - y + gcBounds.y, + x, + y, services, defaultIndex, flavor, attributes, (Dialog)owner); } Rectangle dlgBounds = dialog.getBounds(); - // get union of all GC bounds - GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); - GraphicsDevice[] gs = ge.getScreenDevices(); - for (int j=0; j gcBounds.x + gcBounds.width) { + if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) { + x = (gcBounds.x + gcBounds.width) - dlgBounds.width; + } else { + x = gcBounds.x; + } + } + if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) { + if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) { + y = (gcBounds.y + gcBounds.height) - dlgBounds.height; + } else { + y = gcBounds.y; + } + } + dialog.setBounds(x, y, dlgBounds.width, dlgBounds.height); } dialog.show(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java index 18f30579f4e..74778d50267 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/DefaultDesktopManager.java @@ -191,12 +191,6 @@ public class DefaultDesktopManager implements DesktopManager, java.io.Serializab JLayeredPane.putLayer(desktopIcon, layer); } - // If we are maximized we already have the normal bounds recorded - // don't try to re-record them, otherwise we incorrectly set the - // normal bounds to maximized state. - if (!f.isMaximum()) { - f.setNormalBounds(f.getBounds()); - } if (findNext) { if (d.selectFrame(true) == null) { // The icon is the last frame. diff --git a/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java b/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java index bbc35bf9c1d..e573cf6f6af 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/filechooser/FileSystemView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -583,6 +583,69 @@ public abstract class FileSystemView { } } + /** + * Returns an array of files representing the values to show by default in + * the file chooser selector. + * + * @return an array of {@code File} objects. + * @throws SecurityException if the caller does not have necessary + * permissions + * @since 9 + */ + public File[] getChooserComboBoxFiles() { + return (File[]) ShellFolder.get("fileChooserComboBoxFolders"); + } + + /** + * Returns whether the specified file denotes a shell interpreted link which + * can be obtained by the {@link #getLinkLocation(File)}. + * + * @param file a file + * @return whether this is a link + * @throws NullPointerException if {@code file} equals {@code null} + * @throws SecurityException if the caller does not have necessary + * permissions + * @see #getLinkLocation(File) + * @since 9 + */ + public boolean isLink(File file) { + if (file == null) { + throw new NullPointerException("file is null"); + } + try { + return ShellFolder.getShellFolder(file).isLink(); + } catch (FileNotFoundException e) { + return false; + } + } + + /** + * Returns the regular file referenced by the specified link file if + * the specified file is a shell interpreted link. + * Returns {@code null} if the specified file is not + * a shell interpreted link. + * + * @param file a file + * @return the linked file or {@code null}. + * @throws FileNotFoundException if the linked file does not exist + * @throws NullPointerException if {@code file} equals {@code null} + * @throws SecurityException if the caller does not have necessary + * permissions + * @since 9 + */ + public File getLinkLocation(File file) throws FileNotFoundException { + if (file == null) { + throw new NullPointerException("file is null"); + } + ShellFolder shellFolder; + try { + shellFolder = ShellFolder.getShellFolder(file); + } catch (FileNotFoundException e) { + return null; + } + return shellFolder.isLink() ? shellFolder.getLinkLocation() : null; + } + /** * Throws {@code FileNotFoundException} if file not found or current thread was interrupted */ diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java index a9b0b80e444..2a3df571977 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -962,18 +962,13 @@ public class BasicScrollPaneUI int orientation = SwingConstants.VERTICAL; // find which scrollbar to scroll, or return if none - if (toScroll == null || !toScroll.isVisible()) { + if (toScroll == null || !toScroll.isVisible() + || e.isShiftDown()) { toScroll = scrollpane.getHorizontalScrollBar(); if (toScroll == null || !toScroll.isVisible()) { return; } orientation = SwingConstants.HORIZONTAL; - } else if(e.isShiftDown()){ - JScrollBar hScroll = scrollpane.getHorizontalScrollBar(); - if (hScroll != null && hScroll.isVisible()) { - toScroll = hScroll; - orientation = SwingConstants.HORIZONTAL; - } } e.consume(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java index b22941c8f6f..f7b370eb35b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthDesktopPaneUI.java @@ -362,9 +362,6 @@ public class SynthDesktopPaneUI extends BasicDesktopPaneUI implements setWasIcon(f, Boolean.TRUE); } - if (!f.isMaximum()) { - f.setNormalBounds(f.getBounds()); - } c.remove(f); c.repaint(f.getX(), f.getY(), f.getWidth(), f.getHeight()); try { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java index 904172fa049..16272ffa819 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthTableHeaderUI.java @@ -230,9 +230,10 @@ public class SynthTableHeaderUI extends BasicTableHeaderUI boolean hasRollover = (column == getRolloverColumn()); if (isSelected || hasRollover || hasFocus) { + boolean enabled = (table == null)? true : table.isEnabled(); SynthLookAndFeel.setSelectedUI((SynthLabelUI)SynthLookAndFeel. getUIOfType(getUI(), SynthLabelUI.class), - isSelected, hasFocus, table.isEnabled(), + isSelected, hasFocus, enabled, hasRollover); } else { SynthLookAndFeel.resetSelectedUI(); diff --git a/jdk/src/java.desktop/share/classes/sun/applet/Main.java b/jdk/src/java.desktop/share/classes/sun/applet/Main.java index 681fb81c6db..086b1113614 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/Main.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/Main.java @@ -30,8 +30,6 @@ import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; import java.net.URL; import java.net.MalformedURLException; import java.util.Enumeration; @@ -75,7 +73,6 @@ public class Main { /** * Member variables set according to options passed in to AppletViewer. */ - private boolean debugFlag = false; private boolean helpFlag = false; private String encoding = null; private boolean noSecurityFlag = false; @@ -136,14 +133,6 @@ public class Main { return 1; } - if (debugFlag) { - // START A DEBUG SESSION - // Given the current architecture, we will end up decoding the - // arguments again, but at least we are guaranteed to have - // arguments which are valid. - return invokeDebugger(args); - } - // INSTALL THE SECURITY MANAGER (if necessary) if (!noSecurityFlag && (System.getSecurityManager() == null)) init(); @@ -191,9 +180,6 @@ public class Main { throw new ParseException(lookup("main.err.dupoption", arg)); encoding = args[++i]; return 2; - } else if ("-debug".equals(arg)) { - debugFlag = true; - return 1; } else if ("-Xnosecurity".equals(arg)) { // This is an undocumented (and, in the future, unsupported) // flag which prevents AppletViewer from installing its own @@ -267,68 +253,6 @@ public class Main { return u; } - /** - * Invoke the debugger with the arguments passed in to appletviewer. - * - * @param args The arguments passed into the debugger. - * @return {@code 0} if the debugger is invoked successfully, - * {@code 1} otherwise. - */ - private int invokeDebugger(String [] args) { - // CONSTRUCT THE COMMAND LINE - String [] newArgs = new String[args.length + 1]; - int current = 0; - - // Add a -classpath argument that prevents - // the debugger from launching appletviewer with the default of - // ".". appletviewer's classpath should never contain valid - // classes since they will result in security exceptions. - // Ideally, the classpath should be set to "", but the VM won't - // allow an empty classpath, so a phony directory name is used. - String phonyDir = System.getProperty("java.home") + - File.separator + "phony"; - newArgs[current++] = "-Djava.class.path=" + phonyDir; - - // Appletviewer's main class is the debuggee - newArgs[current++] = "sun.applet.Main"; - - // Append all the of the original appletviewer arguments, - // leaving out the "-debug" option. - for (int i = 0; i < args.length; i++) { - if (!("-debug".equals(args[i]))) { - newArgs[current++] = args[i]; - } - } - - // LAUNCH THE DEBUGGER - // Reflection is used for two reasons: - // 1) The debugger classes are on classpath and thus must be loaded - // by the application class loader. (Currently, appletviewer are - // loaded through the boot class path out of rt.jar.) - // 2) Reflection removes any build dependency between appletviewer - // and jdb. - try { - Class c = Class.forName("com.sun.tools.example.debug.tty.TTY", true, - ClassLoader.getSystemClassLoader()); - Method m = c.getDeclaredMethod("main", - new Class[] { String[].class }); - m.invoke(null, new Object[] { newArgs }); - } catch (ClassNotFoundException cnfe) { - System.err.println(lookup("main.debug.cantfinddebug")); - return 1; - } catch (NoSuchMethodException nsme) { - System.err.println(lookup("main.debug.cantfindmain")); - return 1; - } catch (InvocationTargetException ite) { - System.err.println(lookup("main.debug.exceptionindebug")); - return 1; - } catch (IllegalAccessException iae) { - System.err.println(lookup("main.debug.cantaccess")); - return 1; - } - return 0; - } - private void init() { // GET APPLETVIEWER USER-SPECIFIC PROPERTIES Properties avProps = getAVProps(); diff --git a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java index f05729b972e..2b2bf2de74f 100644 --- a/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java +++ b/jdk/src/java.desktop/share/classes/sun/applet/resources/MsgAppletViewer.java @@ -74,7 +74,7 @@ public class MsgAppletViewer extends ListResourceBundle { {"appletviewer.parse.warning.embed.requireswidth", "Warning: tag requires width attribute."}, {"appletviewer.parse.warning.appnotLongersupported", "Warning: tag no longer supported, use instead:"}, {"appletviewer.deprecated", "AppletViewer is deprecated."}, - {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -debug Start the applet viewer in the Java debugger\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, + {"appletviewer.usage", "Usage: appletviewer url(s)\n\nwhere include:\n -encoding Specify character encoding used by HTML files\n -J Pass argument to the java interpreter\n\nThe -J option is non-standard and subject to change without notice."}, {"appletviewer.main.err.unsupportedopt", "Unsupported option: {0}"}, {"appletviewer.main.err.unrecognizedarg", "Unrecognized argument: {0}"}, {"appletviewer.main.err.dupoption", "Duplicate use of option: {0}"}, diff --git a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java index 1e054b9de81..c034dbebd44 100644 --- a/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java +++ b/jdk/src/java.desktop/share/classes/sun/awt/ExtendedKeyCodes.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2009, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ package sun.awt; import java.util.Collections; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java new file mode 100644 index 00000000000..fc067b0070d --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContext.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.java2d; + +import java.lang.ref.Reference; + +/** + * ReentrantContext is a base class to hold thread-local data supporting + * reentrancy in either a ThreadLocal or a ConcurrentLinkedQueue + * + * @see ReentrantContextProvider + */ +public class ReentrantContext { + // usage stored as a byte + byte usage = ReentrantContextProvider.USAGE_TL_INACTIVE; + /* + * Reference to this instance (hard, soft or weak). + * @see ReentrantContextProvider#refType + */ + Reference reference = null; +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java new file mode 100644 index 00000000000..92132aabcc4 --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProvider.java @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.java2d; + +import java.lang.ref.Reference; +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; + +/** + * This abstract ReentrantContextProvider helper class manages the creation, + * storage, and retrieval of concrete ReentrantContext instances which can be + * subclassed to hold cached contextual data. + * + * It supports reentrancy as every call to acquire() provides a new unique context + * instance that must later be returned for reuse by a call to release(ctx) + * (typically in a try/finally block). + * + * It has a couple of abstract implementations which store references in a queue + * and/or thread-local storage. + * The Providers can be configured to hold ReentrantContext instances in memory + * using hard, soft or weak references. + * + * The acquire() and release() methods are used to retrieve and return the contexts. + * + * The {@code newContext()} method remains abstract in all implementations and + * must be provided by the module to create a new subclass of ReentrantContext + * with the appropriate contextual data in it. + * + * Sample Usage: + * - create a subclass ReentrantContextImpl to hold the thread state: + * + * static final class ReentrantContextImpl extends ReentrantContext { + * // specific cached data + * } + * + * - create the appropriate ReentrantContextProvider: + * + * private static final ReentrantContextProvider contextProvider = + * new ReentrantContextProviderTL(ReentrantContextProvider.REF_WEAK) + * { + * @Override + * protected ReentrantContextImpl newContext() { + * return new ReentrantContextImpl(); + * } + * }; + * ... + * void someMethod() { + * ReentrantContextImpl ctx = contextProvider.acquire(); + * try { + * // use the context + * } finally { + * contextProvider.release(ctx); + * } + * } + * + * @param ReentrantContext subclass + * + * @see ReentrantContext + */ +public abstract class ReentrantContextProvider +{ + // thread-local storage: inactive + static final byte USAGE_TL_INACTIVE = 0; + // thread-local storage: in use + static final byte USAGE_TL_IN_USE = 1; + // CLQ storage + static final byte USAGE_CLQ = 2; + + // hard reference + public static final int REF_HARD = 0; + // soft reference + public static final int REF_SOFT = 1; + // weak reference + public static final int REF_WEAK = 2; + + /* members */ + // internal reference type + private final int refType; + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak + * + * @param refType reference type + */ + protected ReentrantContextProvider(final int refType) { + this.refType = refType; + } + + /** + * Create a new ReentrantContext instance + * + * @return new ReentrantContext instance + */ + protected abstract K newContext(); + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + public abstract K acquire(); + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + public abstract void release(K ctx); + + @SuppressWarnings("unchecked") + protected final Reference getOrCreateReference(final K ctx) { + if (ctx.reference == null) { + // Create the reference: + switch (refType) { + case REF_HARD: + ctx.reference = new HardReference(ctx); + break; + case REF_SOFT: + ctx.reference = new SoftReference(ctx); + break; + default: + case REF_WEAK: + ctx.reference = new WeakReference(ctx); + break; + } + } + return (Reference) ctx.reference; + } + + /* Missing HardReference implementation */ + static final class HardReference extends WeakReference { + // kept strong reference: + private final V strongRef; + + HardReference(final V referent) { + // no referent needed for the parent WeakReference: + super(null); + this.strongRef = referent; + } + + @Override + public V get() { + return strongRef; + } + } +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java new file mode 100644 index 00000000000..22978cef888 --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderCLQ.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.java2d; + +import java.lang.ref.Reference; +import java.util.concurrent.ConcurrentLinkedQueue; + +/** + * This ReentrantContextProvider implementation uses one ConcurrentLinkedQueue + * to store all ReentrantContext instances (thread and its child contexts) + * + * Note: this implementation keeps less contexts in memory depending on the + * concurrent active threads in contrary to a ThreadLocal provider. However, + * it is slower in highly concurrent workloads. + * + * @param ReentrantContext subclass + */ +public abstract class ReentrantContextProviderCLQ + extends ReentrantContextProvider +{ + // ReentrantContext queue to store all contexts + private final ConcurrentLinkedQueue> ctxQueue + = new ConcurrentLinkedQueue>(); + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak based using a ConcurrentLinkedQueue storage + * + * @param refType reference type + */ + public ReentrantContextProviderCLQ(final int refType) { + super(refType); + } + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + @Override + public final K acquire() { + K ctx = null; + // Drain queue if all referent are null: + Reference ref = null; + while ((ctx == null) && ((ref = ctxQueue.poll()) != null)) { + ctx = ref.get(); + } + if (ctx == null) { + // create a new ReentrantContext if none is available + ctx = newContext(); + ctx.usage = USAGE_CLQ; + } + return ctx; + } + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + @Override + public final void release(final K ctx) { + if (ctx.usage == USAGE_CLQ) { + ctxQueue.offer(getOrCreateReference(ctx)); + } + } +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java new file mode 100644 index 00000000000..14dcb84d6d5 --- /dev/null +++ b/jdk/src/java.desktop/share/classes/sun/java2d/ReentrantContextProviderTL.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package sun.java2d; + +import java.lang.ref.Reference; + +/** +* This ReentrantContextProvider implementation uses a ThreadLocal to hold + * the first ReentrantContext per thread and a ReentrantContextProviderCLQ to + * store child ReentrantContext instances needed during recursion. + * + * Note: this implementation may keep up to one context in memory per thread. + * Child contexts for recursive uses are stored in the queue using a WEAK + * reference by default unless specified in the 2 argument constructor. + * + * @param ReentrantContext subclass + */ +public abstract class ReentrantContextProviderTL + extends ReentrantContextProvider +{ + // Thread-local storage: + private final ThreadLocal> ctxTL + = new ThreadLocal>(); + + // ReentrantContext CLQ provider for child contexts: + private final ReentrantContextProviderCLQ ctxProviderCLQ; + + /** + * Create a new ReentrantContext provider using the given reference type + * among hard, soft or weak. + * It uses weak reference for the child contexts. + * + * @param refType reference type + */ + public ReentrantContextProviderTL(final int refType) { + this(refType, REF_WEAK); + } + + /** + * Create a new ReentrantContext provider using the given reference types + * among hard, soft or weak + * + * @param refTypeTL reference type used by ThreadLocal + * @param refTypeCLQ reference type used by ReentrantContextProviderCLQ + */ + public ReentrantContextProviderTL(final int refTypeTL, final int refTypeCLQ) + { + super(refTypeTL); + + final ReentrantContextProviderTL parent = this; + + this.ctxProviderCLQ = new ReentrantContextProviderCLQ(refTypeCLQ) { + @Override + protected K newContext() { + return parent.newContext(); + } + }; + } + + /** + * Give a ReentrantContext instance for the current thread + * + * @return ReentrantContext instance + */ + @Override + public final K acquire() { + K ctx = null; + final Reference ref = ctxTL.get(); + if (ref != null) { + ctx = ref.get(); + } + if (ctx == null) { + // create a new ReentrantContext if none is available + ctx = newContext(); + // update thread local reference: + ctxTL.set(getOrCreateReference(ctx)); + } + // Check reentrance: + if (ctx.usage == USAGE_TL_INACTIVE) { + ctx.usage = USAGE_TL_IN_USE; + } else { + // get or create another ReentrantContext from CLQ provider: + ctx = ctxProviderCLQ.acquire(); + } + return ctx; + } + + /** + * Restore the given ReentrantContext instance for reuse + * + * @param ctx ReentrantContext instance + */ + @Override + public final void release(final K ctx) { + if (ctx.usage == USAGE_TL_IN_USE) { + ctx.usage = USAGE_TL_INACTIVE; + } else { + ctxProviderCLQ.release(ctx); + } + } +} diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java index 226a3d2e30d..6e8da24453e 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/ByteArrayCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,7 @@ final class ByteArrayCache implements MarlinConst { } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -135,9 +135,10 @@ final class ByteArrayCache implements MarlinConst { { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java index 06d7f351e28..681c75d4ceb 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/FloatArrayCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -127,7 +127,7 @@ final class FloatArrayCache implements MarlinConst { } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -136,9 +136,10 @@ final class FloatArrayCache implements MarlinConst { { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java index 11c5aae84f6..af4d0b69529 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/IntArrayCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -126,7 +126,7 @@ final class IntArrayCache implements MarlinConst { } if (doChecks) { - check(array, 0, array.length, value); + check(array, fromIndex, toIndex, value); } } @@ -135,9 +135,10 @@ final class IntArrayCache implements MarlinConst { { if (doChecks) { // check zero on full array: - for (int i = fromIndex; i < toIndex; i++) { + for (int i = 0; i < array.length; i++) { if (array[i] != value) { - logException("Invalid array value at " + i + "\n" + logException("Invalid value at: " + i + " = " + array[i] + + " from: " + fromIndex + " to: " + toIndex + "\n" + Arrays.toString(array), new Throwable()); // ensure array is correctly filled: diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java index 18cb441c571..40afc7fe9a6 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinCache.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -590,8 +590,8 @@ public final class MarlinCache implements MarlinConst { alphaRow[to + 1] = 0; } if (doChecks) { - IntArrayCache.check(blkFlags, 0, blkFlags.length, 0); - IntArrayCache.check(alphaRow, 0, alphaRow.length, 0); + IntArrayCache.check(blkFlags, blkW, blkE, 0); + IntArrayCache.check(alphaRow, from, px1 - bboxX0, 0); } if (doMonitors) { diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java index f7b5f7c43a8..e01a5e77f9c 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/MarlinRenderingEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,11 +30,12 @@ import java.awt.Shape; import java.awt.geom.AffineTransform; import java.awt.geom.Path2D; import java.awt.geom.PathIterator; -import java.lang.ref.Reference; import java.security.AccessController; -import java.util.concurrent.ConcurrentLinkedQueue; import static sun.java2d.marlin.MarlinUtils.logInfo; import sun.awt.geom.PathConsumer2D; +import sun.java2d.ReentrantContextProvider; +import sun.java2d.ReentrantContextProviderCLQ; +import sun.java2d.ReentrantContextProviderTL; import sun.java2d.pipe.AATileGenerator; import sun.java2d.pipe.Region; import sun.java2d.pipe.RenderingEngine; @@ -882,46 +883,50 @@ public class MarlinRenderingEngine extends RenderingEngine // use ThreadLocal or ConcurrentLinkedQueue to get one RendererContext private static final boolean useThreadLocal; - // hard reference - static final int REF_HARD = 0; - // soft reference - static final int REF_SOFT = 1; - // weak reference - static final int REF_WEAK = 2; - // reference type stored in either TL or CLQ static final int REF_TYPE; // Per-thread RendererContext - private static final ThreadLocal rdrCtxThreadLocal; - // RendererContext queue when ThreadLocal is disabled - private static final ConcurrentLinkedQueue rdrCtxQueue; + private static final ReentrantContextProvider rdrCtxProvider; // Static initializer to use TL or CLQ mode static { - // CLQ mode by default: useThreadLocal = MarlinProperties.isUseThreadLocal(); - rdrCtxThreadLocal = (useThreadLocal) ? new ThreadLocal() - : null; - rdrCtxQueue = (!useThreadLocal) ? new ConcurrentLinkedQueue() - : null; // Soft reference by default: - String refType = AccessController.doPrivileged( + final String refType = AccessController.doPrivileged( new GetPropertyAction("sun.java2d.renderer.useRef", "soft")); switch (refType) { default: case "soft": - REF_TYPE = REF_SOFT; + REF_TYPE = ReentrantContextProvider.REF_SOFT; break; case "weak": - REF_TYPE = REF_WEAK; + REF_TYPE = ReentrantContextProvider.REF_WEAK; break; case "hard": - REF_TYPE = REF_HARD; + REF_TYPE = ReentrantContextProvider.REF_HARD; break; } + + if (useThreadLocal) { + rdrCtxProvider = new ReentrantContextProviderTL(REF_TYPE) + { + @Override + protected RendererContext newContext() { + return RendererContext.createContext(); + } + }; + } else { + rdrCtxProvider = new ReentrantContextProviderCLQ(REF_TYPE) + { + @Override + protected RendererContext newContext() { + return RendererContext.createContext(); + } + }; + } } private static boolean settingsLogged = !enableLogs; @@ -936,13 +941,13 @@ public class MarlinRenderingEngine extends RenderingEngine String refType; switch (REF_TYPE) { default: - case REF_HARD: + case ReentrantContextProvider.REF_HARD: refType = "hard"; break; - case REF_SOFT: + case ReentrantContextProvider.REF_SOFT: refType = "soft"; break; - case REF_WEAK: + case ReentrantContextProvider.REF_WEAK: refType = "weak"; break; } @@ -1025,22 +1030,7 @@ public class MarlinRenderingEngine extends RenderingEngine */ @SuppressWarnings({"unchecked"}) static RendererContext getRendererContext() { - RendererContext rdrCtx = null; - final Object ref = (useThreadLocal) ? rdrCtxThreadLocal.get() - : rdrCtxQueue.poll(); - if (ref != null) { - // resolve reference: - rdrCtx = (REF_TYPE == REF_HARD) ? ((RendererContext) ref) - : ((Reference) ref).get(); - } - // create a new RendererContext if none is available - if (rdrCtx == null) { - rdrCtx = RendererContext.createContext(); - if (useThreadLocal) { - // update thread local reference: - rdrCtxThreadLocal.set(rdrCtx.reference); - } - } + final RendererContext rdrCtx = rdrCtxProvider.acquire(); if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.start(); } @@ -1057,8 +1047,6 @@ public class MarlinRenderingEngine extends RenderingEngine if (doMonitors) { RendererContext.stats.mon_pre_getAATileGenerator.stop(); } - if (!useThreadLocal) { - rdrCtxQueue.offer(rdrCtx.reference); - } + rdrCtxProvider.release(rdrCtx); } } diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java index 043db8adeba..f9b5e081785 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Renderer.java @@ -148,8 +148,8 @@ final class Renderer implements PathConsumer2D, MarlinConst { ////////////////////////////////////////////////////////////////////////////// // EDGE LIST ////////////////////////////////////////////////////////////////////////////// - private float edgeMinY = Float.POSITIVE_INFINITY; - private float edgeMaxY = Float.NEGATIVE_INFINITY; + private int edgeMinY = Integer.MAX_VALUE; + private int edgeMaxY = Integer.MIN_VALUE; private float edgeMinX = Float.POSITIVE_INFINITY; private float edgeMaxX = Float.NEGATIVE_INFINITY; @@ -357,18 +357,21 @@ final class Renderer implements PathConsumer2D, MarlinConst { } return; } - // edge min/max X/Y are in subpixel space (inclusive) - if (y1 < edgeMinY) { - edgeMinY = y1; + + // edge min/max X/Y are in subpixel space (inclusive) within bounds: + // note: Use integer crossings to ensure consistent range within + // edgeBuckets / edgeBucketCounts arrays in case of NaN values (int = 0) + if (firstCrossing < edgeMinY) { + edgeMinY = firstCrossing; } - if (y2 > edgeMaxY) { - edgeMaxY = y2; + if (lastCrossing > edgeMaxY) { + edgeMaxY = lastCrossing; } // Use double-precision for improved accuracy: final double x1d = x1; final double y1d = y1; - final double slope = (x2 - x1d) / (y2 - y1d); + final double slope = (x1d - x2) / (y1d - y2); if (slope >= 0.0) { // <==> x1 < x2 if (x1 < edgeMinX) { @@ -504,7 +507,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { private float x0, y0; // Position of most recent 'moveTo' command - private float pix_sx0, pix_sy0; + private float sx0, sy0; // per-thread renderer context final RendererContext rdrCtx; @@ -570,8 +573,8 @@ final class Renderer implements PathConsumer2D, MarlinConst { edgeBucketCounts = rdrCtx.getIntArray(edgeBucketsLength); } - edgeMinY = Float.POSITIVE_INFINITY; - edgeMaxY = Float.NEGATIVE_INFINITY; + edgeMinY = Integer.MAX_VALUE; + edgeMaxY = Integer.MIN_VALUE; edgeMinX = Float.POSITIVE_INFINITY; edgeMaxX = Float.NEGATIVE_INFINITY; @@ -628,7 +631,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { blkFlags = blkFlags_initial; } - if (edgeMinY != Float.POSITIVE_INFINITY) { + if (edgeMinY != Integer.MAX_VALUE) { // if context is maked as DIRTY: if (rdrCtx.dirty) { // may happen if an exception if thrown in the pipeline processing: @@ -688,16 +691,18 @@ final class Renderer implements PathConsumer2D, MarlinConst { @Override public void moveTo(float pix_x0, float pix_y0) { closePath(); - this.pix_sx0 = pix_x0; - this.pix_sy0 = pix_y0; - this.y0 = tosubpixy(pix_y0); - this.x0 = tosubpixx(pix_x0); + final float sx = tosubpixx(pix_x0); + final float sy = tosubpixy(pix_y0); + this.sx0 = sx; + this.sy0 = sy; + this.x0 = sx; + this.y0 = sy; } @Override public void lineTo(float pix_x1, float pix_y1) { - float x1 = tosubpixx(pix_x1); - float y1 = tosubpixy(pix_y1); + final float x1 = tosubpixx(pix_x1); + final float y1 = tosubpixy(pix_y1); addLine(x0, y0, x1, y1); x0 = x1; y0 = y1; @@ -729,8 +734,9 @@ final class Renderer implements PathConsumer2D, MarlinConst { @Override public void closePath() { - // lineTo expects its input in pixel coordinates. - lineTo(pix_sx0, pix_sy0); + addLine(x0, y0, sx0, sy0); + x0 = sx0; + y0 = sy0; } @Override @@ -1396,7 +1402,7 @@ final class Renderer implements PathConsumer2D, MarlinConst { if (doMonitors) { RendererContext.stats.mon_rdr_endRendering.start(); } - if (edgeMinY == Float.POSITIVE_INFINITY) { + if (edgeMinY == Integer.MAX_VALUE) { return false; // undefined edges bounds } @@ -1407,11 +1413,10 @@ final class Renderer implements PathConsumer2D, MarlinConst { final int spminX = FloatMath.max(FloatMath.ceil_int(edgeMinX - 0.5f), boundsMinX); final int spmaxX = FloatMath.min(FloatMath.ceil_int(edgeMaxX - 0.5f), boundsMaxX - 1); - // y1 (and y2) are already biased by -0.5 in tosubpixy(): - final int spminY = FloatMath.max(FloatMath.ceil_int(edgeMinY), _boundsMinY); - int maxY = FloatMath.ceil_int(edgeMaxY); - + // edge Min/Max Y are already rounded to subpixels within bounds: + final int spminY = edgeMinY; final int spmaxY; + int maxY = edgeMaxY; if (maxY <= _boundsMaxY - 1) { spmaxY = maxY; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java index f9524c88870..60de2c31570 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/RendererContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,9 +26,10 @@ package sun.java2d.marlin; import java.awt.geom.Path2D; -import java.lang.ref.SoftReference; import java.lang.ref.WeakReference; import java.util.concurrent.atomic.AtomicInteger; +import sun.java2d.ReentrantContext; +import sun.java2d.ReentrantContextProvider; import static sun.java2d.marlin.ArrayCache.*; import sun.java2d.marlin.MarlinRenderingEngine.NormalizingPathIterator; import static sun.java2d.marlin.MarlinUtils.logInfo; @@ -36,7 +37,7 @@ import static sun.java2d.marlin.MarlinUtils.logInfo; /** * This class is a renderer context dedicated to a single thread */ -final class RendererContext implements MarlinConst { +final class RendererContext extends ReentrantContext implements MarlinConst { // RendererContext creation counter private static final AtomicInteger contextCount = new AtomicInteger(1); @@ -45,7 +46,7 @@ final class RendererContext implements MarlinConst { ? RendererStats.getInstance(): null; private static final boolean USE_CACHE_HARD_REF = doStats - || (MarlinRenderingEngine.REF_TYPE == MarlinRenderingEngine.REF_WEAK); + || (MarlinRenderingEngine.REF_TYPE == ReentrantContextProvider.REF_WEAK); /** * Create a new renderer context @@ -55,6 +56,7 @@ final class RendererContext implements MarlinConst { static RendererContext createContext() { final RendererContext newCtx = new RendererContext("ctx" + Integer.toString(contextCount.getAndIncrement())); + if (RendererContext.stats != null) { RendererContext.stats.allContexts.add(newCtx); } @@ -63,11 +65,6 @@ final class RendererContext implements MarlinConst { // context name (debugging purposes) final String name; - /* - * Reference to this instance (hard, soft or weak). - * @see MarlinRenderingEngine#REF_TYPE - */ - final Object reference; // Smallest object used as Cleaner's parent reference final Object cleanerObj = new Object(); // dirty flag indicating an exception occured during pipeline in pathTo() @@ -101,7 +98,7 @@ final class RendererContext implements MarlinConst { /** * Constructor * - * @param name + * @param name context name (debugging) */ RendererContext(final String name) { if (logCreateContext) { @@ -124,20 +121,6 @@ final class RendererContext implements MarlinConst { stroker = new Stroker(this); dasher = new Dasher(this); - - // Create the reference to this instance (hard, soft or weak): - switch (MarlinRenderingEngine.REF_TYPE) { - default: - case MarlinRenderingEngine.REF_HARD: - reference = this; - break; - case MarlinRenderingEngine.REF_SOFT: - reference = new SoftReference(this); - break; - case MarlinRenderingEngine.REF_WEAK: - reference = new WeakReference(this); - break; - } } /** diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java index 94b0e2f1e59..1d144169376 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/marlin/Version.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,7 +27,7 @@ package sun.java2d.marlin; public final class Version { - private static final String version = "marlin-0.7.3-Unsafe-OpenJDK"; + private static final String version = "marlin-0.7.3.2-Unsafe-OpenJDK"; public static String getVersion() { return version; diff --git a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java index e071b967a02..3046ff69c60 100644 --- a/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java +++ b/jdk/src/java.desktop/share/classes/sun/java2d/pipe/AAShapePipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,11 @@ import java.awt.BasicStroke; import java.awt.Rectangle; import java.awt.Shape; import java.awt.geom.Rectangle2D; +import java.util.concurrent.ConcurrentLinkedQueue; import sun.awt.SunHints; +import sun.java2d.ReentrantContext; +import sun.java2d.ReentrantContextProvider; +import sun.java2d.ReentrantContextProviderTL; import sun.java2d.SunGraphics2D; /** @@ -38,28 +42,31 @@ import sun.java2d.SunGraphics2D; * This class sets up the Generator and computes the alpha tiles * and then passes them on to a CompositePipe object for painting. */ -public class AAShapePipe +public final class AAShapePipe implements ShapeDrawPipe, ParallelogramPipe { - static RenderingEngine renderengine = RenderingEngine.getInstance(); + static final RenderingEngine renderengine = RenderingEngine.getInstance(); // Per-thread TileState (~1K very small so do not use any Weak Reference) - private static final ThreadLocal tileStateThreadLocal = - new ThreadLocal() { - @Override - protected TileState initialValue() { - return new TileState(); - } - }; + private static final ReentrantContextProvider tileStateProvider = + new ReentrantContextProviderTL( + ReentrantContextProvider.REF_HARD) + { + @Override + protected TileState newContext() { + return new TileState(); + } + }; - CompositePipe outpipe; + final CompositePipe outpipe; public AAShapePipe(CompositePipe pipe) { outpipe = pipe; } + @Override public void draw(SunGraphics2D sg, Shape s) { - BasicStroke bs; + final BasicStroke bs; if (sg.stroke instanceof BasicStroke) { bs = (BasicStroke) sg.stroke; @@ -71,10 +78,12 @@ public class AAShapePipe renderPath(sg, s, bs); } + @Override public void fill(SunGraphics2D sg, Shape s) { renderPath(sg, s, null); } + @Override public void fillParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, @@ -82,21 +91,23 @@ public class AAShapePipe double dx1, double dy1, double dx2, double dy2) { - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, - clip, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, 0, 0, + sg.getCompClip(), abox); + if (aatg != null) { + renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), + aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } + @Override public void drawParallelogram(SunGraphics2D sg, double ux1, double uy1, double ux2, double uy2, @@ -105,52 +116,61 @@ public class AAShapePipe double dx2, double dy2, double lw1, double lw2) { - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, lw2, - clip, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(x, y, dx1, dy1, dx2, dy2, lw1, + lw2, sg.getCompClip(), abox); + if (aatg != null) { + // Note that bbox is of the original shape, not the wide path. + // This is appropriate for handing to Paint methods... + renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), + aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - // Note that bbox is of the original shape, not the wide path. - // This is appropriate for handing to Paint methods... - renderTiles(sg, ts.computeBBox(ux1, uy1, ux2, uy2), aatg, abox, ts); } public void renderPath(SunGraphics2D sg, Shape s, BasicStroke bs) { - boolean adjust = (bs != null && + final boolean adjust = (bs != null && sg.strokeHint != SunHints.INTVAL_STROKE_PURE); - boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); + final boolean thin = (sg.strokeState <= SunGraphics2D.STROKE_THINDASHED); - Region clip = sg.getCompClip(); - final TileState ts = tileStateThreadLocal.get(); - final int[] abox = ts.abox; + final TileState ts = tileStateProvider.acquire(); + try { + final int[] abox = ts.abox; - AATileGenerator aatg = - renderengine.getAATileGenerator(s, sg.transform, clip, - bs, thin, adjust, abox); - if (aatg == null) { - // Nothing to render - return; + final AATileGenerator aatg = + renderengine.getAATileGenerator(s, sg.transform, sg.getCompClip(), + bs, thin, adjust, abox); + if (aatg != null) { + renderTiles(sg, s, aatg, abox, ts); + } + } finally { + tileStateProvider.release(ts); } - - renderTiles(sg, s, aatg, abox, ts); } public void renderTiles(SunGraphics2D sg, Shape s, - AATileGenerator aatg, int abox[], TileState ts) + final AATileGenerator aatg, + final int[] abox, final TileState ts) { Object context = null; try { + // reentrance: outpipe may also use AAShapePipe: context = outpipe.startSequence(sg, s, ts.computeDevBox(abox), abox); + // copy of int[] abox as local variables for performance: + final int x0 = abox[0]; + final int y0 = abox[1]; + final int x1 = abox[2]; + final int y1 = abox[3]; + final int tw = aatg.getTileWidth(); final int th = aatg.getTileHeight(); @@ -158,16 +178,15 @@ public class AAShapePipe final byte[] alpha = ts.getAlphaTile(tw * th); byte[] atile; - for (int y = abox[1]; y < abox[3]; y += th) { - int h = Math.min(th, abox[3] - y); + for (int y = y0; y < y1; y += th) { + final int h = Math.min(th, y1 - y); - for (int x = abox[0]; x < abox[2]; x += tw) { - int w = Math.min(tw, abox[2] - x); + for (int x = x0; x < x1; x += tw) { + final int w = Math.min(tw, x1 - x); - int a = aatg.getTypicalAlpha(); - if (a == 0x00 || - outpipe.needTile(context, x, y, w, h) == false) - { + final int a = aatg.getTypicalAlpha(); + + if (a == 0x00 || !outpipe.needTile(context, x, y, w, h)) { aatg.nextTile(); outpipe.skipTile(context, x, y); continue; @@ -180,8 +199,7 @@ public class AAShapePipe aatg.getAlpha(alpha, 0, tw); } - outpipe.renderPathTile(context, atile, 0, tw, - x, y, w, h); + outpipe.renderPathTile(context, atile, 0, tw, x, y, w, h); } } } finally { @@ -193,7 +211,7 @@ public class AAShapePipe } // Tile state used by AAShapePipe - static final class TileState { + static final class TileState extends ReentrantContext { // cached tile (32 x 32 tile by default) private byte[] theTile = new byte[32 * 32]; // dirty aabox array @@ -240,5 +258,4 @@ public class AAShapePipe return box; } } - } diff --git a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java index 1ffb6a18e1d..7ba84ab1630 100644 --- a/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/java.desktop/share/classes/sun/print/RasterPrinterJob.java @@ -791,12 +791,15 @@ public abstract class RasterPrinterJob extends PrinterJob { return page; } - final GraphicsConfiguration gc = - GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); - Rectangle bounds = gc.getBounds(); - int x = bounds.x+bounds.width/3; - int y = bounds.y+bounds.height/3; + GraphicsConfiguration grCfg = null; + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if (w != null) { + grCfg = w.getGraphicsConfiguration(); + } else { + grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + final GraphicsConfiguration gc = grCfg; PrintService service = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -814,9 +817,39 @@ public abstract class RasterPrinterJob extends PrinterJob { return null; } + // we position the dialog a little beyond the upper-left corner of the window + // which is consistent with the NATIVE page dialog + Rectangle gcBounds = gc.getBounds(); + int x = gcBounds.x+50; + int y = gcBounds.y+50; ServiceDialog pageDialog = new ServiceDialog(gc, x, y, service, DocFlavor.SERVICE_FORMATTED.PAGEABLE, attributes, (Frame)null); + Rectangle dlgBounds = pageDialog.getBounds(); + + // if portion of dialog is not within the gc boundary + if (!gcBounds.contains(dlgBounds)) { + // check if dialog exceed window bounds at left or bottom + // Then position the dialog by moving it by the amount it exceeds + // the window bounds + // If it results in dialog moving beyond the window bounds at top/left + // then position it at window top/left + if (dlgBounds.x + dlgBounds.width > gcBounds.x + gcBounds.width) { + if ((gcBounds.x + gcBounds.width - dlgBounds.width) > gcBounds.x) { + x = (gcBounds.x + gcBounds.width) - dlgBounds.width; + } else { + x = gcBounds.x; + } + } + if (dlgBounds.y + dlgBounds.height > gcBounds.y + gcBounds.height) { + if ((gcBounds.y + gcBounds.height - dlgBounds.height) > gcBounds.y) { + y = (gcBounds.y + gcBounds.height) - dlgBounds.height; + } else { + y = gcBounds.y; + } + } + pageDialog.setBounds(x, y, dlgBounds.width, dlgBounds.height); + } pageDialog.show(); if (pageDialog.getStatus() == ServiceDialog.APPROVE) { @@ -893,9 +926,15 @@ public abstract class RasterPrinterJob extends PrinterJob { * We raise privilege when we put up the dialog, to avoid * the "warning applet window" banner. */ - final GraphicsConfiguration gc = - GraphicsEnvironment.getLocalGraphicsEnvironment(). - getDefaultScreenDevice().getDefaultConfiguration(); + GraphicsConfiguration grCfg = null; + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + if (w != null) { + grCfg = w.getGraphicsConfiguration(); + } else { + grCfg = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(); + } + final GraphicsConfiguration gc = grCfg; PrintService service = java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { @@ -940,9 +979,10 @@ public abstract class RasterPrinterJob extends PrinterJob { } } - Rectangle bounds = gc.getBounds(); - int x = bounds.x+bounds.width/3; - int y = bounds.y+bounds.height/3; + // we position the dialog a little beyond the upper-left corner of the window + // which is consistent with the NATIVE print dialog + int x = 50; + int y = 50; PrintService newService; // temporarily add an attribute pointing back to this job. PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this); diff --git a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java index 8e71a80a0e9..dbae176dd7e 100644 --- a/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java +++ b/jdk/src/java.desktop/unix/classes/sun/java2d/x11/XSurfaceData.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ package sun.java2d.x11; import java.awt.image.*; diff --git a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java index f84f855cce3..d602b3c712a 100644 --- a/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java +++ b/jdk/src/java.desktop/unix/classes/sun/print/CUPSPrinter.java @@ -52,6 +52,7 @@ public class CUPSPrinter { private boolean initialized; private static native String getCupsServer(); private static native int getCupsPort(); + private static native String getCupsDefaultPrinter(); private static native boolean canConnect(String server, int port); private static native boolean initIDs(); // These functions need to be synchronized as @@ -266,6 +267,15 @@ public class CUPSPrinter { * Returns 2 values - index 0 is printer name, index 1 is the uri. */ static String[] getDefaultPrinter() { + // Try to get user/lpoptions-defined printer name from CUPS + // if not user-set, then go for server default destination + String printerInfo[] = new String[2]; + printerInfo[0] = getCupsDefaultPrinter(); + + if (printerInfo[0] != null) { + printerInfo[1] = null; + return printerInfo.clone(); + } try { URL url = new URL("http", getServer(), getPort(), ""); final HttpURLConnection urlConnection = @@ -301,7 +311,7 @@ public class CUPSPrinter { attCl)) { HashMap defaultMap = null; - String[] printerInfo = new String[2]; + InputStream is = urlConnection.getInputStream(); HashMap[] responseMap = IPPPrintService.readIPPResponse( is); diff --git a/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c b/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c index a530a47fb84..7ba8652b478 100644 --- a/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c +++ b/jdk/src/java.desktop/unix/native/common/awt/CUPSfuncs.c @@ -43,6 +43,10 @@ typedef int (*fn_ippPort)(void); typedef http_t* (*fn_httpConnect)(const char *, int); typedef void (*fn_httpClose)(http_t *); typedef char* (*fn_cupsGetPPD)(const char *); +typedef cups_dest_t* (*fn_cupsGetDest)(const char *name, + const char *instance, int num_dests, cups_dest_t *dests); +typedef int (*fn_cupsGetDests)(cups_dest_t **dests); +typedef void (*fn_cupsFreeDests)(int num_dests, cups_dest_t *dests); typedef ppd_file_t* (*fn_ppdOpenFile)(const char *); typedef void (*fn_ppdClose)(ppd_file_t *); typedef ppd_option_t* (*fn_ppdFindOption)(ppd_file_t *, const char *); @@ -53,6 +57,9 @@ fn_ippPort j2d_ippPort; fn_httpConnect j2d_httpConnect; fn_httpClose j2d_httpClose; fn_cupsGetPPD j2d_cupsGetPPD; +fn_cupsGetDest j2d_cupsGetDest; +fn_cupsGetDests j2d_cupsGetDests; +fn_cupsFreeDests j2d_cupsFreeDests; fn_ppdOpenFile j2d_ppdOpenFile; fn_ppdClose j2d_ppdClose; fn_ppdFindOption j2d_ppdFindOption; @@ -106,6 +113,24 @@ Java_sun_print_CUPSPrinter_initIDs(JNIEnv *env, return JNI_FALSE; } + j2d_cupsGetDest = (fn_cupsGetDest)dlsym(handle, "cupsGetDest"); + if (j2d_cupsGetDest == NULL) { + dlclose(handle); + return JNI_FALSE; + } + + j2d_cupsGetDests = (fn_cupsGetDests)dlsym(handle, "cupsGetDests"); + if (j2d_cupsGetDests == NULL) { + dlclose(handle); + return JNI_FALSE; + } + + j2d_cupsFreeDests = (fn_cupsFreeDests)dlsym(handle, "cupsFreeDests"); + if (j2d_cupsFreeDests == NULL) { + dlclose(handle); + return JNI_FALSE; + } + j2d_ppdOpenFile = (fn_ppdOpenFile)dlsym(handle, "ppdOpenFile"); if (j2d_ppdOpenFile == NULL) { dlclose(handle); @@ -169,6 +194,30 @@ Java_sun_print_CUPSPrinter_getCupsPort(JNIEnv *env, } +/* + * Gets CUPS default printer name. + * + */ +JNIEXPORT jstring JNICALL +Java_sun_print_CUPSPrinter_getCupsDefaultPrinter(JNIEnv *env, + jobject printObj) +{ + jstring cDefPrinter = NULL; + cups_dest_t *dests; + char *defaultPrinter = NULL; + int num_dests = j2d_cupsGetDests(&dests); + int i = 0; + cups_dest_t *dest = j2d_cupsGetDest(NULL, NULL, num_dests, dests); + if (dest != NULL) { + defaultPrinter = dest->name; + if (defaultPrinter != NULL) { + cDefPrinter = JNU_NewStringPlatform(env, defaultPrinter); + } + } + j2d_cupsFreeDests(num_dests, dests); + return cDefPrinter; +} + /* * Checks if connection can be made to the server. * diff --git a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java index 93dc53d4f27..8f4da91eef2 100644 --- a/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java +++ b/jdk/src/java.desktop/windows/classes/sun/java2d/d3d/D3DBlitLoops.java @@ -500,6 +500,7 @@ class D3DRTTSurfaceToSurfaceTransform extends TransformBlit { class D3DSurfaceToSwBlit extends Blit { private int typeval; + private WeakReference srcTmp; // REMIND: destination will actually be opaque/premultiplied... D3DSurfaceToSwBlit(SurfaceType dstType, int typeval) { @@ -509,11 +510,97 @@ class D3DSurfaceToSwBlit extends Blit { this.typeval = typeval; } + /* + * Clip value is ignored in D3D SurfaceToSw blit. + * Root Cause: The native interfaces to D3D use StretchRect API followed + * by custom copy of pixels from Surface to Sysmem. As a result, clipping + * in D3DSurfaceToSw works 'only' for Rect clips, provided, proper srcX, + * srcY, dstX, dstY, width and height are passed to native interfaces. + * Non rect clips (For example: Shape clips) are ignored completely. + * + * Solution: There are three solutions possible to fix this issue. + * 1. Convert the entire Surface to Sysmem and perform regular Blit. + * An optimized version of this is to take up the conversion only + * when Shape clips are needed. Existing native interface will suffice + * for supporting Rect clips. + * 2. With help of existing classes we could perform SwToSurface, + * SurfaceToSurface (implements clip) and SurfaceToSw (complete copy) + * in order. + * 3. Modify the native D3D interface to accept clip and perform same logic + * as the second approach but at native side. + * + * Upon multiple experiments, the first approach has been found to be + * faster than the others as it deploys 1-draw/copy operation for rect clip + * and 2-draw/copy operations for shape clip compared to 3-draws/copy + * operations deployed by the remaining approaches. + * + * complexClipBlit method helps to convert or copy the contents from + * D3DSurface onto Sysmem and perform a regular Blit with the clip + * information as required. This method is used when non-rectangular + * clip is needed. + */ + private synchronized void complexClipBlit(SurfaceData src, SurfaceData dst, + Composite comp, Region clip, + int sx, int sy, int dx, int dy, + int w, int h) { + SurfaceData cachedSrc = null; + if (srcTmp != null) { + // use cached intermediate surface, if available + cachedSrc = srcTmp.get(); + } + + // Type- indicates the pixel format of Sysmem based BufferedImage. + // Native d3d interfaces support on the fly conversion of pixels from + // d3d surface to destination sysmem memory of type IntARGB only. + final int type = BufferedImage.TYPE_INT_ARGB; + src = convertFrom(this, src, sx, sy, w, h, cachedSrc, type); + + // copy intermediate SW to destination SW using complex clip + final Blit performop = Blit.getFromCache(src.getSurfaceType(), + CompositeType.SrcNoEa, + dst.getSurfaceType()); + performop.Blit(src, dst, comp, clip, 0, 0, dx, dy, w, h); + + if (src != cachedSrc) { + // cache the intermediate surface + srcTmp = new WeakReference<>(src); + } + } + public void Blit(SurfaceData src, SurfaceData dst, Composite comp, Region clip, int sx, int sy, int dx, int dy, int w, int h) { + if (clip != null) { + clip = clip.getIntersectionXYWH(dx, dy, w, h); + // At the end this method will flush the RenderQueue, we should exit + // from it as soon as possible. + if (clip.isEmpty()) { + return; + } + + // Adjust final dst(x,y) and src(x,y) based on the clip. The + // logic is that, when clip limits drawing on the destination, + // corresponding pixels from the src should be skipped. + sx += clip.getLoX() - dx; + sy += clip.getLoY() - dy; + dx = clip.getLoX(); + dy = clip.getLoY(); + w = clip.getWidth(); + h = clip.getHeight(); + + // Check if the clip is Rectangular. For non-rectangular clips + // complexClipBlit will convert Surface To Sysmem and perform + // regular Blit. + if (!clip.isRectangular()) { + complexClipBlit(src, dst, comp, clip, + sx, sy, dx, dy, + w, h); + return; + } + } + D3DRenderQueue rq = D3DRenderQueue.getInstance(); rq.lock(); try { diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java similarity index 53% rename from jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java rename to jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java index 1e05192986c..1cd606fe7a5 100644 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchMainQueue.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AsyncEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,34 +20,39 @@ * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any - * questions. */ -package com.apple.concurrent; +package java.net.http; -import java.util.concurrent.Executor; +import java.nio.channels.SelectableChannel; -abstract class LibDispatchMainQueue extends LibDispatchQueue implements Executor { - public LibDispatchMainQueue() { - super(LibDispatchNative.nativeGetMainQueue()); - } +/** + * Event handling interface from HttpClientImpl's selector. + * + *

    If blockingChannel is true, then the channel will be put in blocking + * mode prior to handle() being called. If false, then it remains non-blocking. + */ +abstract class AsyncEvent { - @Override - protected synchronized void dispose() { - // should not dispose the main queue - } + /** + * Implement this if channel should be made blocking before calling handle() + */ + public interface Blocking { } - static class Sync extends LibDispatchMainQueue { - @Override - public void execute(final Runnable task) { - LibDispatchNative.nativeExecuteSync(ptr, task); - } - } + /** + * Implement this if channel should remain non-blocking before calling handle() + */ + public interface NonBlocking { } - static class ASync extends LibDispatchMainQueue { - @Override - public void execute(final Runnable task) { - LibDispatchNative.nativeExecuteAsync(ptr, task); - } - } + /** Returns the channel */ + public abstract SelectableChannel channel(); + + /** Returns the selector interest op flags OR'd */ + public abstract int interestOps(); + + /** Called when event occurs */ + public abstract void handle(); + + /** Called when selector is shutting down. Abort all exchanges. */ + public abstract void abort(); } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java new file mode 100644 index 00000000000..c06f3886a85 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/AuthenticationFilter.java @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import static java.net.Authenticator.RequestorType.PROXY; +import static java.net.Authenticator.RequestorType.SERVER; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.InetSocketAddress; +import java.net.URISyntaxException; +import java.util.Base64; +import java.util.HashMap; +import java.util.LinkedList; +import static java.nio.charset.StandardCharsets.ISO_8859_1; + +/** + * Implementation of Http Basic authentication. + */ +class AuthenticationFilter implements HeaderFilter { + + static private final Base64.Encoder encoder = Base64.getEncoder(); + + static final int DEFAULT_RETRY_LIMIT = 3; + + static final int retry_limit = Utils.getIntegerNetProperty( + "sun.net.httpclient.auth.retrylimit", DEFAULT_RETRY_LIMIT); + + static final int UNAUTHORIZED = 401; + static final int PROXY_UNAUTHORIZED = 407; + + private PasswordAuthentication getCredentials(String header, + boolean proxy, + HttpRequestImpl req) + throws IOException + { + HttpClientImpl client = req.client(); + java.net.Authenticator auth = + client.authenticator() + .orElseThrow(() -> new IOException("No authenticator set")); + URI uri = req.uri(); + HeaderParser parser = new HeaderParser(header); + String authscheme = parser.findKey(0); + + String realm = parser.findValue("realm"); + java.net.Authenticator.RequestorType rtype = proxy ? PROXY : SERVER; + + // needs to be instance method in Authenticator + return auth.requestPasswordAuthenticationInstance(uri.getHost(), + null, + uri.getPort(), + uri.getScheme(), + realm, + authscheme, + uri.toURL(), + rtype + ); + } + + private URI getProxyURI(HttpRequestImpl r) { + InetSocketAddress proxy = r.proxy(); + if (proxy == null) { + return null; + } + + // our own private scheme for proxy URLs + // eg. proxy.http://host:port/ + String scheme = "proxy." + r.uri().getScheme(); + try { + return new URI(scheme, + null, + proxy.getHostString(), + proxy.getPort(), + null, + null, + null); + } catch (URISyntaxException e) { + throw new InternalError(e); + } + } + + @Override + public void request(HttpRequestImpl r) throws IOException { + // use preemptive authentication if an entry exists. + Cache cache = getCache(r); + + // Proxy + if (r.exchange.proxyauth == null) { + URI proxyURI = getProxyURI(r); + if (proxyURI != null) { + CacheEntry ca = cache.get(proxyURI, true); + if (ca != null) { + r.exchange.proxyauth = new AuthInfo(true, ca.scheme, null, ca); + addBasicCredentials(r, true, ca.value); + } + } + } + + // Server + if (r.exchange.serverauth == null) { + CacheEntry ca = cache.get(r.uri(), false); + if (ca != null) { + r.exchange.serverauth = new AuthInfo(true, ca.scheme, null, ca); + addBasicCredentials(r, false, ca.value); + } + } + } + + // TODO: refactor into per auth scheme class + static private void addBasicCredentials(HttpRequestImpl r, + boolean proxy, + PasswordAuthentication pw) { + String hdrname = proxy ? "Proxy-Authorization" : "Authorization"; + StringBuilder sb = new StringBuilder(128); + sb.append(pw.getUserName()).append(':').append(pw.getPassword()); + String s = encoder.encodeToString(sb.toString().getBytes(ISO_8859_1)); + String value = "Basic " + s; + r.setSystemHeader(hdrname, value); + } + + // Information attached to a HttpRequestImpl relating to authentication + static class AuthInfo { + final boolean fromcache; + final String scheme; + int retries; + PasswordAuthentication credentials; // used in request + CacheEntry cacheEntry; // if used + + AuthInfo(boolean fromcache, + String scheme, + PasswordAuthentication credentials) { + this.fromcache = fromcache; + this.scheme = scheme; + this.credentials = credentials; + this.retries = 1; + } + + AuthInfo(boolean fromcache, + String scheme, + PasswordAuthentication credentials, + CacheEntry ca) { + this(fromcache, scheme, credentials); + assert credentials == null || (ca != null && ca.value == null); + cacheEntry = ca; + } + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + Cache cache = getCache(r.request); + int status = r.statusCode(); + HttpHeaders hdrs = r.headers(); + HttpRequestImpl req = r.request(); + + if (status != UNAUTHORIZED && status != PROXY_UNAUTHORIZED) { + // check if any authentication succeeded for first time + if (req.exchange.serverauth != null && !req.exchange.serverauth.fromcache) { + AuthInfo au = req.exchange.serverauth; + cache.store(au.scheme, req.uri(), false, au.credentials); + } + if (req.exchange.proxyauth != null && !req.exchange.proxyauth.fromcache) { + AuthInfo au = req.exchange.proxyauth; + cache.store(au.scheme, req.uri(), false, au.credentials); + } + return null; + } + + boolean proxy = status == PROXY_UNAUTHORIZED; + String authname = proxy ? "Proxy-Authentication" : "WWW-Authenticate"; + String authval = hdrs.firstValue(authname).orElseThrow(() -> { + return new IOException("Invalid auth header"); + }); + HeaderParser parser = new HeaderParser(authval); + String scheme = parser.findKey(0); + + // TODO: Need to generalise from Basic only. Delegate to a provider class etc. + + if (!scheme.equalsIgnoreCase("Basic")) { + return null; // error gets returned to app + } + + String realm = parser.findValue("realm"); + AuthInfo au = proxy ? req.exchange.proxyauth : req.exchange.serverauth; + if (au == null) { + PasswordAuthentication pw = getCredentials(authval, proxy, req); + if (pw == null) { + throw new IOException("No credentials provided"); + } + // No authentication in request. Get credentials from user + au = new AuthInfo(false, "Basic", pw); + if (proxy) + req.exchange.proxyauth = au; + else + req.exchange.serverauth = au; + addBasicCredentials(req, proxy, pw); + return req; + } else if (au.retries > retry_limit) { + throw new IOException("too many authentication attempts"); + } else { + // we sent credentials, but they were rejected + if (au.fromcache) { + cache.remove(au.cacheEntry); + } + // try again + au.credentials = getCredentials(authval, proxy, req); + addBasicCredentials(req, proxy, au.credentials); + au.retries++; + return req; + } + } + + static final HashMap caches = new HashMap<>(); + + static synchronized Cache getCache(HttpRequestImpl req) { + HttpClientImpl client = req.client(); + Cache c = caches.get(client); + if (c == null) { + c = new Cache(); + caches.put(client, c); + } + return c; + } + + static class Cache { + final LinkedList entries = new LinkedList<>(); + + synchronized CacheEntry get(URI uri, boolean proxy) { + for (CacheEntry entry : entries) { + if (entry.equalsKey(uri, proxy)) { + return entry; + } + } + return null; + } + + synchronized void remove(String authscheme, URI domain, boolean proxy) { + for (CacheEntry entry : entries) { + if (entry.equalsKey(domain, proxy)) { + entries.remove(entry); + } + } + } + + synchronized void remove(CacheEntry entry) { + entries.remove(entry); + } + + synchronized void store(String authscheme, + URI domain, + boolean proxy, + PasswordAuthentication value) { + remove(authscheme, domain, proxy); + entries.add(new CacheEntry(authscheme, domain, proxy, value)); + } + } + + static class CacheEntry { + final String root; + final String scheme; + final boolean proxy; + final PasswordAuthentication value; + + CacheEntry(String authscheme, + URI uri, + boolean proxy, + PasswordAuthentication value) { + this.scheme = authscheme; + this.root = uri.resolve(".").toString(); // remove extraneous components + this.proxy = proxy; + this.value = value; + } + + public PasswordAuthentication value() { + return value; + } + + public boolean equalsKey(URI uri, boolean proxy) { + if (this.proxy != proxy) { + return false; + } + String other = uri.toString(); + return other.startsWith(root); + } + } +} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java similarity index 81% rename from jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java rename to jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java index f464f698541..a311422a782 100644 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchQueue.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/BufferHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,13 +20,18 @@ * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any - * questions. */ -package com.apple.concurrent; +package java.net.http; -class LibDispatchQueue extends LibDispatchRetainedResource { - LibDispatchQueue(final long queuePtr) { - super(queuePtr); - } +import java.nio.ByteBuffer; + +/** + * Implemented by buffer pools. + */ +interface BufferHandler { + + ByteBuffer getBuffer(); + + void returnBuffer(ByteBuffer buffer); } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java new file mode 100644 index 00000000000..70e475ec6e3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ConnectionPool.java @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.net.InetSocketAddress; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.ListIterator; +import java.util.Objects; + +/** + * Http 1.1 connection pool. + */ +class ConnectionPool { + + static final long KEEP_ALIVE = Utils.getIntegerNetProperty( + "sun.net.httpclient.keepalive.timeout", 1200); // seconds + + // Pools of idle connections + + final HashMap> plainPool; + final HashMap> sslPool; + CacheCleaner cleaner; + + /** + * Entries in connection pool are keyed by destination address and/or + * proxy address: + * case 1: plain TCP not via proxy (destination only) + * case 2: plain TCP via proxy (proxy only) + * case 3: SSL not via proxy (destination only) + * case 4: SSL over tunnel (destination and proxy) + */ + static class CacheKey { + final InetSocketAddress proxy; + final InetSocketAddress destination; + + CacheKey(InetSocketAddress destination, InetSocketAddress proxy) { + this.proxy = proxy; + this.destination = destination; + } + + @Override + public boolean equals(Object obj) { + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + final CacheKey other = (CacheKey) obj; + if (!Objects.equals(this.proxy, other.proxy)) { + return false; + } + if (!Objects.equals(this.destination, other.destination)) { + return false; + } + return true; + } + + @Override + public int hashCode() { + return Objects.hash(proxy, destination); + } + } + + static class ExpiryEntry { + final HttpConnection connection; + final long expiry; // absolute time in seconds of expiry time + ExpiryEntry(HttpConnection connection, long expiry) { + this.connection = connection; + this.expiry = expiry; + } + } + + final LinkedList expiryList; + + /** + * There should be one of these per HttpClient. + */ + ConnectionPool() { + plainPool = new HashMap<>(); + sslPool = new HashMap<>(); + expiryList = new LinkedList<>(); + cleaner = new CacheCleaner(); + } + + void start() { + cleaner.start(); + } + + static CacheKey cacheKey(InetSocketAddress destination, + InetSocketAddress proxy) { + return new CacheKey(destination, proxy); + } + + synchronized HttpConnection getConnection(boolean secure, + InetSocketAddress addr, + InetSocketAddress proxy) { + CacheKey key = new CacheKey(addr, proxy); + HttpConnection c = secure ? findConnection(key, sslPool) + : findConnection(key, plainPool); + //System.out.println ("getConnection returning: " + c); + return c; + } + + /** + * Returns the connection to the pool. + * + * @param conn + */ + synchronized void returnToPool(HttpConnection conn) { + if (conn instanceof PlainHttpConnection) { + putConnection(conn, plainPool); + } else { + putConnection(conn, sslPool); + } + addToExpiryList(conn); + //System.out.println("Return to pool: " + conn); + } + + private HttpConnection + findConnection(CacheKey key, + HashMap> pool) { + LinkedList l = pool.get(key); + if (l == null || l.size() == 0) { + return null; + } else { + HttpConnection c = l.removeFirst(); + removeFromExpiryList(c); + return c; + } + } + + /* called from cache cleaner only */ + private void + removeFromPool(HttpConnection c, + HashMap> pool) { + //System.out.println("cacheCleaner removing: " + c); + LinkedList l = pool.get(c.cacheKey()); + assert l != null; + boolean wasPresent = l.remove(c); + assert wasPresent; + } + + private void + putConnection(HttpConnection c, + HashMap> pool) { + CacheKey key = c.cacheKey(); + LinkedList l = pool.get(key); + if (l == null) { + l = new LinkedList<>(); + pool.put(key, l); + } + l.add(c); + } + + // only runs while entries exist in cache + + class CacheCleaner extends Thread { + + volatile boolean stopping; + + CacheCleaner() { + super(null, null, "HTTP-Cache-cleaner", 0, false); + setDaemon(true); + } + + synchronized boolean stopping() { + return stopping; + } + + synchronized void stopCleaner() { + stopping = true; + } + + @Override + public void run() { + while (!stopping()) { + try { + Thread.sleep(3000); + } catch (InterruptedException e) {} + cleanCache(); + } + } + } + + synchronized void removeFromExpiryList(HttpConnection c) { + if (c == null) { + return; + } + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry e = li.next(); + if (e.connection.equals(c)) { + li.remove(); + return; + } + } + if (expiryList.isEmpty()) { + cleaner.stopCleaner(); + } + } + + private void cleanCache() { + long now = System.currentTimeMillis() / 1000; + LinkedList closelist = new LinkedList<>(); + + synchronized (this) { + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry entry = li.next(); + if (entry.expiry <= now) { + li.remove(); + HttpConnection c = entry.connection; + closelist.add(c); + if (c instanceof PlainHttpConnection) { + removeFromPool(c, plainPool); + } else { + removeFromPool(c, sslPool); + } + } + } + } + for (HttpConnection c : closelist) { + //System.out.println ("KAC: closing " + c); + c.close(); + } + } + + private synchronized void addToExpiryList(HttpConnection conn) { + long now = System.currentTimeMillis() / 1000; + long then = now + KEEP_ALIVE; + + if (expiryList.isEmpty()) + cleaner = new CacheCleaner(); + + ListIterator li = expiryList.listIterator(); + while (li.hasNext()) { + ExpiryEntry entry = li.next(); + + if (then > entry.expiry) { + li.previous(); + // insert here + li.add(new ExpiryEntry(conn, then)); + return; + } + } + // first element of list + expiryList.add(new ExpiryEntry(conn, then)); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java new file mode 100644 index 00000000000..1a95b667fdd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/CookieFilter.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.net.CookieManager; +import java.util.List; +import java.util.Map; +import java.util.Set; + +class CookieFilter implements HeaderFilter { + + final HttpClientImpl client; + final CookieManager cookieMan; + + CookieFilter(HttpClientImpl client) { + this.client = client; + this.cookieMan = client.cookieManager().orElseThrow( + () -> new IllegalArgumentException("no cookie manager")); + } + + @Override + public void request(HttpRequestImpl r) throws IOException { + Map> userheaders, cookies; + userheaders = r.getUserHeaders().directMap(); + cookies = cookieMan.get(r.uri(), userheaders); + // add the returned cookies + HttpHeadersImpl systemHeaders = r.getSystemHeaders(); + Set keys = cookies.keySet(); + for (String hdrname : keys) { + List vals = cookies.get(hdrname); + for (String val : vals) { + systemHeaders.addHeader(hdrname, val); + } + } + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + HttpHeaders hdrs = r.headers(); + cookieMan.put(r.uri(), hdrs.map()); + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java new file mode 100644 index 00000000000..9201d22160a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Exchange.java @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.net.SocketPermission; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.URLPermission; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CompletableFuture; + +/** + * One request/response exchange (handles 100/101 intermediate response also). + * depth field used to track number of times a new request is being sent + * for a given API request. If limit exceeded exception is thrown. + * + * Security check is performed here: + * - uses AccessControlContext captured at API level + * - checks for appropriate URLPermission for request + * - if permission allowed, grants equivalent SocketPermission to call + * - in case of direct HTTP proxy, checks additionally for access to proxy + * (CONNECT proxying uses its own Exchange, so check done there) + * + */ +class Exchange { + + final HttpRequestImpl request; + final HttpClientImpl client; + ExchangeImpl exchImpl; + HttpResponseImpl response; + final List permissions = new LinkedList<>(); + AccessControlContext acc; + boolean upgrading; // to HTTP/2 + + Exchange(HttpRequestImpl request) { + this.request = request; + this.upgrading = false; + this.client = request.client(); + } + + /* If different AccessControlContext to be used */ + Exchange(HttpRequestImpl request, AccessControlContext acc) { + this.request = request; + this.acc = acc; + this.upgrading = false; + this.client = request.client(); + } + + public HttpRequestImpl request() { + return request; + } + + public HttpResponseImpl response() throws IOException, InterruptedException { + response = responseImpl(null); + return response; + } + + public void cancel() { + if (exchImpl != null) + exchImpl.cancel(); + } + + public void h2Upgrade() { + upgrading = true; + request.setH2Upgrade(); + } + + static final SocketPermission[] SOCKET_ARRAY = new SocketPermission[0]; + + HttpResponseImpl responseImpl(HttpConnection connection) + throws IOException, InterruptedException + { + if (acc == null) { + acc = request.getAccessControlContext(); + } + SecurityException e = securityCheck(acc); + if (e != null) + throw e; + + if (permissions.size() > 0) { + try { + return AccessController.doPrivileged( + (PrivilegedExceptionAction)() -> + responseImpl0(connection), + null, + permissions.toArray(SOCKET_ARRAY)); + } catch (Throwable ee) { + if (ee instanceof PrivilegedActionException) { + ee = ee.getCause(); + } + if (ee instanceof IOException) + throw (IOException)ee; + else + throw new RuntimeException(ee); // TODO: fix + } + } else { + return responseImpl0(connection); + } + } + + HttpResponseImpl responseImpl0(HttpConnection connection) + throws IOException, InterruptedException + { + exchImpl = ExchangeImpl.get(this, connection); + if (request.expectContinue()) { + request.addSystemHeader("Expect", "100-Continue"); + exchImpl.sendHeadersOnly(); + HttpResponseImpl resp = exchImpl.getResponse(); + logResponse(resp); + if (resp.statusCode() != 100) { + return resp; + } + exchImpl.sendBody(); + return exchImpl.getResponse(); + } else { + exchImpl.sendRequest(); + HttpResponseImpl resp = exchImpl.getResponse(); + logResponse(resp); + return checkForUpgrade(resp, exchImpl); + } + } + + // Completed HttpResponse will be null if response succeeded + // will be a non null responseAsync if expect continue returns an error + + public CompletableFuture responseAsync(Void v) { + return responseAsyncImpl(null); + } + + CompletableFuture responseAsyncImpl(HttpConnection connection) { + if (acc == null) { + acc = request.getAccessControlContext(); + } + SecurityException e = securityCheck(acc); + if (e != null) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(e); + return cf; + } + if (permissions.size() > 0) { + return AccessController.doPrivileged( + (PrivilegedAction>)() -> + responseAsyncImpl0(connection), + null, + permissions.toArray(SOCKET_ARRAY)); + } else { + return responseAsyncImpl0(connection); + } + } + + CompletableFuture responseAsyncImpl0(HttpConnection connection) { + try { + exchImpl = ExchangeImpl.get(this, connection); + } catch (IOException | InterruptedException e) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(e); + return cf; + } + if (request.expectContinue()) { + request.addSystemHeader("Expect", "100-Continue"); + return exchImpl.sendHeadersAsync() + .thenCompose(exchImpl::getResponseAsync) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) + return cf; + if (rcode == 100) { + return exchImpl.sendBodyAsync() + .thenCompose(exchImpl::getResponseAsync) + .thenApply((r) -> { + logResponse(r); + return r; + }); + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } + }); + } else { + return exchImpl + .sendHeadersAsync() + .thenCompose((Void v) -> { + // send body and get response at same time + return exchImpl.sendBodyAsync() + .thenCompose(exchImpl::getResponseAsync); + }) + .thenCompose((HttpResponseImpl r1) -> { + int rcode = r1.statusCode(); + CompletableFuture cf = + checkForUpgradeAsync(r1, exchImpl); + if (cf != null) { + return cf; + } else { + Exchange.this.response = r1; + logResponse(r1); + return CompletableFuture.completedFuture(r1); + } + }) + .thenApply((HttpResponseImpl response) -> { + this.response = response; + logResponse(response); + return response; + }); + } + } + + // if this response was received in reply to an upgrade + // then create the Http2Connection from the HttpConnection + // initialize it and wait for the real response on a newly created Stream + + private CompletableFuture + checkForUpgradeAsync(HttpResponseImpl resp, + ExchangeImpl ex) { + int rcode = resp.statusCode(); + if (upgrading && (rcode == 101)) { + Http1Exchange e = (Http1Exchange)ex; + // check for 101 switching protocols + return e.responseBodyAsync(HttpResponse.ignoreBody()) + .thenCompose((Void v) -> + Http2Connection.createAsync(e.connection(), + client.client2(), + this) + .thenCompose((Http2Connection c) -> { + Stream s = c.getStream(1); + exchImpl = s; + c.putConnection(); + return s.getResponseAsync(null); + }) + ); + } + return CompletableFuture.completedFuture(resp); + } + + private HttpResponseImpl checkForUpgrade(HttpResponseImpl resp, + ExchangeImpl ex) + throws IOException, InterruptedException + { + int rcode = resp.statusCode(); + if (upgrading && (rcode == 101)) { + Http1Exchange e = (Http1Exchange) ex; + // must get connection from Http1Exchange + e.responseBody(HttpResponse.ignoreBody(), false); + Http2Connection h2con = new Http2Connection(e.connection(), + client.client2(), + this); + h2con.putConnection(); + Stream s = h2con.getStream(1); + exchImpl = s; + return s.getResponse(); + } + return resp; + } + + + T responseBody(HttpResponse.BodyProcessor processor) { + try { + return exchImpl.responseBody(processor); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + + + private void logResponse(HttpResponseImpl r) { + if (!Log.requests()) + return; + StringBuilder sb = new StringBuilder(); + String method = r.request().method(); + URI uri = r.uri(); + String uristring = uri == null ? "" : uri.toString(); + sb.append('(') + .append(method) + .append(" ") + .append(uristring) + .append(") ") + .append(Integer.toString(r.statusCode())); + Log.logResponse(sb.toString()); + } + + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return exchImpl.responseBodyAsync(processor); + } + + private URI getURIForSecurityCheck() { + URI u; + String method = request.method(); + InetSocketAddress authority = request.authority(); + URI uri = request.uri(); + + // CONNECT should be restricted at API level + if (method.equalsIgnoreCase("CONNECT")) { + try { + u = new URI("socket", + null, + authority.getHostString(), + authority.getPort(), + null, + null, + null); + } catch (URISyntaxException e) { + throw new InternalError(e); // shouldn't happen + } + } else { + u = uri; + } + return u; + } + + /** + * Do the security check and return any exception. + * Return null if no check needed or passes. + * + * Also adds any generated permissions to the "permissions" list. + */ + private SecurityException securityCheck(AccessControlContext acc) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) { + return null; + } + + String method = request.method(); + HttpHeadersImpl userHeaders = request.getUserHeaders(); + URI u = getURIForSecurityCheck(); + URLPermission p = Utils.getPermission(u, method, userHeaders.directMap()); + + try { + assert acc != null; + sm.checkPermission(p, acc); + permissions.add(getSocketPermissionFor(u)); + } catch (SecurityException e) { + return e; + } + InetSocketAddress proxy = request.proxy(); + if (proxy != null) { + // may need additional check + if (!method.equals("CONNECT")) { + // a direct http proxy. Need to check access to proxy + try { + u = new URI("socket", null, proxy.getHostString(), + proxy.getPort(), null, null, null); + } catch (URISyntaxException e) { + throw new InternalError(e); // shouldn't happen + } + p = new URLPermission(u.toString(), "CONNECT"); + try { + sm.checkPermission(p, acc); + } catch (SecurityException e) { + permissions.clear(); + return e; + } + String sockperm = proxy.getHostString() + + ":" + Integer.toString(proxy.getPort()); + + permissions.add(new SocketPermission(sockperm, "connect,resolve")); + } + } + return null; + } + + private static SocketPermission getSocketPermissionFor(URI url) { + if (System.getSecurityManager() == null) + return null; + + StringBuilder sb = new StringBuilder(); + String host = url.getHost(); + sb.append(host); + int port = url.getPort(); + if (port == -1) { + String scheme = url.getScheme(); + if ("http".equals(scheme)) { + sb.append(":80"); + } else { // scheme must be https + sb.append(":443"); + } + } else { + sb.append(':') + .append(Integer.toString(port)); + } + String target = sb.toString(); + return new SocketPermission(target, "connect"); + } + + AccessControlContext getAccessControlContext() { + return acc; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java new file mode 100644 index 00000000000..bc3b6508d3c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExchangeImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; +import static java.net.http.HttpClient.Version.HTTP_1_1; + +/** + * Splits request so that headers and body can be sent separately with optional + * (multiple) responses in between (e.g. 100 Continue). Also request and + * response always sent/received in different calls. + * + * Synchronous and asynchronous versions of each method are provided. + * + * Separate implementations of this class exist for HTTP/1.1 and HTTP/2 + * Http1Exchange (HTTP/1.1) + * Stream (HTTP/2) + * + * These implementation classes are where work is allocated to threads. + */ +abstract class ExchangeImpl { + + final Exchange exchange; + + ExchangeImpl(Exchange e) { + this.exchange = e; + } + + /** + * Initiates a new exchange and assigns it to a connection if one exists + * already. connection usually null. + */ + static ExchangeImpl get(Exchange exchange, HttpConnection connection) + throws IOException, InterruptedException + { + HttpRequestImpl req = exchange.request(); + if (req.version() == HTTP_1_1) { + return new Http1Exchange(exchange, connection); + } else { + Http2ClientImpl c2 = exchange.request().client().client2(); // TODO: improve + HttpRequestImpl request = exchange.request(); + Http2Connection c = c2.getConnectionFor(request); + if (c == null) { + // no existing connection. Send request with HTTP 1 and then + // upgrade if successful + ExchangeImpl ex = new Http1Exchange(exchange, connection); + exchange.h2Upgrade(); + return ex; + } + return c.createStream(exchange); + } + } + + /* The following methods have separate HTTP/1.1 and HTTP/2 implementations */ + + /** + * Sends the request headers only. May block until all sent. + */ + abstract void sendHeadersOnly() throws IOException, InterruptedException; + + /** + * Gets response headers by blocking if necessary. This may be an + * intermediate response (like 101) or a final response 200 etc. + */ + abstract HttpResponseImpl getResponse() throws IOException; + + /** + * Sends a request body after request headers. + */ + abstract void sendBody() throws IOException, InterruptedException; + + /** + * Sends the entire request (headers and body) blocking. + */ + abstract void sendRequest() throws IOException, InterruptedException; + + /** + * Asynchronous version of sendHeaders(). + */ + abstract CompletableFuture sendHeadersAsync(); + + /** + * Asynchronous version of getResponse(). Requires void parameter for + * CompletableFuture chaining. + */ + abstract CompletableFuture getResponseAsync(Void v); + + /** + * Asynchronous version of sendBody(). + */ + abstract CompletableFuture sendBodyAsync(); + + /** + * Cancels a request. Not currently exposed through API. + */ + abstract void cancel(); + + /** + * Asynchronous version of sendRequest(). + */ + abstract CompletableFuture sendRequestAsync(); + + abstract T responseBody(HttpResponse.BodyProcessor processor) + throws IOException; + + /** + * Asynchronous version of responseBody(). + */ + abstract CompletableFuture + responseBodyAsync(HttpResponse.BodyProcessor processor); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java new file mode 100644 index 00000000000..ba8a07cf1cc --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ExecutorWrapper.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.security.AccessControlContext; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; +import java.util.function.Supplier; + +/** + * Wraps the supplied user ExecutorService. + * + * 1) when a Security manager set, the correct access control context + * is used to execute task + * + * 2) memory fence implemented + */ +class ExecutorWrapper { + + final ExecutorService userExecutor; // the actual executor service used + final Executor executor; + + public static ExecutorWrapper wrap(ExecutorService userExecutor) { + return new ExecutorWrapper(userExecutor); + } + + /** + * Returns a dummy ExecutorWrapper which uses the calling thread + */ + public static ExecutorWrapper callingThread() { + return new ExecutorWrapper(); + } + + private ExecutorWrapper(ExecutorService userExecutor) { + // used for executing in calling thread + this.userExecutor = userExecutor; + this.executor = userExecutor; + } + + private ExecutorWrapper() { + this.userExecutor = null; + this.executor = (Runnable command) -> { + command.run(); + }; + } + + public ExecutorService userExecutor() { + return userExecutor; + } + + public synchronized void synchronize() {} + + public void execute(Runnable r, Supplier ctxSupplier) { + synchronize(); + Runnable r1 = () -> { + try { + r.run(); + } catch (Throwable t) { + Log.logError(t); + } + }; + + if (ctxSupplier != null && System.getSecurityManager() != null) { + AccessControlContext acc = ctxSupplier.get(); + if (acc == null) { + throw new InternalError(); + } + AccessController.doPrivilegedWithCombiner( + (PrivilegedAction)() -> { + executor.execute(r1); // all throwables must be caught + return null; + }, acc); + } else { + executor.execute(r1); // all throwables must be caught + } + } +} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java similarity index 56% rename from jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java rename to jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java index 9b89ac546e3..cf67771331a 100644 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchNative.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/FilterFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,29 +20,30 @@ * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any - * questions. */ -package com.apple.concurrent; +package java.net.http; -final class LibDispatchNative { - static { - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { - public Void run() { - System.loadLibrary("osx"); - return null; - } - }); +import java.util.LinkedList; +import java.util.List; + +class FilterFactory { + + final LinkedList> filterClasses = new LinkedList<>(); + + public void addFilter(Class type) { + filterClasses.add(type); } - static native boolean nativeIsDispatchSupported(); - static native long nativeGetMainQueue(); - static native long nativeCreateConcurrentQueue(int priority); - static native long nativeCreateSerialQueue(String name); - static native void nativeReleaseQueue(long nativeQueue); - static native void nativeExecuteAsync(long nativeQueue, Runnable task); - static native void nativeExecuteSync(long nativeQueue, Runnable task); - - private LibDispatchNative() { } + List getFilterChain() { + List l = new LinkedList<>(); + for (Class clazz : filterClasses) { + try { + l.add(clazz.newInstance()); + } catch (ReflectiveOperationException e) { + throw new InternalError(e); + } + } + return l; + } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java new file mode 100644 index 00000000000..d0fae94ada8 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderFilter.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.io.IOException; + +/** + * A header filter that can examine or modify, typically system headers for + * requests before they are sent, and responses before they are returned to the + * user. Some ability to resend requests is provided. + * + */ +interface HeaderFilter { + + void request(HttpRequestImpl r) throws IOException; + + /** + * Returns null if response ok to be given to user. Non null is a request + * that must be resent and its response given to user. If impl throws an + * exception that is returned to user instead. + */ + HttpRequestImpl response(HttpResponseImpl r) throws IOException; +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java new file mode 100644 index 00000000000..d4922d6a141 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HeaderParser.java @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.util.Iterator; +import java.util.Locale; +import java.util.NoSuchElementException; + +/* This is useful for the nightmare of parsing multi-part HTTP/RFC822 headers + * sensibly: + * From a String like: 'timeout=15, max=5' + * create an array of Strings: + * { {"timeout", "15"}, + * {"max", "5"} + * } + * From one like: 'Basic Realm="FuzzFace" Foo="Biz Bar Baz"' + * create one like (no quotes in literal): + * { {"basic", null}, + * {"realm", "FuzzFace"} + * {"foo", "Biz Bar Baz"} + * } + * keys are converted to lower case, vals are left as is.... + */ +class HeaderParser { + + /* table of key/val pairs */ + String raw; + String[][] tab; + int nkeys; + int asize = 10; // initial size of array is 10 + + public HeaderParser(String raw) { + this.raw = raw; + tab = new String[asize][2]; + parse(); + } + + private HeaderParser () { } + + /** + * Creates a new HeaderParser from this, whose keys (and corresponding + * values) range from "start" to "end-1" + */ + public HeaderParser subsequence(int start, int end) { + if (start == 0 && end == nkeys) { + return this; + } + if (start < 0 || start >= end || end > nkeys) + throw new IllegalArgumentException("invalid start or end"); + HeaderParser n = new HeaderParser(); + n.tab = new String [asize][2]; + n.asize = asize; + System.arraycopy (tab, start, n.tab, 0, (end-start)); + n.nkeys= (end-start); + return n; + } + + private void parse() { + + if (raw != null) { + raw = raw.trim(); + char[] ca = raw.toCharArray(); + int beg = 0, end = 0, i = 0; + boolean inKey = true; + boolean inQuote = false; + int len = ca.length; + while (end < len) { + char c = ca[end]; + if ((c == '=') && !inQuote) { // end of a key + tab[i][0] = new String(ca, beg, end-beg).toLowerCase(Locale.US); + inKey = false; + end++; + beg = end; + } else if (c == '\"') { + if (inQuote) { + tab[i++][1]= new String(ca, beg, end-beg); + inQuote=false; + do { + end++; + } while (end < len && (ca[end] == ' ' || ca[end] == ',')); + inKey=true; + beg=end; + } else { + inQuote=true; + end++; + beg=end; + } + } else if (c == ' ' || c == ',') { // end key/val, of whatever we're in + if (inQuote) { + end++; + continue; + } else if (inKey) { + tab[i++][0] = (new String(ca, beg, end-beg)).toLowerCase(Locale.US); + } else { + tab[i++][1] = (new String(ca, beg, end-beg)); + } + while (end < len && (ca[end] == ' ' || ca[end] == ',')) { + end++; + } + inKey = true; + beg = end; + } else { + end++; + } + if (i == asize) { + asize = asize * 2; + String[][] ntab = new String[asize][2]; + System.arraycopy (tab, 0, ntab, 0, tab.length); + tab = ntab; + } + } + // get last key/val, if any + if (--end > beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = (new String(ca, beg, end-beg)); + } else { + tab[i++][1] = (new String(ca, beg, end-beg+1)); + } + } else { + tab[i++][0] = (new String(ca, beg, end-beg+1)).toLowerCase(); + } + } else if (end == beg) { + if (!inKey) { + if (ca[end] == '\"') { + tab[i++][1] = String.valueOf(ca[end-1]); + } else { + tab[i++][1] = String.valueOf(ca[end]); + } + } else { + tab[i++][0] = String.valueOf(ca[end]).toLowerCase(); + } + } + nkeys=i; + } + } + + public String findKey(int i) { + if (i < 0 || i > asize) + return null; + return tab[i][0]; + } + + public String findValue(int i) { + if (i < 0 || i > asize) + return null; + return tab[i][1]; + } + + public String findValue(String key) { + return findValue(key, null); + } + + public String findValue(String k, String Default) { + if (k == null) + return Default; + k = k.toLowerCase(Locale.US); + for (int i = 0; i < asize; ++i) { + if (tab[i][0] == null) { + return Default; + } else if (k.equals(tab[i][0])) { + return tab[i][1]; + } + } + return Default; + } + + class ParserIterator implements Iterator { + int index; + boolean returnsValue; // or key + + ParserIterator (boolean returnValue) { + returnsValue = returnValue; + } + @Override + public boolean hasNext () { + return index= nkeys) + throw new NoSuchElementException(); + return tab[index++][returnsValue?1:0]; + } + } + + public Iterator keys () { + return new ParserIterator (false); + } + + public Iterator values () { + return new ParserIterator (true); + } + + @Override + public String toString () { + Iterator k = keys(); + StringBuilder sb = new StringBuilder(); + sb.append("{size=").append(asize).append(" nkeys=").append(nkeys) + .append(' '); + for (int i=0; k.hasNext(); i++) { + String key = k.next(); + String val = findValue (i); + if (val != null && "".equals (val)) { + val = null; + } + sb.append(" {").append(key).append(val == null ? "" : "," + val) + .append('}'); + if (k.hasNext()) { + sb.append (','); + } + } + sb.append (" }"); + return sb.toString(); + } + + public int findInt(String k, int Default) { + try { + return Integer.parseInt(findValue(k, String.valueOf(Default))); + } catch (Throwable t) { + return Default; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java new file mode 100644 index 00000000000..3266eada6c6 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Exchange.java @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.concurrent.CompletableFuture; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + +/** + * Encapsulates one HTTP/1.1 request/responseAsync exchange. + */ +class Http1Exchange extends ExchangeImpl { + + final HttpRequestImpl request; // main request + final List> operations; // used for cancel + final Http1Request requestAction; + volatile Http1Response response; + final HttpConnection connection; + final HttpClientImpl client; + final ExecutorWrapper executor; + + @Override + public String toString() { + return request.toString(); + } + + HttpRequestImpl request() { + return request; + } + + Http1Exchange(Exchange exchange, HttpConnection connection) + throws IOException + { + super(exchange); + this.request = exchange.request(); + this.client = request.client(); + this.executor = client.executorWrapper(); + this.operations = Collections.synchronizedList(new LinkedList<>()); + if (connection != null) { + this.connection = connection; + } else { + InetSocketAddress addr = getAddress(request); + this.connection = HttpConnection.getConnection(addr, request); + } + this.requestAction = new Http1Request(request, this.connection); + } + + private static InetSocketAddress getAddress(HttpRequestImpl req) { + URI uri = req.uri(); + if (uri == null) { + return req.authority(); + } + int port = uri.getPort(); + if (port == -1) { + if (uri.getScheme().equalsIgnoreCase("https")) { + port = 443; + } else { + port = 80; + } + } + String host = uri.getHost(); + if (req.proxy() == null) { + return new InetSocketAddress(host, port); + } else { + return InetSocketAddress.createUnresolved(host, port); + } + } + + HttpConnection connection() { + return connection; + } + + @Override + T responseBody(HttpResponse.BodyProcessor processor) + throws IOException + { + return responseBody(processor, true); + } + + T responseBody(HttpResponse.BodyProcessor processor, + boolean return2Cache) + throws IOException + { + try { + T body = response.readBody(processor, return2Cache); + return body; + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + @Override + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + CompletableFuture cf = new CompletableFuture<>(); + request.client() + .executorWrapper() + .execute(() -> { + try { + T body = responseBody(processor); + cf.complete(body); + } catch (Throwable e) { + cf.completeExceptionally(e); + } + }, + () -> response.response.getAccessControlContext()); // TODO: fix + return cf; + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + try { + if (!connection.connected()) { + connection.connect(); + } + requestAction.sendHeadersOnly(); + } catch (Throwable e) { + connection.close(); + throw e; + } + } + + @Override + void sendBody() throws IOException { + try { + requestAction.continueRequest(); + } catch (Throwable e) { + connection.close(); + throw e; + } + } + + @Override + HttpResponseImpl getResponse() throws IOException { + try { + response = new Http1Response(connection, this); + response.readHeaders(); + return response.response(); + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + @Override + void sendRequest() throws IOException, InterruptedException { + try { + if (!connection.connected()) { + connection.connect(); + } + requestAction.sendRequest(); + } catch (Throwable t) { + connection.close(); + throw t; + } + } + + private void closeConnection() { + connection.close(); + } + + @Override + CompletableFuture sendHeadersAsync() { + if (!connection.connected()) { + CompletableFuture op = connection.connectAsync() + .thenCompose(this::sendHdrsAsyncImpl) + .whenComplete((Void b, Throwable t) -> { + if (t != null) + closeConnection(); + }); + operations.add(op); + return op; + } else { + return sendHdrsAsyncImpl(null); + } + } + + private CompletableFuture sendHdrsAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.sendHeadersOnly(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, + () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } + + /** + * Cancel checks to see if request and responseAsync finished already. + * If not it closes the connection and completes all pending operations + */ + @Override + synchronized void cancel() { + if (requestAction != null && requestAction.finished() + && response != null && response.finished()) { + return; + } + connection.close(); + IOException e = new IOException("Request cancelled"); + int count = 0; + for (CompletableFuture cf : operations) { + cf.completeExceptionally(e); + count++; + } + Log.logError("Http1Exchange.cancel: count=" + count); + } + + CompletableFuture getResponseAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + try { + response = new Http1Response(connection, Http1Exchange.this); + response.readHeaders(); + cf.complete(response.response()); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + } + + @Override + CompletableFuture getResponseAsync(Void v) { + CompletableFuture cf = + connection.whenReceivingResponse() + .thenCompose(this::getResponseAsyncImpl); + + operations.add(cf); + return cf; + } + + @Override + CompletableFuture sendBodyAsync() { + final CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.continueRequest(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } + + @Override + CompletableFuture sendRequestAsync() { + CompletableFuture op; + if (!connection.connected()) { + op = connection.connectAsync() + .thenCompose(this::sendRequestAsyncImpl) + .whenComplete((Void v, Throwable t) -> { + if (t != null) { + closeConnection(); + } + }); + } else { + op = sendRequestAsyncImpl(null); + } + operations.add(op); + return op; + } + + CompletableFuture sendRequestAsyncImpl(Void v) { + CompletableFuture cf = new CompletableFuture<>(); + executor.execute(() -> { + try { + requestAction.sendRequest(); + cf.complete(null); + } catch (Throwable e) { + cf.completeExceptionally(e); + connection.close(); + } + }, () -> request.getAccessControlContext()); + operations.add(cf); + return cf; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java new file mode 100644 index 00000000000..f0da88b3b5c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Request.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.net.InetSocketAddress; +import java.nio.charset.StandardCharsets; +import java.util.function.LongConsumer; +import static java.nio.charset.StandardCharsets.US_ASCII; + +/** + * A HTTP/1.1 request. + * + * send() -> Writes the request + body to the given channel, in one blocking + * operation. + */ +class Http1Request { + + final HttpRequestImpl request; + final HttpConnection chan; + // Multiple buffers are used to hold different parts of request + // See line 206 and below for description + final ByteBuffer[] buffers; + final HttpRequest.BodyProcessor requestProc; + final HttpHeadersImpl userHeaders, systemHeaders; + final LongConsumer flowController; + boolean streaming; + long contentLength; + + Http1Request(HttpRequestImpl request, HttpConnection connection) + throws IOException + { + this.request = request; + this.chan = connection; + buffers = new ByteBuffer[5]; // TODO: check + this.requestProc = request.requestProcessor(); + this.userHeaders = request.getUserHeaders(); + this.systemHeaders = request.getSystemHeaders(); + this.flowController = this::dummy; + } + + private void logHeaders() throws IOException { + StringBuilder sb = new StringBuilder(256); + sb.append("REQUEST HEADERS:\r\n"); + collectHeaders1(sb, request, systemHeaders); + collectHeaders1(sb, request, userHeaders); + Log.logHeaders(sb.toString()); + } + + private void dummy(long x) { + // not used in this class + } + + private void collectHeaders0() throws IOException { + if (Log.headers()) { + logHeaders(); + } + StringBuilder sb = new StringBuilder(256); + collectHeaders1(sb, request, systemHeaders); + collectHeaders1(sb, request, userHeaders); + sb.append("\r\n"); + String headers = sb.toString(); + buffers[1] = ByteBuffer.wrap(headers.getBytes(StandardCharsets.US_ASCII)); + } + + private void collectHeaders1(StringBuilder sb, + HttpRequestImpl request, + HttpHeadersImpl headers) + throws IOException + { + Map> h = headers.directMap(); + Set>> entries = h.entrySet(); + + for (Map.Entry> entry : entries) { + String key = entry.getKey(); + sb.append(key).append(": "); + List values = entry.getValue(); + int num = values.size(); + for (String value : values) { + sb.append(value); + if (--num > 0) { + sb.append(','); + } + } + sb.append("\r\n"); + } + } + + private static final int BUFSIZE = 64 * 1024; // TODO: configurable? + + private String getPathAndQuery(URI uri) { + String path = uri.getPath(); + String query = uri.getQuery(); + if (path == null || path.equals("")) { + path = "/"; + } + if (query == null) { + query = ""; + } + if (query.equals("")) { + return path; + } else { + return path + "?" + query; + } + } + + private String authorityString(InetSocketAddress addr) { + return addr.getHostString() + ":" + addr.getPort(); + } + + private String requestURI() { + URI uri = request.uri(); + String method = request.method(); + + if ((request.proxy() == null && !method.equals("CONNECT")) + || request.isWebSocket()) { + return getPathAndQuery(uri); + } + if (request.secure()) { + if (request.method().equals("CONNECT")) { + // use authority for connect itself + return authorityString(request.authority()); + } else { + // requests over tunnel do not require full URL + return getPathAndQuery(uri); + } + } + return uri == null? authorityString(request.authority()) : uri.toString(); + } + + void sendHeadersOnly() throws IOException { + collectHeaders(); + chan.write(buffers, 0, 2); + } + + void sendRequest() throws IOException { + collectHeaders(); + if (contentLength == 0) { + chan.write(buffers, 0, 2); + } else if (contentLength > 0) { + writeFixedContent(true); + } else { + writeStreamedContent(true); + } + setFinished(); + } + + private boolean finished; + + synchronized boolean finished() { + return finished; + } + + synchronized void setFinished() { + finished = true; + } + + private void collectHeaders() throws IOException { + if (Log.requests() && request != null) { + Log.logRequest(request.toString()); + } + String uriString = requestURI(); + StringBuilder sb = new StringBuilder(64); + sb.append(request.method()) + .append(' ') + .append(uriString) + .append(" HTTP/1.1\r\n"); + String cmd = sb.toString(); + + buffers[0] = ByteBuffer.wrap(cmd.getBytes(StandardCharsets.US_ASCII)); + URI uri = request.uri(); + if (uri != null) { + systemHeaders.setHeader("Host", uri.getHost()); + } + if (request == null) { + // this is not a user request. No content + contentLength = 0; + } else { + contentLength = requestProc.onRequestStart(request, flowController); + } + + if (contentLength == 0) { + systemHeaders.setHeader("Content-Length", "0"); + collectHeaders0(); + } else if (contentLength > 0) { + /* [0] request line [1] headers [2] body */ + systemHeaders.setHeader("Content-Length", + Integer.toString((int) contentLength)); + streaming = false; + collectHeaders0(); + buffers[2] = chan.getBuffer(); + } else { + /* Chunked: + * + * [0] request line [1] headers [2] chunk header [3] chunk data [4] + * final chunk header and trailing CRLF of previous chunks + * + * 2,3,4 used repeatedly */ + streaming = true; + systemHeaders.setHeader("Transfer-encoding", "chunked"); + collectHeaders0(); + buffers[3] = chan.getBuffer(); + } + } + + // The following two methods used by Http1Exchange to handle expect continue + + void continueRequest() throws IOException { + if (streaming) { + writeStreamedContent(false); + } else { + writeFixedContent(false); + } + setFinished(); + } + + /* Entire request is sent, or just body only */ + private void writeStreamedContent(boolean includeHeaders) + throws IOException + { + if (requestProc instanceof HttpRequest.BodyProcessor) { + HttpRequest.BodyProcessor pullproc = requestProc; + int startbuf, nbufs; + + if (includeHeaders) { + startbuf = 0; + nbufs = 5; + } else { + startbuf = 2; + nbufs = 3; + } + try { + // TODO: currently each write goes out as one chunk + // TODO: should be collecting data and buffer it. + + buffers[3].clear(); + boolean done = pullproc.onRequestBodyChunk(buffers[3]); + int chunklen = buffers[3].position(); + buffers[2] = getHeader(chunklen); + buffers[3].flip(); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, startbuf, nbufs); + while (!done) { + buffers[3].clear(); + done = pullproc.onRequestBodyChunk(buffers[3]); + if (done) + break; + buffers[3].flip(); + chunklen = buffers[3].remaining(); + buffers[2] = getHeader(chunklen); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, 2, 3); + } + buffers[3] = EMPTY_CHUNK_HEADER(); + buffers[4] = CRLF_BUFFER(); + chan.write(buffers, 3, 2); + } catch (IOException e) { + requestProc.onRequestError(e); + throw e; + } + } + } + /* Entire request is sent, or just body only */ + private void writeFixedContent(boolean includeHeaders) + throws IOException + { + try { + int startbuf, nbufs; + + if (contentLength == 0) { + return; + } + if (includeHeaders) { + startbuf = 0; + nbufs = 3; + } else { + startbuf = 2; + nbufs = 1; + buffers[0].clear().flip(); + buffers[1].clear().flip(); + } + buffers[2] = chan.getBuffer(); + if (requestProc instanceof HttpRequest.BodyProcessor) { + HttpRequest.BodyProcessor pullproc = requestProc; + + boolean done = pullproc.onRequestBodyChunk(buffers[2]); + buffers[2].flip(); + long headersLength = buffers[0].remaining() + buffers[1].remaining(); + long contentWritten = buffers[2].remaining(); + chan.checkWrite(headersLength + contentWritten, + buffers, + startbuf, + nbufs); + while (!done) { + buffers[2].clear(); + done = pullproc.onRequestBodyChunk(buffers[2]); + buffers[2].flip(); + long len = buffers[2].remaining(); + if (contentWritten + len > contentLength) { + break; + } + chan.checkWrite(len, buffers[2]); + contentWritten += len; + } + if (contentWritten != contentLength) { + throw new IOException("wrong content length"); + } + } + } catch (IOException e) { + requestProc.onRequestError(e); + throw e; + } + } + + private static final byte[] CRLF = {'\r', '\n'}; + private static final byte[] EMPTY_CHUNK_BYTES = {'0', '\r', '\n'}; + + private ByteBuffer CRLF_BUFFER() { + return ByteBuffer.wrap(CRLF); + } + + private ByteBuffer EMPTY_CHUNK_HEADER() { + return ByteBuffer.wrap(EMPTY_CHUNK_BYTES); + } + + /* Returns a header for a particular chunk size */ + private static ByteBuffer getHeader(int size){ + String hexStr = Integer.toHexString(size); + byte[] hexBytes = hexStr.getBytes(US_ASCII); + byte[] header = new byte[hexStr.length()+2]; + System.arraycopy(hexBytes, 0, header, 0, hexBytes.length); + header[hexBytes.length] = CRLF[0]; + header[hexBytes.length+1] = CRLF[1]; + return ByteBuffer.wrap(header); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java new file mode 100644 index 00000000000..6fad37b6b8f --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http1Response.java @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.function.LongConsumer; +import static java.net.http.HttpClient.Version.HTTP_1_1; + +/** + * Handles a HTTP/1.1 response in two blocking calls. readHeaders() and + * readBody(). There can be more than one of these per Http exchange. + */ +class Http1Response { + + private ResponseContent content; + private final HttpRequestImpl request; + HttpResponseImpl response; + private final HttpConnection connection; + private ResponseHeaders headers; + private int responseCode; + private ByteBuffer buffer; // same buffer used for reading status line and headers + private final Http1Exchange exchange; + private final boolean redirecting; // redirecting + private boolean return2Cache; // return connection to cache when finished + + Http1Response(HttpConnection conn, Http1Exchange exchange) { + this.request = exchange.request(); + this.exchange = exchange; + this.connection = conn; + this.redirecting = false; + buffer = connection.getRemaining(); + } + + // called when the initial read should come from a buffer left + // over from a previous response. + void setBuffer(ByteBuffer buffer) { + this.buffer = buffer; + } + + @SuppressWarnings("unchecked") + public void readHeaders() throws IOException { + String statusline = readStatusLine(); + if (statusline == null) { + if (Log.errors()) { + Log.logError("Connection closed. Retry"); + } + connection.close(); + // connection was closed + throw new IOException("Connection closed"); + } + if (!statusline.startsWith("HTTP/1.")) { + throw new IOException("Invalid status line: " + statusline); + } + char c = statusline.charAt(7); + responseCode = Integer.parseInt(statusline.substring(9, 12)); + + headers = new ResponseHeaders(connection, buffer); + headers.initHeaders(); + if (Log.headers()) { + logHeaders(headers); + } + response = new HttpResponseImpl(responseCode, + exchange.exchange, + headers, + null, + connection.sslParameters(), + HTTP_1_1, + connection); + } + + private boolean finished; + + synchronized void completed() { + finished = true; + } + + synchronized boolean finished() { + return finished; + } + + // Blocking flow controller implementation. Only works when a + // thread is dedicated to reading response body + + static class FlowController implements LongConsumer { + long window ; + + @Override + public synchronized void accept(long value) { + window += value; + notifyAll(); + } + + public synchronized void request(long value) throws InterruptedException { + while (window < value) { + wait(); + } + window -= value; + } + } + + FlowController flowController; + + int fixupContentLen(int clen) { + if (request.method().equalsIgnoreCase("HEAD")) { + return 0; + } + if (clen == -1) { + if (headers.firstValue("Transfer-encoding").orElse("") + .equalsIgnoreCase("chunked")) { + return -1; + } + return 0; + } + return clen; + } + + private void returnBuffer(ByteBuffer buf) { + // not currently used, but will be when we change SSL to use fixed + // sized buffers and a single buffer pool for HttpClientImpl + } + + @SuppressWarnings("unchecked") + public T readBody(java.net.http.HttpResponse.BodyProcessor p, + boolean return2Cache) + throws IOException + { + T body = null; // TODO: check null case below + this.return2Cache = return2Cache; + final java.net.http.HttpResponse.BodyProcessor pusher = p; + + int clen0 = headers.getContentLength(); + final int clen = fixupContentLen(clen0); + + flowController = new FlowController(); + + body = pusher.onResponseBodyStart(clen, headers, flowController); + + ExecutorWrapper executor; + if (body == null) { + executor = ExecutorWrapper.callingThread(); + } else { + executor = request.client().executorWrapper(); + } + + final ResponseHeaders h = headers; + if (body == null) { + content = new ResponseContent(connection, + clen, + h, + pusher, + flowController); + content.pushBody(headers.getResidue()); + body = pusher.onResponseComplete(); + completed(); + onFinished(); + return body; + } else { + executor.execute(() -> { + try { + content = new ResponseContent(connection, + clen, + h, + pusher, + flowController); + content.pushBody(headers.getResidue()); + pusher.onResponseComplete(); + completed(); + onFinished(); + } catch (Throwable e) { + pusher.onResponseError(e); + } + }, + () -> response.getAccessControlContext()); + } + return body; + } + + private void onFinished() { + connection.buffer = content.getResidue(); + if (return2Cache) { + connection.returnToCache(headers); + } + } + + private void logHeaders(ResponseHeaders headers) { + Map> h = headers.mapInternal(); + Set keys = h.keySet(); + Set>> entries = h.entrySet(); + for (Map.Entry> entry : entries) { + String key = entry.getKey(); + StringBuilder sb = new StringBuilder(); + sb.append(key).append(": "); + List values = entry.getValue(); + if (values != null) { + for (String value : values) { + sb.append(value).append(' '); + } + } + Log.logHeaders(sb.toString()); + } + } + + HttpResponseImpl response() { + return response; + } + + boolean redirecting() { + return redirecting; + } + + HttpHeaders responseHeaders() { + return headers; + } + + int responseCode() { + return responseCode; + } + + static final char CR = '\r'; + static final char LF = '\n'; + + private ByteBuffer getBuffer() throws IOException { + if (buffer == null || !buffer.hasRemaining()) { + buffer = connection.read(); + } + return buffer; + } + + ByteBuffer buffer() { + return buffer; + } + + String readStatusLine() throws IOException { + boolean cr = false; + StringBuilder statusLine = new StringBuilder(128); + ByteBuffer b; + while ((b = getBuffer()) != null) { + byte[] buf = b.array(); + int offset = b.position(); + int len = b.limit() - offset; + + for (int i = 0; i < len; i++) { + char c = (char) buf[i+offset]; + + if (cr) { + if (c == LF) { + b.position(i + 1 + offset); + return statusLine.toString(); + } else { + throw new IOException("invalid status line"); + } + } + if (c == CR) { + cr = true; + } else { + statusLine.append(c); + } + } + // unlikely, but possible, that multiple reads required + b.position(b.limit()); + } + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java new file mode 100644 index 00000000000..4491168225b --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2ClientImpl.java @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 + */ +package java.net.http; + +class Http2ClientImpl { + Http2ClientImpl(HttpClientImpl t) {} + String getSettingsString() {return "";} + void debugPrint() {} + Http2Connection getConnectionFor(HttpRequestImpl r) { + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java new file mode 100644 index 00000000000..3f60c4f805e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Http2Connection.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.net.URI; +import static java.net.http.Utils.BUFSIZE; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import java.nio.channels.Selector; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; +import java.util.concurrent.*; +import java.security.NoSuchAlgorithmException; +import java.util.ListIterator; +import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +class Http2Connection { + static CompletableFuture createAsync( + HttpConnection connection, Http2ClientImpl client2, Exchange exchange) { + return null; + } + + Http2Connection(HttpConnection connection, Http2ClientImpl client2, + Exchange exchange) throws IOException, InterruptedException { + } + + Stream getStream(int i) {return null;} + Stream createStream(Exchange ex) {return null;} + void putConnection() {} +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java new file mode 100644 index 00000000000..d0989f399cb --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClient.java @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.InetSocketAddress; +import java.net.NetPermission; +import java.net.ProxySelector; +import java.net.URI; +import java.util.Optional; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +/** + * A container for configuration information common to multiple {@link + * HttpRequest}s. All requests are associated with, and created from a {@code + * HttpClient}. + * + *

    {@code HttpClient}s are immutable and created from a builder returned + * from {@link HttpClient#create()}. Request builders that are associated with + * an application created client, are created by calling {@link #request(URI) }. + * It is also possible to create a request builder directly which is associated + * with the default {@code HttpClient} by calling {@link + * HttpRequest#create(URI)}. + * + *

    The HTTP API functions asynchronously (using {@link + * java.util.concurrent.CompletableFuture}) and also in a simple synchronous + * mode, where all work may be done on the calling thread. In asynchronous mode, + * work is done on the threads supplied by the client's {@link + * java.util.concurrent.ExecutorService}. + * + *

    The default {@code HttpClient} is + * used whenever a request is created without specifying a client explicitly + * (by calling {@link HttpRequest#create(java.net.URI) HttpRequest.create}). + * There is only one static instance of this {@code HttpClient}. A reference to + * the default client can be obtained by calling {@link #getDefault() }. If a + * security manager is set, then a permission is required for this. + * + *

    See {@link HttpRequest} for examples of usage of this API. + * + * @since 9 + */ +public abstract class HttpClient { + + HttpClient() {} + + private static HttpClient defaultClient; + + /** + * Creates a new {@code HttpClient} builder. + * + * @return a {@code HttpClient.Builder} + */ + public static Builder create() { + return new HttpClientBuilderImpl(); + } + + //public abstract void debugPrint(); + + /** + * Returns the default {@code HttpClient} that is used when a {@link + * HttpRequest} is created without specifying a client. If a security + * manager is set, then its {@code checkPermission} method is called with a + * {@link java.net.NetPermission} specifying the name "getDefaultHttpClient". + * If the caller does not possess this permission a {@code SecurityException} + * is thrown. + * + * @implNote Code running under a security manager can avoid the security + * manager check by creating a {@code HttpClient} explicitly. + * + * @return the default {@code HttpClient} + * @throws SecurityException if the caller does not have the required + * permission + */ + public synchronized static HttpClient getDefault() { + Utils.checkNetPermission("getDefaultHttpClient"); + if (defaultClient == null) { + Builder b = create(); + defaultClient = b.executorService(Executors.newCachedThreadPool()) + .build(); + } + return defaultClient; + } + + /** + * Creates a {@code HttpRequest} builder associated with this client. + * + * @return a new builder + */ + public abstract HttpRequest.Builder request(); + + /** + * Creates a {@code HttpRequest} builder associated with this client and + * using the given request URI. + * + * @param uri the request URI + * @return a new builder + */ + public abstract HttpRequest.Builder request(URI uri); + + /** + * A builder of immutable {@link HttpClient}s. {@code HttpClient.Builder}s + * are created by calling {@link HttpClient#create()}. + * + *

    Each of the setter methods in this class modifies the state of the + * builder and returns this (ie. the same instance). The methods are + * not synchronized and should not be called from multiple threads without + * external synchronization. + * + *

    {@link #build() } returns a new {@code HttpClient} each time it is + * called. + * + * @since 9 + */ + public abstract static class Builder { + + Builder() {} + + /** + * Sets a cookie manager. + * + * @param manager the CookieManager + * @return this builder + * @throws NullPointerException if {@code manager} is null + */ + public abstract Builder cookieManager(CookieManager manager); + + /** + * Sets an SSLContext. If a security manager is set, then the caller + * must have the {@link java.net.NetPermission NetPermission} + * ("setSSLContext") + * + *

    The effect of not calling this method, is that a default {@link + * javax.net.ssl.SSLContext} is used, which is normally adequate for + * client applications that do not need to specify protocols, or require + * client authentication. + * + * @param sslContext the SSLContext + * @return this builder + * @throws NullPointerException if {@code sslContext} is null + * @throws SecurityException if a security manager is set and the + * caller does not have any required permission + */ + public abstract Builder sslContext(SSLContext sslContext); + + /** + * Sets an SSLParameters. If this method is not called, then a default + * set of parameters are used. The contents of the given object are + * copied. Some parameters which are used internally by the HTTP protocol + * implementation (such as application protocol list) should not be set + * by callers, as they are ignored. + * + * @param sslParameters the SSLParameters + * @return this builder + * @throws NullPointerException if {@code sslParameters} is null + */ + public abstract Builder sslParameters(SSLParameters sslParameters); + + /** + * Sets the ExecutorService to be used for sending and receiving + * asynchronous requests. If this method is not called, a default + * executor service is set, which is the one returned from {@link + * java.util.concurrent.Executors#newCachedThreadPool() + * Executors.newCachedThreadPool}. + * + * @param s the ExecutorService + * @return this builder + * @throws NullPointerException if {@code s} is null + */ + public abstract Builder executorService(ExecutorService s); + + /** + * Specifies whether requests will automatically follow redirects issued + * by the server. This setting can be overridden on each request. The + * default value for this setting is {@link Redirect#NEVER NEVER} + * + * @param policy the redirection policy + * @return this builder + * @throws NullPointerException if {@code policy} is null + */ + public abstract Builder followRedirects(Redirect policy); + + /** + * Requests a specific HTTP protocol version where possible. If not set, + * the version defaults to {@link HttpClient.Version#HTTP_1_1}. If + * {@link HttpClient.Version#HTTP_2} is set, then each request will + * attempt to upgrade to HTTP/2. If the upgrade succeeds, then the + * response to this request will use HTTP/2 and all subsequent requests + * and responses to the same + * origin server + * will use HTTP/2. If the upgrade fails, then the response will be + * handled using HTTP/1.1 + * + *

    This setting can be over-ridden per request. + * + * @param version the requested HTTP protocol version + * @return this builder + * @throws NullPointerException if {@code version} is null + */ + public abstract Builder version(HttpClient.Version version); + + /** + * Sets the default priority for any HTTP/2 requests sent from this + * client. The value provided must be between {@code 1} and {@code 255}. + * + * @param priority the priority weighting + * @return this builder + * @throws IllegalArgumentException if the given priority is out of range + */ + public abstract Builder priority(int priority); + + /** + * Enables pipelining mode for HTTP/1.1 requests sent through this + * client. When pipelining is enabled requests to the same destination + * are sent over existing TCP connections that may already have requests + * outstanding. This reduces the number of connections, but may have + * a performance impact since responses must be delivered in the same + * order that they were sent. By default, pipelining is disabled. + * + * @param enable {@code true} enables pipelining + * @return this builder + * @throws UnsupportedOperationException if pipelining mode is not + * supported by this implementation + */ + public abstract Builder pipelining(boolean enable); + + /** + * Sets a {@link java.net.ProxySelector} for this client. If no selector + * is set, then no proxies are used. If a {@code null} parameter is + * given then the system wide default proxy selector is used. + * + * @implNote {@link java.net.ProxySelector#of(InetSocketAddress)} + * provides a ProxySelector which uses one proxy for all requests. + * + * @param selector the ProxySelector + * @return this builder + */ + public abstract Builder proxy(ProxySelector selector); + + /** + * Sets an authenticator to use for HTTP authentication. + * + * @param a the Authenticator + * @return this builder + */ + public abstract Builder authenticator(Authenticator a); + + /** + * Returns a {@link HttpClient} built from the current state of this + * builder. + * + * @return this builder + */ + public abstract HttpClient build(); + } + + + /** + * Returns an {@code Optional} which contains this client's {@link + * CookieManager}. If no CookieManager was set in this client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's CookieManager + */ + public abstract Optional cookieManager(); + + /** + * Returns the follow-redirects setting for this client. The default value + * for this setting is {@link HttpClient.Redirect#NEVER} + * + * @return this client's follow redirects setting + */ + public abstract Redirect followRedirects(); + + /** + * Returns an {@code Optional} containing the ProxySelector for this client. + * If no proxy is set then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's proxy selector + */ + public abstract Optional proxy(); + + /** + * Returns the SSLContext, if one was set on this client. If a security + * manager is set then then caller must then the caller must have the + * {@link java.net.NetPermission NetPermission}("getSSLContext") permission. + * If no SSLContext was set, then the default context is returned. + * + * @return this client's SSLContext + */ + public abstract SSLContext sslContext(); + + /** + * Returns an {@code Optional} containing the {@link SSLParameters} set on + * this client. If no {@code SSLParameters} were set in the client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's SSLParameters + */ + public abstract Optional sslParameters(); + + /** + * Returns an {@code Optional} containing the {@link Authenticator} set on + * this client. If no {@code Authenticator} was set in the client's builder, + * then the {@code Optional} is empty. + * + * @return an {@code Optional} containing this client's Authenticator + */ + public abstract Optional authenticator(); + + /** + * Returns the HTTP protocol version requested for this client. The default + * value is {@link HttpClient.Version#HTTP_1_1} + * + * @return the HTTP protocol version requested + */ + public abstract HttpClient.Version version(); + + /** + * Returns whether this client supports HTTP/1.1 pipelining. + * + * @return whether pipelining allowed + */ + public abstract boolean pipelining(); + + /** + * Returns the {@code ExecutorService} set on this client. If an {@code + * ExecutorService} was not set on the client's builder, then a default + * object is returned. The default ExecutorService is created independently + * for each client. + * + * @return this client's ExecutorService + */ + public abstract ExecutorService executorService(); + + /** + * The HTTP protocol version. + * + * @since 9 + */ + public static enum Version { + + /** + * HTTP version 1.1 + */ + HTTP_1_1, + + /** + * HTTP version 2 + */ + HTTP_2 + } + + /** + * Defines automatic redirection policy. This is checked whenever a 3XX + * response code is received. If redirection does not happen automatically + * then the response is returned to the user, where it can be handled + * manually. + * + *

    {@code Redirect} policy is set via the {@link + * HttpClient.Builder#followRedirects(HttpClient.Redirect)} method. + * + * @since 9 + */ + public static enum Redirect { + + /** + * Never redirect. + */ + NEVER, + + /** + * Always redirect. + */ + ALWAYS, + + /** + * Redirect to same protocol only. Redirection may occur from HTTP URLs + * to other HTTP URLs, and from HTTPS URLs to other HTTPS URLs. + */ + SAME_PROTOCOL, + + /** + * Redirect always except from HTTPS URLs to HTTP URLs. + */ + SECURE + } + +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java new file mode 100644 index 00000000000..c93025d477a --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientBuilderImpl.java @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +class HttpClientBuilderImpl extends HttpClient.Builder { + + CookieManager cookieManager; + HttpClient.Redirect followRedirects; + ProxySelector proxy; + Authenticator authenticator; + HttpClient.Version version = HttpClient.Version.HTTP_1_1; + ExecutorService executor; + // Security parameters + SSLContext sslContext; + SSLParameters sslParams; + int priority = -1; + + @Override + public HttpClientBuilderImpl cookieManager(CookieManager manager) { + Objects.requireNonNull(manager); + this.cookieManager = manager; + return this; + } + + + @Override + public HttpClientBuilderImpl sslContext(SSLContext sslContext) { + Objects.requireNonNull(sslContext); + Utils.checkNetPermission("setSSLContext"); + this.sslContext = sslContext; + return this; + } + + + @Override + public HttpClientBuilderImpl sslParameters(SSLParameters sslParameters) { + Objects.requireNonNull(sslParameters); + this.sslParams = sslParameters; + return this; + } + + + @Override + public HttpClientBuilderImpl executorService(ExecutorService s) { + Objects.requireNonNull(s); + this.executor = s; + return this; + } + + + @Override + public HttpClientBuilderImpl followRedirects(HttpClient.Redirect policy) { + Objects.requireNonNull(policy); + this.followRedirects = policy; + return this; + } + + + @Override + public HttpClientBuilderImpl version(HttpClient.Version version) { + Objects.requireNonNull(version); + this.version = version; + return this; + } + + + @Override + public HttpClientBuilderImpl priority(int priority) { + if (priority < 1 || priority > 255) { + throw new IllegalArgumentException("priority must be between 1 and 255"); + } + this.priority = priority; + return this; + } + + + @Override + public HttpClientBuilderImpl pipelining(boolean enable) { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } + + + @Override + public HttpClientBuilderImpl proxy(ProxySelector proxy) { + Objects.requireNonNull(proxy); + this.proxy = proxy; + return this; + } + + + @Override + public HttpClientBuilderImpl authenticator(Authenticator a) { + Objects.requireNonNull(a); + this.authenticator = a; + return this; + } + + @Override + public HttpClient build() { + return HttpClientImpl.create(this); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java new file mode 100644 index 00000000000..fd1ab0b012d --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpClientImpl.java @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.Authenticator; +import java.net.CookieManager; +import java.net.ProxySelector; +import java.net.URI; +import static java.net.http.Utils.BUFSIZE; +import java.nio.ByteBuffer; +import java.nio.channels.ClosedChannelException; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import static java.nio.channels.SelectionKey.OP_CONNECT; +import static java.nio.channels.SelectionKey.OP_READ; +import static java.nio.channels.SelectionKey.OP_WRITE; +import java.nio.channels.Selector; +import java.util.*; +import java.util.stream.Stream; +import java.util.concurrent.ExecutorService; +import java.security.NoSuchAlgorithmException; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLParameters; + +/** + * Client implementation. Contains all configuration information and also + * the selector manager thread which allows async events to be registered + * and delivered when they occur. See AsyncEvent. + */ +class HttpClientImpl extends HttpClient implements BufferHandler { + + private final CookieManager cookieManager; + private final Redirect followRedirects; + private final ProxySelector proxySelector; + private final Authenticator authenticator; + private final Version version; + private boolean pipelining = false; + private final ConnectionPool connections; + private final ExecutorWrapper executor; + // Security parameters + private final SSLContext sslContext; + private final SSLParameters sslParams; + private final SelectorManager selmgr; + private final FilterFactory filters; + private final Http2ClientImpl client2; + private static final ThreadFactory defaultFactory = Executors.defaultThreadFactory(); + private final LinkedList timeouts; + + public static HttpClientImpl create(HttpClientBuilderImpl builder) { + HttpClientImpl impl = new HttpClientImpl(builder); + impl.start(); + return impl; + } + + private HttpClientImpl(HttpClientBuilderImpl builder) { + if (builder.sslContext == null) { + try { + sslContext = SSLContext.getDefault(); + } catch (NoSuchAlgorithmException ex) { + throw new InternalError(ex); + } + } else { + sslContext = builder.sslContext; + } + ExecutorService ex = builder.executor; + if (ex == null) { + ex = Executors.newCachedThreadPool((r) -> { + Thread t = defaultFactory.newThread(r); + t.setDaemon(true); + return t; + }); + } else { + ex = builder.executor; + } + client2 = new Http2ClientImpl(this); + executor = ExecutorWrapper.wrap(ex); + cookieManager = builder.cookieManager; + followRedirects = builder.followRedirects == null ? + Redirect.NEVER : builder.followRedirects; + this.proxySelector = builder.proxy; + authenticator = builder.authenticator; + version = builder.version; + sslParams = builder.sslParams; + connections = new ConnectionPool(); + connections.start(); + timeouts = new LinkedList<>(); + try { + selmgr = new SelectorManager(); + } catch (IOException e) { + // unlikely + throw new InternalError(e); + } + selmgr.setDaemon(true); + selmgr.setName("HttpSelector"); + filters = new FilterFactory(); + initFilters(); + } + + private void start() { + selmgr.start(); + } + + /** + * Wait for activity on given exchange (assuming blocking = false). + * It's a no-op if blocking = true. In particular, the following occurs + * in the SelectorManager thread. + * + * 1) mark the connection non-blocking + * 2) add to selector + * 3) If selector fires for this exchange then + * 4) - mark connection as blocking + * 5) - call AsyncEvent.handle() + * + * If exchange needs to block again, then call registerEvent() again + */ + void registerEvent(AsyncEvent exchange) throws IOException { + selmgr.register(exchange); + } + + Http2ClientImpl client2() { + return client2; + } + + LinkedList freelist = new LinkedList<>(); + + @Override + public synchronized ByteBuffer getBuffer() { + if (freelist.isEmpty()) { + return ByteBuffer.allocate(BUFSIZE); + } + return freelist.removeFirst(); + } + + @Override + public synchronized void returnBuffer(ByteBuffer buffer) { + buffer.clear(); + freelist.add(buffer); + } + + + // Main loop for this client's selector + + class SelectorManager extends Thread { + final Selector selector; + boolean closed; + + final List readyList; + final List registrations; + + SelectorManager() throws IOException { + readyList = new LinkedList<>(); + registrations = new LinkedList<>(); + selector = Selector.open(); + } + + // This returns immediately. So caller not allowed to send/receive + // on connection. + + synchronized void register(AsyncEvent e) throws IOException { + registrations.add(e); + selector.wakeup(); + } + + void wakeupSelector() { + selector.wakeup(); + } + + synchronized void shutdown() { + closed = true; + try { + selector.close(); + } catch (IOException e) {} + } + + private List copy(List list) { + LinkedList c = new LinkedList<>(); + for (AsyncEvent e : list) { + c.add(e); + } + return c; + } + + String opvals(int i) { + StringBuilder sb = new StringBuilder(); + if ((i & OP_READ) != 0) + sb.append("OP_READ "); + if ((i & OP_CONNECT) != 0) + sb.append("OP_CONNECT "); + if ((i & OP_WRITE) != 0) + sb.append("OP_WRITE "); + return sb.toString(); + } + + @Override + public void run() { + try { + while (true) { + synchronized (this) { + for (AsyncEvent exchange : registrations) { + SelectableChannel c = exchange.channel(); + try { + c.configureBlocking(false); + SelectionKey key = c.keyFor(selector); + SelectorAttachment sa; + if (key == null) { + sa = new SelectorAttachment(c, selector); + } else { + sa = (SelectorAttachment)key.attachment(); + } + sa.register(exchange); + } catch (IOException e) { + Log.logError("HttpClientImpl: " + e); + c.close(); + // let the exchange deal with it + handleEvent(exchange); + } + } + registrations.clear(); + } + long timeval = getTimeoutValue(); + long now = System.currentTimeMillis(); + int n = selector.select(timeval); + if (n == 0) { + signalTimeouts(now); + continue; + } + Set keys = selector.selectedKeys(); + + for (SelectionKey key : keys) { + SelectorAttachment sa = (SelectorAttachment)key.attachment(); + int eventsOccurred = key.readyOps(); + sa.events(eventsOccurred).forEach(readyList::add); + sa.resetInterestOps(eventsOccurred); + } + selector.selectNow(); // complete cancellation + selector.selectedKeys().clear(); + + for (AsyncEvent exchange : readyList) { + if (exchange instanceof AsyncEvent.Blocking) { + exchange.channel().configureBlocking(true); + } else { + assert exchange instanceof AsyncEvent.NonBlocking; + } + executor.synchronize(); + handleEvent(exchange); // will be delegated to executor + } + readyList.clear(); + } + } catch (Throwable e) { + if (!closed) { + System.err.println("HttpClientImpl terminating on error"); + // This terminates thread. So, better just print stack trace + String err = Utils.stackTrace(e); + Log.logError("HttpClientImpl: fatal error: " + err); + } + } + } + + void handleEvent(AsyncEvent e) { + if (closed) { + e.abort(); + } else { + e.handle(); + } + } + } + + /** + * Tracks multiple user level registrations associated with one NIO + * registration (SelectionKey). In this implementation, registrations + * are one-off and when an event is posted the registration is cancelled + * until explicitly registered again. + * + *

    No external synchronization required as this class is only used + * by the SelectorManager thread. One of these objects required per + * connection. + */ + private static class SelectorAttachment { + private final SelectableChannel chan; + private final Selector selector; + private final ArrayList pending; + private int interestops; + + SelectorAttachment(SelectableChannel chan, Selector selector) { + this.pending = new ArrayList<>(); + this.chan = chan; + this.selector = selector; + } + + void register(AsyncEvent e) throws ClosedChannelException { + int newops = e.interestOps(); + boolean reRegister = (interestops & newops) != newops; + interestops |= newops; + pending.add(e); + if (reRegister) { + // first time registration happens here also + chan.register(selector, interestops, this); + } + } + + int interestOps() { + return interestops; + } + + /** + * Returns a Stream containing only events that are + * registered with the given {@code interestop}. + */ + Stream events(int interestop) { + return pending.stream() + .filter(ev -> (ev.interestOps() & interestop) != 0); + } + + /** + * Removes any events with the given {@code interestop}, and if no + * events remaining, cancels the associated SelectionKey. + */ + void resetInterestOps(int interestop) { + int newops = 0; + + Iterator itr = pending.iterator(); + while (itr.hasNext()) { + AsyncEvent event = itr.next(); + int evops = event.interestOps(); + if ((evops & interestop) != 0) { + itr.remove(); + } else { + newops |= evops; + } + } + + interestops = newops; + SelectionKey key = chan.keyFor(selector); + if (newops == 0) { + key.cancel(); + } else { + key.interestOps(newops); + } + } + } + + /** + * Creates a HttpRequest associated with this group. + * + * @throws IllegalStateException if the group has been stopped + */ + @Override + public HttpRequestBuilderImpl request() { + return new HttpRequestBuilderImpl(this, null); + } + + /** + * Creates a HttpRequest associated with this group. + * + * @throws IllegalStateException if the group has been stopped + */ + @Override + public HttpRequestBuilderImpl request(URI uri) { + return new HttpRequestBuilderImpl(this, uri); + } + + @Override + public SSLContext sslContext() { + Utils.checkNetPermission("getSSLContext"); + return sslContext; + } + + @Override + public Optional sslParameters() { + return Optional.ofNullable(sslParams); + } + + @Override + public Optional authenticator() { + return Optional.ofNullable(authenticator); + } + + @Override + public ExecutorService executorService() { + return executor.userExecutor(); + } + + ExecutorWrapper executorWrapper() { + return executor; + } + + @Override + public boolean pipelining() { + return this.pipelining; + } + + ConnectionPool connectionPool() { + return connections; + } + + @Override + public Redirect followRedirects() { + return followRedirects; + } + + + @Override + public Optional cookieManager() { + return Optional.ofNullable(cookieManager); + } + + @Override + public Optional proxy() { + return Optional.ofNullable(this.proxySelector); + } + + @Override + public Version version() { + return version; + } + + //private final HashMap http2NotSupported = new HashMap<>(); + + boolean getHttp2Allowed() { + return version.equals(Version.HTTP_2); + } + + //void setHttp2NotSupported(String host) { + //http2NotSupported.put(host, false); + //} + + final void initFilters() { + addFilter(AuthenticationFilter.class); + addFilter(RedirectFilter.class); + } + + final void addFilter(Class f) { + filters.addFilter(f); + } + + final List filterChain() { + return filters.getFilterChain(); + } + + // Timer controls. Timers are implemented through timed Selector.select() + // calls. + synchronized void registerTimer(TimeoutEvent event) { + long elapse = event.timevalMillis(); + ListIterator iter = timeouts.listIterator(); + long listval = 0; + event.delta = event.timeval; // in case list empty + TimeoutEvent next; + while (iter.hasNext()) { + next = iter.next(); + listval += next.delta; + if (elapse < listval) { + listval -= next.delta; + event.delta = elapse - listval; + next.delta -= event.delta; + iter.previous(); + break; + } else if (!iter.hasNext()) { + event.delta = event.timeval - listval ; + } + } + iter.add(event); + selmgr.wakeupSelector(); + } + + synchronized void signalTimeouts(long then) { + if (timeouts.isEmpty()) { + return; + } + long now = System.currentTimeMillis(); + long duration = now - then; + ListIterator iter = timeouts.listIterator(); + TimeoutEvent event = iter.next(); + long delta = event.delta; + if (duration < delta) { + event.delta -= duration; + return; + } + event.handle(); + iter.remove(); + while (iter.hasNext()) { + event = iter.next(); + if (event.delta == 0) { + event.handle(); + iter.remove(); + } else { + event.delta += delta; + break; + } + } + } + + synchronized void cancelTimer(TimeoutEvent event) { + ListIterator iter = timeouts.listIterator(); + while (iter.hasNext()) { + TimeoutEvent ev = iter.next(); + if (event == ev) { + if (iter.hasNext()) { + // adjust + TimeoutEvent next = iter.next(); + next.delta += ev.delta; + iter.previous(); + } + iter.remove(); + } + } + } + + // used for the connection window + int getReceiveBufferSize() { + return Utils.getIntegerNetProperty( + "sun.net.httpclient.connectionWindowSize", 256 * 1024 + ); + } + + // returns 0 meaning block forever, or a number of millis to block for + synchronized long getTimeoutValue() { + if (timeouts.isEmpty()) { + return 0; + } else { + return timeouts.get(0).delta; + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java new file mode 100644 index 00000000000..ea82531b469 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpConnection.java @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLParameters; + +/** + * Wraps socket channel layer and takes care of SSL also. + * + * Subtypes are: + * PlainHttpConnection: regular direct TCP connection to server + * PlainProxyConnection: plain text proxy connection + * PlainTunnelingConnection: opens plain text (CONNECT) tunnel to server + * SSLConnection: TLS channel direct to server + * SSLTunnelConnection: TLS channel via (CONNECT) proxy tunnel + */ +abstract class HttpConnection implements BufferHandler { + + // address we are connected to. Could be a server or a proxy + final InetSocketAddress address; + final HttpClientImpl client; + protected volatile ByteBuffer buffer; + + HttpConnection(InetSocketAddress address, HttpClientImpl client) { + this.address = address; + this.client = client; + } + + /** + * Public API to this class. addr is the ultimate destination. Any proxies + * etc are figured out from the request. Returns an instance of one of the + * following + * PlainHttpConnection + * PlainTunnelingConnection + * SSLConnection + * SSLTunnelConnection + * + * When object returned, connect() or connectAsync() must be called, which + * when it returns/completes, the connection is usable for requests. + */ + public static HttpConnection getConnection(InetSocketAddress addr, + HttpRequestImpl request) { + return getConnectionImpl(addr, request); + } + + public abstract void connect() throws IOException, InterruptedException; + + public abstract CompletableFuture connectAsync(); + + /** + * Returns whether this connection is connected to its destination + */ + abstract boolean connected(); + + abstract boolean isSecure(); + + abstract boolean isProxied(); + + /** + * Completes when the first byte of the response is available to be read. + */ + abstract CompletableFuture whenReceivingResponse(); + + // must be called before reading any data off connection + // at beginning of response. + ByteBuffer getRemaining() { + ByteBuffer b = buffer; + buffer = null; + return b; + } + + final boolean isOpen() { + return channel().isOpen(); + } + + /* Returns either a plain HTTP connection or a plain tunnelling connection + * for proxied websockets */ + private static HttpConnection getPlainConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpRequestImpl request) { + HttpClientImpl client = request.client(); + + if (request.isWebSocket() && proxy != null) { + return new PlainTunnelingConnection(addr, + proxy, + client, + request.getAccessControlContext()); + } else { + if (proxy == null) { + return new PlainHttpConnection(addr, client); + } else { + return new PlainProxyConnection(proxy, client); + } + } + } + + private static HttpConnection getSSLConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpRequestImpl request, + String[] alpn) { + HttpClientImpl client = request.client(); + if (proxy != null) { + return new SSLTunnelConnection(addr, + client, + proxy, + request.getAccessControlContext()); + } else { + return new SSLConnection(addr, client, alpn); + } + } + + /** + * Main factory method. Gets a HttpConnection, either cached or new if + * none available. + */ + private static HttpConnection getConnectionImpl(InetSocketAddress addr, + HttpRequestImpl request) { + HttpConnection c; + HttpClientImpl client = request.client(); + InetSocketAddress proxy = request.proxy(); + boolean secure = request.secure(); + ConnectionPool pool = client.connectionPool(); + String[] alpn = null; + + if (secure && request.requestHttp2()) { + alpn = new String[1]; + alpn[0] = "h2"; + } + + if (!secure) { + c = pool.getConnection(false, addr, proxy); + if (c != null) { + return c; + } else { + return getPlainConnection(addr, proxy, request); + } + } else { + c = pool.getConnection(true, addr, proxy); + if (c != null) { + return c; + } else { + return getSSLConnection(addr, proxy, request, alpn); + } + } + } + + void returnToCache(HttpHeaders hdrs) { + if (hdrs == null) { + // the connection was closed by server + close(); + return; + } + if (!isOpen()) { + return; + } + ConnectionPool pool = client.connectionPool(); + boolean keepAlive = hdrs.firstValue("Connection") + .map((s) -> !s.equalsIgnoreCase("close")) + .orElse(true); + + if (keepAlive) { + pool.returnToPool(this); + } else { + close(); + } + } + + /** + * Also check that the number of bytes written is what was expected. This + * could be different if the buffer is user-supplied and its internal + * pointers were manipulated in a race condition. + */ + final void checkWrite(long expected, ByteBuffer buffer) throws IOException { + long written = write(buffer); + if (written != expected) { + throw new IOException("incorrect number of bytes written"); + } + } + + final void checkWrite(long expected, + ByteBuffer[] buffers, + int start, + int length) + throws IOException + { + long written = write(buffers, start, length); + if (written != expected) { + throw new IOException("incorrect number of bytes written"); + } + } + + abstract SocketChannel channel(); + + final InetSocketAddress address() { + return address; + } + + void configureBlocking(boolean mode) throws IOException { + channel().configureBlocking(mode); + } + + abstract ConnectionPool.CacheKey cacheKey(); + + /* + static PrintStream ps; + + static { + try { + String propval = Utils.getNetProperty("java.net.httpclient.showData"); + if (propval != null && propval.equalsIgnoreCase("true")) { + ps = new PrintStream(new FileOutputStream("/tmp/httplog.txt"), false); + } + } catch (IOException e) { + e.printStackTrace(); + } + } + + synchronized final void debugPrint(String s, ByteBuffer b) { + ByteBuffer[] bufs = new ByteBuffer[1]; + bufs[0] = b; + debugPrint(s, bufs, 0, 1); + } + + synchronized final void debugPrint(String s, + ByteBuffer[] bufs, + int start, + int number) { + if (ps == null) { + return; + } + + ps.printf("\n%s:\n", s); + + for (int i=start; i 0x20 && c <= 0x7F) { + ps.printf("%c", (char)c); + } else { + ps.printf("0x%02x ", c); + } + } + } + ps.printf("\n---------------------\n"); + } + + */ + + // overridden in SSL only + SSLParameters sslParameters() { + return null; + } + + // Methods to be implemented for Plain TCP and SSL + + abstract long write(ByteBuffer[] buffers, int start, int number) + throws IOException; + + abstract long write(ByteBuffer buffer) throws IOException; + + /** + * Closes this connection, by returning the socket to its connection pool. + */ + abstract void close(); + + /** + * Returns a ByteBuffer with data, or null if EOF. + */ + final ByteBuffer read() throws IOException { + return read(-1); + } + + /** + * Puts position to limit and limit to capacity so we can resume reading + * into this buffer, but if required > 0 then limit may be reduced so that + * no more than required bytes are read next time. + */ + static void resumeChannelRead(ByteBuffer buf, int required) { + int limit = buf.limit(); + buf.position(limit); + int capacity = buf.capacity() - limit; + if (required > 0 && required < capacity) { + buf.limit(limit + required); + } else { + buf.limit(buf.capacity()); + } + } + + /** + * Blocks ands return requested amount. + */ + final ByteBuffer read(int length) throws IOException { + if (length <= 0) { + buffer = readImpl(length); + return buffer; + } + buffer = readImpl(length); + int required = length - buffer.remaining(); + while (buffer.remaining() < length) { + resumeChannelRead(buffer, required); + int n = readImpl(buffer); + required -= n; + } + return buffer; + } + + final int read(ByteBuffer buffer) throws IOException { + int n = readImpl(buffer); + return n; + } + + /** Reads up to length bytes. */ + protected abstract ByteBuffer readImpl(int length) throws IOException; + + /** Reads as much as possible into given buffer and returns amount read. */ + protected abstract int readImpl(ByteBuffer buffer) throws IOException; + + @Override + public String toString() { + return "HttpConnection: " + channel().toString(); + } + + @Override + public final ByteBuffer getBuffer() { + return client.getBuffer(); + } + + @Override + public final void returnBuffer(ByteBuffer buffer) { + client.returnBuffer(buffer); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java new file mode 100644 index 00000000000..587e0af14bf --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** + * A read-only view of a set of received HTTP headers. + * + * @since 9 + */ +public interface HttpHeaders { + + /** + * Returns an {@link java.util.Optional} containing the first value of the + * given named (and possibly multi-valued) header. If the header is not + * present, then the returned {@code Optional} is empty. + * + * @param name the header name + * @return an {@code Optional} for the first named value + */ + public Optional firstValue(String name); + + /** + * Returns an {@link java.util.Optional} containing the first value of the + * named header field as an {@literal Optional}. If the header is not + * present, then the Optional is empty. If the header is present but + * contains a value that does not parse as a {@code Long} value, then an + * exception is thrown. + * + * @param name the header name + * @return an {@code Optional} + * @throws NumberFormatException if a value is found, but does not parse as + * a Long + */ + public Optional firstValueAsLong(String name); + + /** + * Returns an unmodifiable List of all of the values of the given named + * header. Always returns a List, which may be empty if the header is not + * present. + * + * @param name the header name + * @return a List of String values + */ + public List allValues(String name); + + /** + * Returns an unmodifiable multi Map view of this HttpHeaders. This + * interface should only be used when it is required to iterate over the + * entire set of headers. + * + * @return the Map + */ + public Map> map(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java new file mode 100644 index 00000000000..c9ff689a931 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeaders1.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +public interface HttpHeaders1 extends HttpHeaders { + public void makeUnmodifiable(); +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java new file mode 100644 index 00000000000..532625e65da --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpHeadersImpl.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Implementation of HttpHeaders. + */ +class HttpHeadersImpl implements HttpHeaders1 { + + private final HashMap> headers; + private boolean isUnmodifiable = false; + + public HttpHeadersImpl() { + headers = new HashMap<>(); + } + + /** + * Replace all List in headers with unmodifiable Lists. Call + * this only after all headers are added. The headers HashMap + * is wrapped with an unmodifiable HashMap in map() + */ + @Override + public void makeUnmodifiable() { + if (isUnmodifiable) + return; + + Set keys = new HashSet<>(headers.keySet()); + for (String key : keys) { + List values = headers.remove(key); + if (values != null) { + headers.put(key, Collections.unmodifiableList(values)); + } + } + isUnmodifiable = true; + } + + @Override + public Optional firstValue(String name) { + List l = headers.get(name); + return Optional.ofNullable(l == null ? null : l.get(0)); + } + + @Override + public List allValues(String name) { + return headers.get(name); + } + + @Override + public Map> map() { + return Collections.unmodifiableMap(headers); + } + + Map> directMap() { + return headers; + } + + // package private mutators + + public HttpHeadersImpl deepCopy() { + HttpHeadersImpl h1 = new HttpHeadersImpl(); + HashMap> headers1 = h1.headers; + Set keys = headers.keySet(); + for (String key : keys) { + List vals = headers.get(key); + LinkedList vals1 = new LinkedList<>(vals); + headers1.put(key, vals1); + } + return h1; + } + + private List getOrCreate(String name) { + List l = headers.get(name); + if (l == null) { + l = new LinkedList<>(); + headers.put(name, l); + } + return l; + } + + void addHeader(String name, String value) { + List l = getOrCreate(name); + l.add(value); + } + + void setHeader(String name, String value) { + List l = getOrCreate(name); + l.clear(); + l.add(value); + } + + @Override + public Optional firstValueAsLong(String name) { + List l = headers.get(name); + if (l == null) { + return Optional.ofNullable(null); + } else { + String v = l.get(0); + Long lv = Long.parseLong(v); + return Optional.of(lv); + } + } + + void clear() { + headers.clear(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java new file mode 100644 index 00000000000..fd177827fe3 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRedirectImpl.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.net.*; + +interface HttpRedirectImpl { + + static HttpRedirectImpl getRedirects(java.net.http.HttpClient.Redirect redir) { + switch (redir) { + case NEVER: + return HttpRedirectImpl.NEVER; + case ALWAYS: + return HttpRedirectImpl.ALWAYS; + case SECURE: + return HttpRedirectImpl.SECURE; + case SAME_PROTOCOL: + return HttpRedirectImpl.SAME_PROTOCOL; + } + return HttpRedirectImpl.NEVER; + } + + static HttpClient.Redirect getRedirects(HttpRedirectImpl redir) { + if (redir == HttpRedirectImpl.NEVER) { + return HttpClient.Redirect.NEVER; + } else if (redir == HttpRedirectImpl.ALWAYS) { + return HttpClient.Redirect.ALWAYS; + } else if (redir == HttpRedirectImpl.SECURE) { + return HttpClient.Redirect.SECURE; + } else { + return HttpClient.Redirect.SAME_PROTOCOL; + } + } + + /** + * Called to determine whether the given intermediate response + * with a redirection response code should be redirected. The target URI + * can be obtained from the "Location" header in the given response object. + * + * @param rsp the response from the redirected resource + * @return {@code true} if the redirect should be attempted automatically + * or {@code false} if not. + */ + boolean redirect(HttpResponse rsp); + + /** + * Never redirect. + */ + static HttpRedirectImpl NEVER = (HttpResponse rsp) -> false; + + /** + * Always redirect. + */ + static HttpRedirectImpl ALWAYS = (HttpResponse rsp) -> true; + + /** + * Redirect to same protocol only. Redirection may occur from HTTP URLs to + * other THHP URLs and from HTTPS URLs to other HTTPS URLs. + */ + static HttpRedirectImpl SAME_PROTOCOL = (HttpResponse rsp) -> { + String orig = rsp.request().uri().getScheme().toLowerCase(); + String redirect = URI.create( + rsp.headers().firstValue("Location").orElse("")) + .getScheme().toLowerCase(); + return orig.equals(redirect); + }; + + /** + * Redirect always except from HTTPS URLs to HTTP URLs. + */ + static HttpRedirectImpl SECURE = (HttpResponse rsp) -> { + String orig = rsp.request().uri().getScheme().toLowerCase(); + String redirect = URI.create( + rsp.headers().firstValue("Location").orElse("")) + .getScheme().toLowerCase(); + if (orig.equals("https")) { + return redirect.equals("https"); + } + return true; + }; +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java new file mode 100644 index 00000000000..66f84e360ce --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequest.java @@ -0,0 +1,871 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.net.URI; +import java.net.ProxySelector; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.*; +import java.nio.file.Path; +import java.util.Iterator; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.TimeUnit; +import java.util.function.LongConsumer; + +/** + * Represents one HTTP request which can be sent to a server. {@code + * HttpRequest}s are built from {@code HttpRequest} {@link HttpRequest.Builder + * builder}s. {@code HttpRequest} builders are obtained from a {@link HttpClient} + * by calling {@link HttpClient#request(java.net.URI) HttpClient.request}, or + * by calling {@link #create(java.net.URI) HttpRequest.create} which returns a + * builder on the default client. + * A request's {@link java.net.URI}, headers and body can be set. Request bodies + * are provided through a {@link BodyProcessor} object. Once all required + * parameters have been set in the builder, one of the builder methods should be + * called, which sets the request method and returns a {@code HttpRequest}. + * These methods are {@link Builder#GET() GET}, {@link HttpRequest.Builder#POST() + * POST} and {@link HttpRequest.Builder#PUT() PUT} which return a GET, POST or + * PUT request respectively. Alternatively, {@link + * HttpRequest.Builder#method(String) method} can be called to set an arbitrary + * method type (and return a {@code HttpRequest}). Builders can also be copied + * and modified multiple times in order to build multiple related requests that + * differ in some parameters. + * + *

    Two simple, example HTTP interactions are shown below: + *

    + * {@code
    + *      // GET
    + *      HttpResponse response = HttpRequest
    + *          .create(new URI("http://www.foo.com"))
    + *          .headers("Foo", "foovalue", "Bar", "barvalue")
    + *          .GET()
    + *          .response();
    + *
    + *      int statusCode = response.statusCode();
    + *      String responseBody = response.body(asString());
    + *
    + *      // POST
    + *      response = HttpRequest
    + *          .create(new URI("http://www.foo.com"))
    + *          .body(fromString("param1=foo,param2=bar"))
    + *          .POST()
    + *          .response();}
    + * 
    + * + *

    The request is sent and the response obtained by calling one of the + * following methods. + *

    • {@link #response() response} blocks until the entire request has been + * sent and the response status code and headers have been received.
    • + *
    • {@link #responseAsync() responseAsync} sends the request and receives the + * response asynchronously. Returns immediately with a + * {@link java.util.concurrent.CompletableFuture CompletableFuture}<{@link + * HttpResponse}>.
    • + *
    • {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync} + * sends the request asynchronously, expecting multiple responses. This + * capability is of most relevance to HTTP/2 server push, but can be used for + * single responses (HTTP/1.1 or HTTP/2) also.
    • + *
    + * + *

    Once a request has been sent, it is an error to try and send it again. + * + *

    Once a {@code HttpResponse} is received, the headers and response code are + * available. The body can then be received by calling one of the body methods + * on {@code HttpResponse}. + * + *

    See below for discussion of synchronous versus asynchronous usage. + * + *

    Request bodies + * + *

    Request bodies are sent using one of the request processor implementations + * below provided in {@code HttpRequest}, or else a custom implementation can be + * used. + *

      + *
    • {@link #fromByteArray(byte[]) } from byte array
    • + *
    • {@link #fromByteArrays(java.util.Iterator) fromByteArrays(Iterator)} + * from an iterator of byte arrays
    • + *
    • {@link #fromFile(java.nio.file.Path) fromFile(Path)} from the file located + * at the given Path
    • + *
    • {@link #fromString(java.lang.String) fromString(String)} from a String
    • + *
    • {@link #fromInputStream(java.io.InputStream) fromInputStream(InputStream)} + * request body from InputStream
    • + *
    • {@link #noBody() } no request body is sent
    • + *
    + * + *

    Response bodies + * + *

    Responses bodies are handled by the {@link HttpResponse.BodyProcessor} + * {@code } supplied to the {@link HttpResponse#body(HttpResponse.BodyProcessor) + * HttpResponse.body} and {@link HttpResponse#bodyAsync(HttpResponse.BodyProcessor) + * HttpResponse.bodyAsync} methods. Some implementations of {@code + * HttpResponse.BodyProcessor} are provided in {@link HttpResponse}: + *

      + *
    • {@link HttpResponse#asByteArray() } stores the body in a byte array
    • + *
    • {@link HttpResponse#asString()} stores the body as a String
    • + *
    • {@link HttpResponse#asFile(java.nio.file.Path) } stores the body in a + * named file
    • + *
    • {@link HttpResponse#ignoreBody() } ignores any received response body
    • + *
    + * + *

    The output of a response processor is the response body, and its + * parameterized type {@code T} determines the type of the body object returned + * from {@code HttpResponse.body} and {@code HttpResponse.bodyAsync}. Therefore, + * as an example, the second response processor in the list above has the type + * {@code HttpResponse.BodyProcessor} which means the type returned by + * {@code HttpResponse.body()} is a String. Response processors can be defined + * to return potentially any type as body. + * + *

    Multi responses + * + *

    With HTTP/2 it is possible for a server to return a main response and zero + * or more additional responses (known as server pushes) to a client-initiated + * request. These are handled using a special response processor called {@link + * HttpResponse.MultiProcessor}. + * + *

    Blocking/asynchronous behavior and thread usage + * + *

    There are two styles of request sending: synchronous and + * asynchronous. {@link #response() response} blocks the calling thread + * until the request has been sent and the response received. + * + *

    {@link #responseAsync() responseAsync} is asynchronous and returns + * immediately with a {@link java.util.concurrent.CompletableFuture}<{@link + * HttpResponse}> and when this object completes (in a background thread) the + * response has been received. + * + *

    {@link #multiResponseAsync(HttpResponse.MultiProcessor) multiResponseAsync} + * is the variant for multi responses and is also asynchronous. + * + *

    CompletableFutures can be combined in different ways to declare the + * dependencies among several asynchronous tasks, while allowing for the maximum + * level of parallelism to be utilized. + * + *

    Security checks + * + *

    If a security manager is present then security checks are performed by + * the {@link #response() } and {@link #responseAsync() } methods. A {@link + * java.net.URLPermission} or {@link java.net.SocketPermission} is required to + * access any destination origin server and proxy server utilised. URLPermissions + * should be preferred in policy files over SocketPermissions given the more + * limited scope of URLPermission. Permission is always implicitly granted to a + * system's default proxies. The URLPermission form used to access proxies uses + * a method parameter of "CONNECT" (for all kinds of proxying) and a url string + * of the form "socket://host:port" where host and port specify the proxy's + * address. + * + *

    Examples + *

    + *     import static java.net.http.HttpRequest.*;
    + *     import static java.net.http.HttpResponse.*;
    + *
    + *     //Simple blocking
    + *
    + *     HttpResponse r1 = HttpRequest.create(new URI("http://www.foo.com/"))
    + *                                  .GET()
    + *                                 .response();
    + *     int responseCode = r1.statusCode());
    + *     String body = r1.body(asString());
    + *
    + *     HttpResponse r2 = HttpRequest.create(new URI("http://www.foo.com/"))
    + *                                  .GET()
    + *                                  .response();
    + *
    + *     System.out.println("Response was " + r1.statusCode());
    + *     Path body1 = r2.body(asFile(Paths.get("/tmp/response.txt")));
    + *     // Content stored in /tmp/response.txt
    + *
    + *     HttpResponse r3 = HttpRequest.create(new URI("http://www.foo.com/"))
    + *                                  .body(fromString("param1=1, param2=2"))
    + *                                  .POST()
    + *                                  .response();
    + *
    + *     Void body2 = r3.body(ignoreBody()); // body is Void in this case
    + * 
    + * + *

    Asynchronous Example + * + *

    All of the above examples will work asynchronously, if {@link + * #responseAsync()} is used instead of {@link #response()} in which case the + * returned object is a {@code CompletableFuture} instead of + * {@code HttpResponse}. The following example shows how multiple requests can + * be sent asynchronously. It also shows how dependent asynchronous operations + * (receiving response, and receiving response body) can be chained easily using + * one of the many methods in {@code CompletableFuture}. + *

    + * {@code
    + *      // fetch a list of target URIs asynchronously and store them in Files.
    + *
    + *      List targets = ...
    + *
    + *      List> futures = targets
    + *          .stream()
    + *          .map(target -> {
    + *              return HttpRequest
    + *                  .create(target)
    + *                  .GET()
    + *                  .responseAsync()
    + *                  .thenCompose(response -> {
    + *                      Path dest = Paths.get("base", target.getPath());
    + *                      if (response.statusCode() == 200) {
    + *                          return response.bodyAsync(asFile(dest));
    + *                      } else {
    + *                          return CompletableFuture.completedFuture(dest);
    + *                      }
    + *                  })
    + *                  // convert Path -> File
    + *                  .thenApply((Path dest) -> {
    + *                      return dest.toFile();
    + *                  });
    + *              })
    + *          .collect(Collectors.toList());
    + *
    + *      // all async operations waited for here
    + *
    + *      CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]))
    + *          .join();
    + *
    + *      // all elements of futures have completed and can be examined.
    + *      // Use File.exists() to check whether file was successfully downloaded
    + * }
    + * 
    + * + * @since 9 + */ +public abstract class HttpRequest { + + HttpRequest() {} + + /** + * A builder of {@link HttpRequest}s. {@code HttpRequest.Builder}s are + * created by calling {@link HttpRequest#create(URI)} or {@link + * HttpClient#request(URI)}. + * + *

    Each of the setter methods in this class modifies the state of the + * builder and returns this (ie. the same instance). The methods are + * not synchronized and should not be called from multiple threads without + * external synchronization. + * + *

    The build methods return a new {@code HttpRequest} each time they are + * called. + * + * @since 9 + */ + public abstract static class Builder { + + Builder() {} + + /** + * Sets this HttpRequest's request URI. + * + * @param uri the request URI + * @return this request builder + */ + public abstract Builder uri(URI uri); + + /** + * Specifies whether this request will automatically follow redirects + * issued by the server. The default value for this setting is the value + * of {@link HttpClient#followRedirects() } + * + * @param policy the redirection policy + * @return this request builder + */ + public abstract Builder followRedirects(HttpClient.Redirect policy); + + /** + * Request server to acknowledge request before sending request + * body. This is disabled by default. If enabled, the server is requested + * to send an error response or a 100-Continue response before the client + * sends the request body. This means the request processor for the + * request will not be invoked until this interim response is received. + * + * @param enable {@code true} if Expect continue to be sent + * @return this request builder + */ + public abstract Builder expectContinue(boolean enable); + + /** + * Overrides the {@link HttpClient#version() } setting for this + * request. + * + * @param version the HTTP protocol version requested + * @return this request builder + */ + public abstract Builder version(HttpClient.Version version); + + /** + * Adds the given name value pair to the set of headers for this request. + * + * @param name the header name + * @param value the header value + * @return this request builder + */ + public abstract Builder header(String name, String value); + + /** + * Overrides the ProxySelector set on the request's client for this + * request. + * + * @param proxy the ProxySelector to use + * @return this request builder + */ + public abstract Builder proxy(ProxySelector proxy); + + /** + * Adds the given name value pairs to the set of headers for this + * request. The supplied Strings must alternate as names and values. + * + * @param headers the list of String name value pairs + * @return this request builder + * @throws IllegalArgumentException if there is an odd number of + * parameters + */ + public abstract Builder headers(String... headers); + + /** + * Sets a timeout for this request. If the response is not received + * within the specified timeout then a {@link HttpTimeoutException} is + * thrown from {@link #response() } or {@link #responseAsync() } + * completes exceptionally with a {@code HttpTimeoutException}. + * + * @param unit the timeout units + * @param timeval the number of units to wait for + * @return this request builder + */ + public abstract Builder timeout(TimeUnit unit, long timeval); + + /** + * Sets the given name value pair to the set of headers for this + * request. This overwrites any previously set values for name. + * + * @param name the header name + * @param value the header value + * @return this request builder + */ + public abstract Builder setHeader(String name, String value); + + /** + * Sets a request body for this builder. See {@link HttpRequest} + * for example {@code BodyProcessor} implementations. + * If no body is specified, then no body is sent with the request. + * + * @param reqproc the request body processor + * @return this request builder + */ + public abstract Builder body(BodyProcessor reqproc); + + /** + * Builds and returns a GET {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest GET(); + + /** + * Builds and returns a POST {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest POST(); + + /** + * Builds and returns a PUT {@link HttpRequest} from this builder. + * + * @return a {@code HttpRequest} + */ + public abstract HttpRequest PUT(); + + /** + * Builds and returns a {@link HttpRequest} from this builder using + * the given method String. The method string is case-sensitive, and + * may be rejected if an upper-case string is not used. + * + * @param method the method to use + * @return a {@code HttpRequest} + * @throws IllegalArgumentException if an unrecognised method is used + */ + public abstract HttpRequest method(String method); + + /** + * Returns an exact duplicate copy of this Builder based on current + * state. The new builder can then be modified independently of this + * builder. + * + * @return an exact copy of this Builder + */ + public abstract Builder copy(); + } + + /** + * Creates a HttpRequest builder from the default HttpClient. + * + * @param uri the request URI + * @return a new request builder + */ + public static HttpRequest.Builder create(URI uri) { + return HttpClient.getDefault().request(uri); + } + + /** + * Returns the follow-redirects setting for this request. + * + * @return follow redirects setting + */ + public abstract HttpClient.Redirect followRedirects(); + + /** + * Returns the response to this request, by sending it and blocking if + * necessary to get the response. The {@link HttpResponse} contains the + * response status and headers. + * + * @return a HttpResponse for this request + * @throws IOException if an I/O error occurs + * @throws InterruptedException if the operation was interrupted + * @throws SecurityException if the caller does not have the required + * permission + * @throws IllegalStateException if called more than once or if + * responseAsync() called previously + */ + public abstract HttpResponse response() + throws IOException, InterruptedException; + + /** + * Sends the request and returns the response asynchronously. This method + * returns immediately with a {@link CompletableFuture}<{@link + * HttpResponse}> + * + * @return a {@code CompletableFuture} + * @throws IllegalStateException if called more than once or if response() + * called previously. + */ + public abstract CompletableFuture responseAsync(); + + /** + * Sends the request asynchronously expecting multiple responses. + * + *

    This method must be given a {@link HttpResponse.MultiProcessor} to + * handle the multiple responses. + * + *

    If a security manager is set, the caller must possess a {@link + * java.net.URLPermission} for the request's URI, method and any user set + * headers. The security manager is also checked for each incoming + * additional server generated request/response. Any request that fails the + * security check, is canceled and ignored. + * + *

    This method can be used for both HTTP/1.1 and HTTP/2, but in cases + * where multiple responses are not supported, the MultiProcessor + * only receives the main response. + * + *

    The aggregate {@code CompletableFuture} returned from this method + * returns a {@code } defined by the {@link HttpResponse.MultiProcessor} + * implementation supplied. This will typically be a Collection of + * HttpResponses or of some response body type. + * + * @param the aggregate response type + * @param rspproc the MultiProcessor for the request + * @return a {@code CompletableFuture} + * @throws IllegalStateException if the request has already been sent. + */ + public abstract CompletableFuture + multiResponseAsync(HttpResponse.MultiProcessor rspproc); + + /** + * Returns the request method for this request. If not set explicitly, + * the default method for any request is "GET". + * + * @return this request's method + */ + public abstract String method(); + + /** + * Returns this request's {@link HttpRequest.Builder#expectContinue(boolean) + * expect continue } setting. + * + * @return this request's expect continue setting + */ + public abstract boolean expectContinue(); + + /** + * Returns this request's request URI. + * + * @return this request's URI + */ + public abstract URI uri(); + + /** + * Returns this request's {@link HttpClient}. + * + * @return this request's HttpClient + */ + public abstract HttpClient client(); + + /** + * Returns the HTTP protocol version that this request will use or used. + * + * @return HTTP protocol version + */ + public abstract HttpClient.Version version(); + + /** + * The (user-accessible) request headers that this request was (or will be) + * sent with. + * + * @return this request's HttpHeaders + */ + public abstract HttpHeaders headers(); + + /** + * Returns a request processor whose body is the given String, converted + * using the {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} + * character set. + * + * @param body the String containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromString(String body) { + return fromString(body, StandardCharsets.ISO_8859_1); + } + + /** + * A request processor that takes data from the contents of a File. + * + * @param path the path to the file containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromFile(Path path) { + FileChannel fc; + long size; + + try { + fc = FileChannel.open(path); + size = fc.size(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + + return new BodyProcessor() { + LongConsumer flow; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + // could return exact file length, but for now -1 + this.flow = flow; + flow.accept(1); + if (size != 0) { + return size; + } else { + return -1; + } + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException { + int n = fc.read(buffer); + if (n == -1) { + fc.close(); + return true; + } + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + try { + fc.close(); + } catch (IOException ex) { + Log.logError(ex.toString()); + } + } + }; + } + + /** + * Returns a request processor whose body is the given String, converted + * using the given character set. + * + * @param s the String containing the body + * @param charset the character set to convert the string to bytes + * @return a BodyProcessor + */ + public static BodyProcessor fromString(String s, Charset charset) { + return fromByteArray(s.getBytes(charset)); + } + + /** + * Returns a request processor whose body is the given byte array. + * + * @param buf the byte array containing the body + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArray(byte[] buf) { + return fromByteArray(buf, 0, buf.length); + } + + /** + * Returns a request processor whose body is the content of the given byte + * array length bytes starting from the specified offset. + * + * @param buf the byte array containing the body + * @param offset the offset of the first byte + * @param length the number of bytes to use + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArray(byte[] buf, int offset, int length) { + + return new BodyProcessor() { + LongConsumer flow; + byte[] barray; + int index; + int sent; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + barray = buf; + index = offset; + return length; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + if (sent == length) { + return true; + } + + int remaining = buffer.remaining(); + int left = length - sent; + int n = remaining > left ? left : remaining; + buffer.put(barray, index, n); + index += n; + sent += n; + flow.accept(1); + return sent == length; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor that takes data from an Iterator of byte arrays. + * + * @param iter an Iterator of byte arrays + * @return a BodyProcessor + */ + public static BodyProcessor fromByteArrays(Iterator iter) { + + return new BodyProcessor() { + LongConsumer flow; + byte[] current; + int curIndex; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + return -1; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + int remaining; + + while ((remaining = buffer.remaining()) > 0) { + if (current == null) { + if (!iter.hasNext()) { + return true; + } + current = iter.next(); + curIndex = 0; + } + int n = Math.min(remaining, current.length - curIndex); + buffer.put(current, curIndex, n); + curIndex += n; + + if (curIndex == current.length) { + current = null; + flow.accept(1); + return false; + } + } + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor that reads its data from an InputStream. + * + * @param stream an InputStream + * @return a BodyProcessor + */ + public static BodyProcessor fromInputStream(InputStream stream) { + // for now, this blocks. It could be offloaded to a separate thread + // to do reading and guarantee that onRequestBodyChunk() won't block + return new BodyProcessor() { + LongConsumer flow; + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + this.flow = flow; + flow.accept(1); + return -1; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + int remaining = buffer.remaining(); + int n = stream.read(buffer.array(), buffer.arrayOffset(), remaining); + if (n == -1) { + stream.close(); + return true; + } + buffer.position(buffer.position() + n); + flow.accept(1); + return false; + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor which sends no request body. + * + * @return a BodyProcessor + */ + public static BodyProcessor noBody() { + return new BodyProcessor() { + + @Override + public long onRequestStart(HttpRequest hr, LongConsumer flow) { + return 0; + } + + @Override + public boolean onRequestBodyChunk(ByteBuffer buffer) + throws IOException + { + throw new InternalError("should never reach here"); + } + + @Override + public void onRequestError(Throwable t) { + Log.logError(t.toString()); + } + }; + } + + /** + * A request processor which obtains the request body from some source. + * Implementations of this interface are provided which allow request bodies + * to be supplied from standard types, such as {@code String, byte[], File, + * InputStream}. Other implementations can be provided. + * + *

    The methods of this interface may be called from multiple threads, + * but only one method is invoked at a time, and behaves as if called from + * one thread. + * + *

    See {@link HttpRequest} for implementations that take request bodies + * from {@code byte arrays, Strings, Paths} etc. + * + * @since 9 + */ + public interface BodyProcessor { + + /** + * Called before a request is sent. Is expected to return the content + * length of the request body. Zero means no content. Less than zero + * means an unknown positive content-length, and the body will be + * streamed. + * + *

    The flowController object must be used to manage the flow of + * calls to {@link #onRequestBodyChunk(ByteBuffer)}. The typical usage + * for a non-blocking processor is to call it once inside + * onRequestStart() and once during each call to onRequestBodyChunk(). + * + * @param hr the request + * @param flowController the HttpFlowController + * @return the content length + * @throws IOException if an I/O error occurs + */ + long onRequestStart(HttpRequest hr, LongConsumer flowController) + throws IOException; + + /** + * Called if sending a request body fails. + * + * @implSpec The default implementation does nothing. + * + * @param t the Throwable that caused the failure + */ + default void onRequestError(Throwable t) { } + + /** + * Called to obtain a buffer of data to send. The data must be placed + * in the provided buffer. The implementation should not block. The + * boolean return code notifies the protocol implementation if the + * supplied buffer is the final one (or not). + * + * @param buffer a ByteBuffer to write data into + * @return whether or not this is the last buffer + * @throws IOException if an I/O error occurs + */ + boolean onRequestBodyChunk(ByteBuffer buffer) throws IOException; + + /** + * Called when the request body has been completely sent. + * + * @implSpec The default implementation does nothing + */ + default void onComplete() { + // TODO: need to call this + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java new file mode 100644 index 00000000000..bc04ab3e921 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpRequestBuilderImpl.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.net.URI; +import java.net.ProxySelector; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +class HttpRequestBuilderImpl extends HttpRequest.Builder { + + private HttpHeadersImpl userHeaders; + private URI uri; + private String method; + private HttpClient.Redirect followRedirects; + private boolean expectContinue; + private HttpRequest.BodyProcessor body; + private HttpClient.Version version; + private final HttpClientImpl client; + private ProxySelector proxy; + private long timeval = 0; + + public HttpRequestBuilderImpl(HttpClientImpl client, URI uri) { + this.client = client; + this.uri = uri; + this.version = client.version(); + this.userHeaders = new HttpHeadersImpl(); + } + + @Override + public HttpRequestBuilderImpl body(HttpRequest.BodyProcessor reqproc) { + Objects.requireNonNull(reqproc); + this.body = reqproc; + return this; + } + + @Override + public HttpRequestBuilderImpl uri(URI uri) { + Objects.requireNonNull(uri); + this.uri = uri; + return this; + } + + @Override + public HttpRequestBuilderImpl followRedirects(HttpClient.Redirect follow) { + Objects.requireNonNull(follow); + this.followRedirects = follow; + return this; + } + + @Override + public HttpRequestBuilderImpl header(String name, String value) { + Objects.requireNonNull(name); + Objects.requireNonNull(value); + Utils.validateToken(name, "invalid header name"); + userHeaders.addHeader(name, value); + return this; + } + + @Override + public HttpRequestBuilderImpl headers(String... params) { + Objects.requireNonNull(params); + if (params.length % 2 != 0) { + throw new IllegalArgumentException("wrong number of parameters"); + } + for (int i=0; i DISALLOWED_HEADERS_SET = Set.of( + "authorization", "connection", "cookie", "content-length", + "date", "expect", "from", "host", "origin", "proxy-authorization", + "referer", "user-agent", "upgrade", "via", "warning"); + + + // we silently drop headers that are disallowed + private void dropDisallowedHeaders() { + Set hdrnames = userHeaders.directMap().keySet(); + + hdrnames.removeIf((s) -> + DISALLOWED_HEADERS_SET.contains(s.toLowerCase()) + ); + } + + private synchronized void receiving() { + if (receiving) { + throw new IllegalStateException("already receiving response"); + } + receiving = true; + } + + /* + * Response filters may result in a new HttpRequestImpl being created + * (but still associated with the same API HttpRequest) and the process + * is repeated. + */ + @Override + public HttpResponse response() throws IOException, InterruptedException { + receiving(); // TODO: update docs + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + return exchange.response(); + } + + @Override + public synchronized CompletableFuture responseAsync() { + receiving(); // TODO: update docs + if (System.getSecurityManager() != null) { + acc = AccessController.getContext(); + } + return exchange.responseAsync(null) + .thenApply((r) -> (HttpResponse)r); + } + + public CompletableFuture + sendAsyncMulti(HttpResponse.MultiProcessor rspproc) { + // To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + public boolean expectContinue() { return expectContinue; } + + public boolean requestHttp2() { + return version.equals(HttpClient.Version.HTTP_2); + //return client.getHttp2Allowed(); + } + + AccessControlContext getAccessControlContext() { return acc; } + + InetSocketAddress proxy() { + ProxySelector ps = this.proxy; + if (ps == null) { + ps = client.proxy().orElse(null); + } + if (ps == null || method.equalsIgnoreCase("CONNECT")) { + return null; + } + return (InetSocketAddress)ps.select(uri).get(0).address(); + } + + boolean secure() { return secure; } + + void isWebSocket(boolean is) { + isWebSocket = is; + } + + boolean isWebSocket() { + return isWebSocket; + } + + /** Returns the follow-redirects setting for this request. */ + @Override + public java.net.http.HttpClient.Redirect followRedirects() { + return getRedirects(followRedirects); + } + + HttpRedirectImpl followRedirectsImpl() { return followRedirects; } + + /** + * Returns the request method for this request. If not set explicitly, + * the default method for any request is "GET". + */ + @Override + public String method() { return method; } + + @Override + public URI uri() { return uri; } + + HttpHeadersImpl getUserHeaders() { return userHeaders; } + + HttpHeadersImpl getSystemHeaders() { return systemHeaders; } + + HttpClientImpl getClient() { return client; } + + BodyProcessor requestProcessor() { return requestProcessor; } + + @Override + public Version version() { return version; } + + void addSystemHeader(String name, String value) { + systemHeaders.addHeader(name, value); + } + + void setSystemHeader(String name, String value) { + systemHeaders.setHeader(name, value); + } + + long timeval() { return timeval; } + + @Override + public CompletableFuture + multiResponseAsync(MultiProcessor rspproc) { + //To change body of generated methods, choose Tools | Templates. + throw new UnsupportedOperationException("Not supported yet."); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java new file mode 100644 index 00000000000..c1ff5adb44e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponse.java @@ -0,0 +1,977 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.net.http; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.nio.file.OpenOption; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.LongConsumer; +import javax.net.ssl.SSLParameters; + +/** + * Represents a response to a {@link HttpRequest}. A {@code HttpResponse} is + * available when the response status code and headers have been received, but + * before the response body is received. + * + *

    Methods are provided in this class for accessing the response headers, + * and status code immediately and also methods for retrieving the response body. + * Static methods are provided which implement {@link BodyProcessor} for + * standard body types such as {@code String, byte arrays, files}. + * + *

    The {@link #body(BodyProcessor) body} or {@link #bodyAsync(BodyProcessor) + * bodyAsync} which retrieve any response body must be called to ensure that the + * TCP connection can be re-used subsequently, and any response trailers + * accessed, if they exist, unless it is known that no response body was received. + * + * @since 9 + */ +public abstract class HttpResponse { + + HttpResponse() { } + + /** + * Returns the status code for this response. + * + * @return the response code + */ + public abstract int statusCode(); + + /** + * Returns the {@link HttpRequest} for this response. + * + * @return the request + */ + public abstract HttpRequest request(); + + /** + * Returns the received response headers. + * + * @return the response headers + */ + public abstract HttpHeaders headers(); + + /** + * Returns the received response trailers, if there are any. This must only + * be called after the response body has been received. + * + * @return the response trailers (may be empty) + * @throws IllegalStateException if the response body has not been received + * yet + */ + public abstract HttpHeaders trailers(); + + /** + * Returns the body, blocking if necessary. The type T is determined by the + * {@link BodyProcessor} implementation supplied. The body object will be + * returned immediately if it is a type (such as {@link java.io.InputStream} + * which reads the data itself. If the body object represents the fully read + * body then it blocks until it is fully read. + * + * @param the type of the returned body object + * @param processor the processor to handle the response body + * @return the body + * @throws java.io.UncheckedIOException if an I/O error occurs reading the + * response + */ + public abstract T body(BodyProcessor processor); + + /** + * Returns a {@link java.util.concurrent.CompletableFuture} of type T. This + * always returns immediately and the future completes when the body object + * is available. The body will be available immediately if it is a type + * (such as {@link java.io.InputStream} which reads the data itself. If the + * body object represents the fully read body then it will not be available + * until it is fully read. + * + * @param the type of the returned body object + * @param processor the processor to handle the response body + * @return a CompletableFuture + */ + public abstract CompletableFuture bodyAsync(BodyProcessor processor); + + /** + * Returns the {@link javax.net.ssl.SSLParameters} in effect for this + * response. Returns {@code null} if this is not a https response. + * + * @return the SSLParameters associated with the response + */ + public abstract SSLParameters sslParameters(); + + /** + * Returns the URI that the response was received from. This may be + * different from the request URI if redirection occurred. + * + * @return the URI of the response + */ + public abstract URI uri(); + + /** + * Returns the HTTP protocol version that was used for this response. + * + * @return HTTP protocol version + */ + public abstract HttpClient.Version version(); + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}> where + * the file is created if it does not already exist. When the Path object is + * returned, the body has been completely written to the file. + * + * @param file the file to store the body in + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFile(Path file) { + return asFile(file, StandardOpenOption.CREATE, StandardOpenOption.WRITE); + } + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}> where + * the download directory is specified, but the filename is obtained from + * the Content-Disposition response header. The Content-Disposition header + * must specify the attachment type and must also contain a + * filename parameter. If the filename specifies multiple path + * components only the final component is used as the filename (with the + * given directory name). When the Path object is returned, the body has + * been completely written to the file. The returned Path is the combination + * of the supplied directory name and the file name supplied by the server. + * If the destination directory does not exist or cannot be written to, then + * the response will fail with an IOException. + * + * @param directory the directory to store the file in + * @param openOptions open options + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFileDownload(Path directory, + OpenOption... openOptions) { + return new AbstractResponseProcessor() { + + FileChannel fc; + Path file; + + @Override + public Path onResponseBodyStartImpl(long contentLength, + HttpHeaders headers) + throws IOException + { + String dispoHeader = headers.firstValue("Content-Disposition") + .orElseThrow(() -> new IOException("No Content-Disposition")); + if (!dispoHeader.startsWith("attachment;")) { + throw new IOException("Unknown Content-Disposition type"); + } + int n = dispoHeader.indexOf("filename="); + if (n == -1) { + throw new IOException("Bad Content-Disposition type"); + } + String disposition = dispoHeader.substring(n + 9, + dispoHeader.lastIndexOf(';')); + file = Paths.get(directory.toString(), disposition); + fc = FileChannel.open(file, openOptions); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + fc.write(b); + } + + @Override + public Path onResponseComplete() throws IOException { + fc.close(); + return file; + } + + @Override + public void onResponseError(Throwable t) { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + } + } + }; + } + + /** + * Returns a {@link BodyProcessor}<{@link java.nio.file.Path}>. + * + *

    {@link HttpResponse}s returned using this response processor complete + * after the entire response, including body has been read. + * + * @param file the filename to store the body in + * @param openOptions any options to use when opening/creating the file + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asFile(Path file, + OpenOption... openOptions) { + return new AbstractResponseProcessor() { + + FileChannel fc; + + @Override + public Path onResponseBodyStartImpl(long contentLength, + HttpHeaders headers) + throws IOException + { + fc = FileChannel.open(file, openOptions); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException + { + fc.write(b); + } + + @Override + public Path onResponseComplete() throws IOException { + fc.close(); + return file; + } + + @Override + public void onResponseError(Throwable t) { + try { + if (fc != null) { + fc.close(); + } + } catch (IOException e) { + } + } + }; + } + + static class ByteArrayResponseProcessor { + + static final int INITIAL_BUFLEN = 1024; + + byte[] buffer; + int capacity; + boolean knownLength; + int position; + + ByteArrayResponseProcessor() { } + + public byte[] onStart(long contentLength) throws IOException { + if (contentLength > Integer.MAX_VALUE) { + throw new IllegalArgumentException( + "byte array response limited to MAX_INT size"); + } + capacity = (int) contentLength; + if (capacity != -1) { + buffer = new byte[capacity]; + knownLength = true; + } else { + buffer = new byte[INITIAL_BUFLEN]; + capacity = INITIAL_BUFLEN; + knownLength = false; + } + position = 0; + return null; + } + + public void onBodyContent(ByteBuffer b) throws IOException { + int toCopy = b.remaining(); + int size = capacity; + if (toCopy > capacity - position) { + // resize + size += toCopy * 2; + } + if (size != capacity) { + if (knownLength) { + // capacity should have been right from start + throw new IOException("Inconsistent content length"); + } + byte[] newbuf = new byte[size]; + System.arraycopy(buffer, 0, newbuf, 0, position); + buffer = newbuf; + capacity = size; + } + int srcposition = b.arrayOffset() + b.position(); + System.arraycopy(b.array(), srcposition, buffer, position, toCopy); + b.position(b.limit()); + position += toCopy; + } + + public byte[] onComplete() throws IOException { + if (knownLength) { + if (position != capacity) { + throw new IOException("Wrong number of bytes received"); + } + return buffer; + } + byte[] buf1 = new byte[position]; + System.arraycopy(buffer, 0, buf1, 0, position); + return buf1; + } + + public void onError(Throwable t) { + // TODO: + } + } + + static final byte[] EMPTY = new byte[0]; + + /** + * Returns a response processor which supplies the response body to the + * given Consumer. Each time data is received the consumer is invoked with a + * byte[] containing at least one byte of data. After the final buffer is + * received, the consumer is invoked one last time, with an empty byte + * array. + * + * @param consumer a Consumer to accept the response body + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asByteArrayConsumer(Consumer consumer) { + return new AbstractResponseProcessor() { + @Override + public Void onResponseBodyStartImpl(long clen, + HttpHeaders h) + throws IOException + { + return null; + } + + @Override + public void onResponseError(Throwable t) { + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + if (!b.hasRemaining()) { + return; + } + byte[] buf = new byte[b.remaining()]; + b.get(buf); + consumer.accept(buf); + } + + @Override + public Void onResponseComplete() throws IOException { + consumer.accept(EMPTY); + return null; + } + }; + } + + /** + * Returns a BodyProcessor which delivers the response data to a + * {@link java.util.concurrent.Flow.Subscriber}{@code ByteBuffer}. + *

    + * The given {@code Supplier} is invoked when the Flow is completed in + * order to convert the flow data into the U object that is returned as the + * response body. + * + * @param the response body type + * @param subscriber the Flow.Subscriber + * @param bufferSize the maximum number of bytes of data to be supplied in + * each ByteBuffer + * @param bodySupplier an object that converts the received data to the body + * type U. + * @return a BodyProcessor + * + * public static BodyProcessor> + * asFlowSubscriber() { + * + * return new BodyProcessor() { Flow.Subscriber subscriber; + * LongConsumer flowController; FlowSubscription subscription; Supplier + * bodySupplier; int bufferSize; // down-stream Flow window. long + * buffersWindow; // upstream window long bytesWindow; + * LinkedList buffers = new LinkedList<>(); + * + * class FlowSubscription implements Subscription { int recurseLevel = 0; + * @Override public void request(long n) { boolean goodToGo = recurseLevel++ + * == 0; + * + * while (goodToGo && buffers.size() > 0 && n > 0) { ByteBuffer buf = + * buffers.get(0); subscriber.onNext(buf); n--; } buffersWindow += n; + * flowController.accept(n * bufferSize); recurseLevel--; } + * + * @Override public void cancel() { // ?? set flag and throw exception on + * next receipt of buffer } } + * + * @Override public U onResponseBodyStart(long contentLength, HttpHeaders + * responseHeaders, LongConsumer flowController) throws IOException { + * this.subscriber = subscriber; this.flowController = flowController; + * this.subscription = new FlowSubscription(); this.bufferSize = bufferSize; + * subscriber.onSubscribe(subscription); return null; } + * + * @Override public void onResponseError(Throwable t) { + * subscriber.onError(t); } + * + * @Override public void onResponseBodyChunk(ByteBuffer b) throws + * IOException { if (buffersWindow > 0) { buffersWindow --; + * subscriber.onNext(b); } else { buffers.add(b); // or could combine + * buffers? } } + * + * @Override public U onResponseComplete() throws IOException { + * subscriber.onComplete(); return bodySupplier.get(); } }; } + */ + private static final ByteBuffer EOF = ByteBuffer.allocate(0); + private static final ByteBuffer CLOSED = ByteBuffer.allocate(0); + + // prototype using ByteBuffer based flow control. InputStream feeds off a + // BlockingQueue. Size of Q is determined from the the bufsize (bytes) and + // the default ByteBuffer size. bufsize should be a reasonable multiple of + // ByteBuffer size to prevent underflow/starvation. The InputStream updates + // the flowControl window by one as each ByteBuffer is fully consumed. + // Special sentinels are used to indicate stream closed and EOF. + /** + * Returns a response body processor which provides an InputStream to read + * the body. + * + * @implNote This mechanism is provided primarily for backwards + * compatibility for code that expects InputStream. It is recommended for + * better performance to use one of the other response processor + * implementations. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asInputStream() { + return new BodyProcessor() { + int queueSize = 2; + private volatile Throwable throwable; + + BlockingQueue queue = new LinkedBlockingQueue<>(); + + private void closeImpl() { + try { + queue.put(CLOSED); + } catch (InterruptedException e) { } + } + + @Override + public InputStream onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException + { + flowController.accept(queueSize); + + return new InputStream() { + ByteBuffer buffer; + + @Override + public int read() throws IOException { + byte[] bb = new byte[1]; + int n = read(bb, 0, 1); + if (n == -1) { + return -1; + } else { + return bb[0]; + } + } + + @Override + public int read(byte[] bb) throws IOException { + return read(bb, 0, bb.length); + } + + @Override + public int read(byte[] bb, int offset, int length) + throws IOException + { + int n; + if (getBuffer()) { + return -1; // EOF + } else { + int remaining = buffer.remaining(); + if (length >= remaining) { + buffer.get(bb, offset, remaining); + return remaining; + } else { + buffer.get(bb, offset, length); + return length; + } + } + } + + @Override + public void close() { + closeImpl(); + } + + private boolean getBuffer() throws IOException { + while (buffer == null || (buffer != EOF && + buffer != CLOSED && !buffer.hasRemaining())) { + try { + buffer = queue.take(); + flowController.accept(1); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + if (buffer == CLOSED) { + if (throwable != null) { + if (throwable instanceof IOException) { + throw (IOException) throwable; + } else { + throw new IOException(throwable); + } + } + throw new IOException("Closed"); + } + + if (buffer == EOF) { + return true; // EOF + } + return false; // not EOF + } + + }; + } + + @Override + public void onResponseError(Throwable t) { + throwable = t; + closeImpl(); + } + + @Override + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + try { + queue.put(Utils.copy(b)); + } catch (InterruptedException e) { + // shouldn't happen as queue should never block + throw new IOException(e); + } + } + + @Override + public InputStream onResponseComplete() throws IOException { + try { + queue.put(EOF); + } catch (InterruptedException e) { + throw new IOException(e); // can't happen + } + return null; + } + + }; + } + + /** + * Common super class that takes care of flow control + * + * @param + */ + private static abstract class AbstractResponseProcessor + implements BodyProcessor + { + LongConsumer flowController; + + @Override + public final T onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException + { + this.flowController = flowController; + flowController.accept(1); + return onResponseBodyStartImpl(contentLength, responseHeaders); + } + + public abstract T onResponseBodyStartImpl(long contentLength, + HttpHeaders responseHeaders) + throws IOException; + + public abstract void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException; + + @Override + public final void onResponseBodyChunk(ByteBuffer b) throws IOException { + onResponseBodyChunkImpl(b); + flowController.accept(1); + } + } + + /** + * Returns a {@link BodyProcessor}<byte[]> which returns the response + * body as a {@code byte array}. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asByteArray() { + ByteArrayResponseProcessor brp = new ByteArrayResponseProcessor(); + + return new AbstractResponseProcessor() { + + @Override + public byte[] onResponseBodyStartImpl(long contentLength, + HttpHeaders h) + throws IOException + { + brp.onStart(contentLength); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) + throws IOException + { + brp.onBodyContent(b); + } + + @Override + public byte[] onResponseComplete() throws IOException { + return brp.onComplete(); + } + + @Override + public void onResponseError(Throwable t) { + brp.onError(t); + } + }; + } + + /** + * Returns a response processor which decodes the body using the character + * set specified in the {@code Content-encoding} response header. If there + * is no such header, or the character set is not supported, then + * {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} is used. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asString() { + return asString(null); + } + + /** + * Returns a MultiProcessor that handles multiple responses, writes the + * response bodies to files and which returns an aggregate response object + * that is a {@code Map}. The keyset of the Map represents the + * URIs of the original request and any additional requests generated by the + * server. The values are the paths of the destination files. Each path uses + * the URI path of the request offset from the destination parent directory + * provided. + * + *

    All incoming additional requests (push promises) are accepted by this + * multi response processor. Errors are effectively ignored and any failed + * responses are simply omitted from the result Map. Other implementations + * of MultiProcessor can handle these situations + * + *

    Example usage + *

    +     * {@code
    +     *    CompletableFuture> cf =
    +     *    HttpRequest.create(new URI("https://www.foo.com/"))
    +     *               .version(Version.HTTP2)
    +     *               .GET()
    +     *               .sendAsyncMulti(HttpResponse.multiFile("/usr/destination"));
    +     *
    +     *    Map results = cf.join();
    +     * }
    +     * 
    + * + * @param destination the destination parent directory of all response + * bodies + * @return a MultiProcessor + */ + public static MultiProcessor> multiFile(Path destination) { + + return new MultiProcessor>() { + Map> bodyCFs = new HashMap<>(); + + Map results = new HashMap<>(); + + @Override + public BiFunction, Boolean> + onStart(HttpRequest mainRequest, + CompletableFuture response) { + bodyCFs.put(mainRequest.uri(), getBody(mainRequest, response)); + return (HttpRequest additional, CompletableFuture cf) -> { + CompletableFuture bcf = getBody(additional, cf); + bodyCFs.put(additional.uri(), bcf); + // we accept all comers + return true; + }; + } + + private CompletableFuture getBody(HttpRequest req, + CompletableFuture cf) { + URI u = req.uri(); + String path = u.getPath(); + return cf.thenCompose((HttpResponse resp) -> { + return resp.bodyAsync(HttpResponse.asFile(destination.resolve(path))); + }); + } + + @Override + public Map onComplete() { + // all CFs have completed normally or in error. + Set>> entries = bodyCFs.entrySet(); + for (Map.Entry> entry : entries) { + CompletableFuture v = entry.getValue(); + URI uri = entry.getKey(); + if (v.isDone() && !v.isCompletedExceptionally()) { + results.put(uri, v.join()); + } + } + return results; + } + }; + } + + /** + * Returns a {@link BodyProcessor}<{@link String}>. + * + * @param charset the name of the charset to interpret the body as. If + * {@code null} then the processor tries to determine the character set from + * the {@code Content-encoding} header. If that charset is not supported + * then {@link java.nio.charset.StandardCharsets#ISO_8859_1 ISO_8859_1} is + * used. + * @return a {@code BodyProcessor} + */ + public static BodyProcessor asString(Charset charset) { + + ByteArrayResponseProcessor brp = new ByteArrayResponseProcessor(); + + return new AbstractResponseProcessor() { + Charset cs = charset; + HttpHeaders headers; + + @Override + public String onResponseBodyStartImpl(long contentLength, + HttpHeaders h) + throws IOException + { + headers = h; + brp.onStart(contentLength); + return null; + } + + @Override + public void onResponseBodyChunkImpl(ByteBuffer b) throws IOException { + brp.onBodyContent(b); + } + + @Override + public String onResponseComplete() throws IOException { + byte[] buf = brp.onComplete(); + if (cs == null) { + cs = headers.firstValue("Content-encoding") + .map((String s) -> Charset.forName(s)) + .orElse(StandardCharsets.ISO_8859_1); + } + return new String(buf, cs); + } + + @Override + public void onResponseError(Throwable t) { + brp.onError(t); + } + + }; + } + + /** + * Returns a response processor which ignores the response body. + * + * @return a {@code BodyProcessor} + */ + public static BodyProcessor ignoreBody() { + return asByteArrayConsumer((byte[] buf) -> { /* ignore */ }); + } + + /** + * A processor for response bodies, which determines the type of the + * response body returned from {@link HttpResponse}. Response processors can + * either return an object that represents the body itself (after it has + * been read) or else an object that is used to read the body (such as an + * {@code InputStream}). The parameterized type {@code } is the type of + * the returned body object from + * {@link HttpResponse#body(BodyProcessor) HttpResponse.body} and + * (indirectly) from {@link HttpResponse#bodyAsync(BodyProcessor) + * HttpResponse.bodyAsync}. + * + *

    Implementations of this interface are provided in {@link HttpResponse} + * which write responses to {@code String, byte[], File, Consumer}. + * Custom implementations can also be used. + * + *

    The methods of this interface may be called from multiple threads, + * but only one method is invoked at a time, and behaves as if called from + * one thread. + * + * @param the type of the response body + * + * @since 9 + */ + public interface BodyProcessor { + + /** + * Called immediately before the response body is read. If {@code } + * is an object used to read or accept the response body, such as a + * {@code Consumer} or {@code InputStream} then it should be returned + * from this method, and the body object will be returned before any + * data is read. If {@code } represents the body itself after being + * read, then this method must return {@code null} and the body will be + * returned from {@link #onResponseComplete()}. In both cases, the + * actual body data is provided by the + * {@link #onResponseBodyChunk(ByteBuffer) onResponseBodyChunk} method + * in exactly the same way. + * + *

    flowController is a consumer of long values and is used for + * updating a flow control window as follows. The window represents the + * number of times + * {@link #onResponseBodyChunk(java.nio.ByteBuffer) onResponseBodyChunk} + * may be called before receiving further updates to the window. Each + * time it is called, the window is reduced by {@code 1}. When the + * window reaches zero {@code onResponseBodyChunk()} will not be called + * again until the window has opened again with further calls to + * flowController.accept(). + * {@link java.util.function.LongConsumer#accept(long) flowcontroller.accept()} + * must be called to open (increase) the window by the specified amount. + * The initial value is zero. This implies that if {@code + * onResponseBodyStart()} does not call {@code flowController.accept()} + * with a positive value no data will ever be delivered. + * + * @param contentLength {@code -1} signifies unknown content length. + * Otherwise, a positive integer, or zero. + * @param responseHeaders the response headers + * @param flowController a LongConsumer used to update the flow control + * window + * @return {@code null} or an object that can be used to read the + * response body. + * @throws IOException if an exception occurs starting the response + * body receive + */ + T onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer flowController) + throws IOException; + + /** + * Called if an error occurs while reading the response body. This + * terminates the operation and no further calls will occur after this. + * + * @param t the Throwable + */ + void onResponseError(Throwable t); + + /** + * Called for each buffer of data received for this response. + * ByteBuffers can be reused as soon as this method returns. + * + * @param b a ByteBuffer whose position is at the first byte that can be + * read, and whose limit is after the last byte that can be read + * @throws IOException in case of I/O error + */ + void onResponseBodyChunk(ByteBuffer b) throws IOException; + + /** + * Called after the last time + * {@link #onResponseBodyChunk(java.nio.ByteBuffer)} has been called and + * returned indicating that the entire content has been read. This + * method must return an object that represents or contains the response + * body just received, but only if an object was not returned from + * {@link #onResponseBodyStart(long, HttpHeaders, LongConsumer) + * onResponseBodyStart}. + * + * @return a T, or {@code null} if an object was already returned + * @throws IOException in case of I/O error + */ + T onResponseComplete() throws IOException; + } + + /** + * A response processor for a HTTP/2 multi response. A multi response + * comprises a main response, and zero or more additional responses. Each + * additional response is sent by the server in response to requests that + * the server also generates. Additional responses are typically resources + * that the server guesses the client will need which are related to the + * initial request. + * + *

    The server generated requests are also known as push promises. + * The server is permitted to send any number of these requests up to the + * point where the main response is fully received. Therefore, after + * completion of the main response body, the final number of additional + * responses is known. Additional responses may be cancelled, but given that + * the server does not wait for any acknowledgment before sending the + * response, this must be done quickly to avoid unnecessary data transmission. + * + *

    {@code MultiProcessor}s are parameterised with a type {@code T} which + * represents some meaningful aggregate of the responses received. This + * would typically be a Collection of response or response body objects. One + * example implementation can be found at {@link + * HttpResponse#multiFile(java.nio.file.Path)}. + * + * @param a type representing the aggregated results + * + * @since 9 + */ + public interface MultiProcessor { + + /** + * Called before or soon after a multi request is sent. The request that + * initiated the multi response is supplied, as well as a + * CompletableFuture for the main response. The implementation of this + * method must return a BiFunction which is called once for each push + * promise received. + * + *

    The parameters to the {@code BiFunction} are the {@code HttpRequest} + * for the push promise and a {@code CompletableFuture} for its + * response. The function must return a Boolean indicating whether the + * push promise has been accepted (true) or should be canceled (false). + * The CompletableFutures for any canceled pushes are themselves + * completed exceptionally soon after the function returns. + * + * @param mainRequest the main request + * @param response a CompletableFuture for the main response + * @return a BiFunction that is called for each push promise + */ + BiFunction, Boolean> + onStart(HttpRequest mainRequest, + CompletableFuture response); + + /** + * Called after all responses associated with the multi response have + * been fully processed, including response bodies. + * + *

    Example types for {@code T} could be Collections of response body + * types or {@code Map}s from request {@code URI} to a response body + * type. + * + * @return the aggregate response object + */ + T onComplete(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java new file mode 100644 index 00000000000..c71f53a04ea --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpResponseImpl.java @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.net.http; + +import java.io.IOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.security.AccessControlContext; +import java.security.AccessController; +import java.util.concurrent.CompletableFuture; +import java.util.function.LongConsumer; +import javax.net.ssl.SSLParameters; + +/** + * The implementation class for HttpResponse + */ +class HttpResponseImpl extends HttpResponse { + + int responseCode; + Exchange exchange; + HttpRequestImpl request; + HttpHeaders1 headers; + HttpHeaders1 trailers; + SSLParameters sslParameters; + URI uri; + HttpClient.Version version; + AccessControlContext acc; + RawChannel rawchan; + HttpConnection connection; + + public HttpResponseImpl(int responseCode, Exchange exch, HttpHeaders1 headers, + HttpHeaders1 trailers, SSLParameters sslParameters, + HttpClient.Version version, HttpConnection connection) { + this.responseCode = responseCode; + this.exchange = exch; + this.request = exchange.request(); + this.headers = headers; + this.trailers = trailers; + this.sslParameters = sslParameters; + this.uri = request.uri(); + this.version = version; + this.connection = connection; + } + + @Override + public int statusCode() { + return responseCode; + } + + @Override + public HttpRequestImpl request() { + return request; + } + + @Override + public HttpHeaders headers() { + headers.makeUnmodifiable(); + return headers; + } + + @Override + public HttpHeaders trailers() { + trailers.makeUnmodifiable(); + return trailers; + } + + + @Override + public T body(java.net.http.HttpResponse.BodyProcessor processor) { + return exchange.responseBody(processor); + } + + @Override + public CompletableFuture bodyAsync(java.net.http.HttpResponse.BodyProcessor processor) { + acc = AccessController.getContext(); + return exchange.responseBodyAsync(processor); + } + + @Override + public SSLParameters sslParameters() { + return sslParameters; + } + + public AccessControlContext getAccessControlContext() { + return acc; + } + + @Override + public URI uri() { + return uri; + } + + @Override + public HttpClient.Version version() { + return version; + } + // keepalive flag determines whether connection is closed or kept alive + // by reading/skipping data + + public static java.net.http.HttpResponse.BodyProcessor ignoreBody(boolean keepalive) { + return new java.net.http.HttpResponse.BodyProcessor() { + + @Override + public Void onResponseBodyStart(long clen, HttpHeaders h, + LongConsumer flowController) throws IOException { + return null; + } + + @Override + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + } + + @Override + public Void onResponseComplete() throws IOException { + return null; + } + + @Override + public void onResponseError(Throwable t) { + } + }; + } + + /** + * + * @return + */ + RawChannel rawChannel() { + if (rawchan == null) { + rawchan = new RawChannel(request.client(), connection); + } + return rawchan; + } +} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java b/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java similarity index 69% rename from jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java rename to jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java index 9d6b59543b0..448fda35156 100644 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchRetainedResource.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/HttpTimeoutException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,21 +23,18 @@ * questions. */ -package com.apple.concurrent; +package java.net.http; -class LibDispatchRetainedResource { - protected long ptr; +import java.io.IOException; - protected LibDispatchRetainedResource(final long ptr) { - this.ptr = ptr; - } +/** + * Thrown when a response is not received within a specified time period. + */ +public class HttpTimeoutException extends IOException { - protected synchronized void dispose() { - if (ptr != 0) LibDispatchNative.nativeReleaseQueue(ptr); - ptr = 0; - } + private static final long serialVersionUID = 981344271622632951L; - protected void finalize() throws Throwable { - dispose(); - } + public HttpTimeoutException(String message) { + super(message); + } } diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Log.java b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java new file mode 100644 index 00000000000..d696854c5b5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Log.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.util.Locale; +import sun.util.logging.PlatformLogger; + +/** + * -Djava.net.HttpClient.log=errors,requests,headers,frames[:type:type2:..],content + * + * Any of errors, requests, headers or content are optional. + * + * Other handlers may be added. All logging is at level INFO + * + * Logger name is "java.net.http.HttpClient" + */ +class Log { + + final static String logProp = "java.net.http.HttpClient.log"; + + public static final int OFF = 0; + public static final int ERRORS = 0x1; + public static final int REQUESTS = 0x2; + public static final int HEADERS = 0x4; + public static final int CONTENT = 0x8; + public static final int FRAMES = 0x10; + public static final int SSL = 0x20; + static int logging; + + // Frame types: "control", "data", "window", "all" + public static final int CONTROL = 1; // all except DATA and WINDOW_UPDATES + public static final int DATA = 2; + public static final int WINDOW_UPDATES = 4; + public static final int ALL = CONTROL| DATA | WINDOW_UPDATES; + static int frametypes; + + static sun.util.logging.PlatformLogger logger; + + static { + String s = Utils.getNetProperty(logProp); + if (s == null) { + logging = OFF; + } else { + String[] vals = s.split(","); + for (String val : vals) { + switch (val.toLowerCase(Locale.US)) { + case "errors": + logging |= ERRORS; + break; + case "requests": + logging |= REQUESTS; + break; + case "headers": + logging |= HEADERS; + break; + case "content": + logging |= CONTENT; + break; + case "ssl": + logging |= SSL; + break; + case "all": + logging |= CONTENT|HEADERS|REQUESTS|FRAMES|ERRORS; + break; + } + if (val.startsWith("frames")) { + logging |= FRAMES; + String[] types = val.split(":"); + if (types.length == 1) { + frametypes = CONTROL | DATA | WINDOW_UPDATES; + } else { + for (String type : types) { + switch (type.toLowerCase()) { + case "control": + frametypes |= CONTROL; + break; + case "data": + frametypes |= DATA; + break; + case "window": + frametypes |= WINDOW_UPDATES; + break; + case "all": + frametypes = ALL; + break; + } + } + } + } + } + } + if (logging != OFF) { + logger = PlatformLogger.getLogger("java.net.http.HttpClient"); + } + } + + static boolean errors() { + return (logging & ERRORS) != 0; + } + + static boolean requests() { + return (logging & REQUESTS) != 0; + } + + static boolean headers() { + return (logging & HEADERS) != 0; + } + + static boolean ssl() { + return (logging & SSL) != 0; + } + + static boolean frames() { + return (logging & FRAMES) != 0; + } + + static void logError(String s) { + if (errors()) + logger.info("ERROR: " + s); + } + + static void logError(Throwable t) { + if (errors()) { + String s = Utils.stackTrace(t); + logger.info("ERROR: " + s); + } + } + + static void logSSL(String s) { + if (ssl()) + logger.info("SSL: " + s); + } + + static void logRequest(String s) { + if (requests()) + logger.info("REQUEST: " + s); + } + + static void logResponse(String s) { + if (requests()) + logger.info("RESPONSE: " + s); + } + + static void logHeaders(String s) { + if (headers()) + logger.info("HEADERS: " + s); + } +// END HTTP2 +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java new file mode 100644 index 00000000000..8a53565ae51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/MultiExchange.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ExecutionException; +import java.util.function.BiFunction; + +import static java.net.http.Pair.pair; + +/** + * Encapsulates multiple Exchanges belonging to one HttpRequestImpl. + * - manages filters + * - retries due to filters. + * - I/O errors and most other exceptions get returned directly to user + * + * Creates a new Exchange for each request/response interaction + */ +class MultiExchange { + + final HttpRequestImpl request; // the user request + final HttpClientImpl client; + HttpRequestImpl currentreq; // used for async only + Exchange exchange; // the current exchange + Exchange previous; + int attempts; + // Maximum number of times a request will be retried/redirected + // for any reason + + final static int DEFAULT_MAX_ATTEMPTS = 5; + final static int max_attempts = Utils.getIntegerNetProperty( + "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_ATTEMPTS + ); + + private final List filters; + TimedEvent td; + boolean cancelled = false; + + /** + * Filter fields. These are attached as required by filters + * and only used by the filter implementations. This could be + * generalised into Objects that are passed explicitly to the filters + * (one per MultiExchange object, and one per Exchange object possibly) + */ + volatile AuthenticationFilter.AuthInfo serverauth, proxyauth; + // RedirectHandler + volatile int numberOfRedirects = 0; + + /** + */ + MultiExchange(HttpRequestImpl request) { + this.exchange = new Exchange(request); + this.previous = null; + this.request = request; + this.currentreq = request; + this.attempts = 0; + this.client = request.client(); + this.filters = client.filterChain(); + } + + public HttpResponseImpl response() throws IOException, InterruptedException { + HttpRequestImpl r = request; + if (r.timeval() != 0) { + // set timer + td = new TimedEvent(r.timeval()); + client.registerTimer(td); + } + while (attempts < max_attempts) { + try { + attempts++; + Exchange currExchange = getExchange(); + requestFilters(r); + HttpResponseImpl response = currExchange.response(); + Pair filterResult = responseFilters(response); + HttpRequestImpl newreq = filterResult.second; + if (newreq == null) { + if (attempts > 1) { + Log.logError("Succeeded on attempt: " + attempts); + } + cancelTimer(); + return response; + } + response.body(HttpResponse.ignoreBody()); + setExchange(new Exchange(newreq, currExchange.getAccessControlContext() )); + r = newreq; + } catch (IOException e) { + if (cancelled) { + throw new HttpTimeoutException("Request timed out"); + } + throw e; + } + } + cancelTimer(); + throw new IOException("Retry limit exceeded"); + } + + private synchronized Exchange getExchange() { + return exchange; + } + + private synchronized void setExchange(Exchange exchange) { + this.exchange = exchange; + } + + private void cancelTimer() { + if (td != null) { + client.cancelTimer(td); + } + } + + private void requestFilters(HttpRequestImpl r) throws IOException { + for (HeaderFilter filter : filters) { + filter.request(r); + } + } + + // Filters are assumed to be non-blocking so the async + // versions of these methods just call the blocking ones + + private CompletableFuture requestFiltersAsync(HttpRequestImpl r) { + CompletableFuture cf = new CompletableFuture<>(); + try { + requestFilters(r); + cf.complete(null); + } catch(Throwable e) { + cf.completeExceptionally(e); + } + return cf; + } + + + private Pair + responseFilters(HttpResponse response) throws IOException + { + for (HeaderFilter filter : filters) { + HttpRequestImpl newreq = filter.response((HttpResponseImpl)response); + if (newreq != null) { + return pair(null, newreq); + } + } + return pair(response, null); + } + + private CompletableFuture> + responseFiltersAsync(HttpResponse response) + { + CompletableFuture> cf = new CompletableFuture<>(); + try { + Pair n = responseFilters(response); // assumed to be fast + cf.complete(n); + } catch (Throwable e) { + cf.completeExceptionally(e); + } + return cf; + } + + public void cancel() { + cancelled = true; + getExchange().cancel(); + } + + public CompletableFuture responseAsync(Void v) { + CompletableFuture cf; + if (++attempts > max_attempts) { + cf = new CompletableFuture<>(); + cf.completeExceptionally(new IOException("Too many retries")); + } else { + if (currentreq.timeval() != 0) { + // set timer + td = new TimedEvent(currentreq.timeval()); + client.registerTimer(td); + } + Exchange exch = getExchange(); + cf = requestFiltersAsync(currentreq) + .thenCompose(exch::responseAsync) + .thenCompose(this::responseFiltersAsync) + .thenCompose((Pair pair) -> { + HttpResponseImpl resp = (HttpResponseImpl)pair.first; + if (resp != null) { + if (attempts > 1) { + Log.logError("Succeeded on attempt: " + attempts); + } + return CompletableFuture.completedFuture(resp); + } else { + currentreq = pair.second; + Exchange previous = exch; + setExchange(new Exchange(currentreq, + currentreq.getAccessControlContext())); + //reads body off previous, and then waits for next response + return previous + .responseBodyAsync(HttpResponse.ignoreBody()) + .thenCompose(this::responseAsync); + } + }) + .handle((BiFunction>) Pair::new) + .thenCompose((Pair obj) -> { + HttpResponseImpl response = (HttpResponseImpl)obj.first; + if (response != null) { + return CompletableFuture.completedFuture(response); + } + // all exceptions thrown are handled here + CompletableFuture error = getExceptionalCF(obj.second); + if (error == null) { + cancelTimer(); + return responseAsync(null); + } else { + return error; + } + }); + } + return cf; + } + + /** + * Take a Throwable and return a suitable CompletableFuture that is + * completed exceptionally. + */ + private CompletableFuture getExceptionalCF(Throwable t) { + CompletableFuture error = new CompletableFuture<>(); + if ((t instanceof CompletionException) || (t instanceof ExecutionException)) { + if (t.getCause() != null) { + t = t.getCause(); + } + } + if (cancelled && t instanceof IOException) { + t = new HttpTimeoutException("request timed out"); + } + error.completeExceptionally(t); + return error; + } + + T responseBody(HttpResponse.BodyProcessor processor) { + return getExchange().responseBody(processor); + } + + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return getExchange().responseBodyAsync(processor); + } + + class TimedEvent extends TimeoutEvent { + TimedEvent(long timeval) { + super(timeval); + } + @Override + public void handle() { + cancel(); + } + + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java new file mode 100644 index 00000000000..5ffeaf6c961 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Pair.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2016 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General 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 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 License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.net.http; + +/** + * A simple paired value class + */ +final class Pair { + + Pair(T first, U second) { + this.second = second; + this.first = first; + } + + final T first; + final U second; + + // Because 'pair()' is shorter than 'new Pair<>()'. + // Sometimes this difference might be very significant (especially in a + // 80-ish characters boundary). Sorry diamond operator. + static Pair pair(T first, U second) { + return new Pair<>(first, second); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java new file mode 100644 index 00000000000..e206f9204e2 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainHttpConnection.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.net.StandardSocketOptions; +import java.nio.ByteBuffer; +import java.nio.channels.SelectableChannel; +import java.nio.channels.SelectionKey; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; + +/** + * Plain raw TCP connection direct to destination + */ +class PlainHttpConnection extends HttpConnection { + + protected SocketChannel chan; + private volatile boolean connected; + private boolean closed; + + class ConnectEvent extends AsyncEvent implements AsyncEvent.Blocking { + CompletableFuture cf; + + ConnectEvent(CompletableFuture cf) { + this.cf = cf; + } + + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public int interestOps() { + return SelectionKey.OP_CONNECT; + } + + @Override + public void handle() { + try { + chan.finishConnect(); + } catch (IOException e) { + cf.completeExceptionally(e); + } + connected = true; + cf.complete(null); + } + + @Override + public void abort() { + close(); + } + } + + @Override + public CompletableFuture connectAsync() { + CompletableFuture plainFuture = new CompletableFuture<>(); + try { + chan.configureBlocking(false); + chan.connect(address); + client.registerEvent(new ConnectEvent(plainFuture)); + } catch (IOException e) { + plainFuture.completeExceptionally(e); + } + return plainFuture; + } + + @Override + public void connect() throws IOException { + chan.connect(address); + connected = true; + } + + @Override + SocketChannel channel() { + return chan; + } + + PlainHttpConnection(InetSocketAddress addr, HttpClientImpl client) { + super(addr, client); + try { + this.chan = SocketChannel.open(); + int bufsize = client.getReceiveBufferSize(); + chan.setOption(StandardSocketOptions.SO_RCVBUF, bufsize); + } catch (IOException e) { + throw new InternalError(e); + } + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + //debugPrint("Send", buffers, start, number); + return chan.write(buffers, start, number); + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + return chan.write(buffer); + } + + @Override + public String toString() { + return "PlainHttpConnection: " + super.toString(); + } + + /** + * Close this connection + */ + @Override + synchronized void close() { + if (closed) + return; + closed = true; + try { + Log.logError("Closing: " + toString()); + //System.out.println("Closing: " + this); + chan.close(); + } catch (IOException e) {} + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = getBuffer(); // TODO not using length + int n = chan.read(buf); + if (n == -1) { + return null; + } + buf.flip(); + String s = "Receive (" + n + " bytes) "; + //debugPrint(s, buf); + return buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + int mark = buf.position(); + int n = chan.read(buf); + if (n == -1) { + return -1; + } + Utils.flipToMark(buffer, mark); + String s = "Receive (" + n + " bytes) "; + //debugPrint(s, buf); + return n; + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(address, null); + } + + @Override + synchronized boolean connected() { + return connected; + } + + class ReceiveResponseEvent extends AsyncEvent implements AsyncEvent.Blocking { + CompletableFuture cf; + + ReceiveResponseEvent(CompletableFuture cf) { + this.cf = cf; + } + @Override + public SelectableChannel channel() { + return chan; + } + + @Override + public void handle() { + cf.complete(null); + } + + @Override + public int interestOps() { + return SelectionKey.OP_READ; + } + + @Override + public void abort() { + close(); + } + } + + @Override + boolean isSecure() { + return false; + } + + @Override + boolean isProxied() { + return false; + } + + @Override + CompletableFuture whenReceivingResponse() { + CompletableFuture cf = new CompletableFuture<>(); + try { + client.registerEvent(new ReceiveResponseEvent(cf)); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java new file mode 100644 index 00000000000..1e1170ad184 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainProxyConnection.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.net.InetSocketAddress; + +class PlainProxyConnection extends PlainHttpConnection { + + PlainProxyConnection(InetSocketAddress proxy, HttpClientImpl client) { + super(proxy, client); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(null, address); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java new file mode 100644 index 00000000000..2042baa2c4e --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/PlainTunnelingConnection.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.security.AccessControlContext; +import java.util.concurrent.CompletableFuture; + +/** + * A plain text socket tunnel through a proxy. Uses "CONNECT" but does not + * encrypt. Used by WebSockets. Subclassed in SSLTunnelConnection for encryption. + */ +class PlainTunnelingConnection extends HttpConnection { + + final PlainHttpConnection delegate; + protected final InetSocketAddress proxyAddr; + private volatile boolean connected; + private final AccessControlContext acc; + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenCompose((Void v) -> { + HttpRequestImpl req = new HttpRequestImpl(client, "CONNECT", address); + Exchange connectExchange = new Exchange(req, acc); + return connectExchange + .responseAsyncImpl(delegate) + .thenCompose((HttpResponse r) -> { + CompletableFuture cf = new CompletableFuture<>(); + if (r.statusCode() != 200) { + cf.completeExceptionally(new IOException("Tunnel failed")); + } else { + connected = true; + cf.complete(null); + } + return cf; + }); + }); + } + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + HttpRequestImpl req = new HttpRequestImpl(client, "CONNECT", address); + Exchange connectExchange = new Exchange(req, acc); + HttpResponse r = connectExchange.responseImpl(delegate); + if (r.statusCode() != 200) { + throw new IOException("Tunnel failed"); + } + connected = true; + } + + @Override + boolean connected() { + return connected; + } + + protected PlainTunnelingConnection(InetSocketAddress addr, + InetSocketAddress proxy, + HttpClientImpl client, + AccessControlContext acc) { + super(addr, client); + this.proxyAddr = proxy; + this.acc = acc; + delegate = new PlainHttpConnection(proxy, client); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + ConnectionPool.CacheKey cacheKey() { + return new ConnectionPool.CacheKey(null, proxyAddr); + } + + @Override + long write(ByteBuffer[] buffers, int start, int number) throws IOException { + return delegate.write(buffers, start, number); + } + + @Override + long write(ByteBuffer buffer) throws IOException { + return delegate.write(buffer); + } + + @Override + void close() { + delegate.close(); + connected = false; + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + return delegate.readImpl(length); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + protected int readImpl(ByteBuffer buffer) throws IOException { + return delegate.readImpl(buffer); + } + + @Override + boolean isSecure() { + return false; + } + + @Override + boolean isProxied() { + return true; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java new file mode 100644 index 00000000000..9566eeb555c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RawChannel.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; +import java.nio.channels.GatheringByteChannel; +import java.nio.channels.SelectableChannel; + +/** + * Used to implement WebSocket. Each RawChannel corresponds to + * a TCP connection (SocketChannel) but is connected to a Selector + * and an ExecutorService for invoking the send and receive callbacks + * Also includes SSL processing. + */ +class RawChannel implements ByteChannel, GatheringByteChannel { + + private final HttpClientImpl client; + private final HttpConnection connection; + private boolean closed; + + private interface RawEvent { + + /** must return the selector interest op flags OR'd. */ + int interestOps(); + + /** called when event occurs. */ + void handle(); + } + + interface BlockingEvent extends RawEvent { } + + interface NonBlockingEvent extends RawEvent { } + + RawChannel(HttpClientImpl client, HttpConnection connection) { + this.client = client; + this.connection = connection; + } + + private class RawAsyncEvent extends AsyncEvent { + + private final RawEvent re; + + RawAsyncEvent(RawEvent re) { + this.re = re; + } + + public SelectableChannel channel() { + return connection.channel(); + } + + // must return the selector interest op flags OR'd + public int interestOps() { + return re.interestOps(); + } + + // called when event occurs + public void handle() { + re.handle(); + } + + public void abort() {} + } + + private class BlockingRawAsyncEvent extends RawAsyncEvent + implements AsyncEvent.Blocking { + + BlockingRawAsyncEvent(RawEvent re) { + super(re); + } + } + + private class NonBlockingRawAsyncEvent extends RawAsyncEvent + implements AsyncEvent.NonBlocking { + + NonBlockingRawAsyncEvent(RawEvent re) { + super(re); + } + } + + /* + * Register given event whose callback will be called once only. + * (i.e. register new event for each callback) + */ + public void registerEvent(RawEvent event) throws IOException { + if (event instanceof BlockingEvent) { + client.registerEvent(new BlockingRawAsyncEvent(event)); + } else if (event instanceof NonBlockingEvent) { + client.registerEvent(new NonBlockingRawAsyncEvent(event)); + } else { + throw new InternalError(); + } + } + + @Override + public int read(ByteBuffer dst) throws IOException { + return connection.read(dst); + } + + @Override + public boolean isOpen() { + return !closed; + } + + @Override + public void close() throws IOException { + closed = true; + connection.close(); + } + + @Override + public long write(ByteBuffer[] src) throws IOException { + return connection.write(src, 0, src.length); + } + + @Override + public long write(ByteBuffer[] src, int offset, int len) + throws IOException { + return connection.write(src, offset, len); + } + + @Override + public int write(ByteBuffer src) throws IOException { + return (int) connection.write(src); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java new file mode 100644 index 00000000000..3c3be4d17c5 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/RedirectFilter.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; + +class RedirectFilter implements HeaderFilter { + + HttpRequestImpl requestImpl; + HttpRequest request; + HttpClientImpl client; + String method; + final static int DEFAULT_MAX_REDIRECTS = 5; + URI uri; + + final static int max_redirects = Utils.getIntegerNetProperty( + "sun.net.httpclient.redirects.retrylimit", DEFAULT_MAX_REDIRECTS + ); + + @Override + public void request(HttpRequestImpl r) throws IOException { + this.request = r; + this.client = r.getClient(); + this.method = r.method(); + this.requestImpl = r; + this.uri = r.uri(); + } + + @Override + public HttpRequestImpl response(HttpResponseImpl r) throws IOException { + return handleResponse(r); + } + + /** + * checks to see if new request needed and returns it. + * Null means response is ok to return to user. + */ + private HttpRequestImpl handleResponse(HttpResponseImpl r) { + int rcode = r.statusCode(); + if (rcode == 200) { + return null; + } + if (rcode >= 300 && rcode <= 399) { + URI redir = getRedirectedURI(r.headers()); + if (canRedirect(r) && ++r.request.exchange.numberOfRedirects < max_redirects) { + //System.out.println("Redirecting to: " + redir); + return new HttpRequestImpl(redir, request, client, method, requestImpl); + } else { + //System.out.println("Redirect: giving up"); + return null; + } + } + return null; + } + + private URI getRedirectedURI(HttpHeaders headers) { + URI redirectedURI; + redirectedURI = headers.firstValue("Location") + .map((s) -> URI.create(s)) + .orElseThrow(() -> new UncheckedIOException( + new IOException("Invalid redirection"))); + + // redirect could be relative to original URL, but if not + // then redirect is used. + redirectedURI = uri.resolve(redirectedURI); + return redirectedURI; + } + + private boolean canRedirect(HttpResponse r) { + return requestImpl.followRedirectsImpl().redirect(r); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java new file mode 100644 index 00000000000..f6e8d7504d9 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseContent.java @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; + +/** + * Implements chunked/fixed transfer encodings of HTTP/1.1 responses. + */ +class ResponseContent { + + final HttpResponse.BodyProcessor userProcessor; + final HttpResponse.BodyProcessor pusher; + final HttpConnection connection; + final int contentLength; + ByteBuffer buffer; + ByteBuffer lastBufferUsed; + final ResponseHeaders headers; + final Http1Response.FlowController flowController; + + ResponseContent(HttpConnection connection, + int contentLength, + ResponseHeaders h, + HttpResponse.BodyProcessor userProcessor, + Http1Response.FlowController flowController) { + this.userProcessor = userProcessor; + this.pusher = (HttpResponse.BodyProcessor)userProcessor; + this.connection = connection; + this.contentLength = contentLength; + this.headers = h; + this.flowController = flowController; + } + + static final int LF = 10; + static final int CR = 13; + static final int SP = 0x20; + static final int BUF_SIZE = 1024; + + boolean chunkedContent, chunkedContentInitialized; + + private boolean contentChunked() throws IOException { + if (chunkedContentInitialized) { + return chunkedContent; + } + if (contentLength == -1) { + String tc = headers.firstValue("Transfer-Encoding") + .orElse(""); + if (!tc.equals("")) { + if (tc.equalsIgnoreCase("chunked")) { + chunkedContent = true; + } else { + throw new IOException("invalid content"); + } + } else { + chunkedContent = false; + } + } + chunkedContentInitialized = true; + return chunkedContent; + } + + /** + * Entry point for pusher. b is an initial ByteBuffer that may + * have some data in it. When this method returns, the body + * has been fully processed. + */ + void pushBody(ByteBuffer b) throws IOException { + // TODO: check status + if (contentChunked()) { + pushBodyChunked(b); + } else { + pushBodyFixed(b); + } + } + + // reads and returns chunklen. Position of chunkbuf is first byte + // of chunk on return. chunklen includes the CR LF at end of chunk + int readChunkLen() throws IOException { + chunklen = 0; + boolean cr = false; + while (true) { + getHunk(); + int c = chunkbuf.get(); + if (cr) { + if (c == LF) { + return chunklen + 2; + } else { + throw new IOException("invalid chunk header"); + } + } + if (c == CR) { + cr = true; + } else { + int digit = toDigit(c); + chunklen = chunklen * 16 + digit; + } + } + } + + int chunklen = -1; // number of bytes in chunk (fixed) + int bytesremaining; // number of bytes in chunk left to be read incl CRLF + int bytesread; + ByteBuffer chunkbuf; // initialise + + // make sure we have at least 1 byte to look at + private void getHunk() throws IOException { + while (chunkbuf == null || !chunkbuf.hasRemaining()) { + + if (chunkbuf != null) { + connection.returnBuffer(chunkbuf); + } + chunkbuf = connection.read(); + } + } + + private void consumeBytes(int n) throws IOException { + getHunk(); + while (n > 0) { + int e = Math.min(chunkbuf.remaining(), n); + chunkbuf.position(chunkbuf.position() + e); + n -= e; + if (n > 0) + getHunk(); + } + } + + /** + * Returns a ByteBuffer containing a chunk of data or a "hunk" of data + * (a chunk of a chunk if the chunk size is larger than our ByteBuffers). + */ + ByteBuffer readChunkedBuffer() throws IOException { + if (chunklen == -1) { + // new chunk + bytesremaining = readChunkLen(); + chunklen = bytesremaining - 2; + if (chunklen == 0) { + consumeBytes(2); + return null; + } + } + + getHunk(); + bytesread = chunkbuf.remaining(); + ByteBuffer returnBuffer; + + /** + * Cases. Always at least one byte is read by getHunk() + * + * 1) one read contains exactly 1 chunk. Strip off CRLF and pass buffer on + * 2) one read contains a hunk. If at end of chunk, consume CRLF.Pass buffer up. + * 3) read contains rest of chunk and more data. Copy buffer. + */ + if (bytesread == bytesremaining) { + // common case: 1 read = 1 chunk (or final hunk of chunk) + chunkbuf.limit(chunkbuf.limit() - 2); // remove trailing CRLF + bytesremaining = 0; + returnBuffer = chunkbuf; + chunkbuf = null; + chunklen = -1; + } else if (bytesread < bytesremaining) { + // read a hunk, maybe including CR or LF or both + bytesremaining -= bytesread; + if (bytesremaining <= 2) { + // remove any trailing CR LF already read, and then read the rest + chunkbuf.limit(chunkbuf.limit() - (2 - bytesremaining)); + consumeBytes(bytesremaining); + chunklen = -1; + } + returnBuffer = chunkbuf; + chunkbuf = null; + } else { + // bytesread > bytesremaining + returnBuffer = splitChunkedBuffer(bytesremaining-2); + bytesremaining = 0; + chunklen = -1; + consumeBytes(2); + } + return returnBuffer; + } + + ByteBuffer initialBuffer; + int fixedBytesReturned; + + ByteBuffer getResidue() { + return lastBufferUsed; + } + + private void compactBuffer(ByteBuffer buf) { + buf.compact() + .flip(); + } + + /** + * Copies inbuf (numBytes from its position) to new buffer. The returned + * buffer's position is zero and limit is at end (numBytes) + */ + private ByteBuffer copyBuffer(ByteBuffer inbuf, int numBytes) { + ByteBuffer b1 = connection.getBuffer(); + assert b1.remaining() >= numBytes; + byte[] b = b1.array(); + inbuf.get(b, 0, numBytes); + b1.limit(numBytes); + return b1; + } + + /** + * Split numBytes of data out of chunkbuf from the remainder, + * copying whichever part is smaller. chunkbuf points to second part + * of buffer on return. The returned buffer is the data from position + * to position + numBytes. Both buffers positions are reset so same + * data can be re-read. + */ + private ByteBuffer splitChunkedBuffer(int numBytes) { + ByteBuffer newbuf = connection.getBuffer(); + byte[] b = newbuf.array(); + int midpoint = chunkbuf.position() + numBytes; + int remainder = chunkbuf.limit() - midpoint; + + if (numBytes < remainder) { + // copy first part of chunkbuf to new buf + chunkbuf.get(b, 0, numBytes); + newbuf.limit(numBytes); + return newbuf; + } else { + // copy remainder of chunkbuf to newbuf and make newbuf chunkbuf + chunkbuf.mark(); + chunkbuf.position(midpoint); + chunkbuf.get(b, 0, remainder); + chunkbuf.reset(); + chunkbuf.limit(midpoint); + newbuf.limit(remainder); + newbuf.position(0); + ByteBuffer tmp = chunkbuf; + chunkbuf = newbuf; + return tmp; + } + } + + private void pushBodyChunked(ByteBuffer b) throws IOException { + chunkbuf = b; + while (true) { + ByteBuffer b1 = readChunkedBuffer(); + if (b1 != null) { + if (b1.hasRemaining()) { + request(1); // wait till we can send + pusher.onResponseBodyChunk(b1); + lastBufferUsed = b1; + } + } else { + return; + } + } + } + + private int toDigit(int b) throws IOException { + if (b >= 0x30 && b <= 0x39) { + return b - 0x30; + } + if (b >= 0x41 && b <= 0x46) { + return b - 0x41 + 10; + } + if (b >= 0x61 && b <= 0x66) { + return b - 0x61 + 10; + } + throw new IOException("Invalid chunk header byte " + b); + } + + private void request(long value) throws IOException { + try { + flowController.request(value); + } catch (InterruptedException e) { + throw new IOException(e); + } + } + + private void pushBodyFixed(ByteBuffer b) throws IOException { + lastBufferUsed = b; + for (int remaining = contentLength; remaining > 0;) { + int bufsize = b.remaining(); + if (bufsize > remaining) { + // more data available than required, must copy + lastBufferUsed = b; + b = copyBuffer(b, remaining); + remaining = 0; + } else { + // pass entire buffer up to user + remaining -= bufsize; + compactBuffer(b); + } + request(1); // wait till we can send + pusher.onResponseBodyChunk(b); + if (remaining > 0) { + b = connection.read(); + if (b == null) { + throw new IOException("Error reading response"); + } + lastBufferUsed = b; + } + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java new file mode 100644 index 00000000000..b378e784c51 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/ResponseHeaders.java @@ -0,0 +1,480 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Optional; +import java.util.Set; + +/** + * Reads response headers off channel, in blocking mode. Entire header + * block is collected in a byte[]. The offset location of the start of + * each header name is recorded in an array to facilitate later searching. + * + * The location of "Content-length" is recorded explicitly. Similar approach + * could be taken for other common headers. + * + * This class is not thread-safe + */ +class ResponseHeaders implements HttpHeaders1 { + + static final int DATA_SIZE = 16 * 1024; // initial space for headers + static final int NUM_HEADERS = 50; // initial expected max number of headers + + final HttpConnection connection; + byte[] data; + int contentlen = -2; // means not initialized + ByteBuffer buffer; + + /** + * Following used for scanning the array looking for: + * - well known headers + * - end of header block + */ + int[] headerOffsets; // index into data + int numHeaders; + int count; + + ByteBuffer residue; // after headers processed, data may be here + + ResponseHeaders(HttpConnection connection, ByteBuffer buffer) { + this.connection = connection; + initOffsets(); + this.buffer = buffer; + data = new byte[DATA_SIZE]; + } + + int getContentLength() throws IOException { + if (contentlen != -2) { + return contentlen; + } + int[] search = findHeaderValue("Content-length"); + if (search[0] == -1) { + contentlen = -1; + return -1; + } + + int i = search[0]; + + while (data[i] == ' ' || data[i] == '\t') { + i++; + if (i == data.length || data[i] == CR || data[i] == LF) { + throw new IOException("Bad header"); + } + } + contentlen = 0; + int digit = data[i++] - 0x30; + while (digit >= 0 && digit <= 9) { + contentlen = contentlen * 10 + digit; + digit = data[i++] - 0x30; + } + return contentlen; + } + + void log() { + populateMap(false); + } + + void populateMap(boolean clearOffsets) { + StringBuilder sb; + + for (int i = 0; i < numHeaders; i++) { + sb = new StringBuilder(32); + int offset = headerOffsets[i]; + if (offset == -1) { + continue; + } + int j; + for (j=0; data[offset+j] != ':'; j++) { + // byte to char promotion ok for US-ASCII + sb.append((char)data[offset+j]); + } + String name = sb.toString(); + List l = getOrCreate(name); + addEntry(l, name, offset + j + 1); + // clear the offset + if (clearOffsets) + headerOffsets[i] = -1; + } + } + + void addEntry(List l, String name, int j) { + + while (data[j] == ' ' || data[j] == '\t') { + j++; + } + + int vstart = j; + // TODO: back slash ?? + + while (data[j] != CR) { + j++; + } + try { + String value = new String(data, vstart, j - vstart, "US-ASCII"); + l.add(value); + } catch (UnsupportedEncodingException e) { + // can't happen + throw new InternalError(e); + } + } + + // returns an int[2]: [0] = offset of value in data[] + // [1] = offset in headerOffsets. Both are -1 in error + + private int[] findHeaderValue(String name) { + int[] result = new int[2]; + byte[] namebytes = getBytes(name); + + outer: for (int i = 0; i < numHeaders; i++) { + int offset = headerOffsets[i]; + if (offset == -1) { + continue; + } + + for (int j=0; j populateMapEntry(String name) { + List l = getOrCreate(name); + int[] search = findHeaderValue(name); + if (search[0] != -1) { + addEntry(l, name, search[0]); + // clear the offset + headerOffsets[search[1]] = -1; + } + return l; + } + + static final Locale usLocale = Locale.US; + static final Charset ascii = StandardCharsets.US_ASCII; + + private byte[] getBytes(String name) { + return name.toLowerCase(usLocale).getBytes(ascii); + } + + /* + * We read buffers in a loop until we detect end of headers + * CRLFCRLF. Each byte received is copied into the byte[] data + * The position of the first byte of each header (after a CRLF) + * is recorded in a separate array showing the location of + * each header name. + */ + void initHeaders() throws IOException { + + inHeaderName = true; + endOfHeader = true; + + for (int numBuffers = 0; true; numBuffers++) { + + if (numBuffers > 0) { + buffer = connection.read(); + } + + if (buffer == null) { + throw new IOException("Error reading headers"); + } + + if (!buffer.hasRemaining()) { + continue; + } + + // Position set to first byte + int start = buffer.position(); + byte[] backing = buffer.array(); + int len = buffer.limit() - start; + + for (int i = 0; i < len; i++) { + byte b = backing[i + start]; + if (inHeaderName) { + b = lowerCase(b); + } + if (b == ':') { + inHeaderName = false; + } + data[count++] = b; + checkByte(b); + if (firstChar) { + recordHeaderOffset(count-1); + firstChar = false; + } + if (endOfHeader && numHeaders == 0) { + // empty headers + endOfAllHeaders = true; + } + if (endOfAllHeaders) { + int newposition = i + 1 + start; + if (newposition <= buffer.limit()) { + buffer.position(newposition); + residue = buffer; + } else { + residue = null; + } + return; + } + + if (count == data.length) { + resizeData(); + } + } + } + } + + static final int CR = 13; + static final int LF = 10; + int crlfCount = 0; + + // results of checkByte() + boolean endOfHeader; // just seen LF after CR before + boolean endOfAllHeaders; // just seen LF after CRLFCR before + boolean firstChar; // + boolean inHeaderName; // examining header name + + void checkByte(byte b) throws IOException { + if (endOfHeader && b != CR && b != LF) + firstChar = true; + endOfHeader = false; + endOfAllHeaders = false; + switch (crlfCount) { + case 0: + crlfCount = b == CR ? 1 : 0; + break; + case 1: + crlfCount = b == LF ? 2 : 0; + endOfHeader = true; + inHeaderName = true; + break; + case 2: + crlfCount = b == CR ? 3 : 0; + break; + case 3: + if (b != LF) { + throw new IOException("Bad header block termination"); + } + endOfAllHeaders = true; + break; + } + } + + byte lowerCase(byte b) { + if (b >= 0x41 && b <= 0x5A) + b = (byte)(b + 32); + return b; + } + + void resizeData() { + int oldlen = data.length; + int newlen = oldlen * 2; + byte[] newdata = new byte[newlen]; + System.arraycopy(data, 0, newdata, 0, oldlen); + data = newdata; + } + + final void initOffsets() { + headerOffsets = new int[NUM_HEADERS]; + numHeaders = 0; + } + + ByteBuffer getResidue() { + return residue; + } + + void recordHeaderOffset(int index) { + if (numHeaders >= headerOffsets.length) { + int oldlen = headerOffsets.length; + int newlen = oldlen * 2; + int[] new1 = new int[newlen]; + System.arraycopy(headerOffsets, 0, new1, 0, oldlen); + headerOffsets = new1; + } + headerOffsets[numHeaders++] = index; + } + + /** + * As entries are read from the byte[] they are placed in here + * So we always check this map first + */ + Map> headers = new HashMap<>(); + + @Override + public Optional firstValue(String name) { + List l = allValues(name); + if (l == null || l.isEmpty()) { + return Optional.ofNullable(null); + } else { + return Optional.of(l.get(0)); + } + } + + @Override + public List allValues(String name) { + name = name.toLowerCase(usLocale); + List l = headers.get(name); + if (l == null) { + l = populateMapEntry(name); + } + return Collections.unmodifiableList(l); + } + + @Override + public void makeUnmodifiable() { + } + + // Delegates map to HashMap but converts keys to lower case + + static class HeaderMap implements Map> { + Map> inner; + + HeaderMap(Map> inner) { + this.inner = inner; + } + @Override + public int size() { + return inner.size(); + } + + @Override + public boolean isEmpty() { + return inner.isEmpty(); + } + + @Override + public boolean containsKey(Object key) { + if (!(key instanceof String)) { + return false; + } + String s = ((String)key).toLowerCase(usLocale); + return inner.containsKey(s); + } + + @Override + public boolean containsValue(Object value) { + return inner.containsValue(value); + } + + @Override + public List get(Object key) { + String s = ((String)key).toLowerCase(usLocale); + return inner.get(s); + } + + @Override + public List put(String key, List value) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public List remove(Object key) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void putAll(Map> m) { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public void clear() { + throw new UnsupportedOperationException("Not supported"); + } + + @Override + public Set keySet() { + return inner.keySet(); + } + + @Override + public Collection> values() { + return inner.values(); + } + + @Override + public Set>> entrySet() { + return inner.entrySet(); + } + } + + @Override + public Map> map() { + populateMap(true); + return new HeaderMap(headers); + } + + Map> mapInternal() { + populateMap(false); + return new HeaderMap(headers); + } + + private List getOrCreate(String name) { + List l = headers.get(name); + if (l == null) { + l = new LinkedList<>(); + headers.put(name, l); + } + return l; + } + + @Override + public Optional firstValueAsLong(String name) { + List l = allValues(name); + if (l == null) { + return Optional.ofNullable(null); + } else { + String v = l.get(0); + Long lv = Long.parseLong(v); + return Optional.of(lv); + } + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java new file mode 100644 index 00000000000..4b8cb3c0516 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLConnection.java @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import java.net.http.SSLDelegate.BufType; +import java.net.http.SSLDelegate.WrapperResult; + +/** + * An SSL connection built on a Plain TCP connection. + */ +class SSLConnection extends HttpConnection { + + PlainHttpConnection delegate; + SSLDelegate sslDelegate; + final String[] alpn; + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenCompose((Void v) -> { + CompletableFuture cf = new CompletableFuture<>(); + try { + this.sslDelegate = new SSLDelegate(delegate.channel(), + client, + alpn); + cf.complete(null); + } catch (IOException e) { + cf.completeExceptionally(e); + } + return cf; + }); + } + + @Override + public void connect() throws IOException { + delegate.connect(); + this.sslDelegate = new SSLDelegate(delegate.channel(), client, alpn); + } + + SSLConnection(InetSocketAddress addr, HttpClientImpl client, String[] ap) { + super(addr, client); + this.alpn = ap; + delegate = new PlainHttpConnection(addr, client); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "SSLConnection: " + super.toString(); + } + + private static long countBytes(ByteBuffer[] buffers, int start, int length) { + long c = 0; + for (int i=0; i 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long l = buffer.remaining(); + WrapperResult r = sslDelegate.sendData(buffer); + if (r.result.getStatus() == Status.CLOSED) { + if (l > 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + void close() { + try { + //System.err.println ("Closing: " + this); + delegate.channel().close(); // TODO: proper close + } catch (IOException ex) { + Log.logError(ex.toString()); + } + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length); + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + // TODO: need to ensure that buf is big enough for application data + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.result.bytesProduced(); + } + + @Override + boolean connected() { + return delegate.connected(); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return false; + } + +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java new file mode 100644 index 00000000000..fbc0674513c --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLDelegate.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.util.Arrays; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLEngineResult; +import javax.net.ssl.SSLEngineResult.HandshakeStatus; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; +import static javax.net.ssl.SSLEngineResult.HandshakeStatus.*; + +/** + * Implements the mechanics of SSL by managing an SSLEngine object. + * One of these is associated with each SSLConnection. + */ +class SSLDelegate { + + final SSLEngine engine; + final EngineWrapper wrapper; + final Lock handshaking = new ReentrantLock(); + final SSLParameters sslParameters; + final SocketChannel chan; + final HttpClientImpl client; + + // alpn[] may be null + SSLDelegate(SocketChannel chan, HttpClientImpl client, String[] alpn) + throws IOException + { + SSLContext context = client.sslContext(); + engine = context.createSSLEngine(); + engine.setUseClientMode(true); + SSLParameters sslp = client.sslParameters().orElse(null); + if (sslp == null) { + sslp = context.getDefaultSSLParameters(); + } + sslParameters = Utils.copySSLParameters(sslp); + if (alpn != null) { + sslParameters.setApplicationProtocols(alpn); + Log.logSSL("Setting application protocols: " + Arrays.toString(alpn)); + } else { + Log.logSSL("Warning no application protocols proposed!"); + } + engine.setSSLParameters(sslParameters); + wrapper = new EngineWrapper(chan, engine); + this.chan = chan; + this.client = client; + } + + SSLParameters getSSLParameters() { + return sslParameters; + } + + private static long countBytes(ByteBuffer[] buffers, int start, int number) { + long c = 0; + for (int i=0; i packet_buf_size) { + packet_buf_size = len; + } + size = packet_buf_size; + } else { + if (app_buf_size == 0) { + SSLSession sess = engine.getSession(); + app_buf_size = sess.getApplicationBufferSize(); + } + if (len > app_buf_size) { + app_buf_size = len; + } + size = app_buf_size; + } + return ByteBuffer.allocate (size); + } + } + + /* reallocates the buffer by :- + * 1. creating a new buffer double the size of the old one + * 2. putting the contents of the old buffer into the new one + * 3. set xx_buf_size to the new size if it was smaller than new size + * + * flip is set to true if the old buffer needs to be flipped + * before it is copied. + */ + private ByteBuffer realloc (ByteBuffer b, boolean flip, BufType type) { + synchronized (this) { + int nsize = 2 * b.capacity(); + ByteBuffer n = allocate (type, nsize); + if (flip) { + b.flip(); + } + n.put(b); + b = n; + } + return b; + } + + /** + * This is a thin wrapper over SSLEngine and the SocketChannel, which + * guarantees the ordering of wraps/unwraps with respect to the underlying + * channel read/writes. It handles the UNDER/OVERFLOW status codes + * It does not handle the handshaking status codes, or the CLOSED status code + * though once the engine is closed, any attempt to read/write to it + * will get an exception. The overall result is returned. + * It functions synchronously/blocking + */ + class EngineWrapper { + + SocketChannel chan; + SSLEngine engine; + Object wrapLock, unwrapLock; + ByteBuffer unwrap_src, wrap_dst; + boolean closed = false; + int u_remaining; // the number of bytes left in unwrap_src after an unwrap() + + EngineWrapper (SocketChannel chan, SSLEngine engine) throws IOException { + this.chan = chan; + this.engine = engine; + wrapLock = new Object(); + unwrapLock = new Object(); + unwrap_src = allocate(BufType.PACKET); + wrap_dst = allocate(BufType.PACKET); + } + + void close () throws IOException { + } + + WrapperResult wrapAndSend(ByteBuffer src, boolean ignoreClose) + throws IOException + { + ByteBuffer[] buffers = new ByteBuffer[1]; + buffers[0] = src; + return wrapAndSend(buffers, 0, 1, ignoreClose); + } + + /* try to wrap and send the data in src. Handles OVERFLOW. + * Might block if there is an outbound blockage or if another + * thread is calling wrap(). Also, might not send any data + * if an unwrap is needed. + */ + WrapperResult wrapAndSend(ByteBuffer[] src, + int offset, + int len, + boolean ignoreClose) + throws IOException + { + if (closed && !ignoreClose) { + throw new IOException ("Engine is closed"); + } + Status status; + WrapperResult r = new WrapperResult(); + synchronized (wrapLock) { + wrap_dst.clear(); + do { + r.result = engine.wrap (src, offset, len, wrap_dst); + status = r.result.getStatus(); + if (status == Status.BUFFER_OVERFLOW) { + wrap_dst = realloc (wrap_dst, true, BufType.PACKET); + } + } while (status == Status.BUFFER_OVERFLOW); + if (status == Status.CLOSED && !ignoreClose) { + closed = true; + return r; + } + if (r.result.bytesProduced() > 0) { + wrap_dst.flip(); + int l = wrap_dst.remaining(); + assert l == r.result.bytesProduced(); + while (l>0) { + l -= chan.write (wrap_dst); + } + } + } + return r; + } + + /* block until a complete message is available and return it + * in dst, together with the Result. dst may have been re-allocated + * so caller should check the returned value in Result + * If handshaking is in progress then, possibly no data is returned + */ + WrapperResult recvAndUnwrap(ByteBuffer dst) throws IOException { + Status status; + WrapperResult r = new WrapperResult(); + r.buf = dst; + if (closed) { + throw new IOException ("Engine is closed"); + } + boolean needData; + if (u_remaining > 0) { + unwrap_src.compact(); + unwrap_src.flip(); + needData = false; + } else { + unwrap_src.clear(); + needData = true; + } + synchronized (unwrapLock) { + int x; + do { + if (needData) { + do { + x = chan.read (unwrap_src); + } while (x == 0); + if (x == -1) { + throw new IOException ("connection closed for reading"); + } + unwrap_src.flip(); + } + r.result = engine.unwrap (unwrap_src, r.buf); + status = r.result.getStatus(); + if (status == Status.BUFFER_UNDERFLOW) { + if (unwrap_src.limit() == unwrap_src.capacity()) { + /* buffer not big enough */ + unwrap_src = realloc ( + unwrap_src, false, BufType.PACKET + ); + } else { + /* Buffer not full, just need to read more + * data off the channel. Reset pointers + * for reading off SocketChannel + */ + unwrap_src.position (unwrap_src.limit()); + unwrap_src.limit (unwrap_src.capacity()); + } + needData = true; + } else if (status == Status.BUFFER_OVERFLOW) { + r.buf = realloc (r.buf, true, BufType.APPLICATION); + needData = false; + } else if (status == Status.CLOSED) { + closed = true; + r.buf.flip(); + return r; + } + } while (status != Status.OK); + } + u_remaining = unwrap_src.remaining(); + return r; + } + } + + WrapperResult sendData (ByteBuffer src) throws IOException { + ByteBuffer[] buffers = new ByteBuffer[1]; + buffers[0] = src; + return sendData(buffers, 0, 1); + } + + /** + * send the data in the given ByteBuffer. If a handshake is needed + * then this is handled within this method. When this call returns, + * all of the given user data has been sent and any handshake has been + * completed. Caller should check if engine has been closed. + */ + WrapperResult sendData (ByteBuffer[] src, int offset, int len) throws IOException { + WrapperResult r = WrapperResult.createOK(); + while (countBytes(src, offset, len) > 0) { + r = wrapper.wrapAndSend(src, offset, len, false); + Status status = r.result.getStatus(); + if (status == Status.CLOSED) { + doClosure (); + return r; + } + HandshakeStatus hs_status = r.result.getHandshakeStatus(); + if (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + doHandshake(hs_status); + } + } + return r; + } + + /** + * read data thru the engine into the given ByteBuffer. If the + * given buffer was not large enough, a new one is allocated + * and returned. This call handles handshaking automatically. + * Caller should check if engine has been closed. + */ + WrapperResult recvData (ByteBuffer dst) throws IOException { + /* we wait until some user data arrives */ + int mark = dst.position(); + WrapperResult r = null; + assert dst.position() == 0; + while (dst.position() == 0) { + r = wrapper.recvAndUnwrap (dst); + dst = (r.buf != dst) ? r.buf: dst; + Status status = r.result.getStatus(); + if (status == Status.CLOSED) { + doClosure (); + return r; + } + + HandshakeStatus hs_status = r.result.getHandshakeStatus(); + if (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + doHandshake (hs_status); + } + } + Utils.flipToMark(dst, mark); + return r; + } + + /* we've received a close notify. Need to call wrap to send + * the response + */ + void doClosure () throws IOException { + try { + handshaking.lock(); + ByteBuffer tmp = allocate(BufType.APPLICATION); + WrapperResult r; + do { + tmp.clear(); + tmp.flip (); + r = wrapper.wrapAndSend(tmp, true); + } while (r.result.getStatus() != Status.CLOSED); + } finally { + handshaking.unlock(); + } + } + + /* do the (complete) handshake after acquiring the handshake lock. + * If two threads call this at the same time, then we depend + * on the wrapper methods being idempotent. eg. if wrapAndSend() + * is called with no data to send then there must be no problem + */ + @SuppressWarnings("fallthrough") + void doHandshake (HandshakeStatus hs_status) throws IOException { + boolean wasBlocking = false; + try { + wasBlocking = chan.isBlocking(); + handshaking.lock(); + chan.configureBlocking(true); + ByteBuffer tmp = allocate(BufType.APPLICATION); + while (hs_status != HandshakeStatus.FINISHED && + hs_status != HandshakeStatus.NOT_HANDSHAKING) + { + WrapperResult r = null; + switch (hs_status) { + case NEED_TASK: + Runnable task; + while ((task = engine.getDelegatedTask()) != null) { + /* run in current thread, because we are already + * running an external Executor + */ + task.run(); + } + /* fall thru - call wrap again */ + case NEED_WRAP: + tmp.clear(); + tmp.flip(); + r = wrapper.wrapAndSend(tmp, false); + break; + + case NEED_UNWRAP: + tmp.clear(); + r = wrapper.recvAndUnwrap (tmp); + if (r.buf != tmp) { + tmp = r.buf; + } + assert tmp.position() == 0; + break; + } + hs_status = r.result.getHandshakeStatus(); + } + Log.logSSL(getSessionInfo()); + if (!wasBlocking) { + chan.configureBlocking(false); + } + } finally { + handshaking.unlock(); + } + } + + String getSessionInfo() { + StringBuilder sb = new StringBuilder(); + String application = engine.getApplicationProtocol(); + SSLSession sess = engine.getSession(); + String cipher = sess.getCipherSuite(); + String protocol = sess.getProtocol(); + sb.append("Handshake complete alpn: ") + .append(application) + .append(", Cipher: ") + .append(cipher) + .append(", Protocol: ") + .append(protocol); + return sb.toString(); + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java new file mode 100644 index 00000000000..8ec5786a687 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/SSLTunnelConnection.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.InetSocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.SocketChannel; +import java.security.AccessControlContext; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLEngineResult.Status; +import javax.net.ssl.SSLParameters; +import java.net.http.SSLDelegate.BufType; +import java.net.http.SSLDelegate.WrapperResult; + +/** + * An SSL tunnel built on a Plain (CONNECT) TCP tunnel. + */ +class SSLTunnelConnection extends HttpConnection { + + final PlainTunnelingConnection delegate; + protected SSLDelegate sslDelegate; + private volatile boolean connected; + + @Override + public void connect() throws IOException, InterruptedException { + delegate.connect(); + this.sslDelegate = new SSLDelegate(delegate.channel(), client, null); + connected = true; + } + + @Override + boolean connected() { + return connected && delegate.connected(); + } + + @Override + public CompletableFuture connectAsync() { + return delegate.connectAsync() + .thenAccept((Void v) -> { + try { + // can this block? + this.sslDelegate = new SSLDelegate(delegate.channel(), + client, + null); + connected = true; + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }); + } + + SSLTunnelConnection(InetSocketAddress addr, + HttpClientImpl client, + InetSocketAddress proxy, + AccessControlContext acc) { + super(addr, client); + delegate = new PlainTunnelingConnection(addr, proxy, client, acc); + } + + @Override + SSLParameters sslParameters() { + return sslDelegate.getSSLParameters(); + } + + @Override + public String toString() { + return "SSLTunnelConnection: " + super.toString(); + } + + private static long countBytes(ByteBuffer[] buffers, int start, int number) { + long c = 0; + for (int i=0; i 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + long write(ByteBuffer buffer) throws IOException { + //debugPrint("Send", buffer); + long l = buffer.remaining(); + WrapperResult r = sslDelegate.sendData(buffer); + if (r.result.getStatus() == Status.CLOSED) { + if (l > 0) { + throw new IOException("SSLHttpConnection closed"); + } + } + return l; + } + + @Override + void close() { + try { + //System.err.println ("Closing: " + this); + delegate.channel().close(); // TODO: proper close + } catch (IOException ex) { + } + } + + @Override + protected ByteBuffer readImpl(int length) throws IOException { + ByteBuffer buf = sslDelegate.allocate(BufType.PACKET, length); + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.buf; + } + + @Override + protected int readImpl(ByteBuffer buf) throws IOException { + WrapperResult r = sslDelegate.recvData(buf); + // TODO: check for closure + String s = "Receive) "; + //debugPrint(s, r.buf); + return r.result.bytesProduced(); + } + + @Override + SocketChannel channel() { + return delegate.channel(); + } + + @Override + CompletableFuture whenReceivingResponse() { + return delegate.whenReceivingResponse(); + } + + @Override + boolean isSecure() { + return true; + } + + @Override + boolean isProxied() { + return true; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java new file mode 100644 index 00000000000..271e81c7a68 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Stream.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 + */ + +package java.net.http; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.URI; +import java.nio.ByteBuffer; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.function.LongConsumer; + +/** + * Http/2 Stream + */ +class Stream extends ExchangeImpl { + + void debugPrint() { + } + + @Override + @SuppressWarnings("unchecked") + CompletableFuture responseBodyAsync(HttpResponse.BodyProcessor processor) { + return null; + } + + Stream(HttpClientImpl client, Http2Connection connection, Exchange e) { + super(e); + } + + @Override + HttpResponseImpl getResponse() throws IOException { + return null; + } + + @Override + void sendRequest() throws IOException, InterruptedException { + } + + @Override + void sendHeadersOnly() throws IOException, InterruptedException { + } + + @Override + void sendBody() throws IOException, InterruptedException { + } + + @Override + CompletableFuture sendHeadersAsync() { + return null; + } + + @Override + CompletableFuture getResponseAsync(Void v) { + return null; + } + + @Override + CompletableFuture sendBodyAsync() { + return null; + } + + @Override + void cancel() { + } + + + @Override + CompletableFuture sendRequestAsync() { + return null; + } + + @Override + T responseBody(HttpResponse.BodyProcessor processor) throws IOException { + return null; + } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java new file mode 100644 index 00000000000..87786a62a77 --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/TimeoutEvent.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +/** + * Timeout event delivered by selector thread. Executes given handler + * if the timer not cancelled first. + * + * Register with HttpClientImpl.registerTimer(TimeoutEvent) + * + * Cancel with HttpClientImpl.cancelTimer(TimeoutEvent) + */ +abstract class TimeoutEvent { + + final long timeval; + + long delta; // used when on queue + + TimeoutEvent(long timeval) { this.timeval = timeval; } + + public abstract void handle(); + + /** Returns the timevalue in milli-seconds */ + public long timevalMillis() { return timeval; } +} diff --git a/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java new file mode 100644 index 00000000000..a201a23f4bd --- /dev/null +++ b/jdk/src/java.httpclient/share/classes/java/net/http/Utils.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +package java.net.http; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.io.UnsupportedEncodingException; +import java.net.NetPermission; +import java.net.URI; +import java.net.URLPermission; +import java.nio.ByteBuffer; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.List; +import java.util.Map; +import java.util.Set; +import javax.net.ssl.SSLParameters; +import sun.net.NetProperties; + +/** + * Miscellaneous utilities + */ +class Utils { + + /** + * Allocated buffer size. Must never be higher than 16K. But can be lower + * if smaller allocation units preferred. HTTP/2 mandates that all + * implementations support frame payloads of at least 16K. + */ + public static final int BUFSIZE = 16 * 1024; + + /** Validates a RFC7230 token */ + static void validateToken(String token, String errormsg) { + int length = token.length(); + for (int i = 0; i < length; i++) { + int c = token.codePointAt(i); + if (c >= 0x30 && c <= 0x39 // 0 - 9 + || (c >= 0x61 && c <= 0x7a) // a - z + || (c >= 0x41 && c <= 0x5a) // A - Z + || (c >= 0x21 && c <= 0x2e && c != 0x22 && c != 0x27 && c != 0x2c) + || (c >= 0x5e && c <= 0x60) + || (c == 0x7c) || (c == 0x7e)) { + } else { + throw new IllegalArgumentException(errormsg); + } + } + } + + /** + * Return sthe security permission required for the given details. + * If method is CONNECT, then uri must be of form "scheme://host:port" + */ + static URLPermission getPermission(URI uri, + String method, + Map> headers) { + StringBuilder sb = new StringBuilder(); + + String urlstring, actionstring; + + if (method.equals("CONNECT")) { + urlstring = uri.toString(); + actionstring = "CONNECT"; + } else { + sb.append(uri.getScheme()) + .append("://") + .append(uri.getHost()) + .append(uri.getPath()); + urlstring = sb.toString(); + + sb = new StringBuilder(); + sb.append(method); + if (headers != null && !headers.isEmpty()) { + sb.append(':'); + Set keys = headers.keySet(); + boolean first = true; + for (String key : keys) { + if (!first) { + sb.append(','); + } + sb.append(key); + first = false; + } + } + actionstring = sb.toString(); + } + return new URLPermission(urlstring, actionstring); + } + + static void checkNetPermission(String target) { + SecurityManager sm = System.getSecurityManager(); + if (sm == null) + return; + NetPermission np = new NetPermission(target); + sm.checkPermission(np); + } + + static int getIntegerNetProperty(String name, int defaultValue) { + return AccessController.doPrivileged((PrivilegedAction)() -> + NetProperties.getInteger(name, defaultValue) ); + } + + static String getNetProperty(String name) { + return AccessController.doPrivileged((PrivilegedAction)() -> + NetProperties.get(name) ); + } + + static SSLParameters copySSLParameters(SSLParameters p) { + SSLParameters p1 = new SSLParameters(); + p1.setAlgorithmConstraints(p.getAlgorithmConstraints()); + p1.setCipherSuites(p.getCipherSuites()); + p1.setEnableRetransmissions(p.getEnableRetransmissions()); + p1.setEndpointIdentificationAlgorithm(p.getEndpointIdentificationAlgorithm()); + p1.setMaximumPacketSize(p.getMaximumPacketSize()); + p1.setNeedClientAuth(p.getNeedClientAuth()); + p1.setProtocols(p.getProtocols().clone()); + p1.setSNIMatchers(p.getSNIMatchers()); + p1.setServerNames(p.getServerNames()); + p1.setUseCipherSuitesOrder(p.getUseCipherSuitesOrder()); + p1.setWantClientAuth(p.getWantClientAuth()); + return p1; + } + + + /** Resumes reading into the given buffer. */ + static void unflip(ByteBuffer buf) { + buf.position(buf.limit()); + buf.limit(buf.capacity()); + } + + /** + * Set limit to position, and position to mark. + * + * + * @param buffer + * @param mark + */ + static void flipToMark(ByteBuffer buffer, int mark) { + buffer.limit(buffer.position()); + buffer.position(mark); + } + + /** Compact and leave ready for reading. */ + static void compact(List buffers) { + for (ByteBuffer b : buffers) { + b.compact(); + b.flip(); + } + } + + static String stackTrace(Throwable t) { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + String s = null; + try { + PrintStream p = new PrintStream(bos, true, "US-ASCII"); + t.printStackTrace(p); + s = bos.toString("US-ASCII"); + } catch (UnsupportedEncodingException ex) { + // can't happen + } + return s; + } + + /** Copies as much of src to dst as possible. */ + static void copy (ByteBuffer src, ByteBuffer dst) { + int srcLen = src.remaining(); + int dstLen = dst.remaining(); + if (srcLen > dstLen) { + int diff = srcLen - dstLen; + int limit = src.limit(); + src.limit(limit - diff); + dst.put(src); + src.limit(limit); + } else { + dst.put(src); + } + } + + static ByteBuffer copy(ByteBuffer src) { + ByteBuffer dst = ByteBuffer.allocate(src.remaining()); + dst.put(src); + dst.flip(); + return dst; + } + + static String combine(String[] s) { + StringBuilder sb = new StringBuilder(); + sb.append('['); + boolean first = true; + for (String s1 : s) { + if (!first) { + sb.append(", "); + first = false; + } + sb.append(s1); + } + sb.append(']'); + return sb.toString(); + } +} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java similarity index 69% rename from jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java rename to jdk/src/java.httpclient/share/classes/java/net/http/package-info.java index af055aedb57..fd6d4ae2497 100644 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchConcurrentQueue.java +++ b/jdk/src/java.httpclient/share/classes/java/net/http/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,22 +23,18 @@ * questions. */ -package com.apple.concurrent; - -import java.util.concurrent.Executor; - -class LibDispatchConcurrentQueue extends LibDispatchQueue implements Executor { - LibDispatchConcurrentQueue(final long queuePtr) { - super(queuePtr); - } - - @Override - public void execute(final Runnable task) { - LibDispatchNative.nativeExecuteAsync(ptr, task); - } - - @Override - protected synchronized void dispose() { - // should not dispose the default concurrent queues - } -} +/** + *

    High level HTTP API

    + * This provides a high-level client interface to HTTP (versions 1.1 and 2). + * Synchronous and asynchronous (via + * {@link java.util.concurrent.CompletableFuture}) modes are provided. The main + * classes defined are: + *
      + *
    • {@link java.net.http.HttpClient}
    • + *
    • {@link java.net.http.HttpRequest}
    • + *
    • {@link java.net.http.HttpResponse}
    • + *
    + * + * @since 9 + */ +package java.net.http; diff --git a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java index 3cc00d0e630..48210efeaf6 100644 --- a/jdk/src/java.logging/share/classes/java/util/logging/Logger.java +++ b/jdk/src/java.logging/share/classes/java/util/logging/Logger.java @@ -839,6 +839,7 @@ public class Logger { * @param level One of the message level identifiers, e.g., SEVERE * @param msgSupplier A function, which when called, produces the * desired log message + * @since 1.8 */ public void log(Level level, Supplier msgSupplier) { if (!isLoggable(level)) { diff --git a/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java b/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java index a7f43a095e3..aa4b4eb252c 100644 --- a/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java +++ b/jdk/src/java.naming/share/classes/javax/naming/CompoundName.java @@ -82,7 +82,7 @@ import java.util.Properties; * attribute-value-assertions when specifying multiple attribute/value * pairs. (e.g. "," in age=65,gender=male). *
    jndi.syntax.separator.typeval - *
    If present, specifies the string that separators attribute + *
    If present, specifies the string that separates attribute * from value (e.g. "=" in "age=65") * * These properties are interpreted according to the following rules: diff --git a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java index 177fbb4403c..224b5375283 100644 --- a/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java +++ b/jdk/src/jdk.accessibility/share/classes/com/sun/java/accessibility/util/Translator.java @@ -32,6 +32,7 @@ import java.util.*; import java.awt.*; import java.awt.event.*; import java.awt.image.*; +import java.security.AccessControlException; // Do not import Swing classes. This module is intended to work // with both Swing and AWT. // import javax.swing.*; @@ -77,7 +78,7 @@ public class Translator extends AccessibleContext return null; } try { - t = Class.forName("com.sun.java.accessibility.util.internal" + t = Class.forName("com.sun.java.accessibility.util.internal." + c.getSimpleName() + "Translator"); return t; @@ -105,6 +106,10 @@ public class Translator extends AccessibleContext if (o instanceof Accessible) { a = (Accessible)o; } else { + // About to "newInstance" an object of a class of a restricted package + // so ensure the caller is allowed access to that package. + String pkg = "com.sun.java.accessibility.util.internal"; + System.getSecurityManager().checkPackageAccess(pkg); Class translatorClass = getTranslatorClass(o.getClass()); if (translatorClass != null) { try { diff --git a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java index 972d6593573..1c60443415b 100644 --- a/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java +++ b/jdk/src/jdk.charsets/share/classes/sun/nio/cs/ext/AbstractCharsetProvider.java @@ -33,7 +33,6 @@ import java.util.TreeMap; import java.util.Iterator; import java.util.Locale; import java.util.Map; -import sun.misc.ASCIICaseInsensitiveComparator; /** @@ -49,22 +48,22 @@ public class AbstractCharsetProvider /* Maps canonical names to class names */ private Map classMap - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /* Maps alias names to canonical names */ private Map aliasMap - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /* Maps canonical names to alias-name arrays */ private Map aliasNameMap - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); /* Maps canonical names to soft references that hold cached instances */ private Map> cache - = new TreeMap<>(ASCIICaseInsensitiveComparator.CASE_INSENSITIVE_ORDER); + = new TreeMap<>(String.CASE_INSENSITIVE_ORDER); private String packagePrefix; diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java index f0d193eb8a6..f9ffd5fe697 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/RSAKeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ public final class RSAKeyPairGenerator extends KeyPairGeneratorSpi { // Supported by Microsoft Base, Strong and Enhanced Cryptographic Providers static final int KEY_SIZE_MIN = 512; // disallow MSCAPI min. of 384 static final int KEY_SIZE_MAX = 16384; - private static final int KEY_SIZE_DEFAULT = 1024; + private static final int KEY_SIZE_DEFAULT = 2048; // size of the key to generate, KEY_SIZE_MIN <= keySize <= KEY_SIZE_MAX private int keySize; diff --git a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java index 9b36d662081..94b8535ea8f 100644 --- a/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java +++ b/jdk/src/jdk.crypto.mscapi/windows/classes/sun/security/mscapi/SunMSCAPI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -182,7 +182,7 @@ public final class SunMSCAPI extends Provider { * Key Pair Generator engines */ attrs.clear(); - attrs.put("KeySize", "1024"); + attrs.put("KeySize", "16384"); putService(new ProviderService(p, "KeyPairGenerator", "RSA", "sun.security.mscapi.RSAKeyPairGenerator", null, attrs)); diff --git a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java index 4adac8ce4bf..bccddb41bd1 100644 --- a/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java +++ b/jdk/src/jdk.crypto.pkcs11/share/classes/sun/security/pkcs11/P11KeyPairGenerator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -106,8 +106,15 @@ final class P11KeyPairGenerator extends KeyPairGeneratorSpi { maxKeyLen = 2048; } } else { - // RSA, DH, and DSA - keySize = 1024; + if (algorithm.equals("DSA")) { + // keep default keysize at 1024 since larger keysizes may be + // incompatible with SHA1withDSA and SHA-2 Signature algs + // may not be supported by native pkcs11 implementations + keySize = 1024; + } else { + // RSA and DH + keySize = 2048; + } if ((minKeyLen == -1) || (minKeyLen < 512)) { minKeyLen = 512; } diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java deleted file mode 100644 index e983504a626..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/Dispatch.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2011, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.apple.concurrent; - -import java.util.concurrent.*; - -/** - * Factory for {@link Executor}s and {@link ExecutorService}s backed by - * libdispatch. - * - * Access is controlled through the Dispatch.getInstance() method, because - * performed tasks occur on threads owned by libdispatch. These threads are - * not owned by any particular AppContext or have any specific context - * classloader installed. - * - * @since Java for Mac OS X 10.6 Update 2 - */ -public final class Dispatch { - /** - * The priorities of the three default asynchronous queues. - */ - public enum Priority { - LOW(-2), NORMAL(0), HIGH(2); // values from - - final int nativePriority; - Priority(final int nativePriority) { this.nativePriority = nativePriority; } - }; - - final static Dispatch instance = new Dispatch(); - - /** - * Factory method returns an instnace of Dispatch if supported by the - * underlying operating system, and if the caller's security manager - * permits "canInvokeInSystemThreadGroup". - * - * @return a factory instance of Dispatch, or null if not available - */ - public static Dispatch getInstance() { - checkSecurity(); - if (!LibDispatchNative.nativeIsDispatchSupported()) return null; - - return instance; - } - - private static void checkSecurity() { - final SecurityManager security = System.getSecurityManager(); - if (security != null) security.checkPermission(new RuntimePermission("canInvokeInSystemThreadGroup")); - } - - private Dispatch() { } - - /** - * Creates an {@link Executor} that performs tasks asynchronously. The {@link Executor} - * cannot be shutdown, and enqueued {@link Runnable}s cannot be canceled. Passing null - * returns the {@link Priority.NORMAL} {@link Executor}. - * - * @param priority - the priority of the returned {@link Executor} - * @return an asynchronous {@link Executor} - */ - public Executor getAsyncExecutor(Priority priority) { - if (priority == null) priority = Priority.NORMAL; - final long nativeQueue = LibDispatchNative.nativeCreateConcurrentQueue(priority.nativePriority); - if (nativeQueue == 0L) return null; - return new LibDispatchConcurrentQueue(nativeQueue); - } - - int queueIndex = 0; - /** - * Creates an {@link ExecutorService} that performs tasks synchronously in FIFO order. - * Useful to protect a resource against concurrent modification, in lieu of a lock. - * Passing null returns an {@link ExecutorService} with a uniquely labeled queue. - * - * @param label - a label to name the queue, shown in several debugging tools - * @return a synchronous {@link ExecutorService} - */ - public ExecutorService createSerialExecutor(String label) { - if (label == null) label = ""; - if (label.length() > 256) label = label.substring(0, 256); - String queueName = "com.apple.java.concurrent."; - if ("".equals(label)) { - synchronized (this) { - queueName += queueIndex++; - } - } else { - queueName += label; - } - - final long nativeQueue = LibDispatchNative.nativeCreateSerialQueue(queueName); - if (nativeQueue == 0) return null; - return new LibDispatchSerialQueue(nativeQueue); - } - - Executor nonBlockingMainQueue = null; - /** - * Returns an {@link Executor} that performs the provided Runnables on the main queue of the process. - * Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread. - * - * Submitting a Runnable to this {@link Executor} does not wait for the Runnable to complete. - * @return an asynchronous {@link Executor} that is backed by the main queue - */ - public synchronized Executor getNonBlockingMainQueueExecutor() { - if (nonBlockingMainQueue != null) return nonBlockingMainQueue; - return nonBlockingMainQueue = new LibDispatchMainQueue.ASync(); - } - - Executor blockingMainQueue = null; - /** - * Returns an {@link Executor} that performs the provided Runnables on the main queue of the process. - * Runnables submitted to this {@link Executor} will not run until the AWT is started or another native toolkit is running a CFRunLoop or NSRunLoop on the main thread. - * - * Submitting a Runnable to this {@link Executor} will block until the Runnable has completed. - * @return an {@link Executor} that is backed by the main queue - */ - public synchronized Executor getBlockingMainQueueExecutor() { - if (blockingMainQueue != null) return blockingMainQueue; - return blockingMainQueue = new LibDispatchMainQueue.Sync(); - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java deleted file mode 100644 index bb22566aef0..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/LibDispatchSerialQueue.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2011, 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. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.apple.concurrent; - -import java.util.List; -import java.util.concurrent.*; - -class LibDispatchSerialQueue extends AbstractExecutorService { - static final int RUNNING = 0; - static final int SHUTDOWN = 1; -// static final int STOP = 2; // not supported by GCD - static final int TERMINATED = 3; - - final Object lock = new Object(); - LibDispatchQueue nativeQueueWrapper; - volatile int runState; - - LibDispatchSerialQueue(final long queuePtr) { - nativeQueueWrapper = new LibDispatchQueue(queuePtr); - } - - @Override - public void execute(final Runnable task) { - if (nativeQueueWrapper == null) return; - LibDispatchNative.nativeExecuteAsync(nativeQueueWrapper.ptr, task); - } - - @Override - public boolean isShutdown() { - return runState != RUNNING; - } - - @Override - public boolean isTerminated() { - return runState == TERMINATED; - } - - @Override - public void shutdown() { - synchronized (lock) { - if (runState != RUNNING) return; - - runState = SHUTDOWN; - execute(new Runnable() { - public void run() { - synchronized (lock) { - runState = TERMINATED; - lock.notifyAll(); // for the benefit of awaitTermination() - } - } - }); - nativeQueueWrapper = null; - } - } - - @Override - public List shutdownNow() { - shutdown(); - return null; - } - - @Override - public boolean awaitTermination(final long timeout, final TimeUnit unit) throws InterruptedException { - if (runState == TERMINATED) return true; - - final long millis = unit.toMillis(timeout); - if (millis <= 0) return false; - - synchronized (lock) { - if (runState == TERMINATED) return true; - lock.wait(timeout); - if (runState == TERMINATED) return true; - } - - return false; - } -} diff --git a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html b/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html deleted file mode 100644 index 003a7a239f3..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/classes/com/apple/concurrent/package.html +++ /dev/null @@ -1,7 +0,0 @@ - - - - -Apple-specific implementations of the java.util.concurrent.* API based on libdispatch. - - diff --git a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m b/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m deleted file mode 100644 index cdeac0d435d..00000000000 --- a/jdk/src/jdk.deploy.osx/macosx/native/libosx/Dispatch.m +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. - * 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. - */ - -/* - * Must include this before JavaNativeFoundation.h to get jni.h from build - */ -#include "jni.h" -#include "jni_util.h" - -#import "com_apple_concurrent_LibDispatchNative.h" - -#import -#import - -/* - * Declare library specific JNI_Onload entry if static build - */ -DEF_STATIC_JNI_OnLoad - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeIsDispatchSupported - * Signature: ()Z - */ -JNIEXPORT jboolean JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeIsDispatchSupported -(JNIEnv *env, jclass clazz) -{ - return JNI_TRUE; -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeGetMainQueue - * Signature: ()J - */ -JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeGetMainQueue -(JNIEnv *env, jclass clazz) -{ - dispatch_queue_t queue = dispatch_get_main_queue(); - return ptr_to_jlong(queue); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeCreateConcurrentQueue - * Signature: (I)J - */ -JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeCreateConcurrentQueue -(JNIEnv *env, jclass clazz, jint priority) -{ - dispatch_queue_t queue = dispatch_get_global_queue((long)priority, 0); - return ptr_to_jlong(queue); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeCreateSerialQueue - * Signature: (Ljava/lang/String;)J - */ -JNIEXPORT jlong JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeCreateSerialQueue -(JNIEnv *env, jclass clazz, jstring name) -{ - if (name == NULL) return 0L; - - jboolean isCopy; - const char *queue_name = (*env)->GetStringUTFChars(env, name, &isCopy); - dispatch_queue_t queue = dispatch_queue_create(queue_name, NULL); - (*env)->ReleaseStringUTFChars(env, name, queue_name); - - return ptr_to_jlong(queue); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeReleaseQueue - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeReleaseQueue -(JNIEnv *env, jclass clazz, jlong nativeQueue) -{ - if (nativeQueue == 0L) return; - dispatch_release((dispatch_queue_t)jlong_to_ptr(nativeQueue)); -} - - -static JNF_CLASS_CACHE(jc_Runnable, "java/lang/Runnable"); -static JNF_MEMBER_CACHE(jm_run, jc_Runnable, "run", "()V"); - -static void perform_dispatch(JNIEnv *env, jlong nativeQueue, jobject runnable, void (*dispatch_fxn)(dispatch_queue_t, dispatch_block_t)) -{ -JNF_COCOA_ENTER(env); - dispatch_queue_t queue = (dispatch_queue_t)jlong_to_ptr(nativeQueue); - if (queue == NULL) return; // shouldn't happen - - // create a global-ref around the Runnable, so it can be safely passed to the dispatch thread - JNFJObjectWrapper *wrappedRunnable = [[JNFJObjectWrapper alloc] initWithJObject:runnable withEnv:env]; - - dispatch_fxn(queue, ^{ - // attach the dispatch thread to the JVM if necessary, and get an env - JNFThreadContext ctx = JNFThreadDetachOnThreadDeath | JNFThreadSetSystemClassLoaderOnAttach | JNFThreadAttachAsDaemon; - JNIEnv *blockEnv = JNFObtainEnv(&ctx); - - JNF_COCOA_ENTER(blockEnv); - - // call the user's runnable - JNFCallObjectMethod(blockEnv, [wrappedRunnable jObject], jm_run); - - // explicitly clear object while we have an env (it's cheaper that way) - [wrappedRunnable setJObject:NULL withEnv:blockEnv]; - - JNF_COCOA_EXIT(blockEnv); - - // let the env go, but leave the thread attached as a daemon - JNFReleaseEnv(blockEnv, &ctx); - }); - - // release this thread's interest in the Runnable, the block - // will have retained the it's own interest above - [wrappedRunnable release]; - -JNF_COCOA_EXIT(env); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeExecuteAsync - * Signature: (JLjava/lang/Runnable;)V - */ -JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeExecuteAsync -(JNIEnv *env, jclass clazz, jlong nativeQueue, jobject runnable) -{ - // enqueues and returns - perform_dispatch(env, nativeQueue, runnable, dispatch_async); -} - - -/* - * Class: com_apple_concurrent_LibDispatchNative - * Method: nativeExecuteSync - * Signature: (JLjava/lang/Runnable;)V - */ -JNIEXPORT void JNICALL Java_com_apple_concurrent_LibDispatchNative_nativeExecuteSync -(JNIEnv *env, jclass clazz, jlong nativeQueue, jobject runnable) -{ - // blocks until the Runnable completes - perform_dispatch(env, nativeQueue, runnable, dispatch_sync); -} diff --git a/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c b/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c index 1b42ad4d12c..81419a9d6a7 100644 --- a/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c +++ b/jdk/src/jdk.jdi/share/native/libdt_shmem/shmemBack.c @@ -338,7 +338,7 @@ shmemGetLastError(jdwpTransportEnv* env, char **msgP) return JDWPTRANSPORT_ERROR_NONE; } -JNIEXPORT jint JNICALL +jint JNICALL jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, jint version, jdwpTransportEnv** result) { diff --git a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c index bcd21400ad2..9c86b5a2a27 100644 --- a/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c +++ b/jdk/src/jdk.jdwp.agent/share/native/libdt_socket/socketTransport.c @@ -784,7 +784,7 @@ socketTransport_getLastError(jdwpTransportEnv* env, char** msgP) { return JDWPTRANSPORT_ERROR_NONE; } -JNIEXPORT jint JNICALL +jint JNICALL jdwpTransport_OnLoad(JavaVM *vm, jdwpTransportCallback* cbTablePtr, jint version, jdwpTransportEnv** result) { diff --git a/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java b/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java new file mode 100644 index 00000000000..69c123572d3 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/jdk/internal/netscape/javascript/spi/JSObjectProvider.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.netscape.javascript.spi; + +import java.applet.Applet; +import netscape.javascript.JSException; +import netscape.javascript.JSObject; + +public interface JSObjectProvider { + /** + * Return a JSObject for the window containing the given applet. + * Implementations of this class should return null if not connected to a + * browser, for example, when running in AppletViewer. + * + * @param applet The applet. + * @return JSObject for the window containing the given applet or null if we + * are not connected to a browser. + * @throws JSException when an error is encountered. + */ + public JSObject getWindow(Applet applet) throws JSException; +} diff --git a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java new file mode 100644 index 00000000000..a47ed9f1de7 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package netscape.javascript; + +/** + * Thrown when an exception is raised in the JavaScript engine. This is merely + * a marker class to indicate an exception relating to the JavaScript + * interface. + */ +public class JSException extends RuntimeException { + private static final long serialVersionUID = 2778103758223661489L; + + /** + * Constructs a new JavaScript exception with null as it's detail message. + */ + public JSException() { + super(); + } + + /** + * Construct a new JavaScript exception with the specified detail message. + * + * @param s The detail message + */ + public JSException(String s) { + super(s); + } + + /** + * Construct a new JavaScript exception with the specified cause. + * + * @param t Throwable cause + */ + public JSException(Throwable t) { + super(t); + } +} diff --git a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java new file mode 100644 index 00000000000..250825ad676 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/JSObject.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package netscape.javascript; + +import jdk.internal.netscape.javascript.spi.JSObjectProvider; +import java.applet.Applet; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.Iterator; +import java.util.ServiceLoader; + +/** + *

    + * Allows Java code to manipulate JavaScript objects. + *

    + * + *

    + * When a JavaScript object is passed or returned to Java code, it + * is wrapped in an instance of {@code JSObject}. When a + * {@code JSObject} instance is passed to the JavaScript engine, + * it is unwrapped back to its original JavaScript object. The + * {@code JSObject} class provides a way to invoke JavaScript + * methods and examine JavaScript properties. + *

    + * + *

    Any data returned from the JavaScript engine to Java is + * converted to Java data types. Certain data passed to the JavaScript + * engine is converted to JavaScript data types. + *

    + * + */ +public abstract class JSObject { + /** + * Constructs a new JSObject. Users should neither call this method nor + * subclass JSObject. + */ + protected JSObject() { + } + + /** + * Calls a JavaScript method. Equivalent to + * "this.methodName(args[0], args[1], ...)" in JavaScript. + * + * @param methodName The name of the JavaScript method to be invoked. + * @param args the Java objects passed as arguments to the method. + * @return Result of the method. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object call(String methodName, Object... args) throws JSException; + + /** + * Evaluates a JavaScript expression. The expression is a string of + * JavaScript source code which will be evaluated in the context given by + * "this". + * + * @param s The JavaScript expression. + * @return Result of the JavaScript evaluation. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object eval(String s) throws JSException; + + /** + * Retrieves a named member of a JavaScript object. Equivalent to + * "this.name" in JavaScript. + * + * @param name The name of the JavaScript property to be accessed. + * @return The value of the propery. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object getMember(String name) throws JSException; + + /** + * Sets a named member of a JavaScript object. Equivalent to + * "this.name = value" in JavaScript. + * + * @param name The name of the JavaScript property to be accessed. + * @param value The value of the propery. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract void setMember(String name, Object value) throws JSException; + + /** + * Removes a named member of a JavaScript object. Equivalent + * to "delete this.name" in JavaScript. + * + * @param name The name of the JavaScript property to be removed. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract void removeMember(String name) throws JSException; + + /** + * Retrieves an indexed member of a JavaScript object. Equivalent to + * "this[index]" in JavaScript. + * + * @param index The index of the array to be accessed. + * @return The value of the indexed member. + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract Object getSlot(int index) throws JSException; + + /** + * Sets an indexed member of a JavaScript object. Equivalent to + * "this[index] = value" in JavaScript. + * + * @param index The index of the array to be accessed. + * @param value The value to set + * @throws JSException when an error is reported from the browser or + * JavaScript engine. + */ + public abstract void setSlot(int index, Object value) throws JSException; + + /** + * Returns a JSObject for the window containing the given applet. This + * method only works when the Java code is running in a browser as an + * applet. The object returned may be used to access the HTML DOM directly. + * + * @param applet The applet. + * @return JSObject representing the window containing the given applet or + * {@code null} if we are not connected to a browser. + * @throws JSException when an error is reported from the browser or + * JavaScript engine or if applet is {@code null} + */ + public static JSObject getWindow(Applet applet) throws JSException { + return ProviderLoader.callGetWindow(applet); + } + + private static class ProviderLoader { + private static final JSObjectProvider provider; + + static { + provider = AccessController.doPrivileged( + new PrivilegedAction<>() { + @Override + public JSObjectProvider run() { + Iterator providers = + ServiceLoader.loadInstalled(JSObjectProvider.class).iterator(); + if (providers.hasNext()) { + return providers.next(); + } + return null; + } + } + ); + } + + private static JSObject callGetWindow(Applet applet) { + if (provider != null) { + return provider.getWindow(applet); + } + return null; + } + } +} diff --git a/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java new file mode 100644 index 00000000000..d3770732bc0 --- /dev/null +++ b/jdk/src/jdk.jsobject/share/classes/netscape/javascript/package-info.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + *

    + * Provides Java code the ability to access the JavaScript engine and the + * HTML DOM in the web browser. + *

    + * + *

    + * The classes in this package were initially specified by Netscape, and are the + * de facto standard mechanism for calling JavaScript from the Java runtime. + *

    + */ + +package netscape.javascript; diff --git a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo index b2a0b3ad6c7..076f3b15265 100644 --- a/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo +++ b/jdk/src/jdk.localedata/share/classes/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo @@ -1,2 +1,2 @@ sun.util.resources.provider.NonBaseLocaleDataMetaInfo -sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo_jdk_localedata +sun.util.resources.cldr.provider.CLDRLocaleDataMetaInfo diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 5b07bb2d65f..5296f830828 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -200,6 +200,9 @@ java/nio/channels/Selector/OutOfBand.java macosx-all java/nio/file/WatchService/Basic.java solaris-all java/nio/file/WatchService/LotsOfEvents.java solaris-all +# 8149712 +java/nio/charset/coders/BashStreams.java generic-all + ############################################################################ # jdk_rmi @@ -331,9 +334,6 @@ javax/imageio/plugins/tiff/WriteToSequenceAfterAbort.java generic-all # jdk_time -# 8134979 -java/time/tck/java/time/chrono/TCKJapaneseChronology.java generic-all - ############################################################################ # jdk_tools diff --git a/jdk/test/TEST.groups b/jdk/test/TEST.groups index 7d56e8afd61..ea9a6d6fa7e 100644 --- a/jdk/test/TEST.groups +++ b/jdk/test/TEST.groups @@ -28,7 +28,6 @@ tier1 = \ :jdk_lang \ -java/lang/ProcessHandle/TreeTest.java \ - -java/util/zip/TestLocalTime.java \ :jdk_util \ -java/util/WeakHashMap/GCDuringIteration.java \ -java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ @@ -40,7 +39,6 @@ tier1 = \ tier2 = \ java/lang/ProcessHandle/TreeTest.java \ - java/util/zip/TestLocalTime.java \ java/util/WeakHashMap/GCDuringIteration.java \ java/util/concurrent/ThreadPoolExecutor/ConfigChanges.java \ java/util/concurrent/forkjoin/FJExceptionTableLeak.java \ diff --git a/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java new file mode 100644 index 00000000000..324d80441fb --- /dev/null +++ b/jdk/test/com/sun/crypto/provider/Cipher/PBE/CheckPBEKeySize.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8151149 + * @modules java.base/com.sun.crypto.provider + */ + +import java.lang.reflect.*; +import java.security.*; +import javax.crypto.*; +import javax.crypto.spec.*; +import com.sun.crypto.provider.*; + +public class CheckPBEKeySize { + + private static final String ALGO = "PBEWithSHA1AndDESede"; + private static final int KEYSIZE = 112; // Triple DES effective key size + + public static final void main(String[] args) throws Exception { + + // Generate a PBE key + SecretKeyFactory skFac = SecretKeyFactory.getInstance("PBE"); + SecretKey skey = + skFac.generateSecret(new PBEKeySpec("test123".toCharArray())); + + // Initialize the PBE cipher + Cipher cipher = Cipher.getInstance(ALGO); + cipher.init(Cipher.ENCRYPT_MODE, skey); + + // Permit access to the Cipher.spi field (a CipherSpi object) + Field spi = Cipher.class.getDeclaredField("spi"); + spi.setAccessible(true); + Object value = spi.get(cipher); + + // Permit access to the CipherSpi.engineGetKeySize method + Method engineGetKeySize = + PKCS12PBECipherCore$PBEWithSHA1AndDESede.class + .getDeclaredMethod("engineGetKeySize", Key.class); + engineGetKeySize.setAccessible(true); + + // Check the key size + int keySize = (int) engineGetKeySize.invoke(value, skey); + if (keySize == KEYSIZE) { + System.out.println(ALGO + ".engineGetKeySize returns " + keySize + + " bits, as expected"); + System.out.println("OK"); + } else { + throw new Exception("ERROR: " + ALGO + " key size is incorrect"); + } + } +} diff --git a/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java b/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java index 6226fe9191d..b304121fa0c 100644 --- a/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java +++ b/jdk/test/com/sun/crypto/provider/KeyAgreement/TestExponentSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,10 +83,10 @@ public class TestExponentSize { KeyPair kp; KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH", "SunJCE"); - // Sun's default uses a default psize of 1024 and + // Sun's default uses a default psize of 2048 and // lsize of (pSize / 2) but at least 384 bits kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.five12); + checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); DHPublicKey publicKey = (DHPublicKey)kp.getPublic(); BigInteger p = publicKey.getParams().getP(); @@ -98,15 +98,15 @@ public class TestExponentSize { kpg.initialize(new DHParameterSpec(p, g, Sizes.ten24.getIntSize())); kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.ten24); + checkKeyPair(kp, Sizes.twenty48, Sizes.ten24); kpg.initialize(new DHParameterSpec(p, g, Sizes.five12.getIntSize())); kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.five12); + checkKeyPair(kp, Sizes.twenty48, Sizes.five12); kpg.initialize(new DHParameterSpec(p, g, Sizes.two56.getIntSize())); kp = kpg.generateKeyPair(); - checkKeyPair(kp, Sizes.ten24, Sizes.two56); + checkKeyPair(kp, Sizes.twenty48, Sizes.two56); kpg.initialize(Sizes.five12.getIntSize()); kp = kpg.generateKeyPair(); diff --git a/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh new file mode 100644 index 00000000000..d91f74ab85c --- /dev/null +++ b/jdk/test/com/sun/jdi/RedefineAddPrivateMethod.sh @@ -0,0 +1,79 @@ +#!/bin/sh + +# +# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8149743 +# @summary crash when adding a breakpoint after redefining to add a private static method +# @run shell RedefineAddPrivateMethod.sh + +compileOptions=-g + +createJavaFile() +{ + cat < $1.java.1 +public class $1 { + static public void main(String[] args) { + System.out.println("@1 breakpoint"); + System.out.println("@2 breakpoint"); + } + + // @1 uncomment private static void test() {} +} +EOF +} + +# This is called to feed cmds to jdb. +dojdbCmds() +{ + setBkpts @1 + runToBkpt @1 + redefineClass @1 + setBkpts @2 + runToBkpt @2 + cmd exitJdb +} + + +mysetup() +{ + if [ -z "$TESTSRC" ] ; then + TESTSRC=. + fi + + for ii in . $TESTSRC $TESTSRC/.. ; do + if [ -r "$ii/ShellScaffold.sh" ] ; then + . $ii/ShellScaffold.sh + break + fi + done +} + +# You could replace this next line with the contents +# of ShellScaffold.sh and this script will run just the same. +mysetup + +runit +debuggeeFailIfPresent "Internal exception:" +pass diff --git a/jdk/test/com/sun/jdi/TestScaffold.java b/jdk/test/com/sun/jdi/TestScaffold.java index 079733509e0..f221221a1de 100644 --- a/jdk/test/com/sun/jdi/TestScaffold.java +++ b/jdk/test/com/sun/jdi/TestScaffold.java @@ -752,6 +752,7 @@ abstract public class TestScaffold extends TargetAdapter { sr.addClassExclusionFilter("com.oracle.*"); sr.addClassExclusionFilter("oracle.*"); sr.addClassExclusionFilter("jdk.internal.*"); + sr.addClassExclusionFilter("jdk.jfr.*"); sr.addCountFilter(1); sr.enable(); StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr); diff --git a/jdk/test/com/sun/net/httpserver/FileServerHandler.java b/jdk/test/com/sun/net/httpserver/FileServerHandler.java index c27fe96e406..00ccd7d1a43 100644 --- a/jdk/test/com/sun/net/httpserver/FileServerHandler.java +++ b/jdk/test/com/sun/net/httpserver/FileServerHandler.java @@ -23,6 +23,7 @@ import java.util.*; import java.util.concurrent.*; +import java.util.logging.*; import java.io.*; import java.net.*; import java.security.*; @@ -36,6 +37,10 @@ import com.sun.net.httpserver.*; * Must be given an abs pathname to the document root. * Directory listings together with text + html files * can be served. + * + * File Server created on files sub-path + * + * Echo server created on echo sub-path */ public class FileServerHandler implements HttpHandler { @@ -44,14 +49,24 @@ public class FileServerHandler implements HttpHandler { System.out.println ("usage: java FileServerHandler rootDir port logfilename"); System.exit(1); } + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + String rootDir = args[0]; int port = Integer.parseInt (args[1]); String logfile = args[2]; - HttpServer server = HttpServer.create (new InetSocketAddress (8000), 0); + HttpServer server = HttpServer.create (new InetSocketAddress (port), 0); HttpHandler h = new FileServerHandler (rootDir); + HttpHandler h1 = new EchoHandler (); - HttpContext c = server.createContext ("/", h); + HttpContext c = server.createContext ("/files", h); c.getFilters().add (new LogFilter (new File (logfile))); + HttpContext c1 = server.createContext ("/echo", h1); + c.getFilters().add (new LogFilter (new File (logfile))); + c1.getFilters().add (new LogFilter (new File (logfile))); server.setExecutor (Executors.newCachedThreadPool()); server.start (); } @@ -72,7 +87,8 @@ public class FileServerHandler implements HttpHandler { URI uri = t.getRequestURI(); String path = uri.getPath(); - while (is.read () != -1) ; + int x = 0; + while (is.read () != -1) x++; is.close(); File f = new File (docroot, path); if (!f.exists()) { @@ -164,3 +180,61 @@ public class FileServerHandler implements HttpHandler { t.close(); } } + +class EchoHandler implements HttpHandler { + + byte[] read(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + byte[] result = new byte[0]; + + while (true) { + int n = is.read(buf); + if (n > 0) { + byte[] b1 = new byte[result.length + n]; + System.arraycopy(result, 0, b1, 0, result.length); + System.arraycopy(buf, 0, b1, result.length, n); + result = b1; + } else if (n == -1) { + return result; + } + } + } + + public void handle (HttpExchange t) + throws IOException + { + InputStream is = t.getRequestBody(); + Headers map = t.getRequestHeaders(); + String fixedrequest = map.getFirst ("XFixed"); + + // return the number of bytes received (no echo) + String summary = map.getFirst ("XSummary"); + if (fixedrequest != null && summary == null) { + byte[] in = read(is); + t.sendResponseHeaders(200, in.length); + OutputStream os = t.getResponseBody(); + os.write(in); + os.close(); + is.close(); + } else { + OutputStream os = t.getResponseBody(); + byte[] buf = new byte[64 * 1024]; + t.sendResponseHeaders(200, 0); + int n, count=0;; + + while ((n = is.read(buf)) != -1) { + if (summary == null) { + os.write(buf, 0, n); + } + count += n; + } + if (summary != null) { + String s = Integer.toString(count); + os.write(s.getBytes()); + } + os.close(); + is.close(); + } + } +} + diff --git a/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java new file mode 100644 index 00000000000..5957204ee79 --- /dev/null +++ b/jdk/test/java/awt/Focus/FocusTraversalPolicy/ContainerOrderFTPTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + @test + @bug 8025001 + @summary Tests java.awt.ContainerOrderFocusTraversalPolicy functionality. + @run main ContainerOrderFTPTest +*/ + +import java.awt.Frame; +import java.awt.Button; +import java.awt.Component; +import java.awt.FlowLayout; +import java.awt.ContainerOrderFocusTraversalPolicy; + +public class ContainerOrderFTPTest { + + private final ContainerOrderFocusTraversalPolicy coftp; + private final Frame frame; + private final Button b1; + private final Button b2; + private final String expectedTraversal; + + public ContainerOrderFTPTest() { + expectedTraversal = "B1B2F1"; + b1 = new Button("B1"); + b2 = new Button("B2"); + frame = new Frame("F1"); + + frame.setLayout(new FlowLayout()); + frame.setSize(200, 200); + coftp = new ContainerOrderFocusTraversalPolicy(); + frame.setFocusTraversalPolicy(coftp); + frame.add(b1); + frame.add(b2); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + ContainerOrderFTPTest test = new ContainerOrderFTPTest(); + test.performTest(); + test.dispose(); + } + + public void performTest() { + int count = 0; + Component comp = coftp.getFirstComponent(frame); + String traversal = ""; + do { + comp = coftp.getComponentAfter(frame, comp); + if (comp instanceof Button) { + traversal += ((Button)comp).getLabel(); + } else if (comp instanceof Frame) { + traversal += ((Frame)comp).getTitle(); + } + count++; + } while(count < 3); + + if (!expectedTraversal.equals(traversal)) { + dispose(); + throw new RuntimeException("Incorrect Traversal. Expected : " + + expectedTraversal + "Actual : " + traversal); + } + } + + public void dispose() { + frame.dispose(); + } +} diff --git a/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java b/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java index 3c972b661ea..7e493506be1 100644 --- a/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java +++ b/jdk/test/java/awt/image/DrawImage/IncorrectClipSurface2SW.java @@ -42,11 +42,11 @@ import static java.awt.geom.Rectangle2D.Double; /** * @test - * @bug 8041644 + * @bug 8041644 8044788 * @summary Tests drawing volatile image to BI using different clip. * Results of the blit compatibleImage to BI used for comparison. * @author Sergey Bylokhov - * @run main/othervm -Dsun.java2d.d3d=false IncorrectClipSurface2SW + * @run main/othervm IncorrectClipSurface2SW */ public final class IncorrectClipSurface2SW { diff --git a/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java b/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java new file mode 100644 index 00000000000..332162be952 --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MenuMultiresolutionIconTest.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8150258 + * @author a.stepanov + * @summary Check that correct resolution variants are chosen for menu icons + * when multiresolution image is used for their construction. + * + * @library ../../../../lib/testlibrary/ + * @build ExtendedRobot + * @run main/othervm -Dsun.java2d.uiScale=1 MenuMultiresolutionIconTest + * @run main/othervm -Dsun.java2d.uiScale=2 MenuMultiresolutionIconTest + */ + + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; +import javax.swing.*; + +public class MenuMultiresolutionIconTest extends JPanel { + + private final static int DELAY = 1000; + private final static int SZ = 50; + private final static String SCALE = "sun.java2d.uiScale"; + private final static Color C1X = Color.RED, C2X = Color.BLUE; + private final ExtendedRobot r; + + private static BufferedImage generateImage(int scale, Color c) { + + int x = SZ * scale; + BufferedImage img = new BufferedImage(x, x, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, x, x); + return img; + } + + private static BaseMultiResolutionImage createIcon() { + + return new BaseMultiResolutionImage(new BufferedImage[] { + generateImage(1, C1X), generateImage(2, C2X)}); + } + + private JFrame frame; + private JPopupMenu popup; + private JMenuItem popupItem; + private JMenu menu; + + public MenuMultiresolutionIconTest() throws Exception { + + r = new ExtendedRobot(); + SwingUtilities.invokeAndWait(this::createUI); + } + + private void createUI() { + + ImageIcon ii = new ImageIcon(createIcon()); + + popup = new JPopupMenu(); + popupItem = new JMenuItem("test", ii); + popup.add(popupItem); + popupItem.setHorizontalTextPosition(JMenuItem.RIGHT); + addMouseListener(new MousePopupListener()); + + frame = new JFrame(); + JMenuBar menuBar = new JMenuBar(); + menu = new JMenu("test"); + menuBar.add(menu); + menu.add(new JMenuItem("test", ii)); + menu.add(new JRadioButtonMenuItem("test", ii, true)); + menu.add(new JCheckBoxMenuItem("test", ii, true)); + + frame.setJMenuBar(menuBar); + frame.setContentPane(this); + frame.setSize(300, 300); + frame.setVisible(true); + } + + private class MousePopupListener extends MouseAdapter { + + @Override + public void mousePressed(MouseEvent e) { showPopup(e); } + @Override + public void mouseClicked(MouseEvent e) { showPopup(e); } + @Override + public void mouseReleased(MouseEvent e) { showPopup(e); } + + private void showPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(MenuMultiresolutionIconTest.this, e.getX(), e.getY()); + } + } + } + + private static boolean is2x() { + + return GraphicsEnvironment.getLocalGraphicsEnvironment(). + getDefaultScreenDevice().getDefaultConfiguration(). + getDefaultTransform().getScaleX() > 1.001; + } + + private boolean eqColors(Color c1, Color c2) { + + int tol = 15; + return ( + Math.abs(c2.getRed() - c1.getRed() ) < tol && + Math.abs(c2.getGreen() - c1.getGreen()) < tol && + Math.abs(c2.getBlue() - c1.getBlue() ) < tol); + } + + private void checkIconColor(Point p, String what) { + + Color expected = is2x() ? C2X : C1X; + Color c = r.getPixelColor(p.x + SZ / 2, p.y + SZ / 2); + if (!eqColors(c, expected)) { + frame.dispose(); + throw new RuntimeException("invalid " + what + "menu item icon " + + "color, expected: " + expected + ", got: " + c); + } + System.out.println(what + "item icon check passed"); + } + + private void doTest() { + + r.waitForIdle(2 * DELAY); + + Point p = getLocationOnScreen(); + r.mouseMove(p.x + getWidth() / 4, p.y + getHeight() / 4); + r.waitForIdle(DELAY); + r.click(InputEvent.BUTTON3_DOWN_MASK); + r.waitForIdle(DELAY); + p = popupItem.getLocationOnScreen(); + checkIconColor(p, "popup "); + r.waitForIdle(DELAY); + + p = menu.getLocationOnScreen(); + r.mouseMove(p.x + menu.getWidth() / 2, p.y + menu.getHeight() / 2); + r.waitForIdle(DELAY); + r.click(); + p = menu.getItem(0).getLocationOnScreen(); + checkIconColor(p, ""); + r.waitForIdle(DELAY); + + p = menu.getItem(1).getLocationOnScreen(); + checkIconColor(p, "radiobutton "); + r.waitForIdle(DELAY); + + p = menu.getItem(2).getLocationOnScreen(); + checkIconColor(p, "checkbox "); + r.waitForIdle(DELAY); + + frame.dispose(); + } + + public static void main(String s[]) throws Exception { + + // TODO: remove is2x() after JDK-8150844 fix + if (is2x() == "2".equals(System.getProperty(SCALE))) { + (new MenuMultiresolutionIconTest()).doTest(); + } + } +} diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html new file mode 100644 index 00000000000..7ff1134a69d --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.html @@ -0,0 +1,41 @@ + + + + + MultiResolutionTrayIconTest + + + + +To run test please push "Start" (if system tray is not supported, push "Pass"). + +Two tray icons will appear (note: sometimes they can go to the tray icons pool). + +Please check if both of them have correct size and +the same colouring (white rectagle in a blue mount). In this case please push "Pass". + +Otherwise (if the 2nd red-white small icon appears) please push "Fail". + + + diff --git a/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java new file mode 100644 index 00000000000..f6f069b0ed8 --- /dev/null +++ b/jdk/test/java/awt/image/multiresolution/MultiResolutionTrayIconTest/MultiResolutionTrayIconTest.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + @test + @bug 8150176 + @ignore 8150176 + @summary Check if correct resolution variant is used for tray icon. + @author a.stepanov + @run applet/manual=yesno MultiResolutionTrayIconTest.html +*/ + + +import java.applet.Applet; +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; + + +public class MultiResolutionTrayIconTest extends Applet { + + private SystemTray tray; + private TrayIcon icon, iconMRI; + + public void init() { this.setLayout(new BorderLayout()); } + + public void start() { + + boolean trayIsSupported = SystemTray.isSupported(); + Button b = new Button("Start"); + if (trayIsSupported) { + + prepareIcons(); + b.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { doTest(); } + }); + } else { + b.setLabel("not supported"); + b.setEnabled(false); + System.out.println("system tray is not supported"); + } + add(b, BorderLayout.CENTER); + + validate(); + setVisible(true); + } + + private BufferedImage generateImage(int w, int h, Color c) { + + BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); + Graphics g = img.getGraphics(); + g.setColor(c); + g.fillRect(0, 0, w, h); + g.setColor(Color.WHITE); + int r = (Math.min(w, h) >= 8) ? 3 : 1; + g.fillRect(r, r, w - 2 * r, h - 2 * r); + return img; + } + + private void prepareIcons() { + + tray = SystemTray.getSystemTray(); + Dimension d = tray.getTrayIconSize(); + int w = d.width, h = d.height; + + BufferedImage img = generateImage(w, h, Color.BLUE); + // use wrong icon size for "nok" + BufferedImage nok = generateImage(w / 2 + 2, h / 2 + 2, Color.RED); + BaseMultiResolutionImage mri = + new BaseMultiResolutionImage(new BufferedImage[] {nok, img}); + icon = new TrayIcon(img); + iconMRI = new TrayIcon(mri); + } + + private void doTest() { + + if (tray.getTrayIcons().length > 0) { return; } // icons were added already + try { + tray.add(icon); + tray.add(iconMRI); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void stop() { + + // check for null, just in case + if (tray != null) { + tray.remove(icon); + tray.remove(iconMRI); + } + } +} diff --git a/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java b/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java new file mode 100644 index 00000000000..013de39b8a1 --- /dev/null +++ b/jdk/test/java/awt/print/PrinterJob/MultiMonPrintDlgTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.awt.Button; +import java.awt.Component; +import java.awt.Frame; +import java.awt.GraphicsDevice; +import java.awt.GraphicsEnvironment; +import java.awt.KeyboardFocusManager; +import java.awt.Window; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; + +/** + * @test + * @bug 8138749 + * @summary PrinterJob.printDialog() does not support multi-mon, + * always displayed on primary + * @run main/manual MultiMonPrintDlgTest + */ +public class MultiMonPrintDlgTest implements ActionListener { + + Frame primaryFrame = null; + Frame secFrame = null; + GraphicsDevice gd[] = GraphicsEnvironment.getLocalGraphicsEnvironment(). + getScreenDevices(); + + public MultiMonPrintDlgTest() throws Exception { + if (gd.length <= 1) { + System.out.println("This test should be run only on dual-monitor systems. Aborted!!"); + return; + } + + String[] instructions = + { + " This test should be running on a dual-monitor setup.", + "A frame will be created on each of the 2 monitor. ", + "Click the Print button on the frame displayed in the non-default monitor.", + "Please verify that page dialog followed by print dialog ", + " is displayed in the same screen", + "where the frame is located ie, in the non-default monitor.", + }; + + SwingUtilities.invokeAndWait(() -> { + JOptionPane.showMessageDialog( + (Component) null, + instructions, + "information", JOptionPane.INFORMATION_MESSAGE); + }); + GraphicsDevice defDev = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); + int x = 0; + Frame f = null; + for (x = 0; x < gd.length; x ++) { + if (gd[x] != defDev) { + secFrame = new Frame("Screen " + x + " - secondary", gd[x].getDefaultConfiguration()); + f = secFrame; + } else { + primaryFrame = new Frame("Screen " + x + " - primary", gd[x].getDefaultConfiguration()); + f = primaryFrame; + } + Button b = new Button("Print"); + b.addActionListener(this); + f.add("South", b); + f.addWindowListener (new WindowAdapter() { + public void windowClosing(WindowEvent we) { + ((Window) we.getSource()).dispose(); + } + }); + f.setSize(200, 200); + f.setVisible(true); + } + } + + public void actionPerformed (ActionEvent ae) { + try { + javax.print.attribute.PrintRequestAttributeSet prSet = + new javax.print.attribute.HashPrintRequestAttributeSet(); + java.awt.print.PrinterJob.getPrinterJob().pageDialog(prSet); + Window w = KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow(); + int dialogButton = JOptionPane.showConfirmDialog (w, + "Did the pageDialog shown in non-default monitor?", + null, JOptionPane.YES_NO_OPTION); + if(dialogButton == JOptionPane.NO_OPTION) { + throw new RuntimeException("PageDialog is shown in wrong monitor"); + } + java.awt.print.PrinterJob.getPrinterJob().printDialog(prSet); + dialogButton = JOptionPane.showConfirmDialog (w, + "Did the printDialog shown in non-default monitor?", + null, JOptionPane.YES_NO_OPTION); + if(dialogButton == JOptionPane.NO_OPTION) { + throw new RuntimeException("PrintDialog is shown in wrong monitor"); + } + } finally { + primaryFrame.dispose(); + secFrame.dispose(); + } + } + + public static void main (String args[]) throws Exception { + MultiMonPrintDlgTest test = new MultiMonPrintDlgTest(); + } +} diff --git a/jdk/test/java/lang/ProcessHandle/Basic.java b/jdk/test/java/lang/ProcessHandle/Basic.java index dae37952c65..2d7258f3ccc 100644 --- a/jdk/test/java/lang/ProcessHandle/Basic.java +++ b/jdk/test/java/lang/ProcessHandle/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,8 @@ import org.testng.annotations.Test; /* * @test * @library /test/lib/share/classes - * @run testng InfoTest + * @modules jdk.management + * @run testng Basic * @summary Basic tests for ProcessHandler * @author Roger Riggs */ diff --git a/jdk/test/java/lang/ProcessHandle/InfoTest.java b/jdk/test/java/lang/ProcessHandle/InfoTest.java index cfb21d868db..e269d3e33c8 100644 --- a/jdk/test/java/lang/ProcessHandle/InfoTest.java +++ b/jdk/test/java/lang/ProcessHandle/InfoTest.java @@ -49,6 +49,7 @@ import org.testng.annotations.Test; * @test * @bug 8077350 8081566 8081567 8098852 8136597 * @library /test/lib/share/classes + * @modules jdk.management * @build jdk.test.lib.Platform jdk.test.lib.Utils * @run testng InfoTest * @summary Functions of ProcessHandle.Info @@ -114,9 +115,13 @@ public class InfoTest { long cpuLoopTime = 100; // 100 ms String[] extraArgs = {"pid", "parent", "stdin"}; JavaChild p1 = JavaChild.spawnJavaChild((Object[])extraArgs); - Instant afterStart = Instant.now(); + Instant afterStart = null; try (BufferedReader lines = p1.outputReader()) { + // Read the args line to know the subprocess has started + lines.readLine(); + afterStart = Instant.now(); + Duration lastCpu = Duration.ofMillis(0L); for (int j = 0; j < 10; j++) { @@ -126,8 +131,7 @@ public class InfoTest { // Read cputime from child Duration childCpuTime = null; // Read lines from the child until the result from cputime is returned - String s; - while ((s = lines.readLine()) != null) { + for (String s; (s = lines.readLine()) != null;) { String[] split = s.trim().split(" "); if (split.length == 3 && split[1].equals("cputime")) { long nanos = Long.valueOf(split[2]); diff --git a/jdk/test/java/lang/ProcessHandle/OnExitTest.java b/jdk/test/java/lang/ProcessHandle/OnExitTest.java index 3ec997db342..77cc19d86dd 100644 --- a/jdk/test/java/lang/ProcessHandle/OnExitTest.java +++ b/jdk/test/java/lang/ProcessHandle/OnExitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ import org.testng.TestNG; /* * @test * @library /test/lib/share/classes + * @modules jdk.management * @build jdk.test.lib.Platform jdk.test.lib.Utils * @run testng OnExitTest * @summary Functions of Process.onExit and ProcessHandle.onExit diff --git a/jdk/test/java/lang/ProcessHandle/TreeTest.java b/jdk/test/java/lang/ProcessHandle/TreeTest.java index 85b752a6602..9840718d881 100644 --- a/jdk/test/java/lang/ProcessHandle/TreeTest.java +++ b/jdk/test/java/lang/ProcessHandle/TreeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,6 +45,7 @@ import org.testng.annotations.Test; /* * @test * @library /test/lib/share/classes + * @modules jdk.management * @build jdk.test.lib.Utils * @run testng/othervm TreeTest * @summary Test counting and JavaChild.spawning and counting of Processes. diff --git a/jdk/test/java/lang/StackWalker/StackStreamTest.java b/jdk/test/java/lang/StackWalker/StackStreamTest.java index af9c9706d43..a7b7e43dca6 100644 --- a/jdk/test/java/lang/StackWalker/StackStreamTest.java +++ b/jdk/test/java/lang/StackWalker/StackStreamTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,7 @@ import java.util.stream.Collectors; * @test * @bug 8140450 * @summary Stack Stream Test + * @modules java.logging * @run main/othervm StackStreamTest */ public class StackStreamTest { diff --git a/jdk/test/java/lang/StringBuilder/Capacity.java b/jdk/test/java/lang/StringBuilder/Capacity.java new file mode 100644 index 00000000000..e23e9151b46 --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/Capacity.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149330 + * @summary Basic set of tests of capacity management + * @run testng Capacity + */ + +import java.lang.reflect.Field; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.SplittableRandom; + +import org.testng.annotations.Test; +import org.testng.annotations.DataProvider; +import static org.testng.Assert.*; + +public class Capacity { + static final int DEFAULT_CAPACITY = 16; + + private static int newCapacity(int oldCapacity, + int desiredCapacity) + { + return Math.max(oldCapacity * 2 + 2, desiredCapacity); + } + + private static int nextNewCapacity(int oldCapacity) { + return newCapacity(oldCapacity, oldCapacity + 1); + } + + @Test(dataProvider = "singleChar") + public void defaultCapacity(Character ch) { + StringBuilder sb = new StringBuilder(); + assertEquals(sb.capacity(), DEFAULT_CAPACITY); + for (int i = 0; i < DEFAULT_CAPACITY; i++) { + sb.append(ch); + assertEquals(sb.capacity(), DEFAULT_CAPACITY); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(DEFAULT_CAPACITY)); + } + + @Test(dataProvider = "charCapacity") + public void explicitCapacity(Character ch, int initCapacity) { + StringBuilder sb = new StringBuilder(initCapacity); + assertEquals(sb.capacity(), initCapacity); + for (int i = 0; i < initCapacity; i++) { + sb.append(ch); + assertEquals(sb.capacity(), initCapacity); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(initCapacity)); + } + + @Test(dataProvider = "singleChar") + public void sbFromString(Character ch) { + String s = "string " + ch; + int expectedCapacity = s.length() + DEFAULT_CAPACITY; + StringBuilder sb = new StringBuilder(s); + assertEquals(sb.capacity(), expectedCapacity); + for (int i = 0; i < DEFAULT_CAPACITY; i++) { + sb.append(ch); + assertEquals(sb.capacity(), expectedCapacity); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity)); + } + + @Test(dataProvider = "singleChar") + public void sbFromCharSeq(Character ch) { + CharSequence cs = new MyCharSeq("char seq " + ch); + int expectedCapacity = cs.length() + DEFAULT_CAPACITY; + StringBuilder sb = new StringBuilder(cs); + assertEquals(sb.capacity(), expectedCapacity); + for (int i = 0; i < DEFAULT_CAPACITY; i++) { + sb.append(ch); + assertEquals(sb.capacity(), expectedCapacity); + } + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(expectedCapacity)); + } + + @Test(dataProvider = "charCapacity") + public void ensureCapacity(Character ch, int cap) { + StringBuilder sb = new StringBuilder(0); + assertEquals(sb.capacity(), 0); + sb.ensureCapacity(cap); // only has effect if cap > 0 + int newCap = (cap == 0) ? 0 : newCapacity(0, cap); + assertEquals(sb.capacity(), newCap); + sb.ensureCapacity(newCap + 1); + assertEquals(sb.capacity(), nextNewCapacity(newCap)); + sb.append(ch); + assertEquals(sb.capacity(), nextNewCapacity(newCap)); + } + + @Test(dataProvider = "negativeCapacity", + expectedExceptions = NegativeArraySizeException.class) + public void negativeInitialCapacity(int negCap) { + StringBuilder sb = new StringBuilder(negCap); + } + + @Test(dataProvider = "negativeCapacity") + public void ensureNegativeCapacity(int negCap) { + StringBuilder sb = new StringBuilder(); + sb.ensureCapacity(negCap); + assertEquals(sb.capacity(), DEFAULT_CAPACITY); + } + + @Test(dataProvider = "charCapacity") + public void trimToSize(Character ch, int cap) { + StringBuilder sb = new StringBuilder(cap); + int halfOfCap = cap / 2; + for (int i = 0; i < halfOfCap; i++) { + sb.append(ch); + } + sb.trimToSize(); + // according to the spec, capacity doesn't have to + // become exactly the size + assertTrue(sb.capacity() >= halfOfCap); + } + + @DataProvider + public Object[][] singleChar() { + return new Object[][] { {'J'}, {'\u042b'} }; + } + + @DataProvider + public Object[][] charCapacity() { + return new Object[][] { + {'J', 0}, + {'J', 1}, + {'J', 15}, + {'J', DEFAULT_CAPACITY}, + {'J', 1024}, + {'\u042b', 0}, + {'\u042b', 1}, + {'\u042b', 15}, + {'\u042b', DEFAULT_CAPACITY}, + {'\u042b', 1024}, + }; + } + + @DataProvider + public Object[][] negativeCapacity() { + return new Object[][] { {-1}, {Integer.MIN_VALUE} }; + } + + private static class MyCharSeq implements CharSequence { + private CharSequence s; + public MyCharSeq(CharSequence s) { this.s = s; } + public char charAt(int i) { return s.charAt(i); } + public int length() { return s.length(); } + public CharSequence subSequence(int st, int e) { + return s.subSequence(st, e); + } + public String toString() { return s.toString(); } + } +} diff --git a/jdk/test/java/lang/StringBuilder/HugeCapacity.java b/jdk/test/java/lang/StringBuilder/HugeCapacity.java new file mode 100644 index 00000000000..912a2539e96 --- /dev/null +++ b/jdk/test/java/lang/StringBuilder/HugeCapacity.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8149330 + * @summary Capacity should not get close to Integer.MAX_VALUE unless + * necessary + * @run main/othervm -Xmx5G HugeCapacity + * @ignore This test has huge memory requirements + */ + +public class HugeCapacity { + private static int failures = 0; + + public static void main(String[] args) { + testLatin1(); + testUtf16(); + if (failures > 0) { + throw new RuntimeException(failures + " tests failed"); + } + } + + private static void testLatin1() { + try { + StringBuilder sb = new StringBuilder(); + sb.ensureCapacity(Integer.MAX_VALUE / 2); + sb.ensureCapacity(Integer.MAX_VALUE / 2 + 1); + } catch (OutOfMemoryError oom) { + oom.printStackTrace(); + failures++; + } + } + + private static void testUtf16() { + try { + StringBuilder sb = new StringBuilder(); + sb.append('\u042b'); + sb.ensureCapacity(Integer.MAX_VALUE / 4); + sb.ensureCapacity(Integer.MAX_VALUE / 4 + 1); + } catch (OutOfMemoryError oom) { + oom.printStackTrace(); + failures++; + } + } +} diff --git a/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java b/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java index d93d2ee94e0..044d87145b7 100644 --- a/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java +++ b/jdk/test/java/lang/System/Logger/Level/LoggerLevelTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.util.Set; * @bug 8140364 * @summary Tests System.Logger.Level names and severity. * @author danielfuchs + * @modules java.logging */ public class LoggerLevelTest { public static void main(String[] args) { diff --git a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java index 450ba9a2fee..63ab20e2777 100644 --- a/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java +++ b/jdk/test/java/lang/System/Logger/default/DefaultLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,7 +56,7 @@ import java.util.stream.Stream; * @summary Tests default loggers returned by System.getLogger, and in * particular the implementation of the the System.Logger method * performed by the default binding. - * + * @modules java.logging * @build DefaultLoggerTest AccessSystemLogger * @run driver AccessSystemLogger * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerTest NOSECURITY diff --git a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java index 0f7524ec242..50c789b5d60 100644 --- a/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/DefaultLoggerFinderTest/DefaultLoggerFinderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ import java.util.stream.Stream; * @bug 8140364 * @summary Tests the default implementation of System.Logger, when * JUL is the default backend. + * @modules java.logging * @build AccessSystemLogger DefaultLoggerFinderTest * @run driver AccessSystemLogger * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest NOSECURITY diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java index eca65eec03d..033a7d97315 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/BootstrapLogger/BootstrapLoggerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,7 @@ import jdk.internal.logger.LazyLoggers; Tests the behavior of bootstrap loggers (and SimpleConsoleLoggers * too). * @modules java.base/jdk.internal.logger + * java.logging * @build BootstrapLoggerUtils LogStream * @run main/othervm BootstrapLoggerTest NO_SECURITY * @run main/othervm BootstrapLoggerTest SECURE diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java index 10e480fc363..c3f5e98d39c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerBridgeTest/LoggerBridgeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,9 @@ import sun.util.logging.PlatformLogger; * @summary JDK implementation specific unit test for JDK internal artifacts. * Tests all bridge methods with the a custom backend whose * loggers implement PlatformLogger.Bridge. - * @modules java.base/sun.util.logging java.base/jdk.internal.logger + * @modules java.base/sun.util.logging + * java.base/jdk.internal.logger + * java.logging * @build CustomSystemClassLoader LoggerBridgeTest * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOSECURITY * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader LoggerBridgeTest NOPERMISSIONS diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java index f9b8eabba40..1300c9b2ecd 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/PlatformLoggerBridgeTest/PlatformLoggerBridgeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,7 @@ import sun.util.logging.PlatformLogger; * Tests all bridge methods from PlatformLogger with the a custom * backend whose loggers implement PlatformLogger.Bridge. * @modules java.base/sun.util.logging + * java.logging * @build CustomSystemClassLoader PlatformLoggerBridgeTest * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOSECURITY * @run main/othervm -Djava.system.class.loader=CustomSystemClassLoader PlatformLoggerBridgeTest NOPERMISSIONS diff --git a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java index b616ec81944..e3752b5721c 100644 --- a/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java +++ b/jdk/test/java/lang/System/LoggerFinder/internal/api/LoggerFinderAPITest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * Tests the consistency of the LoggerFinder and JDK extensions. * @modules java.base/sun.util.logging * java.base/jdk.internal.logger + * java.logging * @run main LoggerFinderAPITest */ diff --git a/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java b/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java index f911d5b8653..a3b9b8dddcf 100644 --- a/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java +++ b/jdk/test/java/lang/System/MacEncoding/TestFileEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ import java.util.*; * @bug 8011194 * @summary Test value of file.encoding for corresponding value of LANG, etc * @library ../../../../tools/launcher/ ../ + * @modules jdk.compiler * @build TestHelper TestFileEncoding ExpectedEncoding * @run main TestFileEncoding UTF-8 * @run main/othervm -Dfile.encoding=MyEncoding -DuserEncoding=MyEncoding TestFileEncoding MyEncoding diff --git a/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java b/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java index 1973be456fd..89b958eff3e 100644 --- a/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java +++ b/jdk/test/java/lang/instrument/ManyMethodsBenchmarkAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,8 @@ * @summary Tests and benchmarks the JVMTI RedefineClasses when a * single class (and its parent) contains many methods. * - * @modules java.compiler + * @modules jdk.compiler * java.instrument - * jdk.compiler * @run build ManyMethodsBenchmarkApp ManyMethodsBenchmarkAgent * @run shell MakeJAR3.sh ManyMethodsBenchmarkAgent 'Can-Retransform-Classes: true' * @run main/othervm -javaagent:ManyMethodsBenchmarkAgent.jar ManyMethodsBenchmarkApp diff --git a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java index 8c209c1b87e..4522d8b1055 100644 --- a/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java +++ b/jdk/test/java/lang/instrument/NativeMethodPrefixAgent.java @@ -31,7 +31,7 @@ * java.management * java.instrument * @run shell/timeout=240 MakeJAR2.sh NativeMethodPrefixAgent NativeMethodPrefixApp 'Can-Retransform-Classes: true' 'Can-Set-Native-Method-Prefix: true' - * @run main/othervm -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp + * @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:-CheckIntrinsics -javaagent:NativeMethodPrefixAgent.jar NativeMethodPrefixApp */ import java.lang.instrument.*; diff --git a/jdk/test/java/lang/instrument/RetransformAgent.java b/jdk/test/java/lang/instrument/RetransformAgent.java index 4e1bdac4519..920fffbb0b1 100644 --- a/jdk/test/java/lang/instrument/RetransformAgent.java +++ b/jdk/test/java/lang/instrument/RetransformAgent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * @author Robert Field, Sun Microsystems * * @modules java.base/jdk.internal.org.objectweb.asm + * java.instrument * @run shell/timeout=240 MakeJAR2.sh RetransformAgent RetransformApp 'Can-Retransform-Classes: true' * @run main/othervm -javaagent:RetransformAgent.jar RetransformApp */ diff --git a/jdk/test/java/lang/invoke/FindAccessTest.java b/jdk/test/java/lang/invoke/FindAccessTest.java new file mode 100644 index 00000000000..75cba87e96f --- /dev/null +++ b/jdk/test/java/lang/invoke/FindAccessTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* @test + * @bug 8139885 + * @run testng/othervm -ea -esa test.java.lang.invoke.FindAccessTest + */ + +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +/** + * Tests for Lookup.findClass/accessClass extensions added in JEP 274. + */ +public class FindAccessTest { + + static final Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public static void testFindSpecial() throws Throwable { + FindSpecial.C c = new FindSpecial.C(); + assertEquals("I1.m", c.m()); + MethodType t = MethodType.methodType(String.class); + MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class); + assertEquals("I1.m", (String) ci1m.invoke(c)); + } + + @Test + public static void testFindSpecialAbstract() throws Throwable { + FindSpecial.C c = new FindSpecial.C(); + assertEquals("q", c.q()); + MethodType t = MethodType.methodType(String.class); + boolean caught = false; + try { + MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class); + } catch (Throwable thrown) { + if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) { + throw new AssertionError(thrown.getMessage(), thrown); + } + caught = true; + } + assertTrue(caught); + } + + @Test(expectedExceptions = {ClassNotFoundException.class}) + public static void testFindClassCNFE() throws ClassNotFoundException, IllegalAccessException { + LOOKUP.findClass("does.not.Exist"); + } + + static class FindSpecial { + + interface I1 { + default String m() { + return "I1.m"; + } + } + + interface I2 { + default String m() { + return "I2.m"; + } + } + + interface I3 { + String q(); + } + + static class C implements I1, I2, I3 { + public String m() { + return I1.super.m(); + } + public String q() { + return "q"; + } + } + + static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.FindAccessTest$FindSpecial$I3.q()String/invokeSpecial"; + + } + +} diff --git a/jdk/test/java/lang/invoke/FoldTest.java b/jdk/test/java/lang/invoke/FoldTest.java new file mode 100644 index 00000000000..1e8e4f517db --- /dev/null +++ b/jdk/test/java/lang/invoke/FoldTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* @test + * @bug 8139885 + * @run testng/othervm -ea -esa test.java.lang.invoke.FoldTest + */ + +package test.java.lang.invoke; + +import java.io.StringWriter; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +/** + * Tests for the new fold method handle combinator added in JEP 274. + */ +public class FoldTest { + + static final Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public static void testFold0a() throws Throwable { + // equivalence to foldArguments(MethodHandle,MethodHandle) + MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder); + assertEquals(Fold.MT_folded1, fold.type()); + assertEquals(720, (int) fold.invoke(3, 4, 5)); + } + + @Test + public static void testFold1a() throws Throwable { + // test foldArguments for folding position 1 + MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1); + assertEquals(Fold.MT_folded1, fold.type()); + assertEquals(540, (int) fold.invoke(3, 4, 5)); + } + + @Test + public static void testFold0b() throws Throwable { + // test foldArguments equivalence with multiple types + MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb); + assertEquals(Fold.MT_folded2, fold.type()); + assertEquals(23, (int) fold.invoke("true", true, 23)); + } + + @Test + public static void testFold1b() throws Throwable { + // test folgArguments for folding position 1, with multiple types + MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2); + assertEquals(Fold.MT_folded3, fold.type()); + assertEquals(1, (int) fold.invoke(true, true, 1)); + assertEquals(-1, (int) fold.invoke(true, false, -1)); + } + + @Test + public static void testFoldArgumentsExample() throws Throwable { + // test the JavaDoc foldArguments-with-pos example + StringWriter swr = new StringWriter(); + MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr); + MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class)); + assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); + MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace); + assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); + assertEquals("jum", swr.toString()); + } + + static class Fold { + + static int adder(int a, int b, int c) { + return a + b + c; + } + + static int adder1(int a, int b) { + return a + b; + } + + static int multer(int x, int q, int r, int s) { + return x * q * r * s; + } + + static int str(boolean b1, String s, boolean b2, int x) { + return b1 && s.equals(String.valueOf(b2)) ? x : -x; + } + + static boolean comb(String s, boolean b2) { + return !s.equals(b2); + } + + static String comb2(boolean b2, int x) { + int ib = b2 ? 1 : 0; + return ib == x ? "true" : "false"; + } + + static final Class FOLD = Fold.class; + + static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class); + static final MethodType MT_adder1 = methodType(int.class, int.class, int.class); + static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class); + static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class); + static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class); + static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class); + + static final MethodHandle MH_adder; + static final MethodHandle MH_adder1; + static final MethodHandle MH_multer; + static final MethodHandle MH_str; + static final MethodHandle MH_comb; + static final MethodHandle MH_comb2; + + static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class); + static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class); + static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class); + + static { + try { + MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder); + MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1); + MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer); + MH_str = LOOKUP.findStatic(FOLD, "str", MT_str); + MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb); + MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + } + +} diff --git a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java index 9a4b3f3624b..79a31087550 100644 --- a/jdk/test/java/lang/invoke/JavaDocExamplesTest.java +++ b/jdk/test/java/lang/invoke/JavaDocExamplesTest.java @@ -690,7 +690,7 @@ assertEquals(120, loop.invoke(5)); {{ {} /// JAVADOC // implement the zip function for lists as a loop handle -MethodHandle loop = MethodHandles.doWhileLoop(MH_initZip, MH_zipStep, MH_zipPred); +MethodHandle loop = MethodHandles.whileLoop(MH_initZip, MH_zipPred, MH_zipStep); List a = Arrays.asList("a", "b", "c", "d"); List b = Arrays.asList("e", "f", "g", "h"); List zipped = Arrays.asList("a", "e", "b", "f", "c", "g", "d", "h"); diff --git a/jdk/test/java/lang/invoke/T8139885.java b/jdk/test/java/lang/invoke/LoopCombinatorTest.java similarity index 50% rename from jdk/test/java/lang/invoke/T8139885.java rename to jdk/test/java/lang/invoke/LoopCombinatorTest.java index d9bcb6b3a61..2bae77e6a2e 100644 --- a/jdk/test/java/lang/invoke/T8139885.java +++ b/jdk/test/java/lang/invoke/LoopCombinatorTest.java @@ -25,18 +25,16 @@ /* @test * @bug 8139885 - * @bug 8143798 - * @run testng/othervm -ea -esa test.java.lang.invoke.T8139885 + * @bug 8150635 + * @run testng/othervm -ea -esa test.java.lang.invoke.LoopCombinatorTest */ package test.java.lang.invoke; -import java.io.StringWriter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; -import java.lang.invoke.WrongMethodTypeException; import java.util.*; import static java.lang.invoke.MethodType.methodType; @@ -46,16 +44,12 @@ import static org.testng.AssertJUnit.*; import org.testng.annotations.*; /** - * Example-scale and negative tests for JEP 274 extensions. + * Tests for the loop combinators introduced in JEP 274. */ -public class T8139885 { +public class LoopCombinatorTest { static final Lookup LOOKUP = MethodHandles.lookup(); - // - // Tests. - // - @Test public static void testLoopFac() throws Throwable { MethodHandle[] counterClause = new MethodHandle[]{Fac.MH_zero, Fac.MH_inc}; @@ -75,6 +69,15 @@ public class T8139885 { assertEquals(120, loop.invoke(5)); } + @Test + public static void testLoopNullInit() throws Throwable { + // null initializer for counter, should initialize to 0, one-clause loop + MethodHandle[] counterClause = new MethodHandle[]{null, Loop.MH_inc, Loop.MH_pred, Loop.MH_fin}; + MethodHandle loop = MethodHandles.loop(counterClause); + assertEquals(Loop.MT_loop, loop.type()); + assertEquals(10, loop.invoke(10)); + } + @Test public static void testLoopVoid1() throws Throwable { // construct a post-checked loop that only does one iteration and has a void body and void local state @@ -92,6 +95,15 @@ public class T8139885 { loop.invoke(); } + @Test + public static void testLoopVoid3() throws Throwable { + // construct a post-checked loop that only does one iteration and has a void body and void local state, + // and that has a void finalizer + MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_f}); + assertEquals(MethodType.methodType(void.class), loop.type()); + loop.invoke(); + } + @Test public static void testLoopFacWithVoidState() throws Throwable { // like testLoopFac, but with additional void state that outputs a dot @@ -104,9 +116,32 @@ public class T8139885 { } @Test - public static void testLoopNegative() throws Throwable { - MethodHandle mh_loop = - LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class)); + public static void testLoopVoidInt() throws Throwable { + // construct a post-checked loop that only does one iteration and has a void body and void local state, + // and that returns a constant + MethodHandle loop = MethodHandles.loop(new MethodHandle[]{null, Empty.MH_f, Empty.MH_pred, Empty.MH_c}); + assertEquals(MethodType.methodType(int.class), loop.type()); + assertEquals(23, loop.invoke()); + } + + @Test + public static void testLoopWithVirtuals() throws Throwable { + // construct a loop (to calculate factorial) that uses a mix of static and virtual methods + MethodHandle[] counterClause = new MethodHandle[]{null, LoopWithVirtuals.permute(LoopWithVirtuals.MH_inc)}; + MethodHandle[] accumulatorClause = new MethodHandle[]{ + // init function must indicate the loop arguments (there is no other means to determine them) + MethodHandles.dropArguments(LoopWithVirtuals.MH_one, 0, LoopWithVirtuals.class), + LoopWithVirtuals.permute(LoopWithVirtuals.MH_mult), + LoopWithVirtuals.permute(LoopWithVirtuals.MH_pred), + LoopWithVirtuals.permute(LoopWithVirtuals.MH_fin) + }; + MethodHandle loop = MethodHandles.loop(counterClause, accumulatorClause); + assertEquals(LoopWithVirtuals.MT_loop, loop.type()); + assertEquals(120, loop.invoke(new LoopWithVirtuals(), 5)); + } + + @DataProvider + static Object[][] negativeTestData() { MethodHandle i0 = MethodHandles.constant(int.class, 0); MethodHandle ii = MethodHandles.dropArguments(i0, 0, int.class, int.class); MethodHandle id = MethodHandles.dropArguments(i0, 0, int.class, double.class); @@ -120,44 +155,60 @@ public class T8139885 { List nesteps = Arrays.asList(Fac.MH_inc, eek, Fac.MH_dot); List nepreds = Arrays.asList(null, Fac.MH_pred, null); List nefinis = Arrays.asList(null, Fac.MH_fin, null); - MethodHandle[][][] cases = { - null, - {}, - {{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}}, - {{null, Fac.MH_inc}, null}, - {{Fac.MH_zero, Fac.MH_dot}}, - {{ii}, {id}, {i3}}, - {{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc}, + List lvsteps = Arrays.asList(LoopWithVirtuals.MH_inc, LoopWithVirtuals.MH_mult); + List lvpreds = Arrays.asList(null, LoopWithVirtuals.MH_pred); + List lvfinis = Arrays.asList(null, LoopWithVirtuals.MH_fin); + return new Object[][] { + {null, "null or no clauses passed"}, + {new MethodHandle[][]{}, "null or no clauses passed"}, + {new MethodHandle[][]{{null, Fac.MH_inc}, {Fac.MH_one, null, Fac.MH_mult, Fac.MH_pred, Fac.MH_fin}}, + "All loop clauses must be represented as MethodHandle arrays with at most 4 elements."}, + {new MethodHandle[][]{{null, Fac.MH_inc}, null}, "null clauses are not allowed"}, + {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_dot}}, + "clause 0: init and step return types must match: int != void"}, + {new MethodHandle[][]{{ii}, {id}, {i3}}, + "found non-effectively identical init parameter type lists: " + inits + + " (common suffix: " + ints + ")"}, + {new MethodHandle[][]{{null, Fac.MH_inc, null, Fac.MH_fin}, {null, Fac.MH_inc, null, Fac.MH_inc}, {null, Counted.MH_start, null, Counted.MH_step}}, - {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, {null, Fac.MH_dot}}, - {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, {null, Fac.MH_dot}}, - {{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, {null, Fac.MH_dot}} + "found non-identical finalizer return types: " + finis + " (return type: int)"}, + {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, null, Fac.MH_fin}, + {null, Fac.MH_dot}}, "no predicate found: " + preds1}, + {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, Fac.MH_mult, Fac.MH_fin, Fac.MH_fin}, + {null, Fac.MH_dot}}, "predicates must have boolean return type: " + preds2}, + {new MethodHandle[][]{{Fac.MH_zero, Fac.MH_inc}, {Fac.MH_one, eek, Fac.MH_pred, Fac.MH_fin}, + {null, Fac.MH_dot}}, + "found non-effectively identical parameter type lists:\nstep: " + nesteps + + "\npred: " + nepreds + "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")"}, + {new MethodHandle[][]{{null, LoopWithVirtuals.MH_inc}, + {LoopWithVirtuals.MH_one, LoopWithVirtuals.MH_mult, LoopWithVirtuals.MH_pred, LoopWithVirtuals.MH_fin}}, + "found non-effectively identical parameter type lists:\nstep: " + lvsteps + + "\npred: " + lvpreds + "\nfini: " + lvfinis + " (common parameter sequence: " + ints + ")"} }; - String[] messages = { - "null or no clauses passed", - "null or no clauses passed", - "All loop clauses must be represented as MethodHandle arrays with at most 4 elements.", - "null clauses are not allowed", - "clause 0: init and step return types must match: int != void", - "found non-effectively identical init parameter type lists: " + inits + " (common suffix: " + ints + ")", - "found non-identical finalizer return types: " + finis + " (return type: int)", - "no predicate found: " + preds1, - "predicates must have boolean return type: " + preds2, - "found non-effectively identical parameter type lists:\nstep: " + nesteps + "\npred: " + nepreds + - "\nfini: " + nefinis + " (common parameter sequence: " + ints + ")" - }; - for (int i = 0; i < cases.length; ++i) { - boolean caught = false; - try { - mh_loop.invokeWithArguments(cases[i]); - } catch (IllegalArgumentException iae) { - assertEquals(messages[i], iae.getMessage()); - caught = true; - } - assertTrue(caught); + } + + static final MethodHandle MH_loop; + + static { + try { + MH_loop = LOOKUP.findStatic(MethodHandles.class, "loop", methodType(MethodHandle.class, MethodHandle[][].class)); + } catch (NoSuchMethodException | IllegalAccessException e) { + throw new ExceptionInInitializerError(e); } } + @Test(dataProvider = "negativeTestData") + public static void testLoopNegative(MethodHandle[][] clauses, String expectedMessage) throws Throwable { + boolean caught = false; + try { + MH_loop.invokeWithArguments(clauses); + } catch (IllegalArgumentException iae) { + assertEquals(expectedMessage, iae.getMessage()); + caught = true; + } + assertTrue(caught); + } + @Test public static void testWhileLoop() throws Throwable { // int i = 0; while (i < limit) { ++i; } return i; => limit @@ -182,6 +233,16 @@ public class T8139885 { assertEquals(23, loop.invoke(23)); } + @Test + public static void testDoWhileNullInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.doWhileLoop(null, While.MH_voidBody.bindTo(w), While.MH_voidPred.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + @Test public static void testWhileZip() throws Throwable { MethodHandle loop = MethodHandles.doWhileLoop(While.MH_zipInitZip, While.MH_zipStep, While.MH_zipPred); @@ -192,6 +253,16 @@ public class T8139885 { assertEquals(zipped, (List) loop.invoke(a.iterator(), b.iterator())); } + @Test + public static void testWhileNullInit() throws Throwable { + While w = new While(); + int v = 5; + MethodHandle loop = MethodHandles.whileLoop(null, While.MH_voidPred.bindTo(w), While.MH_voidBody.bindTo(w)); + assertEquals(While.MT_void, loop.type()); + loop.invoke(v); + assertEquals(v, w.i); + } + @Test public static void testCountedLoop() throws Throwable { // String s = "Lambdaman!"; for (int i = 0; i < 13; ++i) { s = "na " + s; } return s; => a variation on a well known theme @@ -283,281 +354,6 @@ public class T8139885 { assertTrue(caught); } - @Test - public static void testTryFinally() throws Throwable { - MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim); - assertEquals(TryFinally.MT_hello, hello.type()); - assertEquals("Hello, world!", hello.invoke("world")); - } - - @Test - public static void testTryFinallyVoid() throws Throwable { - MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore); - assertEquals(TryFinally.MT_printHello, tfVoid.type()); - tfVoid.invoke("world"); - } - - @Test - public static void testTryFinallySublist() throws Throwable { - MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore); - assertEquals(TryFinally.MT_moreHello, helloMore.type()); - assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe")); - } - - @Test - public static void testTryFinallyNegative() { - MethodHandle intid = MethodHandles.identity(int.class); - MethodHandle intco = MethodHandles.constant(int.class, 0); - MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class); - MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class, - int.class, double.class, Object.class); - MethodHandle[][] cases = { - {intid, MethodHandles.identity(double.class)}, - {intid, MethodHandles.dropArguments(intid, 0, String.class)}, - {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class)}, - {errTarget, errCleanup} - }; - String[] messages = { - "target and return types must match: double != int", - "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable", - "cleanup second argument and target return type must match: (Throwable,double,int)int != int", - "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + - errCleanup.type() + " != " + errTarget.type() - }; - for (int i = 0; i < cases.length; ++i) { - boolean caught = false; - try { - MethodHandles.tryFinally(cases[i][0], cases[i][1]); - } catch (IllegalArgumentException iae) { - assertEquals(messages[i], iae.getMessage()); - caught = true; - } - assertTrue(caught); - } - } - - @Test - public static void testFold0a() throws Throwable { - // equivalence to foldArguments(MethodHandle,MethodHandle) - MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 0, Fold.MH_adder); - assertEquals(Fold.MT_folded1, fold.type()); - assertEquals(720, (int) fold.invoke(3, 4, 5)); - } - - @Test - public static void testFold1a() throws Throwable { - // test foldArguments for folding position 1 - MethodHandle fold = MethodHandles.foldArguments(Fold.MH_multer, 1, Fold.MH_adder1); - assertEquals(Fold.MT_folded1, fold.type()); - assertEquals(540, (int) fold.invoke(3, 4, 5)); - } - - @Test - public static void testFold0b() throws Throwable { - // test foldArguments equivalence with multiple types - MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 0, Fold.MH_comb); - assertEquals(Fold.MT_folded2, fold.type()); - assertEquals(23, (int) fold.invoke("true", true, 23)); - } - - @Test - public static void testFold1b() throws Throwable { - // test folgArguments for folding position 1, with multiple types - MethodHandle fold = MethodHandles.foldArguments(Fold.MH_str, 1, Fold.MH_comb2); - assertEquals(Fold.MT_folded3, fold.type()); - assertEquals(1, (int) fold.invoke(true, true, 1)); - assertEquals(-1, (int) fold.invoke(true, false, -1)); - } - - @Test - public static void testFoldArgumentsExample() throws Throwable { - // test the JavaDoc foldArguments-with-pos example - StringWriter swr = new StringWriter(); - MethodHandle trace = LOOKUP.findVirtual(StringWriter.class, "write", methodType(void.class, String.class)).bindTo(swr); - MethodHandle cat = LOOKUP.findVirtual(String.class, "concat", methodType(String.class, String.class)); - assertEquals("boojum", (String) cat.invokeExact("boo", "jum")); - MethodHandle catTrace = MethodHandles.foldArguments(cat, 1, trace); - assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum")); - assertEquals("jum", swr.toString()); - } - - @Test - public static void testAsSpreader() throws Throwable { - MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3); - assertEquals(SpreadCollect.MT_spreader, spreader.type()); - assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B")); - } - - @Test - public static void testAsSpreaderExample() throws Throwable { - // test the JavaDoc asSpreader-with-pos example - MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class)); - MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2); - Object[] ints = new Object[]{3, 9, 7, 7}; - Comparator cmp = (a, b) -> a - b; - assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0); - assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0); - assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0); - } - - @Test - public static void testAsSpreaderIllegalPos() throws Throwable { - int[] illegalPos = {-7, 3, 19}; - int caught = 0; - for (int p : illegalPos) { - try { - SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3); - } catch (IllegalArgumentException iae) { - assertEquals("bad spread position", iae.getMessage()); - ++caught; - } - } - assertEquals(illegalPos.length, caught); - } - - @Test - public static void testAsSpreaderIllegalMethodType() throws Throwable { - MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class); - boolean caught = false; - try { - MethodHandle s = h.asSpreader(String[].class, 1); - } catch (WrongMethodTypeException wmte) { - caught = true; - } - assertTrue(caught); - } - - @Test - public static void testAsCollector() throws Throwable { - MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1); - assertEquals(SpreadCollect.MT_collector1, collector.type()); - assertEquals("A4B", (String) collector.invoke("A", 4, "B")); - collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2); - assertEquals(SpreadCollect.MT_collector2, collector.type()); - assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B")); - collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3); - assertEquals(SpreadCollect.MT_collector3, collector.type()); - assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B")); - } - - @Test - public static void testAsCollectorInvokeWithArguments() throws Throwable { - MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1); - assertEquals(SpreadCollect.MT_collector1, collector.type()); - assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B")); - collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2); - assertEquals(SpreadCollect.MT_collector2, collector.type()); - assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B")); - collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3); - assertEquals(SpreadCollect.MT_collector3, collector.type()); - assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B")); - } - - @Test - public static void testAsCollectorLeading() throws Throwable { - MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1); - assertEquals(SpreadCollect.MT_collectorLeading1, collector.type()); - assertEquals("7Q", (String) collector.invoke(7, "Q")); - collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2); - assertEquals(SpreadCollect.MT_collectorLeading2, collector.type()); - assertEquals("78Q", (String) collector.invoke(7, 8, "Q")); - collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3); - assertEquals(SpreadCollect.MT_collectorLeading3, collector.type()); - assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q")); - } - - @Test - public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable { - MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1); - assertEquals(SpreadCollect.MT_collectorLeading1, collector.type()); - assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q")); - collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2); - assertEquals(SpreadCollect.MT_collectorLeading2, collector.type()); - assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q")); - collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3); - assertEquals(SpreadCollect.MT_collectorLeading3, collector.type()); - assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q")); - } - - @Test - public static void testAsCollectorNone() throws Throwable { - MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0); - assertEquals(SpreadCollect.MT_collector0, collector.type()); - assertEquals("AB", (String) collector.invoke("A", "B")); - } - - @Test - public static void testAsCollectorIllegalPos() throws Throwable { - int[] illegalPos = {-1, 17}; - int caught = 0; - for (int p : illegalPos) { - try { - SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0); - } catch (IllegalArgumentException iae) { - assertEquals("bad collect position", iae.getMessage()); - ++caught; - } - } - assertEquals(illegalPos.length, caught); - } - - @Test - public static void testAsCollectorExample() throws Throwable { - // test the JavaDoc asCollector-with-pos example - StringWriter swr = new StringWriter(); - MethodHandle swWrite = LOOKUP. - findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)). - bindTo(swr); - MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4); - swWrite4.invoke('A', 'B', 'C', 'D', 1, 2); - assertEquals("BC", swr.toString()); - swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4); - assertEquals("BCPQRS", swr.toString()); - swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1); - assertEquals("BCPQRSZ", swr.toString()); - } - - @Test - public static void testFindSpecial() throws Throwable { - FindSpecial.C c = new FindSpecial.C(); - assertEquals("I1.m", c.m()); - MethodType t = MethodType.methodType(String.class); - MethodHandle ci1m = LOOKUP.findSpecial(FindSpecial.I1.class, "m", t, FindSpecial.C.class); - assertEquals("I1.m", (String) ci1m.invoke(c)); - } - - @Test - public static void testFindSpecialAbstract() throws Throwable { - FindSpecial.C c = new FindSpecial.C(); - assertEquals("q", c.q()); - MethodType t = MethodType.methodType(String.class); - boolean caught = false; - try { - MethodHandle ci3q = LOOKUP.findSpecial(FindSpecial.I3.class, "q", t, FindSpecial.C.class); - } catch (Throwable thrown) { - if (!(thrown instanceof IllegalAccessException) || !FindSpecial.ABSTRACT_ERROR.equals(thrown.getMessage())) { - throw new AssertionError(thrown.getMessage(), thrown); - } - caught = true; - } - assertTrue(caught); - } - - @Test - public static void testFindClassCNFE() throws Throwable { - boolean caught = false; - try { - LOOKUP.findClass("does.not.Exist"); - } catch (ClassNotFoundException cnfe) { - caught = true; - } - assertTrue(caught); - } - - // - // Methods used to assemble tests. - // - static class Empty { static void f() { } @@ -566,18 +362,25 @@ public class T8139885 { return false; } + static int c() { + return 23; + } + static final Class EMPTY = Empty.class; static final MethodType MT_f = methodType(void.class); static final MethodType MT_pred = methodType(boolean.class); + static final MethodType MT_c = methodType(int.class); static final MethodHandle MH_f; static final MethodHandle MH_pred; + static final MethodHandle MH_c; static { try { MH_f = LOOKUP.findStatic(EMPTY, "f", MT_f); MH_pred = LOOKUP.findStatic(EMPTY, "pred", MT_pred); + MH_c = LOOKUP.findStatic(EMPTY, "c", MT_c); } catch (Exception e) { throw new ExceptionInInitializerError(e); } @@ -647,6 +450,104 @@ public class T8139885 { } + static class Loop { + + static int inc(int i, int k) { + return i + 1; + } + + static boolean pred(int i, int k) { + return i < k; + } + + static int fin(int i, int k) { + return k; + } + + static final Class LOOP = Loop.class; + + static final MethodType MT_inc = methodType(int.class, int.class, int.class); + static final MethodType MT_pred = methodType(boolean.class, int.class, int.class); + static final MethodType MT_fin = methodType(int.class, int.class, int.class); + + static final MethodHandle MH_inc; + static final MethodHandle MH_pred; + static final MethodHandle MH_fin; + + static final MethodType MT_loop = methodType(int.class, int.class); + + static { + try { + MH_inc = LOOKUP.findStatic(LOOP, "inc", MT_inc); + MH_pred = LOOKUP.findStatic(LOOP, "pred", MT_pred); + MH_fin = LOOKUP.findStatic(LOOP, "fin", MT_fin); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + } + + static class LoopWithVirtuals { + + static int one(int k) { + return 1; + } + + int inc(int i, int acc, int k) { + return i + 1; + } + + int mult(int i, int acc, int k) { + return i * acc; + } + + boolean pred(int i, int acc, int k) { + return i < k; + } + + int fin(int i, int acc, int k) { + return acc; + } + + static final Class LOOP_WITH_VIRTUALS = LoopWithVirtuals.class; + + static final MethodType MT_one = methodType(int.class, int.class); + static final MethodType MT_inc = methodType(int.class, int.class, int.class, int.class); + static final MethodType MT_mult = methodType(int.class, int.class, int.class, int.class); + static final MethodType MT_pred = methodType(boolean.class, int.class, int.class, int.class); + static final MethodType MT_fin = methodType(int.class, int.class, int.class, int.class); + + static final MethodHandle MH_one; + static final MethodHandle MH_inc; + static final MethodHandle MH_mult; + static final MethodHandle MH_pred; + static final MethodHandle MH_fin; + + static final MethodType MT_loop = methodType(int.class, LOOP_WITH_VIRTUALS, int.class); + + static { + try { + MH_one = LOOKUP.findStatic(LOOP_WITH_VIRTUALS, "one", MT_one); + MH_inc = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "inc", MT_inc); + MH_mult = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "mult", MT_mult); + MH_pred = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "pred", MT_pred); + MH_fin = LOOKUP.findVirtual(LOOP_WITH_VIRTUALS, "fin", MT_fin); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + static MethodHandle permute(MethodHandle h) { + // The handles representing virtual methods need to be rearranged to match the required order of arguments + // (loop-local state comes first, then loop arguments). As the receiver comes first in the signature but is + // a loop argument, it must be moved to the appropriate position in the signature. + return MethodHandles.permuteArguments(h, + methodType(h.type().returnType(), int.class, int.class, LOOP_WITH_VIRTUALS, int.class), 2, 0, 1, 3); + } + + } + static class While { static int zero(int limit) { @@ -687,6 +588,16 @@ public class T8139885 { return zip; } + private int i = 0; + + void voidBody(int k) { + ++i; + } + + boolean voidPred(int k) { + return i < k; + } + static final Class WHILE = While.class; static final MethodType MT_zero = methodType(int.class, int.class); @@ -698,6 +609,8 @@ public class T8139885 { static final MethodType MT_zipInitZip = methodType(List.class, Iterator.class, Iterator.class); static final MethodType MT_zipPred = methodType(boolean.class, List.class, Iterator.class, Iterator.class); static final MethodType MT_zipStep = methodType(List.class, List.class, Iterator.class, Iterator.class); + static final MethodType MT_voidBody = methodType(void.class, int.class); + static final MethodType MT_voidPred = methodType(boolean.class, int.class); static final MethodHandle MH_zero; static final MethodHandle MH_pred; @@ -708,10 +621,13 @@ public class T8139885 { static final MethodHandle MH_zipInitZip; static final MethodHandle MH_zipPred; static final MethodHandle MH_zipStep; + static final MethodHandle MH_voidBody; + static final MethodHandle MH_voidPred; static final MethodType MT_while = methodType(int.class, int.class); static final MethodType MT_string = methodType(String.class); static final MethodType MT_zip = methodType(List.class, Iterator.class, Iterator.class); + static final MethodType MT_void = methodType(void.class, int.class); static { try { @@ -724,6 +640,8 @@ public class T8139885 { MH_zipInitZip = LOOKUP.findStatic(WHILE, "zipInitZip", MT_zipInitZip); MH_zipPred = LOOKUP.findStatic(WHILE, "zipPred", MT_zipPred); MH_zipStep = LOOKUP.findStatic(WHILE, "zipStep", MT_zipStep); + MH_voidBody = LOOKUP.findVirtual(WHILE, "voidBody", MT_voidBody); + MH_voidPred = LOOKUP.findVirtual(WHILE, "voidPred", MT_voidPred); } catch (Exception e) { throw new ExceptionInInitializerError(e); } @@ -882,216 +800,4 @@ public class T8139885 { } - static class TryFinally { - - static String greet(String whom) { - return "Hello, " + whom; - } - - static String exclaim(Throwable t, String r, String whom) { - return r + "!"; - } - - static void print(String what) { - System.out.print("Hello, " + what); - } - - static void printMore(Throwable t, String what) { - System.out.println("!"); - } - - static String greetMore(String first, String second) { - return "Hello, " + first + " and " + second; - } - - static String exclaimMore(Throwable t, String r, String first) { - return r + " (but " + first + " first)!"; - } - - static final Class TRY_FINALLY = TryFinally.class; - - static final MethodType MT_greet = methodType(String.class, String.class); - static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class); - static final MethodType MT_print = methodType(void.class, String.class); - static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class); - static final MethodType MT_greetMore = methodType(String.class, String.class, String.class); - static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class); - - static final MethodHandle MH_greet; - static final MethodHandle MH_exclaim; - static final MethodHandle MH_print; - static final MethodHandle MH_printMore; - static final MethodHandle MH_greetMore; - static final MethodHandle MH_exclaimMore; - - static final MethodType MT_hello = methodType(String.class, String.class); - static final MethodType MT_printHello = methodType(void.class, String.class); - static final MethodType MT_moreHello = methodType(String.class, String.class, String.class); - - static { - try { - MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet); - MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim); - MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print); - MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore); - MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore); - MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore); - } catch (Exception e) { - throw new ExceptionInInitializerError(e); - } - } - - } - - static class Fold { - - static int adder(int a, int b, int c) { - return a + b + c; - } - - static int adder1(int a, int b) { - return a + b; - } - - static int multer(int x, int q, int r, int s) { - return x * q * r * s; - } - - static int str(boolean b1, String s, boolean b2, int x) { - return b1 && s.equals(String.valueOf(b2)) ? x : -x; - } - - static boolean comb(String s, boolean b2) { - return !s.equals(b2); - } - - static String comb2(boolean b2, int x) { - int ib = b2 ? 1 : 0; - return ib == x ? "true" : "false"; - } - - static final Class FOLD = Fold.class; - - static final MethodType MT_adder = methodType(int.class, int.class, int.class, int.class); - static final MethodType MT_adder1 = methodType(int.class, int.class, int.class); - static final MethodType MT_multer = methodType(int.class, int.class, int.class, int.class, int.class); - static final MethodType MT_str = methodType(int.class, boolean.class, String.class, boolean.class, int.class); - static final MethodType MT_comb = methodType(boolean.class, String.class, boolean.class); - static final MethodType MT_comb2 = methodType(String.class, boolean.class, int.class); - - static final MethodHandle MH_adder; - static final MethodHandle MH_adder1; - static final MethodHandle MH_multer; - static final MethodHandle MH_str; - static final MethodHandle MH_comb; - static final MethodHandle MH_comb2; - - static final MethodType MT_folded1 = methodType(int.class, int.class, int.class, int.class); - static final MethodType MT_folded2 = methodType(int.class, String.class, boolean.class, int.class); - static final MethodType MT_folded3 = methodType(int.class, boolean.class, boolean.class, int.class); - - static { - try { - MH_adder = LOOKUP.findStatic(FOLD, "adder", MT_adder); - MH_adder1 = LOOKUP.findStatic(FOLD, "adder1", MT_adder1); - MH_multer = LOOKUP.findStatic(FOLD, "multer", MT_multer); - MH_str = LOOKUP.findStatic(FOLD, "str", MT_str); - MH_comb = LOOKUP.findStatic(FOLD, "comb", MT_comb); - MH_comb2 = LOOKUP.findStatic(FOLD, "comb2", MT_comb2); - } catch (Exception e) { - throw new ExceptionInInitializerError(e); - } - } - } - - static class SpreadCollect { - - static String forSpreading(String s1, int i1, int i2, int i3, String s2) { - return s1 + i1 + i2 + i3 + s2; - } - - static String forCollecting(String s1, int[] is, String s2) { - StringBuilder sb = new StringBuilder(s1); - for (int i : is) { - sb.append(i); - } - return sb.append(s2).toString(); - } - - static String forCollectingLeading(int[] is, String s) { - return forCollecting("", is, s); - } - - static final Class SPREAD_COLLECT = SpreadCollect.class; - - static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class); - static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class); - static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class); - - static final MethodHandle MH_forSpreading; - static final MethodHandle MH_forCollecting; - static final MethodHandle MH_forCollectingLeading; - - static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class); - static final MethodType MT_collector0 = methodType(String.class, String.class, String.class); - static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class); - static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class); - static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class); - static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class); - static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class); - static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class); - - static final String NONE_ERROR = "zero array length in MethodHandle.asCollector"; - - static { - try { - MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading); - MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting); - MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading); - } catch (Exception e) { - throw new ExceptionInInitializerError(e); - } - } - - } - - static class FindSpecial { - - interface I1 { - default String m() { - return "I1.m"; - } - } - - interface I2 { - default String m() { - return "I2.m"; - } - } - - interface I3 { - String q(); - } - - static class C implements I1, I2, I3 { - public String m() { - return I1.super.m(); - } - public String q() { - return "q"; - } - } - - static final String ABSTRACT_ERROR = "no such method: test.java.lang.invoke.T8139885$FindSpecial$I3.q()String/invokeSpecial"; - - } - - // - // Auxiliary methods. - // - - static MethodHandle[] mha(MethodHandle... mhs) { - return mhs; - } - } diff --git a/jdk/test/java/lang/invoke/SpreadCollectTest.java b/jdk/test/java/lang/invoke/SpreadCollectTest.java new file mode 100644 index 00000000000..d6644543081 --- /dev/null +++ b/jdk/test/java/lang/invoke/SpreadCollectTest.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* @test + * @bug 8139885 + * @bug 8143798 + * @run testng/othervm -ea -esa test.java.lang.invoke.SpreadCollectTest + */ + +package test.java.lang.invoke; + +import java.io.StringWriter; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; +import java.lang.invoke.WrongMethodTypeException; +import java.util.*; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +/** + * Tests for the new asSpreader/asCollector API added in JEP 274. + */ +public class SpreadCollectTest { + + static final Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public static void testAsSpreader() throws Throwable { + MethodHandle spreader = SpreadCollect.MH_forSpreading.asSpreader(1, int[].class, 3); + assertEquals(SpreadCollect.MT_spreader, spreader.type()); + assertEquals("A456B", (String) spreader.invoke("A", new int[]{4, 5, 6}, "B")); + } + + @Test + public static void testAsSpreaderExample() throws Throwable { + // test the JavaDoc asSpreader-with-pos example + MethodHandle compare = LOOKUP.findStatic(Objects.class, "compare", methodType(int.class, Object.class, Object.class, Comparator.class)); + MethodHandle compare2FromArray = compare.asSpreader(0, Object[].class, 2); + Object[] ints = new Object[]{3, 9, 7, 7}; + Comparator cmp = (a, b) -> a - b; + assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 0, 2), cmp) < 0); + assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 1, 3), cmp) > 0); + assertTrue((int) compare2FromArray.invoke(Arrays.copyOfRange(ints, 2, 4), cmp) == 0); + } + + @DataProvider + static Object[][] asSpreaderIllegalPositions() { + return new Object[][]{{-7}, {3}, {19}}; + } + + @Test(dataProvider = "asSpreaderIllegalPositions") + public static void testAsSpreaderIllegalPos(int p) throws Throwable { + boolean caught = false; + try { + SpreadCollect.MH_forSpreading.asSpreader(p, Object[].class, 3); + } catch (IllegalArgumentException iae) { + assertEquals("bad spread position", iae.getMessage()); + caught = true; + } + assertTrue(caught); + } + + @Test(expectedExceptions = {WrongMethodTypeException.class}) + public static void testAsSpreaderIllegalMethodType() { + MethodHandle h = MethodHandles.dropArguments(MethodHandles.constant(String.class, ""), 0, int.class, int.class); + MethodHandle s = h.asSpreader(String[].class, 1); + } + + @Test + public static void testAsCollector() throws Throwable { + MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1); + assertEquals(SpreadCollect.MT_collector1, collector.type()); + assertEquals("A4B", (String) collector.invoke("A", 4, "B")); + collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2); + assertEquals(SpreadCollect.MT_collector2, collector.type()); + assertEquals("A45B", (String) collector.invoke("A", 4, 5, "B")); + collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3); + assertEquals(SpreadCollect.MT_collector3, collector.type()); + assertEquals("A456B", (String) collector.invoke("A", 4, 5, 6, "B")); + } + + @Test + public static void testAsCollectorInvokeWithArguments() throws Throwable { + MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 1); + assertEquals(SpreadCollect.MT_collector1, collector.type()); + assertEquals("A4B", (String) collector.invokeWithArguments("A", 4, "B")); + collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 2); + assertEquals(SpreadCollect.MT_collector2, collector.type()); + assertEquals("A45B", (String) collector.invokeWithArguments("A", 4, 5, "B")); + collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 3); + assertEquals(SpreadCollect.MT_collector3, collector.type()); + assertEquals("A456B", (String) collector.invokeWithArguments("A", 4, 5, 6, "B")); + } + + @Test + public static void testAsCollectorLeading() throws Throwable { + MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1); + assertEquals(SpreadCollect.MT_collectorLeading1, collector.type()); + assertEquals("7Q", (String) collector.invoke(7, "Q")); + collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2); + assertEquals(SpreadCollect.MT_collectorLeading2, collector.type()); + assertEquals("78Q", (String) collector.invoke(7, 8, "Q")); + collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3); + assertEquals(SpreadCollect.MT_collectorLeading3, collector.type()); + assertEquals("789Q", (String) collector.invoke(7, 8, 9, "Q")); + } + + @Test + public static void testAsCollectorLeadingInvokeWithArguments() throws Throwable { + MethodHandle collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 1); + assertEquals(SpreadCollect.MT_collectorLeading1, collector.type()); + assertEquals("7Q", (String) collector.invokeWithArguments(7, "Q")); + collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 2); + assertEquals(SpreadCollect.MT_collectorLeading2, collector.type()); + assertEquals("78Q", (String) collector.invokeWithArguments(7, 8, "Q")); + collector = SpreadCollect.MH_forCollectingLeading.asCollector(0, int[].class, 3); + assertEquals(SpreadCollect.MT_collectorLeading3, collector.type()); + assertEquals("789Q", (String) collector.invokeWithArguments(7, 8, 9, "Q")); + } + + @Test + public static void testAsCollectorNone() throws Throwable { + MethodHandle collector = SpreadCollect.MH_forCollecting.asCollector(1, int[].class, 0); + assertEquals(SpreadCollect.MT_collector0, collector.type()); + assertEquals("AB", (String) collector.invoke("A", "B")); + } + + @DataProvider + static Object[][] asCollectorIllegalPositions() { + return new Object[][]{{-1}, {17}}; + } + + @Test(dataProvider = "asCollectorIllegalPositions") + public static void testAsCollectorIllegalPos(int p) { + boolean caught = false; + try { + SpreadCollect.MH_forCollecting.asCollector(p, int[].class, 0); + } catch (IllegalArgumentException iae) { + assertEquals("bad collect position", iae.getMessage()); + caught = true; + } + assertTrue(caught); + } + + @Test + public static void testAsCollectorExample() throws Throwable { + // test the JavaDoc asCollector-with-pos example + StringWriter swr = new StringWriter(); + MethodHandle swWrite = LOOKUP. + findVirtual(StringWriter.class, "write", methodType(void.class, char[].class, int.class, int.class)). + bindTo(swr); + MethodHandle swWrite4 = swWrite.asCollector(0, char[].class, 4); + swWrite4.invoke('A', 'B', 'C', 'D', 1, 2); + assertEquals("BC", swr.toString()); + swWrite4.invoke('P', 'Q', 'R', 'S', 0, 4); + assertEquals("BCPQRS", swr.toString()); + swWrite4.invoke('W', 'X', 'Y', 'Z', 3, 1); + assertEquals("BCPQRSZ", swr.toString()); + } + + static class SpreadCollect { + + static String forSpreading(String s1, int i1, int i2, int i3, String s2) { + return s1 + i1 + i2 + i3 + s2; + } + + static String forCollecting(String s1, int[] is, String s2) { + StringBuilder sb = new StringBuilder(s1); + for (int i : is) { + sb.append(i); + } + return sb.append(s2).toString(); + } + + static String forCollectingLeading(int[] is, String s) { + return forCollecting("", is, s); + } + + static final Class SPREAD_COLLECT = SpreadCollect.class; + + static final MethodType MT_forSpreading = methodType(String.class, String.class, int.class, int.class, int.class, String.class); + static final MethodType MT_forCollecting = methodType(String.class, String.class, int[].class, String.class); + static final MethodType MT_forCollectingLeading = methodType(String.class, int[].class, String.class); + + static final MethodHandle MH_forSpreading; + static final MethodHandle MH_forCollecting; + static final MethodHandle MH_forCollectingLeading; + + static final MethodType MT_spreader = methodType(String.class, String.class, int[].class, String.class); + static final MethodType MT_collector0 = methodType(String.class, String.class, String.class); + static final MethodType MT_collector1 = methodType(String.class, String.class, int.class, String.class); + static final MethodType MT_collector2 = methodType(String.class, String.class, int.class, int.class, String.class); + static final MethodType MT_collector3 = methodType(String.class, String.class, int.class, int.class, int.class, String.class); + static final MethodType MT_collectorLeading1 = methodType(String.class, int.class, String.class); + static final MethodType MT_collectorLeading2 = methodType(String.class, int.class, int.class, String.class); + static final MethodType MT_collectorLeading3 = methodType(String.class, int.class, int.class, int.class, String.class); + + static final String NONE_ERROR = "zero array length in MethodHandle.asCollector"; + + static { + try { + MH_forSpreading = LOOKUP.findStatic(SPREAD_COLLECT, "forSpreading", MT_forSpreading); + MH_forCollecting = LOOKUP.findStatic(SPREAD_COLLECT, "forCollecting", MT_forCollecting); + MH_forCollectingLeading = LOOKUP.findStatic(SPREAD_COLLECT, "forCollectingLeading", MT_forCollectingLeading); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + } + +} diff --git a/jdk/test/java/lang/invoke/TryFinallyTest.java b/jdk/test/java/lang/invoke/TryFinallyTest.java new file mode 100644 index 00000000000..efbadeff920 --- /dev/null +++ b/jdk/test/java/lang/invoke/TryFinallyTest.java @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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. + */ + +/* @test + * @bug 8139885 + * @bug 8150825 + * @run testng/othervm -ea -esa test.java.lang.invoke.TryFinallyTest + */ + +package test.java.lang.invoke; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodHandles.Lookup; +import java.lang.invoke.MethodType; + +import static java.lang.invoke.MethodType.methodType; + +import static org.testng.AssertJUnit.*; + +import org.testng.annotations.*; + +/** + * Tests for the tryFinally method handle combinator introduced in JEP 274. + */ +public class TryFinallyTest { + + static final Lookup LOOKUP = MethodHandles.lookup(); + + @Test + public static void testTryFinally() throws Throwable { + MethodHandle hello = MethodHandles.tryFinally(TryFinally.MH_greet, TryFinally.MH_exclaim); + assertEquals(TryFinally.MT_hello, hello.type()); + assertEquals("Hello, world!", hello.invoke("world")); + } + + @Test + public static void testTryFinallyVoid() throws Throwable { + MethodHandle tfVoid = MethodHandles.tryFinally(TryFinally.MH_print, TryFinally.MH_printMore); + assertEquals(TryFinally.MT_printHello, tfVoid.type()); + tfVoid.invoke("world"); + } + + @Test + public static void testTryFinallySublist() throws Throwable { + MethodHandle helloMore = MethodHandles.tryFinally(TryFinally.MH_greetMore, TryFinally.MH_exclaimMore); + assertEquals(TryFinally.MT_moreHello, helloMore.type()); + assertEquals("Hello, world and universe (but world first)!", helloMore.invoke("world", "universe")); + } + + @DataProvider + static Object[][] negativeTestData() { + MethodHandle intid = MethodHandles.identity(int.class); + MethodHandle intco = MethodHandles.constant(int.class, 0); + MethodHandle errTarget = MethodHandles.dropArguments(intco, 0, int.class, double.class, String.class, int.class); + MethodHandle errCleanup = MethodHandles.dropArguments(MethodHandles.constant(int.class, 0), 0, Throwable.class, + int.class, double.class, Object.class); + return new Object[][]{ + {intid, MethodHandles.identity(double.class), + "target and return types must match: double != int"}, + {intid, MethodHandles.dropArguments(intid, 0, String.class), + "cleanup first argument and Throwable must match: (String,int)int != class java.lang.Throwable"}, + {intid, MethodHandles.dropArguments(intid, 0, Throwable.class, double.class), + "cleanup second argument and target return type must match: (Throwable,double,int)int != int"}, + {errTarget, errCleanup, + "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + + errCleanup.type() + " != " + errTarget.type()}, + {TryFinally.MH_voidTarget, TryFinally.MH_voidCleanup, + "cleanup parameters after (Throwable,result) and target parameter list prefix must match: " + + TryFinally.MH_voidCleanup.type() + " != " + TryFinally.MH_voidTarget.type()} + }; + } + + @Test(dataProvider = "negativeTestData") + public static void testTryFinallyNegative(MethodHandle target, MethodHandle cleanup, String expectedMessage) { + boolean caught = false; + try { + MethodHandles.tryFinally(target, cleanup); + } catch (IllegalArgumentException iae) { + assertEquals(expectedMessage, iae.getMessage()); + caught = true; + } + assertTrue(caught); + } + + static class TryFinally { + + static String greet(String whom) { + return "Hello, " + whom; + } + + static String exclaim(Throwable t, String r, String whom) { + return r + "!"; + } + + static void print(String what) { + System.out.print("Hello, " + what); + } + + static void printMore(Throwable t, String what) { + System.out.println("!"); + } + + static String greetMore(String first, String second) { + return "Hello, " + first + " and " + second; + } + + static String exclaimMore(Throwable t, String r, String first) { + return r + " (but " + first + " first)!"; + } + + static void voidTarget() {} + + static void voidCleanup(Throwable t, int a) {} + + static final Class TRY_FINALLY = TryFinally.class; + + static final MethodType MT_greet = methodType(String.class, String.class); + static final MethodType MT_exclaim = methodType(String.class, Throwable.class, String.class, String.class); + static final MethodType MT_print = methodType(void.class, String.class); + static final MethodType MT_printMore = methodType(void.class, Throwable.class, String.class); + static final MethodType MT_greetMore = methodType(String.class, String.class, String.class); + static final MethodType MT_exclaimMore = methodType(String.class, Throwable.class, String.class, String.class); + static final MethodType MT_voidTarget = methodType(void.class); + static final MethodType MT_voidCleanup = methodType(void.class, Throwable.class, int.class); + + static final MethodHandle MH_greet; + static final MethodHandle MH_exclaim; + static final MethodHandle MH_print; + static final MethodHandle MH_printMore; + static final MethodHandle MH_greetMore; + static final MethodHandle MH_exclaimMore; + static final MethodHandle MH_voidTarget; + static final MethodHandle MH_voidCleanup; + + static final MethodType MT_hello = methodType(String.class, String.class); + static final MethodType MT_printHello = methodType(void.class, String.class); + static final MethodType MT_moreHello = methodType(String.class, String.class, String.class); + + static { + try { + MH_greet = LOOKUP.findStatic(TRY_FINALLY, "greet", MT_greet); + MH_exclaim = LOOKUP.findStatic(TRY_FINALLY, "exclaim", MT_exclaim); + MH_print = LOOKUP.findStatic(TRY_FINALLY, "print", MT_print); + MH_printMore = LOOKUP.findStatic(TRY_FINALLY, "printMore", MT_printMore); + MH_greetMore = LOOKUP.findStatic(TRY_FINALLY, "greetMore", MT_greetMore); + MH_exclaimMore = LOOKUP.findStatic(TRY_FINALLY, "exclaimMore", MT_exclaimMore); + MH_voidTarget = LOOKUP.findStatic(TRY_FINALLY, "voidTarget", MT_voidTarget); + MH_voidCleanup = LOOKUP.findStatic(TRY_FINALLY, "voidCleanup", MT_voidCleanup); + } catch (Exception e) { + throw new ExceptionInInitializerError(e); + } + } + + } + +} diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java index 70dd15c6da8..a5917e589a1 100644 --- a/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java +++ b/jdk/test/java/lang/invoke/lambda/LambdaAccessControlDoPrivilegedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ * @summary tests DoPrivileged action (implemented as lambda expressions) by * inserting them into the BootClassPath. * @modules jdk.compiler + * jdk.zipfs * @compile -XDignore.symbol.file LambdaAccessControlDoPrivilegedTest.java LUtils.java * @run main/othervm LambdaAccessControlDoPrivilegedTest */ diff --git a/jdk/test/java/lang/invoke/lambda/LambdaAsm.java b/jdk/test/java/lang/invoke/lambda/LambdaAsm.java index 8148733923c..04faad125b6 100644 --- a/jdk/test/java/lang/invoke/lambda/LambdaAsm.java +++ b/jdk/test/java/lang/invoke/lambda/LambdaAsm.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,7 @@ * generate bytecodes with correct constant pool references * @modules java.base/jdk.internal.org.objectweb.asm * jdk.jdeps/com.sun.tools.classfile + * jdk.zipfs * @compile -XDignore.symbol.file LambdaAsm.java LUtils.java * @run main/othervm LambdaAsm */ diff --git a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java index 1030d27f7fe..430591a8ddc 100644 --- a/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java +++ b/jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java @@ -26,6 +26,8 @@ * @bug 8023524 * @summary tests logging generated classes for lambda * @library /java/nio/file + * @modules jdk.compiler + * jdk.zipfs * @run testng LogGeneratedClassesTest */ import java.io.File; diff --git a/jdk/test/java/lang/ref/CleanerTest.java b/jdk/test/java/lang/ref/CleanerTest.java index 396fbed88bd..25c50dc24c1 100644 --- a/jdk/test/java/lang/ref/CleanerTest.java +++ b/jdk/test/java/lang/ref/CleanerTest.java @@ -52,7 +52,10 @@ import org.testng.annotations.Test; * @library /test/lib/share/classes /lib/testlibrary /test/lib * @build sun.hotspot.WhiteBox * @build jdk.test.lib.Utils - * @modules java.base/jdk.internal.misc java.base/jdk.internal.ref + * @modules java.base/jdk.internal + * java.base/jdk.internal.misc + * java.base/jdk.internal.ref + * java.management * @run main ClassFileInstaller sun.hotspot.WhiteBox * @run testng/othervm * -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. diff --git a/jdk/test/java/lang/ref/FinalizeOverride.java b/jdk/test/java/lang/ref/FinalizeOverride.java index eeb86fe4ab2..7701f5844ea 100644 --- a/jdk/test/java/lang/ref/FinalizeOverride.java +++ b/jdk/test/java/lang/ref/FinalizeOverride.java @@ -29,7 +29,7 @@ import java.nio.file.Paths; import java.util.concurrent.atomic.AtomicInteger; /* @test - * @bug 8027351 + * @bug 8027351 8148940 * @summary Basic test of the finalize method */ @@ -63,6 +63,19 @@ public class FinalizeOverride { while (finalizedCount.get() != (count+1)) { System.gc(); System.runFinalization(); + // Running System.gc() and System.runFinalization() in a + // tight loop can trigger frequent safepointing that slows + // down the VM and, as a result, the test. (With the + // HotSpot VM, the effect of frequent safepointing is + // especially noticeable if the test is run with the + // -Xcomp flag.) Sleeping for a second after every + // garbage collection and finalization cycle gives the VM + // time to make progress. + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + System.out.println("Main thread interrupted, continuing execution."); + } } if (privateFinalizeInvoked) { diff --git a/jdk/test/java/net/SocketOption/ImmutableOptions.java b/jdk/test/java/net/SocketOption/ImmutableOptions.java new file mode 100644 index 00000000000..49c5f8a6831 --- /dev/null +++ b/jdk/test/java/net/SocketOption/ImmutableOptions.java @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + * @test + * @bug 8148609 + * @run testng/othervm ImmutableOptions + * @summary Assert that the set of socket options are immutable + */ +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.*; +import java.util.Set; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +public class ImmutableOptions { + + @BeforeTest + void setupServerSocketFactory() throws IOException { + ServerSocket.setSocketFactory(new ServerSocketImplFactory()); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void socketThrows() throws IOException { + CustomSocketImpl impl = new CustomSocketImpl(); + Socket socket = new CustomSocket(impl); + socket.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void socketImplThrows() throws IOException { + CustomSocketImpl impl = new CustomSocketImpl(); + impl.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void serverSocketThrows() throws IOException { + ServerSocket ss = new ServerSocket(); + ss.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void serverSocketImplThrows() throws IOException { + ServerSocket ss = new ServerSocket(); + ServerSocketImplFactory.mostRecentlyCreated.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void datagramSocketThrows() throws IOException { + CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl(); + DatagramSocket socket = new CustomDatagramSocket(impl); + socket.supportedOptions().clear(); + } + + @Test(expectedExceptions = UnsupportedOperationException.class) + public void datagramSocketImplThrows() throws IOException { + CustomDatagramSocketImpl impl = new CustomDatagramSocketImpl(); + impl.supportedOptions().clear(); + } + + + // Socket descendants + static class CustomSocket extends Socket { + public CustomSocket(SocketImpl impl) throws IOException { + super(impl); + } + } + + static class CustomDatagramSocket extends DatagramSocket { + public CustomDatagramSocket(DatagramSocketImpl impl) { + super(impl); + } + } + + static class ServerSocketImplFactory implements SocketImplFactory { + static volatile CustomSocketImpl mostRecentlyCreated; + + @Override public SocketImpl createSocketImpl() { + return mostRecentlyCreated = new CustomSocketImpl(); + } + } + + // Custom impl's + static class CustomSocketImpl extends SocketImpl { + // The only method interesting to this test. + @Override public Set> supportedOptions() { + return super.supportedOptions(); + } + + public void create(boolean stream) throws IOException { } + + public void connect(String host, int port) throws IOException { } + + public void connect(InetAddress addr, int port) throws IOException { } + + public void connect(SocketAddress addr, int timeout) throws IOException { } + + public void bind(InetAddress host, int port) throws IOException { } + + public void listen(int backlog) throws IOException { } + + public void accept(SocketImpl s) throws IOException { } + + public InputStream getInputStream() throws IOException { return null; } + + public OutputStream getOutputStream() throws IOException { return null; } + + public int available() throws IOException { return 0; } + + public void close() throws IOException { } + + public void sendUrgentData(int data) throws IOException { } + + public Object getOption(int i) throws SocketException { return null; } + + public void setOption(int i, Object o) throws SocketException { } + } + + static class CustomDatagramSocketImpl extends DatagramSocketImpl { + // The only method interesting to this test. + @Override public Set> supportedOptions() { + return super.supportedOptions(); + } + + protected void create() throws SocketException { } + + protected void bind(int lport, InetAddress laddr) throws SocketException { } + + protected void send(DatagramPacket p) throws IOException { } + + protected int peek(InetAddress i) throws IOException { return 0; } + + protected int peekData(DatagramPacket p) throws IOException { return 0; } + + protected void receive(DatagramPacket p) throws IOException { } + + protected void setTTL(byte ttl) throws IOException { } + + protected byte getTTL() throws IOException { return 0; } + + protected void setTimeToLive(int ttl) throws IOException { } + + protected int getTimeToLive() throws IOException { return 0; } + + protected void join(InetAddress inetaddr) throws IOException { } + + protected void leave(InetAddress inetaddr) throws IOException { } + + protected void joinGroup(SocketAddress x, NetworkInterface y) + throws IOException { } + + protected void leaveGroup(SocketAddress x, NetworkInterface y) + throws IOException { } + + protected void close() { } + + public void setOption(int optID, Object value) throws SocketException { } + + public Object getOption(int optID) throws SocketException { return null; } + } +} diff --git a/jdk/test/java/net/SocketOption/OptionsTest.java b/jdk/test/java/net/SocketOption/OptionsTest.java index 947d784aa9d..5b109d533ac 100644 --- a/jdk/test/java/net/SocketOption/OptionsTest.java +++ b/jdk/test/java/net/SocketOption/OptionsTest.java @@ -54,6 +54,7 @@ public class OptionsTest { Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.SO_LINGER, Integer.valueOf(80)), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -61,6 +62,7 @@ public class OptionsTest { static Test[] serverSocketTests = new Test[] { Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -68,6 +70,7 @@ public class OptionsTest { Test.create(StandardSocketOptions.SO_SNDBUF, Integer.valueOf(10 * 100)), Test.create(StandardSocketOptions.SO_RCVBUF, Integer.valueOf(8 * 100)), Test.create(StandardSocketOptions.SO_REUSEADDR, Boolean.FALSE), + Test.create(StandardSocketOptions.SO_REUSEPORT, Boolean.FALSE), Test.create(StandardSocketOptions.IP_TOS, Integer.valueOf(100)) }; @@ -97,15 +100,19 @@ public class OptionsTest { Socket c = new Socket("127.0.0.1", srv.getLocalPort()); Socket s = srv.accept(); ) { + Set> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = c.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); for (int i=0; i> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_KEEPALIVE)) { return Boolean.valueOf(socket.getKeepAlive()); @@ -183,6 +200,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.SO_LINGER)) { return Integer.valueOf(socket.getSoLinger()); } else if (option.equals(StandardSocketOptions.IP_TOS)) { @@ -194,10 +213,15 @@ public class OptionsTest { } } else if (type.equals(ServerSocket.class)) { ServerSocket socket = (ServerSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); + if (option.equals(StandardSocketOptions.SO_RCVBUF)) { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(jdk.net.Sockets.getOption( socket, StandardSocketOptions.IP_TOS)); @@ -206,6 +230,8 @@ public class OptionsTest { } } else if (type.equals(DatagramSocket.class)) { DatagramSocket socket = (DatagramSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_SNDBUF)) { return Integer.valueOf(socket.getSendBufferSize()); @@ -213,6 +239,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else { @@ -221,6 +249,8 @@ public class OptionsTest { } else if (type.equals(MulticastSocket.class)) { MulticastSocket socket = (MulticastSocket)s; + Set> options = socket.supportedOptions(); + boolean reuseport = options.contains(StandardSocketOptions.SO_REUSEPORT); if (option.equals(StandardSocketOptions.SO_SNDBUF)) { return Integer.valueOf(socket.getSendBufferSize()); @@ -228,6 +258,8 @@ public class OptionsTest { return Integer.valueOf(socket.getReceiveBufferSize()); } else if (option.equals(StandardSocketOptions.SO_REUSEADDR)) { return Boolean.valueOf(socket.getReuseAddress()); + } else if (option.equals(StandardSocketOptions.SO_REUSEPORT) && reuseport) { + return Boolean.valueOf(socket.getOption(StandardSocketOptions.SO_REUSEPORT)); } else if (option.equals(StandardSocketOptions.IP_TOS)) { return Integer.valueOf(socket.getTrafficClass()); } else if (option.equals(StandardSocketOptions.IP_MULTICAST_IF)) { diff --git a/jdk/test/java/net/URLPermission/URLTest.java b/jdk/test/java/net/URLPermission/URLTest.java index 266fdfd0a89..710e8f59cf7 100644 --- a/jdk/test/java/net/URLPermission/URLTest.java +++ b/jdk/test/java/net/URLPermission/URLTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import java.net.URLPermission; * * @test * @bug 8010464 + * @key intermittent * @library /lib/testlibrary/ * @build jdk.testlibrary.SimpleSSLContext * @run main/othervm/java.security.policy=policy.1 URLTest one diff --git a/jdk/test/java/net/httpclient/APIErrors.java b/jdk/test/java/net/httpclient/APIErrors.java new file mode 100644 index 00000000000..845c665088a --- /dev/null +++ b/jdk/test/java/net/httpclient/APIErrors.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm APIErrors + */ +//package javaapplication16; + +import com.sun.net.httpserver.*; +import java.io.IOException; +import java.net.*; +import java.net.http.*; +import java.util.LinkedList; +import java.util.List; +import java.util.concurrent.*; +import java.util.function.Supplier; + +/** + * Does stupid things with API, to check appropriate errors/exceptions thrown + */ +public class APIErrors { + + static HttpServer s1 = null; + static ExecutorService executor = null; + static int port; + static HttpClient client; + static String httproot, fileuri, fileroot; + static List clients = new LinkedList<>(); + + public static void main(String[] args) throws Exception { + initServer(); + fileroot = System.getProperty("test.src") + "/docs"; + + client = HttpClient.create().build(); + + clients.add(HttpClient.getDefault()); + + try { + test1(); + test2(); + test3(); + } finally { + s1.stop(0); + executor.shutdownNow(); + for (HttpClient client : clients) + client.executorService().shutdownNow(); + } + } + + static void reject(Runnable r, Class extype) { + try { + r.run(); + throw new RuntimeException("Expected: " + extype); + } catch (Throwable t) { + if (!extype.isAssignableFrom(t.getClass())) { + throw new RuntimeException("Wrong exception type: " + extype + " / " + +t.getClass()); + } + } + } + + static void accept(Runnable r) { + try { + r.run(); + } catch (Throwable t) { + throw new RuntimeException("Unexpected exception: " + t); + } + } + + static void checkNonNull(Supplier r) { + if (r.get() == null) + throw new RuntimeException("Unexpected null return:"); + } + + static void assertTrue(Supplier r) { + if (r.get() == false) + throw new RuntimeException("Assertion failure:"); + } + + // HttpClient.Builder + static void test1() throws Exception { + System.out.println("Test 1"); + HttpClient.Builder cb = HttpClient.create(); + InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); + reject(() -> { cb.priority(-1);}, IllegalArgumentException.class); + reject(() -> { cb.priority(500);}, IllegalArgumentException.class); + accept(() -> { cb.priority(1);}); + accept(() -> { cb.priority(255);}); + + accept(() -> {clients.add(cb.build()); clients.add(cb.build());}); + } + + static void test2() throws Exception { + System.out.println("Test 2"); + HttpClient.Builder cb = HttpClient.create(); + InetSocketAddress addr = new InetSocketAddress("127.0.0.1", 5000); + cb.proxy(ProxySelector.of(addr)); + HttpClient c = cb.build(); + clients.add(c); + checkNonNull(()-> {return c.executorService();}); + assertTrue(()-> {return c.followRedirects() == HttpClient.Redirect.NEVER;}); + assertTrue(()-> {return !c.authenticator().isPresent();}); + } + + static URI accessibleURI() { + return URI.create(fileuri); + } + + static HttpRequest request() { + return HttpRequest.create(accessibleURI()) + .GET(); + } + + static void test3() throws Exception { + System.out.println("Test 3"); + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp = r1.response(); + HttpResponse resp1 = r1.response(); + } catch (IOException |InterruptedException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp = r1.response(); + HttpResponse resp1 = r1.responseAsync().get(); + } catch (IOException |InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + reject(()-> { + try { + HttpRequest r1 = request(); + HttpResponse resp1 = r1.responseAsync().get(); + HttpResponse resp = r1.response(); + } catch (IOException |InterruptedException | ExecutionException e) { + throw new RuntimeException(e); + } + }, IllegalStateException.class); + } + + static class Auth extends java.net.Authenticator { + int count = 0; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (count++ == 0) { + return new PasswordAuthentication("user", "passwd".toCharArray()); + } else { + return new PasswordAuthentication("user", "goober".toCharArray()); + } + } + int count() { + return count; + } + } + + public static void initServer() throws Exception { + String root = System.getProperty ("test.src")+ "/docs"; + InetSocketAddress addr = new InetSocketAddress (0); + s1 = HttpServer.create (addr, 0); + if (s1 instanceof HttpsServer) { + throw new RuntimeException ("should not be httpsserver"); + } + HttpHandler h = new FileServerHandler(root); + + HttpContext c1 = s1.createContext("/files", h); + + executor = Executors.newCachedThreadPool(); + s1.setExecutor (executor); + s1.start(); + + port = s1.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httproot = "http://127.0.0.1:" + port + "/files/"; + fileuri = httproot + "foo.txt"; + } +} diff --git a/jdk/test/java/net/httpclient/BasicAuthTest.java b/jdk/test/java/net/httpclient/BasicAuthTest.java new file mode 100644 index 00000000000..5e3fa6d3374 --- /dev/null +++ b/jdk/test/java/net/httpclient/BasicAuthTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +/** + * @test + * @bug 8087112 + * @run main/othervm BasicAuthTest + * @summary Basic Authentication Test + */ + +import com.sun.net.httpserver.BasicAuthenticator; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class BasicAuthTest { + + static volatile boolean ok; + static final String RESPONSE = "Hello world"; + static final String POST_BODY = "This is the POST body 123909090909090"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + ClientAuth ca = new ClientAuth(); + ServerAuth sa = new ServerAuth("foo realm"); + serverContext.setAuthenticator(sa); + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .authenticator(ca) + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri).GET(); + + HttpResponse resp = req.response(); + ok = resp.statusCode() == 200 && + resp.body(HttpResponse.asString()).equals(RESPONSE); + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + + // repeat same request, should succeed but no additional authenticator calls + + req = client.request(uri).GET(); + resp = req.response(); + ok = resp.statusCode() == 200 && + resp.body(HttpResponse.asString()).equals(RESPONSE); + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + + // try a POST + + req = client.request(uri) + .body(HttpRequest.fromString(POST_BODY)) + .POST(); + resp = req.response(); + ok = resp.statusCode() == 200; + + if (!ok || ca.count != 1) + throw new RuntimeException("Test failed"); + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class ServerAuth extends BasicAuthenticator { + + ServerAuth(String realm) { + super(realm); + } + + @Override + public boolean checkCredentials(String username, String password) { + if (!"user".equals(username) || !"passwd".equals(password)) { + return false; + } + return true; + } + + } + + static class ClientAuth extends java.net.Authenticator { + volatile int count = 0; + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + count++; + return new PasswordAuthentication("user", "passwd".toCharArray()); + } + } + + static class Handler implements HttpHandler { + static volatile boolean ok; + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + if (method.equalsIgnoreCase("POST")) { + String requestBody = new String(is.readAllBytes(), US_ASCII); + if (!requestBody.equals(POST_BODY)) { + he.sendResponseHeaders(500, -1); + ok = false; + } else { + he.sendResponseHeaders(200, -1); + ok = true; + } + } else { // GET + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + ok = true; + } + } + + } +} diff --git a/jdk/test/java/net/httpclient/HeadersTest.java b/jdk/test/java/net/httpclient/HeadersTest.java new file mode 100644 index 00000000000..61faeaa1ec9 --- /dev/null +++ b/jdk/test/java/net/httpclient/HeadersTest.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.http.HttpRequest; +import java.net.URI; + +/** + * @test + * @bug 8087112 + * @summary Basic test for headers + */ +public class HeadersTest { + + static final URI TEST_URI = URI.create("http://www.foo.com/"); + + static void bad(String name) { + HttpRequest.Builder builder = HttpRequest.create(TEST_URI); + try { + builder.header(name, "foo"); + throw new RuntimeException("Expected IAE for header:" + name); + } catch (IllegalArgumentException expected) { } + } + + static void good(String name) { + HttpRequest.Builder builder = HttpRequest.create(TEST_URI); + try { + builder.header(name, "foo"); + } catch (IllegalArgumentException e) { + throw new RuntimeException("Unexpected IAE for header:" + name); + } + } + + public static void main(String[] args) { + bad("bad:header"); + bad("Foo\n"); + good("X-Foo!"); + good("Bar~"); + good("x"); + bad(" "); + bad("Bar\r\n"); + good("Hello#world"); + good("Qwer#ert"); + } +} diff --git a/jdk/test/java/net/httpclient/HttpUtils.java b/jdk/test/java/net/httpclient/HttpUtils.java new file mode 100644 index 00000000000..206cdab362e --- /dev/null +++ b/jdk/test/java/net/httpclient/HttpUtils.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import static java.net.http.HttpRequest.fromByteArray; +import static java.net.http.HttpRequest.fromByteArrays; +import static java.net.http.HttpRequest.fromFile; +import static java.net.http.HttpRequest.fromInputStream; +import static java.net.http.HttpRequest.fromString; +import java.net.http.HttpResponse; +import static java.net.http.HttpResponse.asByteArray; +import static java.net.http.HttpResponse.asFile; +import static java.net.http.HttpResponse.asInputStream; +import static java.net.http.HttpResponse.asString; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +public final class HttpUtils { + + static final int DEFAULT_OFFSET = 10; + static final int DEFAULT_LENGTH = 1000; + static final String midSizedFilename = "/files/notsobigfile.txt"; + static final String smallFilename = "/files/smallfile.txt"; + static final Path midSizedFile; + static final Path smallFile; + static final String fileroot; + + public enum RequestBody { + STRING, FILE, BYTE_ARRAY, BYTE_ARRAY_OFFSET, INPUTSTREAM, STRING_WITH_CHARSET, + } + + static { + fileroot = System.getProperty("test.src") + "/docs"; + midSizedFile = Paths.get(fileroot + midSizedFilename); + smallFile = Paths.get(fileroot + smallFilename); + } + + static public String getFileContent(String path) throws IOException { + FileInputStream fis = new FileInputStream(path); + byte[] buf = new byte[2 * 1024]; + StringBuilder sb = new StringBuilder(); + int byteRead; + while ((byteRead = fis.read(buf)) != -1) { + sb.append(new String(buf, 0, byteRead, "US-ASCII")); + } + return sb.toString(); + } + + public static HttpRequest.Builder getHttpRequestBuilder(final HttpClient client, + final String requestType, + final URI uri) + throws IOException + { + HttpRequest.Builder builder; + String filename = smallFile.toFile().getAbsolutePath(); + String fileContents = HttpUtils.getFileContent(filename); + byte buf[] = fileContents.getBytes(); + switch (requestType) { + case "InputStream": + InputStream inputStream = new FileInputStream(smallFile.toFile()); + builder = client.request(uri) + .body(fromInputStream(inputStream)); + break; + case "byteArray": + builder = client.request(uri) + .body(fromByteArray(buf)); + break; + case "byteArrays": + Iterable iterable = Arrays.asList(buf); + builder = client.request(uri) + .body(fromByteArrays(iterable.iterator())); + break; + case "string": + builder = client.request(uri) + .body(fromString(fileContents)); + break; + case "byteArray_offset": + builder = client.request(uri) + .body(fromByteArray(buf, + DEFAULT_OFFSET, + DEFAULT_LENGTH)); + break; + case "file": + builder = client.request(uri) + .body(fromFile(smallFile)); + break; + case "string_charset": + builder = client.request(uri) + .body(fromString(new String(buf), + Charset.defaultCharset())); + break; + default: + builder = null; + break; + } + return builder; + } + + public static void checkResponse(final HttpResponse response, + String requestType, + final String responseType) + throws IOException + { + String filename = smallFile.toFile().getAbsolutePath(); + String fileContents = HttpUtils.getFileContent(filename); + if (requestType.equals("byteArray_offset")) { + fileContents = fileContents.substring(DEFAULT_OFFSET, + DEFAULT_OFFSET + DEFAULT_LENGTH); + } + byte buf[] = fileContents.getBytes(); + String responseBody; + switch (responseType) { + case "string": + responseBody = response.body(asString()); + if (!responseBody.equals(fileContents)) { + throw new RuntimeException(); + } + break; + case "byteArray": + byte arr[] = response.body(asByteArray()); + if (!Arrays.equals(arr, buf)) { + throw new RuntimeException(); + } + break; + case "file": + response.body(asFile(Paths.get("barf.txt"))); + Path downloaded = Paths.get("barf.txt"); + if (Files.size(downloaded) != fileContents.length()) { + throw new RuntimeException("Size mismatch"); + } + break; + case "InputStream": + InputStream is = response.body(asInputStream()); + byte arr1[] = new byte[1024]; + int byteRead; + StringBuilder sb = new StringBuilder(); + while ((byteRead = is.read(arr1)) != -1) { + sb.append(new String(arr1, 0, byteRead)); + } + if (!sb.toString().equals(fileContents)) { + throw new RuntimeException(); + } + break; + } + } +} diff --git a/jdk/test/java/net/httpclient/ImmutableHeaders.java b/jdk/test/java/net/httpclient/ImmutableHeaders.java new file mode 100644 index 00000000000..9fd6a2162cc --- /dev/null +++ b/jdk/test/java/net/httpclient/ImmutableHeaders.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 + */ + +/** + * @test + * @bug 8087112 + * @run main/othervm ImmutableHeaders + * @summary ImmutableHeaders + */ + +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.Headers; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.PasswordAuthentication; +import java.net.URI; +import java.net.http.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.List; +import static java.nio.charset.StandardCharsets.US_ASCII; + +public class ImmutableHeaders { + + final static String RESPONSE = "Hello world"; + + public static void main(String[] args) throws Exception { + HttpServer server = HttpServer.create(new InetSocketAddress(0), 10); + ExecutorService e = Executors.newCachedThreadPool(); + Handler h = new Handler(); + HttpContext serverContext = server.createContext("/test", h); + int port = server.getAddress().getPort(); + System.out.println("Server port = " + port); + + server.setExecutor(e); + server.start(); + HttpClient client = HttpClient.create() + .build(); + + try { + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/test/foo"); + HttpRequest req = client.request(uri) + .headers("X-Foo", "bar") + .headers("X-Bar", "foo") + .GET(); + + try { + HttpHeaders hd = req.headers(); + List v = hd.allValues("X-Foo"); + if (!v.get(0).equals("bar")) + throw new RuntimeException("Test failed"); + v.add("XX"); + throw new RuntimeException("Test failed"); + } catch (UnsupportedOperationException ex) { + } + HttpResponse resp = req.response(); + try { + HttpHeaders hd = resp.headers(); + List v = hd.allValues("X-Foo-Response"); + if (!v.get(0).equals("resp")) + throw new RuntimeException("Test failed"); + v.add("XX"); + throw new RuntimeException("Test failed"); + } catch (UnsupportedOperationException ex) { + } + + } finally { + client.executorService().shutdownNow(); + server.stop(0); + e.shutdownNow(); + } + System.out.println("OK"); + } + + static class Handler implements HttpHandler { + + @Override + public void handle(HttpExchange he) throws IOException { + String method = he.getRequestMethod(); + InputStream is = he.getRequestBody(); + Headers h = he.getResponseHeaders(); + h.add("X-Foo-Response", "resp"); + he.sendResponseHeaders(200, RESPONSE.length()); + OutputStream os = he.getResponseBody(); + os.write(RESPONSE.getBytes(US_ASCII)); + os.close(); + } + + } +} diff --git a/jdk/test/java/net/httpclient/LightWeightHttpServer.java b/jdk/test/java/net/httpclient/LightWeightHttpServer.java new file mode 100644 index 00000000000..315849521a0 --- /dev/null +++ b/jdk/test/java/net/httpclient/LightWeightHttpServer.java @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + */ +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; +import javax.net.ssl.SSLContext; +import jdk.testlibrary.SimpleSSLContext; + +public class LightWeightHttpServer { + + static SSLContext ctx; + static HttpServer httpServer; + static HttpsServer httpsServer; + static ExecutorService executor; + static int port; + static int httpsport; + static String httproot; + static String httpsroot; + static ProxyServer proxy; + static int proxyPort; + static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; + static RedirectHandler redirectHandler, redirectHandlerSecure; + static DelayHandler delayHandler; + static final String midSizedFilename = "/files/notsobigfile.txt"; + static final String smallFilename = "/files/smallfile.txt"; + static Path midSizedFile; + static Path smallFile; + static String fileroot; + + public static void initServer() throws IOException { + + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + + String root = System.getProperty("test.src") + "/docs"; + InetSocketAddress addr = new InetSocketAddress(0); + httpServer = HttpServer.create(addr, 0); + if (httpServer instanceof HttpsServer) { + throw new RuntimeException("should not be httpsserver"); + } + httpsServer = HttpsServer.create(addr, 0); + HttpHandler h = new FileServerHandler(root); + + HttpContext c1 = httpServer.createContext("/files", h); + HttpContext c2 = httpsServer.createContext("/files", h); + HttpContext c3 = httpServer.createContext("/echo", new EchoHandler()); + redirectHandler = new RedirectHandler("/redirect"); + redirectHandlerSecure = new RedirectHandler("/redirect"); + HttpContext c4 = httpServer.createContext("/redirect", redirectHandler); + HttpContext c41 = httpsServer.createContext("/redirect", redirectHandlerSecure); + HttpContext c5 = httpsServer.createContext("/echo", new EchoHandler()); + HttpContext c6 = httpServer.createContext("/keepalive", new KeepAliveHandler()); + redirectErrorHandler = new RedirectErrorHandler("/redirecterror"); + redirectErrorHandlerSecure = new RedirectErrorHandler("/redirecterror"); + HttpContext c7 = httpServer.createContext("/redirecterror", redirectErrorHandler); + HttpContext c71 = httpsServer.createContext("/redirecterror", redirectErrorHandlerSecure); + delayHandler = new DelayHandler(); + HttpContext c8 = httpServer.createContext("/delay", delayHandler); + HttpContext c81 = httpsServer.createContext("/delay", delayHandler); + + executor = Executors.newCachedThreadPool(); + httpServer.setExecutor(executor); + httpsServer.setExecutor(executor); + ctx = new SimpleSSLContext().get(); + httpsServer.setHttpsConfigurator(new HttpsConfigurator(ctx)); + httpServer.start(); + httpsServer.start(); + + port = httpServer.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httpsport = httpsServer.getAddress().getPort(); + System.out.println("HTTPS server port = " + httpsport); + httproot = "http://127.0.0.1:" + port + "/"; + httpsroot = "https://127.0.0.1:" + httpsport + "/"; + + proxy = new ProxyServer(0, false); + proxyPort = proxy.getPort(); + System.out.println("Proxy port = " + proxyPort); + } + + public static void stop() throws IOException { + if (httpServer != null) { + httpServer.stop(0); + } + if (httpsServer != null) { + httpsServer.stop(0); + } + if (proxy != null) { + proxy.close(); + } + if (executor != null) { + executor.shutdownNow(); + } + } + + static class RedirectErrorHandler implements HttpHandler { + + String root; + volatile int count = 1; + + RedirectErrorHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + String redirect = root + "/foo/" + Integer.toString(count); + increment(); + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } + } + + static class RedirectHandler implements HttpHandler { + + String root; + volatile int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + + if (count++ < 1) { + map.add("Location", root + "/foo/" + count); + } else { + map.add("Location", SmokeTest.midSizedFilename); + } + t.sendResponseHeaders(301, -1); + t.close(); + } + + int count() { + return count; + } + + void reset() { + count = 0; + } + } + + static class KeepAliveHandler implements HttpHandler { + + volatile int counter = 0; + HashSet portSet = new HashSet<>(); + volatile int[] ports = new int[4]; + + void sleep(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) { + } + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + int remotePort = t.getRemoteAddress().getPort(); + String result = "OK"; + + int n = counter++; + /// First test + if (n < 4) { + ports[n] = remotePort; + } + if (n == 3) { + // check all values in ports[] are the same + if (ports[0] != ports[1] || ports[2] != ports[3] + || ports[0] != ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + // Second test + if (n >= 4 && n < 8) { + // delay to ensure ports are different + sleep(500); + ports[n - 4] = remotePort; + } + if (n == 7) { + // should be all different + if (ports[0] == ports[1] || ports[2] == ports[3] + || ports[0] == ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + System.out.printf("Ports: %d, %d, %d, %d\n", + ports[0], ports[1], ports[2], ports[3]); + } + // setup for third test + for (int i = 0; i < 4; i++) { + portSet.add(ports[i]); + } + } + // Third test + if (n > 7) { + // just check that port is one of the ones in portSet + if (!portSet.contains(remotePort)) { + System.out.println("UNEXPECTED REMOTE PORT " + remotePort); + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + byte[] buf = new byte[2048]; + + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + t.sendResponseHeaders(200, result.length()); + OutputStream o = t.getResponseBody(); + o.write(result.getBytes("US-ASCII")); + t.close(); + } + } + + static class DelayHandler implements HttpHandler { + + CyclicBarrier bar1 = new CyclicBarrier(2); + CyclicBarrier bar2 = new CyclicBarrier(2); + CyclicBarrier bar3 = new CyclicBarrier(2); + + CyclicBarrier barrier1() { + return bar1; + } + + CyclicBarrier barrier2() { + return bar2; + } + + @Override + public synchronized void handle(HttpExchange he) throws IOException { + byte[] buf = Util.readAll(he.getRequestBody()); + try { + bar1.await(); + bar2.await(); + } catch (InterruptedException | BrokenBarrierException e) { + } + he.sendResponseHeaders(200, -1); // will probably fail + he.close(); + } + } +} diff --git a/jdk/test/java/net/httpclient/ManyRequests.java b/jdk/test/java/net/httpclient/ManyRequests.java new file mode 100644 index 00000000000..10081f5def7 --- /dev/null +++ b/jdk/test/java/net/httpclient/ManyRequests.java @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm ManyRequests + * @summary Send a large number of requests asynchronously + */ + +//package javaapplication16; + +import com.sun.net.httpserver.HttpsConfigurator; +import com.sun.net.httpserver.HttpsServer; +import java.io.IOException; +import java.io.UncheckedIOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.Arrays; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.Random; +import java.util.concurrent.CompletableFuture; +import javax.net.ssl.SSLContext; +import jdk.testlibrary.SimpleSSLContext; + +public class ManyRequests { + + public static void main(String[] args) throws Exception { + SSLContext ctx = new SimpleSSLContext().get(); + + InetSocketAddress addr = new InetSocketAddress(0); + HttpsServer server = HttpsServer.create(addr, 0); + server.setHttpsConfigurator(new HttpsConfigurator(ctx)); + + HttpClient client = HttpClient.create() + .sslContext(ctx) + .build(); + try { + test(server, client); + System.out.println("OK"); + } finally { + server.stop(0); + client.executorService().shutdownNow(); + } + } + + static final int REQUESTS = 1000; + + static void test(HttpsServer server, HttpClient client) throws Exception { + int port = server.getAddress().getPort(); + URI uri = new URI("https://127.0.0.1:" + port + "/foo/x"); + server.createContext("/foo", new EchoHandler()); + server.start(); + + RequestLimiter limiter = new RequestLimiter(40); + Random rand = new Random(); + CompletableFuture[] results = new CompletableFuture[REQUESTS]; + HashMap bodies = new HashMap<>(); + + for (int i=0; i r.responseAsync()) + .thenCompose((resp) -> { + limiter.requestComplete(); + if (resp.statusCode() != 200) { + resp.bodyAsync(HttpResponse.ignoreBody()); + String s = "Expected 200, got: " + resp.statusCode(); + return completedWithIOException(s); + } + return resp.bodyAsync(HttpResponse.asByteArray()) + .thenApply((b) -> new Pair<>(resp, b)); + }) + .thenAccept((pair) -> { + HttpRequest request = pair.t.request(); + byte[] requestBody = bodies.get(request); + check(Arrays.equals(requestBody, pair.u), + "bodies not equal"); + + }); + } + // wait for them all to complete and throw exception in case of error + CompletableFuture.allOf(results).join(); + } + + static CompletableFuture completedWithIOException(String message) { + CompletableFuture cf = new CompletableFuture<>(); + cf.completeExceptionally(new IOException(message)); + return cf; + } + + static final class Pair { + Pair(T t, U u) { + this.t = t; this.u = u; + } + T t; + U u; + } + + /** + * A simple limiter for controlling the number of requests to be run in + * parallel whenOkToSend() is called which returns a CF that allows + * each individual request to proceed, or block temporarily (blocking occurs + * on the waiters list here. As each request actually completes + * requestComplete() is called to notify this object, and allow some + * requests to continue. + */ + static class RequestLimiter { + + static final CompletableFuture COMPLETED_FUTURE = + CompletableFuture.completedFuture(null); + + final int maxnumber; + final LinkedList> waiters; + int number; + boolean blocked; + + RequestLimiter(int maximum) { + waiters = new LinkedList<>(); + maxnumber = maximum; + } + + synchronized void requestComplete() { + number--; + // don't unblock until number of requests has halved. + if ((blocked && number <= maxnumber / 2) || + (!blocked && waiters.size() > 0)) { + int toRelease = Math.min(maxnumber - number, waiters.size()); + for (int i=0; i f = waiters.remove(); + number ++; + f.complete(null); + } + blocked = number >= maxnumber; + } + } + + synchronized CompletableFuture whenOkToSend() { + if (blocked || number + 1 >= maxnumber) { + blocked = true; + CompletableFuture r = new CompletableFuture<>(); + waiters.add(r); + return r; + } else { + number++; + return COMPLETED_FUTURE; + } + } + } + + static void check(boolean cond, Object... msg) { + if (cond) + return; + StringBuilder sb = new StringBuilder(); + for (Object o : msg) + sb.append(o); + throw new RuntimeException(sb.toString()); + } +} diff --git a/jdk/test/java/net/httpclient/ProxyServer.java b/jdk/test/java/net/httpclient/ProxyServer.java new file mode 100644 index 00000000000..4da9b5e1c55 --- /dev/null +++ b/jdk/test/java/net/httpclient/ProxyServer.java @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.*; +import java.io.*; +import java.util.*; +import java.security.*; + +/** + * A minimal proxy server that supports CONNECT tunneling. It does not do + * any header transformations. In future this could be added. + * Two threads are created per client connection. So, it's not + * intended for large numbers of parallel connections. + */ +public class ProxyServer extends Thread implements Closeable { + + ServerSocket listener; + int port; + volatile boolean debug; + + /** + * Create proxy on port (zero means don't care). Call getPort() + * to get the assigned port. + */ + public ProxyServer(Integer port) throws IOException { + this(port, false); + } + + public ProxyServer(Integer port, Boolean debug) throws IOException { + this.debug = debug; + listener = new ServerSocket(port); + this.port = listener.getLocalPort(); + setName("ProxyListener"); + setDaemon(true); + connections = new LinkedList<>(); + start(); + } + + public ProxyServer(String s) { } + + /** + * Returns the port number this proxy is listening on + */ + public int getPort() { + return port; + } + + /** + * Shuts down the proxy, probably aborting any connections + * currently open + */ + public void close() throws IOException { + if (debug) System.out.println("Proxy: closing"); + done = true; + listener.close(); + for (Connection c : connections) { + if (c.running()) { + c.close(); + } + } + } + + List connections; + + volatile boolean done; + + public void run() { + if (System.getSecurityManager() == null) { + execute(); + } else { + // so calling domain does not need to have socket permission + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { + execute(); + return null; + } + }); + } + } + + public void execute() { + try { + while(!done) { + Socket s = listener.accept(); + if (debug) + System.out.println("Client: " + s); + Connection c = new Connection(s); + connections.add(c); + } + } catch(Throwable e) { + if (debug && !done) { + System.out.println("Fatal error: Listener: " + e); + e.printStackTrace(); + } + } + } + + /** + * Transparently forward everything, once we know what the destination is + */ + class Connection { + + Socket clientSocket, serverSocket; + Thread out, in; + volatile InputStream clientIn, serverIn; + volatile OutputStream clientOut, serverOut; + + boolean forwarding = false; + + final static int CR = 13; + final static int LF = 10; + + Connection(Socket s) throws IOException { + this.clientSocket= s; + this.clientIn = new BufferedInputStream(s.getInputStream()); + this.clientOut = s.getOutputStream(); + init(); + } + + byte[] readHeaders(InputStream is) throws IOException { + byte[] outbuffer = new byte[8000]; + int crlfcount = 0; + int bytecount = 0; + int c; + while ((c=is.read()) != -1 && bytecount < outbuffer.length) { + outbuffer[bytecount++] = (byte)c; + if (debug) System.out.write(c); + // were looking for CRLFCRLF sequence + if (c == CR || c == LF) { + switch(crlfcount) { + case 0: + if (c == CR) crlfcount ++; + break; + case 1: + if (c == LF) crlfcount ++; + break; + case 2: + if (c == CR) crlfcount ++; + break; + case 3: + if (c == LF) crlfcount ++; + break; + } + } else { + crlfcount = 0; + } + if (crlfcount == 4) { + break; + } + } + byte[] ret = new byte[bytecount]; + System.arraycopy(outbuffer, 0, ret, 0, bytecount); + return ret; + } + + boolean running() { + return out.isAlive() || in.isAlive(); + } + + public void close() throws IOException { + if (debug) System.out.println("Closing connection (proxy)"); + if (serverSocket != null) serverSocket.close(); + if (clientSocket != null) clientSocket.close(); + } + + int findCRLF(byte[] b) { + for (int i=0; i=0) { + buf[i--] = (byte)cmdLine.charAt(x--); + } + i++; + + commonInit(dest, 80); + serverOut.write(buf, i, buf.length-i); + proxyCommon(); + + } catch (URISyntaxException e) { + throw new IOException(e); + } + } + + void commonInit(String dest, int defaultPort) throws IOException { + int port; + String[] hostport = dest.split(":"); + if (hostport.length == 1) { + port = defaultPort; + } else { + port = Integer.parseInt(hostport[1]); + } + if (debug) System.out.printf("Server: (%s/%d)\n", hostport[0], port); + serverSocket = new Socket(hostport[0], port); + serverOut = serverSocket.getOutputStream(); + + serverIn = new BufferedInputStream(serverSocket.getInputStream()); + } + + void proxyCommon() throws IOException { + out = new Thread(() -> { + try { + byte[] bb = new byte[8000]; + int n; + while ((n = clientIn.read(bb)) != -1) { + serverOut.write(bb, 0, n); + } + serverSocket.close(); + clientSocket.close(); + } catch (IOException e) { + if (debug) { + System.out.println (e); + } + } + }); + in = new Thread(() -> { + try { + byte[] bb = new byte[8000]; + int n; + while ((n = serverIn.read(bb)) != -1) { + clientOut.write(bb, 0, n); + } + serverSocket.close(); + clientSocket.close(); + } catch (IOException e) { + if (debug) { + System.out.println(e); + e.printStackTrace(); + } + } + }); + out.setName("Proxy-outbound"); + out.setDaemon(true); + in.setDaemon(true); + in.setName("Proxy-inbound"); + out.start(); + in.start(); + } + + void doTunnel(String dest) throws IOException { + commonInit(dest, 443); + clientOut.write("HTTP/1.1 200 OK\r\n\r\n".getBytes()); + proxyCommon(); + } + } + + public static void main(String[] args) throws Exception { + int port = Integer.parseInt(args[0]); + boolean debug = args.length > 1 && args[1].equals("-debug"); + System.out.println("Debugging : " + debug); + ProxyServer ps = new ProxyServer(port, debug); + System.out.println("Proxy server listening on port " + ps.getPort()); + while (true) { + Thread.sleep(5000); + } + } +} diff --git a/jdk/test/java/net/httpclient/QuickResponses.java b/jdk/test/java/net/httpclient/QuickResponses.java new file mode 100644 index 00000000000..5de1f687552 --- /dev/null +++ b/jdk/test/java/net/httpclient/QuickResponses.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +/** + * @test + * @bug 8087112 + * @build Server + * @run main/othervm -Djava.net.HttpClient.log=all QuickResponses + */ + +/** + * Tests the buffering of data on connections across multiple + * responses + */ +public class QuickResponses { + + static Server server; + + static String response(String body) { + return "HTTP/1.1 200 OK\r\nContent-length: " + Integer.toString(body.length()) + + "\r\n\r\n" + body; + } + + static final String responses[] = { + "Lorem ipsum", + "dolor sit amet", + "consectetur adipiscing elit, sed do eiusmod tempor", + "quis nostrud exercitation ullamco", + "laboris nisi", + "ut", + "aliquip ex ea commodo consequat." + + "Duis aute irure dolor in reprehenderit in voluptate velit esse" + + "cillum dolore eu fugiat nulla pariatur.", + "Excepteur sint occaecat cupidatat non proident." + }; + + static String entireResponse() { + String s = ""; + for (String r : responses) { + s += response(r); + } + return s; + } + + public static void main(String[] args) throws Exception { + server = new Server(0); + URI uri = new URI(server.getURL()); + + HttpRequest request = HttpRequest.create(uri) + .GET(); + + CompletableFuture cf1 = request.responseAsync(); + Server.Connection s1 = server.activity(); + s1.send(entireResponse()); + + + HttpResponse r = cf1.join(); + if (r.statusCode()!= 200 || !r.body(HttpResponse.asString()).equals(responses[0])) + throw new RuntimeException("Failed on first response"); + + //now get the same identical response, synchronously to ensure same connection + int remaining = responses.length - 1; + + for (int i=0; i sockets; + AtomicInteger counter = new AtomicInteger(0); + + // waits up to 20 seconds for something to happen + // dont use this unless certain activity coming. + public Connection activity() { + for (int i = 0; i < 80 * 100; i++) { + for (Connection c : sockets) { + if (c.poll()) { + return c; + } + } + try { + Thread.sleep(250); + } catch (InterruptedException e) { + } + } + return null; + } + + // clears all current connections on Server. + public void reset() { + for (Connection c : sockets) { + c.close(); + } + } + + /** + * Reads data into an ArrayBlockingQueue where each String + * is a line of input, that was terminated by CRLF (not included) + */ + class Connection extends Thread { + Connection(Socket s) throws IOException { + this.socket = s; + id = counter.incrementAndGet(); + is = s.getInputStream(); + os = s.getOutputStream(); + incoming = new ArrayBlockingQueue<>(100); + setName("Server-Connection"); + setDaemon(true); + start(); + } + final Socket socket; + final int id; + final InputStream is; + final OutputStream os; + final ArrayBlockingQueue incoming; + + final static String CRLF = "\r\n"; + + // sentinel indicating connection closed + final static String CLOSED = "C.L.O.S.E.D"; + volatile boolean closed = false; + + @Override + public void run() { + byte[] buf = new byte[256]; + String s = ""; + try { + while (true) { + int n = is.read(buf); + if (n == -1) { + cleanup(); + return; + } + String s0 = new String(buf, 0, n, StandardCharsets.ISO_8859_1); + s = s + s0; + int i; + while ((i=s.indexOf(CRLF)) != -1) { + String s1 = s.substring(0, i+2); + incoming.put(s1); + if (i+2 == s.length()) { + s = ""; + break; + } + s = s.substring(i+2); + } + } + } catch (IOException |InterruptedException e1) { + cleanup(); + } catch (Throwable t) { + System.out.println("X: " + t); + cleanup(); + } + } + + @Override + public String toString() { + return "Server.Connection: " + socket.toString(); + } + + public void sendHttpResponse(int code, String body, String... headers) + throws IOException + { + String r1 = "HTTP/1.1 " + Integer.toString(code) + " status" + CRLF; + for (int i=0; i()); + setName("Test-Server"); + setDaemon(true); + start(); + } + + Server() throws IOException { + this(0); + } + + int port() { + return ss.getLocalPort(); + } + + public String getURL() { + return "http://127.0.0.1:" + port() + "/foo/"; + } + + public void close() { + try { + ss.close(); + } catch (IOException e) { + } + for (Connection c : sockets) { + c.close(); + } + } + + @Override + public void run() { + while (true) { + try { + Socket s = ss.accept(); + Connection c = new Connection(s); + sockets.add(c); + } catch (IOException e) { + } + } + } + +} diff --git a/jdk/test/java/net/httpclient/ShortRequestBody.java b/jdk/test/java/net/httpclient/ShortRequestBody.java new file mode 100644 index 00000000000..12a0b6dca51 --- /dev/null +++ b/jdk/test/java/net/httpclient/ShortRequestBody.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.*; +import java.net.http.*; +import java.net.*; +import java.util.concurrent.*; +import java.nio.ByteBuffer; +import java.util.function.LongConsumer; + +/** + * @test + * @bug 8151441 + * @run main/othervm/timeout=10 ShortRequestBody + */ + +/** + * Exception was not being thrown + */ +public class ShortRequestBody { + + static Server server; + static String reqbody = "Hello world"; + + static String response = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n"; + + static class RequestBody implements HttpRequest.BodyProcessor { + public long onRequestStart(HttpRequest hr, LongConsumer flowController) { + return reqbody.length() + 1; // wrong! + } + + public boolean onRequestBodyChunk(ByteBuffer buf) throws IOException { + byte[] b = reqbody.getBytes(); + buf.put(b); + return true; + } + } + + static void close(Closeable c) { + try { + if (c == null) + return; + c.close(); + } catch (IOException e) {} + } + + public static void main(String[] args) throws Exception { + ServerSocket server = new ServerSocket(0); + int port = server.getLocalPort(); + URI uri = new URI("http://127.0.0.1:" + port + "/"); + + HttpRequest request; + HttpResponse r; + Socket s = null; + CompletableFuture cf1; + try { + cf1 = HttpRequest.create(uri) + .body(new RequestBody()) + .GET() + .responseAsync(); + + s = server.accept(); + s.getInputStream().readAllBytes(); + try (OutputStream os = s.getOutputStream()) { + os.write(response.getBytes()); + } catch (IOException ee) { + } + + try { + r = cf1.get(3, TimeUnit.SECONDS); + throw new RuntimeException("Failed"); + } catch (TimeoutException e0) { + throw new RuntimeException("Failed timeout"); + } catch (ExecutionException e) { + System.err.println("OK"); + } + } finally { + HttpClient.getDefault().executorService().shutdownNow(); + close(s); + close(server); + } + } +} diff --git a/jdk/test/java/net/httpclient/SmokeTest.java b/jdk/test/java/net/httpclient/SmokeTest.java new file mode 100644 index 00000000000..ec516623179 --- /dev/null +++ b/jdk/test/java/net/httpclient/SmokeTest.java @@ -0,0 +1,949 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8087112 + * @library /lib/testlibrary/ + * @build jdk.testlibrary.SimpleSSLContext ProxyServer + * @compile ../../../com/sun/net/httpserver/LogFilter.java + * @compile ../../../com/sun/net/httpserver/FileServerHandler.java + * @run main/othervm SmokeTest + */ + +//package javaapplication16; + +import com.sun.net.httpserver.*; +import java.net.*; +import java.net.http.*; +import java.io.*; +import java.util.concurrent.*; +import javax.net.ssl.*; +import java.nio.file.*; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Random; +import jdk.testlibrary.SimpleSSLContext; +import static java.net.http.HttpRequest.*; +import static java.net.http.HttpResponse.*; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * * Basic smoke test for Http/1.1 client + * - basic request response + * - request body POST + * - response body GET + * - redirect + * - chunked request/response + * - SSL + * - proxies + * - 100 continue + * - check keep alive appears to be working + * - cancel of long request + * + * Uses a FileServerHandler serving a couple of known files + * in docs directory. + */ +public class SmokeTest { + static SSLContext ctx; + static HttpServer s1 ; + static HttpsServer s2; + static ExecutorService executor; + static int port; + static int httpsport; + static String httproot; + static String httpsroot; + static HttpClient client; + static ProxyServer proxy; + static int proxyPort; + static RedirectErrorHandler redirectErrorHandler, redirectErrorHandlerSecure; + static RedirectHandler redirectHandler, redirectHandlerSecure; + static DelayHandler delayHandler; + final static String midSizedFilename = "/files/notsobigfile.txt"; + final static String smallFilename = "/files/smallfile.txt"; + static Path midSizedFile; + static Path smallFile; + static String fileroot; + + static String getFileContent(String path) throws IOException { + FileInputStream fis = new FileInputStream(path); + byte[] buf = new byte[2000]; + StringBuilder sb = new StringBuilder(); + int n; + while ((n=fis.read(buf)) != -1) { + sb.append(new String(buf, 0, n, "US-ASCII")); + } + return sb.toString(); + } + + public static void main(String[] args) throws Exception { + initServer(); + fileroot = System.getProperty ("test.src", ".")+ "/docs"; + midSizedFile = Paths.get(fileroot + midSizedFilename); + smallFile = Paths.get(fileroot + smallFilename); + + client = HttpClient.create() + .sslContext(ctx) + .followRedirects(HttpClient.Redirect.ALWAYS) + .executorService(Executors.newCachedThreadPool()) + .build(); + + try { + test1(httproot + "files/foo.txt", true); + + test1(httproot + "files/foo.txt", false); + test1(httpsroot + "files/foo.txt", true); + test1(httpsroot + "files/foo.txt", false); + test2(httproot + "echo/foo", "This is a short test"); + test2(httpsroot + "echo/foo", "This is a short test"); + + test3(httproot + "redirect/foo.txt"); + test3(httpsroot + "redirect/foo.txt"); + test4(httproot + "files/foo.txt"); + test4(httpsroot + "files/foo.txt"); + test5(httproot + "echo/foo", true); + test5(httpsroot + "echo/foo", true); + test5(httproot + "echo/foo", false); + test5(httpsroot + "echo/foo", false); + + test6(httproot + "echo/foo", true); + test6(httpsroot + "echo/foo", true); + test6(httproot + "echo/foo", false); + test6(httpsroot + "echo/foo", false); + + test7(httproot + "keepalive/foo"); + + test8(httproot + "files/foo.txt", true); + test8(httproot + "files/foo.txt", false); + test8(httpsroot + "files/foo.txt", true); + test8(httpsroot + "files/foo.txt", false); + // disabled test9(); + + test10(httproot + "redirecterror/foo.txt"); + + test10(httpsroot + "redirecterror/foo.txt"); + + test11(httproot + "echo/foo"); + test11(httpsroot + "echo/foo"); + //test12(httproot + "delay/foo", delayHandler); + + } finally { + s1.stop(0); + s2.stop(0); + proxy.close(); + executor.shutdownNow(); + client.executorService().shutdownNow(); + } + } + + static class Auth extends java.net.Authenticator { + volatile int count = 0; + @Override + protected PasswordAuthentication getPasswordAuthentication() { + if (count++ == 0) { + return new PasswordAuthentication("user", "passwd".toCharArray()); + } else { + return new PasswordAuthentication("user", "goober".toCharArray()); + } + } + int count() { + return count; + } + } + + // Basic test + static void test1(String target, boolean fixedLen) throws Exception { + System.out.print("test1: " + target); + URI uri = new URI(target); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + String body = response.body(asString()); + if (!body.equals("This is foo.txt\r\n")) { + throw new RuntimeException(); + } + + // repeat async + response = builder.GET().responseAsync().join(); + + body = response.body(asString()); + if (!body.equals("This is foo.txt\r\n")) { + throw new RuntimeException(); + } + System.out.println(" OK"); + } + + // POST use echo to check reply + static void test2(String s, String body) throws Exception { + System.out.print("test2: " + s); + URI uri = new URI(s); + + HttpResponse response = client.request(uri) + .body(fromString(body)) + .POST() + .response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } + String reply = response.body(asString()); + if (!reply.equals(body)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + reply + "]"); + } + System.out.println(" OK"); + } + + // Redirect + static void test3(String s) throws Exception { + System.out.print("test3: " + s); + URI uri = new URI(s); + RedirectHandler handler = uri.getScheme().equals("https") + ? redirectHandlerSecure : redirectHandler; + + HttpResponse response = client.request(uri) + .body(noBody()) + .GET() + .response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } else { + response.body(HttpResponse.asFile(Paths.get("redir1.txt"))); + } + + Path downloaded = Paths.get("redir1.txt"); + if (Files.size(downloaded) != Files.size(midSizedFile)) { + throw new RuntimeException("Size mismatch"); + } + + System.out.printf(" (count: %d) ", handler.count()); + // repeat with async api + + handler.reset(); + + response = client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .join(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } else { + response.body(HttpResponse.asFile(Paths.get("redir2.txt"))); + } + + downloaded = Paths.get("redir2.txt"); + if (Files.size(downloaded) != Files.size(midSizedFile)) { + throw new RuntimeException("Size mismatch 2"); + } + System.out.printf(" (count: %d) ", handler.count()); + System.out.println(" OK"); + } + + // Proxies + static void test4(String s) throws Exception { + System.out.print("test4: " + s); + URI uri = new URI(s); + InetSocketAddress proxyAddr = new InetSocketAddress("127.0.0.1", proxyPort); + String filename = fileroot + uri.getPath(); + + HttpClient cl = HttpClient.create() + .proxy(ProxySelector.of(proxyAddr)) + .sslContext(ctx) + .build(); + + CompletableFuture fut = cl.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenCompose((HttpResponse response) -> + response.bodyAsync(asString()) + ); + + String body = fut.get(5, TimeUnit.HOURS); + + String fc = getFileContent(filename); + + if (!body.equals(fc)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + fc + "]"); + } + cl.executorService().shutdownNow(); + System.out.println(" OK"); + } + + // 100 Continue: use echo target + static void test5(String target, boolean fixedLen) throws Exception { + System.out.print("test5: " + target); + URI uri = new URI(target); + String requestBody = generateString(12 * 1024 + 13); + + HttpRequest.Builder builder = client.request(uri) + .expectContinue(true) + .body(fromString(requestBody)); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + String body = response.body(asString()); + + if (!body.equals(requestBody)) { + throw new RuntimeException( + "Body mismatch: expected [" + body + "], got [" + body + "]"); + } + System.out.println(" OK"); + } + + // use echo + static void test6(String target, boolean fixedLen) throws Exception { + System.out.print("test6: " + target); + URI uri = new URI(target); + String requestBody = generateString(12 * 1024 + 3); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + if (response.statusCode() != 200) { + throw new RuntimeException( + "Expected 200, got [ " + response.statusCode() + " ]"); + } + + String responseBody = response.body(asString()); + + if (responseBody.equals(requestBody)) { + throw new RuntimeException( + "Body mismatch: expected [" + requestBody + "], got [" + responseBody + "]"); + } + System.out.println(" OK"); + } + + @SuppressWarnings("rawtypes") + static void test7(String target) throws Exception { + System.out.print("test7: " + target); + + // First test + URI uri = new URI(target); + for (int i=0; i<4; i++) { + HttpResponse r = client.request(uri) + .body(noBody()) + .GET() + .response(); + String body = r.body(asString()); + if (!body.equals("OK")) { + throw new RuntimeException("Expected OK, got: " + body); + } + } + + // Second test: 4 x parallel + List> futures = new LinkedList<>(); + for (int i=0; i<4; i++) { + futures.add(client.request(uri) + .body(noBody()) + .GET() + .responseAsync()); + } + // all sent? + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + List> futureBodies = new LinkedList<>(); + for (int i=0; i<4; i++) { + futureBodies.add(futures.get(i) + .join() + .bodyAsync(asString())); + } + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + for (CompletableFuture future : futureBodies) { + String body = future.get(); + if (!body.equals("OK")) { + throw new RuntimeException("Expected OK, got: " + body); + } + } + + // Third test: Multiple of 4 parallel requests + BlockingQueue q = new LinkedBlockingQueue<>(); + for (int i=0; i<4; i++) { + client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenApply((HttpResponse resp) -> { + String body = resp.body(asString()); + putQ(q, body); + return body; + }); + } + // we've sent four requests. Now, just send another request + // as each response is received. The idea is to ensure that + // only four sockets ever get used. + + for (int i=0; i<100; i++) { + // block until response received + String body = takeQ(q); + if (!body.equals("OK")) { + throw new RuntimeException(body); + } + client.request(uri) + .body(noBody()) + .GET() + .responseAsync() + .thenApply((HttpResponse resp) -> { + String body1 = resp.body(asString()); + putQ(q, body1); + return body1; + }); + } + // should be four left + for (int i=0; i<4; i++) { + takeQ(q); + } + System.out.println(" OK"); + } + + static String takeQ(BlockingQueue q) { + String r = null; + try { + r = q.take(); + } catch (InterruptedException e) {} + + return r; + } + + static void putQ(BlockingQueue q, String o) { + try { + q.put(o); + } catch (InterruptedException e) { + // can't happen + } + } + + static void test8(String target, boolean fixedLen) throws Exception { + System.out.print("test8: " + target); + URI uri = new URI(target); + + HttpRequest.Builder builder = client.request(uri) + .body(noBody()); + + if (fixedLen) { + builder.header("XFixed", "yes"); + } + + HttpResponse response = builder.GET().response(); + + StringBuilder sb = new StringBuilder(); + + InputStream is = response.body(asInputStream()); + int c; + byte[] buf = new byte[2048]; + while ((c = is.read(buf)) != -1) { + for (int i=0; i cf = request.responseAsync(); + request.cancel(); + h.barrier2().await(); + try { + HttpResponse r = cf.get(); + throw new RuntimeException("failed 2"); + } catch (Exception e) { + } + System.out.println(" OK"); + } +*/ + static void delay(int seconds) { + try { + Thread.sleep(seconds * 1000); + } catch (InterruptedException e) { + } + } +/* + // test won't work until sending fully decoupled from receiving in impl + static void test9() throws Exception { + System.out.print("test9: "); + UploadServer up = new UploadServer(1000 * 1000); + int size = up.size(); + String u = "http://127.0.0.1:" + up.port() + "/"; + URI uri = new URI(u); + + HttpRequest request = client + .request(uri) + .body(new HttpRequestBodyProcessor() { + @Override + public ByteBuffer onRequestBodyChunk(ByteBuffer b) throws IOException { + // slow things down + delay(1); + b.position(b.limit()); // fill it + return b; + } + @Override + public long onRequestStart(HttpRequest req) throws IOException { + return size; + } + }) + .PUT(); + + CompletableFuture cf1 = request.sendAsync(); + CompletableFuture cf = request.responseAsync(); + + HttpResponse resp = cf.get(1, TimeUnit.MINUTES); + if (resp.statusCode() != 201) { + throw new RuntimeException("failed: wrong response code"); + } + delay(2); // allow some data to be sent + request.cancel(); + delay(1); + if (up.failed()) { + throw new RuntimeException("failed to cancel request"); + } + System.out.println(" OK"); + } + */ + // Redirect loop: return an error after a certain number of redirects + static void test10(String s) throws Exception { + System.out.print("test10: " + s); + URI uri = new URI(s); + RedirectErrorHandler handler = uri.getScheme().equals("https") + ? redirectErrorHandlerSecure : redirectErrorHandler; + + CompletableFuture cf = client.request(uri) + .body(noBody()) + .GET() + .responseAsync(); + + try { + HttpResponse response = cf.join(); + throw new RuntimeException("Exepected Completion Exception"); + } catch (CompletionException e) { + //System.out.println(e); + } + + System.out.printf(" (Calls %d) ", handler.count()); + System.out.println(" OK"); + } + + static final int NUM = 50; + + static Random random = new Random(); + static final String alphabet = "ABCDEFGHIJKLMNOPQRST"; + + static char randomChar() { + return alphabet.charAt(random.nextInt(alphabet.length())); + } + + static String generateString(int length) { + StringBuilder sb = new StringBuilder(length); + for (int i=0; i= size; + } finally { + try { + ss.close(); + if (s != null) + s.close(); + } catch (IOException e) {} + } + } + } +} + +class RedirectHandler implements HttpHandler { + String root; + volatile int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException + { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers responseHeaders = t.getResponseHeaders(); + + if (count++ < 1) { + responseHeaders.add("Location", root + "/foo/" + count); + } else { + responseHeaders.add("Location", SmokeTest.midSizedFilename); + } + t.sendResponseHeaders(301, -1); + t.close(); + } + + int count() { + return count; + } + + void reset() { + count = 0; + } +} + +class RedirectErrorHandler implements HttpHandler { + String root; + volatile int count = 1; + + RedirectErrorHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle (HttpExchange t) + throws IOException + { + byte[] buf = new byte[2048]; + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + + Headers map = t.getResponseHeaders(); + String redirect = root + "/foo/" + Integer.toString(count); + increment(); + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } +} + +class Util { + static byte[] readAll(InputStream is) throws IOException { + byte[] buf = new byte[1024]; + byte[] result = new byte[0]; + + while (true) { + int n = is.read(buf); + if (n > 0) { + byte[] b1 = new byte[result.length + n]; + System.arraycopy(result, 0, b1, 0, result.length); + System.arraycopy(buf, 0, b1, result.length, n); + result = b1; + } else if (n == -1) { + return result; + } + } + } +} + +class DelayHandler implements HttpHandler { + + CyclicBarrier bar1 = new CyclicBarrier(2); + CyclicBarrier bar2 = new CyclicBarrier(2); + CyclicBarrier bar3 = new CyclicBarrier(2); + + CyclicBarrier barrier1() { + return bar1; + } + + CyclicBarrier barrier2() { + return bar2; + } + + @Override + public synchronized void handle(HttpExchange he) throws IOException { + byte[] buf = Util.readAll(he.getRequestBody()); + try { + bar1.await(); + bar2.await(); + } catch (Exception e) {} + he.sendResponseHeaders(200, -1); // will probably fail + he.close(); + } + +} + +// check for simple hardcoded sequence and use remote address +// to check. +// First 4 requests executed in sequence (should use same connection/address) +// Next 4 requests parallel (should use different addresses) +// Then send 4 requests in parallel x 100 times (same four addresses used all time) + +class KeepAliveHandler implements HttpHandler { + volatile int counter = 0; + + HashSet portSet = new HashSet<>(); + + volatile int[] ports = new int[4]; + + void sleep(int n) { + try { + Thread.sleep(n); + } catch (InterruptedException e) {} + } + + @Override + public synchronized void handle (HttpExchange t) + throws IOException + { + int remotePort = t.getRemoteAddress().getPort(); + String result = "OK"; + + int n = counter++; + /// First test + if (n < 4) { + ports[n] = remotePort; + } + if (n == 3) { + // check all values in ports[] are the same + if (ports[0] != ports[1] || ports[2] != ports[3] + || ports[0] != ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + // Second test + if (n >=4 && n < 8) { + // delay to ensure ports are different + sleep(500); + ports[n-4] = remotePort; + } + if (n == 7) { + // should be all different + if (ports[0] == ports[1] || ports[2] == ports[3] + || ports[0] == ports[2]) { + result = "Error " + Integer.toString(n); + System.out.println(result); + System.out.printf("Ports: %d, %d, %d, %d\n", ports[0], ports[1], ports[2], ports[3]); + } + // setup for third test + for (int i=0; i<4; i++) { + portSet.add(ports[i]); + } + } + // Third test + if (n > 7) { + // just check that port is one of the ones in portSet + if (!portSet.contains(remotePort)) { + System.out.println ("UNEXPECTED REMOTE PORT " + remotePort); + result = "Error " + Integer.toString(n); + System.out.println(result); + } + } + byte[] buf = new byte[2048]; + + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + t.sendResponseHeaders(200, result.length()); + OutputStream o = t.getResponseBody(); + o.write(result.getBytes("US-ASCII")); + t.close(); + } +} diff --git a/jdk/test/java/net/httpclient/SplitResponse.java b/jdk/test/java/net/httpclient/SplitResponse.java new file mode 100644 index 00000000000..cf887c19a0f --- /dev/null +++ b/jdk/test/java/net/httpclient/SplitResponse.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +//package javaapplication16; + +import java.io.IOException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.URI; +import java.util.concurrent.CompletableFuture; + +/** + * @test + * @bug 8087112 + * @build Server + * @run main/othervm -Djava.net.HttpClient.log=all SplitResponse + */ + +/** + * Similar test to QuickResponses except that each byte of the response + * is sent in a separate packet, which tests the stability of the implementation + * for receiving unusual packet sizes. + */ +public class SplitResponse { + + static Server server; + + static String response(String body) { + return "HTTP/1.1 200 OK\r\nConnection: Close\r\nContent-length: " + + Integer.toString(body.length()) + + "\r\n\r\n" + body; + } + + static final String responses[] = { + "Lorem ipsum", + "dolor sit amet", + "consectetur adipiscing elit, sed do eiusmod tempor", + "quis nostrud exercitation ullamco", + "laboris nisi", + "ut", + "aliquip ex ea commodo consequat." + + "Duis aute irure dolor in reprehenderit in voluptate velit esse" + + "cillum dolore eu fugiat nulla pariatur.", + "Excepteur sint occaecat cupidatat non proident." + }; + + public static void main(String[] args) throws Exception { + server = new Server(0); + URI uri = new URI(server.getURL()); + + HttpRequest request; + HttpResponse r; + CompletableFuture cf1; + + for (int i=0; i { + try { + int len = s.length(); + for (int i = 0; i < len; i++) { + String onechar = s.substring(i, i + 1); + conn.send(onechar); + Thread.sleep(30); + } + System.out.println("sent"); + } catch (IOException | InterruptedException e) { + } + }); + t.setDaemon(true); + t.start(); + } +} diff --git a/jdk/test/java/net/httpclient/TimeoutTest.java b/jdk/test/java/net/httpclient/TimeoutTest.java new file mode 100644 index 00000000000..d7d2ff224a9 --- /dev/null +++ b/jdk/test/java/net/httpclient/TimeoutTest.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.IOException; +import java.net.ServerSocket; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpTimeoutException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.TimeUnit; + +/** + * @test + * @bug 8087112 + * @run main/othervm TimeoutTest + */ + +public class TimeoutTest { + + static int[] timeouts = {6, 4, 8, 6, 6, 4}; + static HttpRequest[] rqs = new HttpRequest[timeouts.length]; + static LinkedBlockingQueue queue = new LinkedBlockingQueue<>(); + static volatile boolean error = false; + static ExecutorService executor = Executors.newCachedThreadPool(); + + public static void main(String[] args) throws Exception { + try { + dotest(); + } finally { + HttpClient.getDefault().executorService().shutdownNow(); + executor.shutdownNow(); + } + } + public static void dotest() throws Exception { + System.out.println("Test takes over 40 seconds"); + ServerSocket ss = new ServerSocket(0, 20); + int port = ss.getLocalPort(); + + URI uri = new URI("http://127.0.0.1:" + Integer.toString(port) + "/foo"); + int i = 0; + for (int timeout : timeouts) { + HttpRequest request; + (request = rqs[i] = HttpRequest.create(uri) + .timeout(TimeUnit.SECONDS, timeout) + .GET()) + .responseAsync() + .whenComplete((HttpResponse r, Throwable t) -> { + if (!(t.getCause() instanceof HttpTimeoutException)) { + System.out.println("Wrong exception type:" + t.toString()); + error = true; + } + if (t != null) { + queue.add(request); + } + }) + .thenAccept((HttpResponse r) -> { + r.bodyAsync(HttpResponse.ignoreBody()); + }); + i++; + } + + System.out.println("SUBMITTED"); + + checkReturnOrder(); + + if (error) + throw new RuntimeException("Failed"); + + // Repeat blocking in separate threads. Use queue to wait. + System.out.println("DOING BLOCKING"); + + i = 0; + for (int timeout : timeouts) { + HttpRequest req = HttpRequest.create(uri) + .timeout(TimeUnit.SECONDS, timeout) + .GET(); + rqs[i] = req; + executor.execute(() -> { + try { + req.response().body(HttpResponse.ignoreBody()); + } catch (HttpTimeoutException e) { + queue.offer(req); + } catch (IOException | InterruptedException ee) { + error = true; + } + }); + i++; + } + + checkReturnOrder(); + + if (error) + throw new RuntimeException("Failed"); + } + + static void checkReturnOrder() throws InterruptedException { + // wait for exceptions and check order + for (int j = 0; j < timeouts.length; j++) { + HttpRequest req = queue.take(); + switch (j) { + case 0: + case 1: + if (req != rqs[1] && req != rqs[5]) { + System.out.printf("Expected 1 or 5. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + break; + case 2: + case 3: + case 4: + if (req != rqs[0] && req != rqs[3] && req != rqs[4]) { + System.out.printf("Expected r1, r4 or r5. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + break; + case 5: + if (req != rqs[2]) { + System.out.printf("Expected r3. Got %s\n", getRequest(req)); + throw new RuntimeException("Error"); + } + } + } + System.out.println("Return order ok"); + } + + static String getRequest(HttpRequest req) { + for (int i=0; i clients = new LinkedList<>(); + static URI uri; + + interface Test { + public void execute() throws IOException, InterruptedException; + } + + static class TestAndResult { + Test test; + boolean result; + + TestAndResult (Test t, boolean result) { + this.test = t; + this.result = result; + } + } + + static TestAndResult test(boolean result, Test t) { + return new TestAndResult(t, result); + } + + static TestAndResult[] tests; + static String testclasses; + static File subdir; + + /** + * The ProxyServer class is compiled by jtreg, but we want to + * move it so it is not on the application claspath. We want to + * load it through a separate classloader so that it has a separate + * protection domain and security permissions. + * + * Its permissions are in the second grant block in each policy file + */ + static void setupProxy() throws IOException, ClassNotFoundException, NoSuchMethodException { + testclasses = System.getProperty("test.classes"); + subdir = new File (testclasses, "proxydir"); + subdir.mkdir(); + + movefile("ProxyServer.class"); + movefile("ProxyServer$Connection.class"); + movefile("ProxyServer$1.class"); + + URL url = subdir.toURL(); + System.out.println("URL for class loader = " + url); + URLClassLoader urlc = new URLClassLoader(new URL[] {url}); + proxyClass = Class.forName("ProxyServer", true, urlc); + proxyConstructor = proxyClass.getConstructor(Integer.class, Boolean.class); + } + + static void movefile(String f) throws IOException { + Path src = Paths.get(testclasses, f); + Path dest = subdir.toPath().resolve(f); + if (!dest.toFile().exists()) { + System.out.printf("moving %s to %s\n", src.toString(), dest.toString()); + Files.move(src, dest, StandardCopyOption.REPLACE_EXISTING); + } else { + System.out.printf("NOT moving %s to %s\n", src.toString(), dest.toString()); + } + } + + static Object getProxy(int port, boolean b) throws Exception { + return proxyConstructor.newInstance(port, b); + } + + static Class proxyClass; + static Constructor proxyConstructor; + + static void setupTests() { + tests = new TestAndResult[]{ + // (0) policy does not have permission for file. Should fail + test(false, () -> { // Policy 0 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (1) policy has permission for file URL + test(true, () -> { //Policy 1 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (2) policy has permission for all file URLs under /files + test(true, () -> { // Policy 2 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (3) policy has permission for first URL but not redirected URL + test(false, () -> { // Policy 3 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (4) policy has permission for both first URL and redirected URL + test(true, () -> { // Policy 4 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (5) policy has permission for redirected but not first URL + test(false, () -> { // Policy 5 + URI u = URI.create("http://127.0.0.1:" + port + "/redirect/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (6) policy has permission for file URL, but not method + test(false, () -> { //Policy 6 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + }), + // (7) policy has permission for file URL, method, but not header + test(false, () -> { //Policy 7 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .header("X-Foo", "bar") + .GET(); + HttpResponse response = request.response(); + }), + // (8) policy has permission for file URL, method and header + test(true, () -> { //Policy 8 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .header("X-Foo", "bar") + .GET(); + HttpResponse response = request.response(); + }), + // (9) policy has permission for file URL, method and header + test(true, () -> { //Policy 9 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .headers("X-Foo", "bar", "X-Bar", "foo") + .GET(); + HttpResponse response = request.response(); + }), + // (10) policy has permission for destination URL but not for proxy + test(false, () -> { //Policy 10 + directProxyTest(27208, true); + }), + // (11) policy has permission for both destination URL and proxy + test(true, () -> { //Policy 11 + directProxyTest(27301, true); + }), + // (12) policy has permission for both destination URL and proxy + test(false, () -> { //Policy 11 + directProxyTest(28301, false); + }), + // (13) async version of test 0 + test(false, () -> { // Policy 0 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + try { + HttpResponse response = request.responseAsync().get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }), + // (14) async version of test 1 + test(true, () -> { //Policy 1 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + try { + HttpResponse response = request.responseAsync().get(); + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }), + // (15) check that user provided unprivileged code running on a worker + // thread does not gain ungranted privileges. + test(false, () -> { //Policy 12 + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = client.request(u) + .GET(); + HttpResponse response = request.response(); + HttpResponse.BodyProcessor stproc = HttpResponse.asString(); + + CompletableFuture cf; + cf = response.bodyAsync(new HttpResponse.BodyProcessor() { + public void onResponseBodyChunk(ByteBuffer b) throws IOException { + // do some mischief here + SecurityManager sm = System.getSecurityManager(); + System.setSecurityManager(null); + System.setSecurityManager(sm); + // problem if we get this far + stproc.onResponseBodyChunk(b); + } + public String onResponseBodyStart(long contentLength, + HttpHeaders responseHeaders, + LongConsumer fc) throws IOException { + + SecurityManager sm = System.getSecurityManager(); + // should succeed. + sm.checkPermission(new RuntimePermission("foobar")); + return stproc.onResponseBodyStart(contentLength,responseHeaders, fc); + } + public String onResponseComplete() throws IOException { + return stproc.onResponseComplete(); + } + public void onResponseError(Throwable t) { + stproc.onResponseError(t); + } + } + ); + try { + System.out.println("Body = " + cf.get());// should not reach here + } catch (ExecutionException e) { + if (e.getCause() instanceof SecurityException) { + throw (SecurityException)e.getCause(); + } else { + throw new RuntimeException(e); + } + } + }) + }; + } + + private static void directProxyTest(int proxyPort, boolean samePort) throws IOException, InterruptedException { + Object proxy = null; + try { + proxy = getProxy(proxyPort, true); + } catch (IOException e) { + System.out.println("Cannot bind. Not running test"); + throw new SecurityException("test not run"); + } catch (Exception ee) { + throw new RuntimeException(ee); + } + System.out.println("Proxy port = " + proxyPort); + if (!samePort) + proxyPort++; + + HttpClient cl = HttpClient.create() + .proxy(ProxySelector.of( + new InetSocketAddress("127.0.0.1", proxyPort))) + .build(); + clients.add(cl); + + URI u = URI.create("http://127.0.0.1:" + port + "/files/foo.txt"); + HttpRequest request = cl.request(u) + .headers("X-Foo", "bar", "X-Bar", "foo") + .GET(); + HttpResponse response = request.response(); + } + + static void runtest(Test r, String policy, boolean succeeds) { + System.out.println("Using policy file: " + policy); + try { + r.execute(); + if (!succeeds) { + System.out.println("FAILED: expected security exception"); + throw new RuntimeException("Failed"); + } + System.out.println (policy + " succeeded as expected"); + } catch (SecurityException e) { + if (succeeds) { + System.out.println("FAILED"); + throw new RuntimeException(e); + } + System.out.println (policy + " threw exception as expected"); + } catch (IOException | InterruptedException ee) { + throw new RuntimeException(ee); + } + } + + public static void main(String[] args) throws Exception { + initServer(); + setupProxy(); + fileroot = System.getProperty ("test.src")+ "/docs"; + int testnum = Integer.parseInt(args[0]); + String policy = args[0]; + + client = HttpClient + .create() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build(); + + clients.add(HttpClient.getDefault()); + clients.add(client); + + try { + setupTests(); + TestAndResult tr = tests[testnum]; + runtest(tr.test, policy, tr.result); + } finally { + s1.stop(0); + //executor.shutdownNow(); + for (HttpClient client : clients) + client.executorService().shutdownNow(); + } + } + + // create Http Server on port range below. So, we can + HttpServer createServer() { + HttpServer server; + for (int i=25800; i<26800; i++) { + InetSocketAddress a = new InetSocketAddress(i); + try { + server = HttpServer.create(a, 0); + return server; + } catch (IOException e) {} + } + return null; + } + + public static void initServer() throws Exception { + Logger logger = Logger.getLogger("com.sun.net.httpserver"); + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + String root = System.getProperty ("test.src")+ "/docs"; + InetSocketAddress addr = new InetSocketAddress (0); + s1 = HttpServer.create (addr, 0); + if (s1 instanceof HttpsServer) { + throw new RuntimeException ("should not be httpsserver"); + } + HttpHandler h = new FileServerHandler (root); + HttpContext c = s1.createContext ("/files", h); + + HttpHandler h1 = new RedirectHandler ("/redirect"); + HttpContext c1 = s1.createContext ("/redirect", h1); + + executor = Executors.newCachedThreadPool(); + s1.setExecutor (executor); + s1.start(); + + port = s1.getAddress().getPort(); + System.out.println("HTTP server port = " + port); + httproot = "http://127.0.0.1:" + port + "/files/"; + redirectroot = "http://127.0.0.1:" + port + "/redirect/"; + uri = new URI(httproot); + fileuri = httproot + "foo.txt"; + } + + static class RedirectHandler implements HttpHandler { + + String root; + int count = 0; + + RedirectHandler(String root) { + this.root = root; + } + + synchronized int count() { + return count; + } + + synchronized void increment() { + count++; + } + + @Override + public synchronized void handle(HttpExchange t) + throws IOException { + byte[] buf = new byte[2048]; + System.out.println("Server: " + t.getRequestURI()); + try (InputStream is = t.getRequestBody()) { + while (is.read(buf) != -1) ; + } + increment(); + if (count() == 1) { + Headers map = t.getResponseHeaders(); + String redirect = "/redirect/bar.txt"; + map.add("Location", redirect); + t.sendResponseHeaders(301, -1); + t.close(); + } else { + String response = "Hello world"; + t.sendResponseHeaders(200, response.length()); + OutputStream os = t.getResponseBody(); + os.write(response.getBytes(StandardCharsets.ISO_8859_1)); + t.close(); + } + } + } +} diff --git a/jdk/test/java/net/httpclient/whitebox/TEST.properties b/jdk/test/java/net/httpclient/whitebox/TEST.properties new file mode 100644 index 00000000000..1d784754199 --- /dev/null +++ b/jdk/test/java/net/httpclient/whitebox/TEST.properties @@ -0,0 +1,3 @@ +TestNG.dirs = . + +bootclasspath.dirs = /java/net/httpclient diff --git a/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java b/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java new file mode 100644 index 00000000000..74ef4ff2991 --- /dev/null +++ b/jdk/test/java/net/httpclient/whitebox/java/net/http/SelectorTest.java @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8151299 + * @summary Http client SelectorManager overwriting read and write events + */ +package java.net.http; + +import java.net.*; +import java.io.*; +import java.nio.channels.*; +import java.nio.ByteBuffer; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicInteger; +import static java.lang.System.out; +import static java.nio.charset.StandardCharsets.US_ASCII; +import static java.util.concurrent.TimeUnit.SECONDS; + +import org.testng.annotations.Test; + +/** + * Whitebox test of selector mechanics. Currently only a simple test + * setting one read and one write event is done. It checks that the + * write event occurs first, followed by the read event and then no + * further events occur despite the conditions actually still existing. + */ +@Test +public class SelectorTest { + + AtomicInteger counter = new AtomicInteger(); + volatile boolean error; + static final CountDownLatch finishingGate = new CountDownLatch(1); + + String readSomeBytes(RawChannel chan) { + try { + ByteBuffer buf = ByteBuffer.allocate(1024); + int t = chan.read(buf); + if (t <= 0) { + out.printf("chan read returned %d\n", t); + return null; + } + byte[] bb = new byte[t]; + buf.get(bb); + return new String(bb, US_ASCII); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + + @Test(timeOut = 10000) + public void test() throws Exception { + + try (ServerSocket server = new ServerSocket(0)) { + int port = server.getLocalPort(); + + out.println("Listening on port " + server.getLocalPort()); + + TestServer t = new TestServer(server); + t.start(); + out.println("Started server thread"); + + final RawChannel chan = getARawChannel(port); + + chan.registerEvent(new RawChannel.NonBlockingEvent() { + @Override + public int interestOps() { + return SelectionKey.OP_READ; + } + + @Override + public void handle() { + readSomeBytes(chan); + out.printf("OP_READ\n"); + if (counter.get() != 1) { + out.printf("OP_READ error counter = %d\n", counter); + error = true; + } + } + }); + + chan.registerEvent(new RawChannel.NonBlockingEvent() { + @Override + public int interestOps() { + return SelectionKey.OP_WRITE; + } + + @Override + public void handle() { + out.printf("OP_WRITE\n"); + if (counter.get() != 0) { + out.printf("OP_WRITE error counter = %d\n", counter); + error = true; + } else { + ByteBuffer bb = ByteBuffer.wrap(TestServer.INPUT); + counter.incrementAndGet(); + try { + chan.write(bb); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + } + + }); + out.println("Events registered. Waiting"); + finishingGate.await(30, SECONDS); + if (error) + throw new RuntimeException("Error"); + else + out.println("No error"); + } + } + + static RawChannel getARawChannel(int port) throws Exception { + URI uri = URI.create("http://127.0.0.1:" + port + "/"); + out.println("client connecting to " + uri.toString()); + HttpRequest req = HttpRequest.create(uri).GET(); + HttpResponse r = req.response(); + r.body(HttpResponse.ignoreBody()); + return ((HttpResponseImpl) r).rawChannel(); + } + + static class TestServer extends Thread { + static final byte[] INPUT = "Hello world".getBytes(US_ASCII); + static final byte[] OUTPUT = "Goodbye world".getBytes(US_ASCII); + static final String FIRST_RESPONSE = "HTTP/1.1 200 OK\r\nContent-length: 0\r\n\r\n"; + final ServerSocket server; + + TestServer(ServerSocket server) throws IOException { + this.server = server; + } + + public void run() { + try (Socket s = server.accept(); + InputStream is = s.getInputStream(); + OutputStream os = s.getOutputStream()) { + + out.println("Got connection"); + readRequest(is); + os.write(FIRST_RESPONSE.getBytes()); + read(is); + write(os); + Thread.sleep(1000); + // send some more data, and make sure WRITE op does not get called + write(os); + out.println("TestServer exiting"); + SelectorTest.finishingGate.countDown(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + // consumes the HTTP request + static void readRequest(InputStream is) throws IOException { + out.println("starting readRequest"); + byte[] buf = new byte[1024]; + String s = ""; + while (true) { + int n = is.read(buf); + if (n <= 0) + throw new IOException("Error"); + s = s + new String(buf, 0, n); + if (s.indexOf("\r\n\r\n") != -1) + break; + } + out.println("returning from readRequest"); + } + + static void read(InputStream is) throws IOException { + out.println("starting read"); + for (int i = 0; i < INPUT.length; i++) { + int c = is.read(); + if (c == -1) + throw new IOException("closed"); + if (INPUT[i] != (byte) c) + throw new IOException("Error. Expected:" + INPUT[i] + ", got:" + c); + } + out.println("returning from read"); + } + + static void write(OutputStream os) throws IOException { + out.println("doing write"); + os.write(OUTPUT); + } + } +} diff --git a/jdk/test/java/net/ipv6tests/TcpTest.java b/jdk/test/java/net/ipv6tests/TcpTest.java index 63008acddba..f538831506c 100644 --- a/jdk/test/java/net/ipv6tests/TcpTest.java +++ b/jdk/test/java/net/ipv6tests/TcpTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 4868820 + * @key intermittent * @summary IPv6 support for Windows XP and 2003 server */ diff --git a/jdk/test/java/net/ipv6tests/UdpTest.java b/jdk/test/java/net/ipv6tests/UdpTest.java index 33fe7e702dd..c5272157c85 100644 --- a/jdk/test/java/net/ipv6tests/UdpTest.java +++ b/jdk/test/java/net/ipv6tests/UdpTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,7 @@ /* * @test * @bug 4868820 + * @key intermittent * @summary IPv6 support for Windows XP and 2003 server */ diff --git a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java index 753629f8e1b..c3450df7d23 100644 --- a/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousServerSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -141,8 +141,11 @@ public class Basic { try { // check supported options Set> options = ch.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_REUSEPORT) && reuseport) + throw new RuntimeException("SO_REUSEPORT should be supported"); if (!options.contains(SO_RCVBUF)) throw new RuntimeException("SO_RCVBUF should be supported"); @@ -156,6 +159,13 @@ public class Basic { checkOption(ch, SO_REUSEADDR, true); ch.setOption(SO_REUSEADDR, false); checkOption(ch, SO_REUSEADDR, false); + + if (reuseport) { + ch.setOption(SO_REUSEPORT, true); + checkOption(ch, SO_REUSEPORT, true); + ch.setOption(SO_REUSEPORT, false); + checkOption(ch, SO_REUSEPORT, false); + } } finally { ch.close(); } diff --git a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java index 23d9eb36e4e..c833735eb0f 100644 --- a/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java +++ b/jdk/test/java/nio/channels/AsynchronousSocketChannel/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.util.concurrent.*; import java.util.concurrent.atomic.*; import java.io.Closeable; import java.io.IOException; +import java.util.Set; public class Basic { static final Random rand = new Random(); @@ -165,6 +166,15 @@ public class Basic { // read others (can't check as actual value is implementation dependent) ch.getOption(SO_RCVBUF); ch.getOption(SO_SNDBUF); + + Set> options = ch.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); + if (reuseport) { + if (ch.getOption(SO_REUSEPORT)) + throw new RuntimeException("Default of SO_REUSEPORT should be 'false'"); + if (!ch.setOption(SO_REUSEPORT, true).getOption(SO_REUSEPORT)) + throw new RuntimeException("SO_REUSEPORT did not change"); + } } } diff --git a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java index b8ec1c1060b..8b23f14f960 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java +++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313882 4981129 + * @bug 4313882 4981129 8143610 * @summary Unit test for datagram-socket-channel adaptors * @library .. * @key randomness @@ -137,7 +137,7 @@ public class AdaptDatagramSocket { echoServer.getPort()); test(address, 0, false, false); test(address, 0, false, true); - test(address, 15000, false, false); + test(address, Integer.MAX_VALUE, false, false); } try (TestServers.UdpDiscardServer discardServer = TestServers.UdpDiscardServer.startNewServer()) { diff --git a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java index bc7146cc982..40aef3282ac 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/DatagramChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,9 +50,17 @@ public class SocketOptionTests { // check supported options Set> options = dc.supportedOptions(); - List> expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, - SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, - IP_MULTICAST_LOOP); + boolean reuseport = options.contains(SO_REUSEPORT); + List> expected; + if (reuseport) { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, + SO_REUSEADDR, SO_REUSEPORT, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, + IP_MULTICAST_TTL, IP_MULTICAST_LOOP); + } else { + expected = Arrays.asList(SO_SNDBUF, SO_RCVBUF, + SO_REUSEADDR, SO_BROADCAST, IP_TOS, IP_MULTICAST_IF, IP_MULTICAST_TTL, + IP_MULTICAST_LOOP); + } for (SocketOption opt: expected) { if (!options.contains(opt)) throw new RuntimeException(opt.name() + " should be supported"); @@ -83,7 +91,12 @@ public class SocketOptionTests { checkOption(dc, SO_REUSEADDR, true); dc.setOption(SO_REUSEADDR, false); checkOption(dc, SO_REUSEADDR, false); - + if (reuseport) { + dc.setOption(SO_REUSEPORT, true); + checkOption(dc, SO_REUSEPORT, true); + dc.setOption(SO_REUSEPORT, false); + checkOption(dc, SO_REUSEPORT, false); + } // bind socket dc.bind(new InetSocketAddress(0)); diff --git a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java index a7756989290..0a3aa9dee32 100644 --- a/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java +++ b/jdk/test/java/nio/channels/ServerSocketChannel/SocketOptionTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,8 +49,11 @@ public class SocketOptionTests { // check supported options Set> options = ssc.supportedOptions(); + boolean reuseport = options.contains(SO_REUSEPORT); if (!options.contains(SO_REUSEADDR)) throw new RuntimeException("SO_REUSEADDR should be supported"); + if (!options.contains(SO_REUSEPORT) && reuseport) + throw new RuntimeException("SO_REUSEPORT should be supported"); if (!options.contains(SO_RCVBUF)) throw new RuntimeException("SO_RCVBUF should be supported"); @@ -64,6 +67,12 @@ public class SocketOptionTests { checkOption(ssc, SO_REUSEADDR, true); ssc.setOption(SO_REUSEADDR, false); checkOption(ssc, SO_REUSEADDR, false); + if (reuseport) { + ssc.setOption(SO_REUSEPORT, true); + checkOption(ssc, SO_REUSEPORT, true); + ssc.setOption(SO_REUSEPORT, false); + checkOption(ssc, SO_REUSEPORT, false); + } // NullPointerException try { diff --git a/jdk/test/java/nio/charset/coders/BashStreams.java b/jdk/test/java/nio/charset/coders/BashStreams.java index 15ea14c3ddf..1658021210b 100644 --- a/jdk/test/java/nio/charset/coders/BashStreams.java +++ b/jdk/test/java/nio/charset/coders/BashStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* @test * @summary Stochastic test of charset-based streams - * @key randomness + * @key randomness intermittent */ import java.io.*; diff --git a/jdk/test/java/nio/file/Files/probeContentType/Basic.java b/jdk/test/java/nio/file/Files/probeContentType/Basic.java index 02298b48fef..ec90ed6b18c 100644 --- a/jdk/test/java/nio/file/Files/probeContentType/Basic.java +++ b/jdk/test/java/nio/file/Files/probeContentType/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,8 +29,9 @@ * @run main/othervm Basic */ -import java.nio.file.*; import java.io.*; +import java.nio.file.*; +import java.util.stream.Stream; /** * Uses Files.probeContentType to probe html file, custom file type, and minimal @@ -38,6 +39,9 @@ import java.io.*; */ public class Basic { + private static final boolean IS_UNIX = + ! System.getProperty("os.name").startsWith("Windows"); + static Path createHtmlFile() throws IOException { Path file = Files.createTempFile("foo", ".html"); try (OutputStream out = Files.newOutputStream(file)) { @@ -51,10 +55,61 @@ public class Basic { return Files.createTempFile("red", ".grape"); } - static void checkContentTypes(String[] extensions, String[] expectedTypes) + private static int checkContentTypes(String expected, String actual) { + assert expected != null; + assert actual != null; + + if (!expected.equals(actual)) { + if (IS_UNIX) { + Path userMimeTypes = + Paths.get(System.getProperty("user.home"), ".mime.types"); + if (!Files.exists(userMimeTypes)) { + System.out.println(userMimeTypes + " does not exist"); + } else if (!Files.isReadable(userMimeTypes)) { + System.out.println(userMimeTypes + " is not readable"); + } else { + System.out.println(userMimeTypes + " contents:"); + try (Stream lines = Files.lines(userMimeTypes)) { + lines.forEach(System.out::println); + System.out.println(""); + } catch (IOException ioe) { + System.err.println("Problem reading " + + userMimeTypes); + } + } + + Path etcMimeTypes = Paths.get("/etc/mime.types"); + if (!Files.exists(etcMimeTypes)) { + System.out.println(etcMimeTypes + " does not exist"); + } else if (!Files.isReadable(etcMimeTypes)) { + System.out.println(etcMimeTypes + " is not readable"); + } else { + System.out.println(etcMimeTypes + " contents:"); + try (Stream lines = Files.lines(etcMimeTypes)) { + lines.forEach(System.out::println); + System.out.println(""); + } catch (IOException ioe) { + System.err.println("Problem reading " + + etcMimeTypes); + } + } + } + + System.err.println("Expected \"" + expected + + "\" but obtained \"" + + actual + "\""); + + return 1; + } + + return 0; + } + + static int checkOSXContentTypes(String[] extensions, String[] expectedTypes) throws IOException { if (extensions.length != expectedTypes.length) { - throw new IllegalArgumentException("Parameter array lengths differ"); + throw new IllegalArgumentException + ("Parameter array lengths differ"); } int failures = 0; @@ -79,12 +134,11 @@ public class Basic { } } - if (failures > 0) { - throw new RuntimeException("Test failed!"); - } + return failures; } public static void main(String[] args) throws IOException { + int failures = 0; // exercise default file type detector Path file = createHtmlFile(); @@ -93,8 +147,7 @@ public class Basic { if (type == null) { System.err.println("Content type cannot be determined - test skipped"); } else { - if (!type.equals("text/html")) - throw new RuntimeException("Unexpected type: " + type); + failures += checkContentTypes("text/html", type); } } finally { Files.delete(file); @@ -106,8 +159,7 @@ public class Basic { String type = Files.probeContentType(file); if (type == null) throw new RuntimeException("Custom file type detector not installed?"); - if (!type.equals("grape/unknown")) - throw new RuntimeException("Unexpected type: " + type); + failures += checkContentTypes("grape/unknown", type); } finally { Files.delete(file); } @@ -122,7 +174,11 @@ public class Basic { "image/jpeg", "audio/mpeg", "video/mp4", "application/pdf", "image/png" }; - checkContentTypes(extensions, expectedTypes); + failures += checkOSXContentTypes(extensions, expectedTypes); + } + + if (failures > 0) { + throw new RuntimeException("Test failed!"); } } } diff --git a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java index 61121578c1e..889a55e9879 100644 --- a/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java +++ b/jdk/test/java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ * java.rmi/sun.rmi.transport.tcp * @build TestLibrary JavaVM LeaseCheckInterval_Stub SelfTerminator * @run main/othervm LeaseCheckInterval + * @key intermittent */ import java.rmi.Remote; diff --git a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java index 663947f78b2..029b51e5cbf 100644 --- a/jdk/test/java/util/WeakHashMap/GCDuringIteration.java +++ b/jdk/test/java/util/WeakHashMap/GCDuringIteration.java @@ -29,26 +29,50 @@ * @run main GCDuringIteration * @summary Check that iterators work properly in the presence of * concurrent finalization and removal of elements. - * @key randomness intermittent + * @key randomness */ -import java.util.*; +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.lang.ref.WeakReference; +import java.util.Arrays; +import java.util.Iterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Random; +import java.util.WeakHashMap; import java.util.concurrent.CountDownLatch; +import java.util.function.BooleanSupplier; import jdk.testlibrary.RandomFactory; public class GCDuringIteration { - private static void waitForFinalizersToRun() { - for (int i = 0; i < 2; i++) - tryWaitForFinalizersToRun(); + + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + CountDownLatch finalizeDone = new CountDownLatch(1); + WeakReference ref = new WeakReference(new Object() { + protected void finalize() { finalizeDone.countDown(); }}); + try { + for (int i = 0; i < 10; i++) { + System.gc(); + if (finalizeDone.await(1L, SECONDS) && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); + } + throw new AssertionError("failed to do a \"full\" gc"); } - private static void tryWaitForFinalizersToRun() { - System.gc(); - final CountDownLatch fin = new CountDownLatch(1); - new Object() { protected void finalize() { fin.countDown(); }}; - System.gc(); - try { fin.await(); } - catch (InterruptedException ie) { throw new Error(ie); } + static void gcAwait(BooleanSupplier s) { + for (int i = 0; i < 10; i++) { + if (s.getAsBoolean()) + return; + forceFullGc(); + } + throw new AssertionError("failed to satisfy condition"); } // A class with the traditional pessimal hashCode implementation, @@ -76,9 +100,13 @@ public class GCDuringIteration { if (rnd.nextBoolean()) check(it.hasNext()); equal(it.next().getValue(), i); } - if (rnd.nextBoolean()) - THROWS(NoSuchElementException.class, - new F(){void f(){it.next();}}); + if (rnd.nextBoolean()) { + try { + it.next(); + throw new AssertionError("should throw"); + } catch (NoSuchElementException success) {} + } + if (rnd.nextBoolean()) check(! it.hasNext()); } @@ -106,9 +134,7 @@ public class GCDuringIteration { int first = firstValue(map); final Iterator> it = map.entrySet().iterator(); foos[first] = null; - for (int i = 0; i < 10 && map.size() != first; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first); + gcAwait(() -> map.size() == first); checkIterator(it, first-1); equal(map.size(), first); equal(firstValue(map), first-1); @@ -119,15 +145,14 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); + int oldSize = map.size(); foos[first] = null; - tryWaitForFinalizersToRun(); - equal(map.size(), first+1); + forceFullGc(); + equal(map.size(), oldSize); System.out.println(map.values()); checkIterator(it, first-1); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first); + gcAwait(() -> map.size() == first); equal(firstValue(map), first-1); } @@ -137,15 +162,12 @@ public class GCDuringIteration { it.next(); // protects first entry System.out.println(map.values()); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); - equal(map.size(), first); + gcAwait(() -> map.size() == first); equal(firstValue(map), first); System.out.println(map.values()); checkIterator(it, first-2); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -155,16 +177,15 @@ public class GCDuringIteration { it.next(); // protects first entry it.hasNext(); // protects second entry System.out.println(map.values()); + int oldSize = map.size(); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); + forceFullGc(); + equal(map.size(), oldSize); equal(firstValue(map), first); - equal(map.size(), first+1); System.out.println(map.values()); checkIterator(it, first-1); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -173,17 +194,16 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.next(); // protects first entry System.out.println(map.values()); + equal(map.size(), first+1); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); + gcAwait(() -> map.size() == first); it.remove(); equal(firstValue(map), first-2); equal(map.size(), first-1); System.out.println(map.values()); checkIterator(it, first-2); // first entry no longer protected - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -194,15 +214,14 @@ public class GCDuringIteration { it.remove(); it.hasNext(); // protects second entry System.out.println(map.values()); + equal(map.size(), first); foos[first] = foos[first-1] = null; - tryWaitForFinalizersToRun(); + forceFullGc(); equal(firstValue(map), first-1); equal(map.size(), first); System.out.println(map.values()); checkIterator(it, first-1); - for (int i = 0; i < 10 && map.size() != first-1; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), first-1); + gcAwait(() -> map.size() == first-1); equal(firstValue(map), first-2); } @@ -211,14 +230,11 @@ public class GCDuringIteration { final Iterator> it = map.entrySet().iterator(); it.hasNext(); // protects first entry Arrays.fill(foos, null); - tryWaitForFinalizersToRun(); - equal(map.size(), 1); + gcAwait(() -> map.size() == 1); System.out.println(map.values()); equal(it.next().getValue(), first); check(! it.hasNext()); - for (int i = 0; i < 10 && map.size() != 0; i++) - tryWaitForFinalizersToRun(); - equal(map.size(), 0); + gcAwait(() -> map.size() == 0); check(map.isEmpty()); } } @@ -239,11 +255,4 @@ public class GCDuringIteration { try {test(args);} catch (Throwable t) {unexpected(t);} System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new AssertionError("Some tests failed");} - abstract class F {abstract void f() throws Throwable;} - void THROWS(Class k, F... fs) { - for (F f : fs) - try {f.f(); fail("Expected " + k.getName() + " not thrown");} - catch (Throwable t) { - if (k.isAssignableFrom(t.getClass())) pass(); - else unexpected(t);}} } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java index c822e7d3b98..db72bfc44d2 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/CancelledProducerConsumerLoops.java @@ -35,8 +35,11 @@ * @test * @bug 4486658 * @summary Checks for responsiveness of blocking queues to cancellation. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.ArrayList; import java.util.List; import java.util.SplittableRandom; @@ -53,8 +56,10 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class CancelledProducerConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -73,7 +78,7 @@ public class CancelledProducerConsumerLoops { new CancelledProducerConsumerLoops(i, queue).run(); } pool.shutdown(); - if (! pool.awaitTermination(10L, TimeUnit.SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); pool = null; } @@ -117,18 +122,18 @@ public class CancelledProducerConsumerLoops { assertCancelled(cons[i]); } - if (!producersInterrupted.await(10L, TimeUnit.SECONDS)) + if (!producersInterrupted.await(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); - if (!consumersInterrupted.await(10L, TimeUnit.SECONDS)) + if (!consumersInterrupted.await(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); if (prods[0].isDone() || prods[0].isCancelled()) throw new AssertionError("completed too early"); done = true; - if (! (prods[0].get(10L, TimeUnit.SECONDS) instanceof Integer)) + if (! (prods[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer)) throw new AssertionError("expected Integer"); - if (! (cons[0].get(10L, TimeUnit.SECONDS) instanceof Integer)) + if (! (cons[0].get(LONG_DELAY_MS, MILLISECONDS) instanceof Integer)) throw new AssertionError("expected Integer"); } @@ -138,7 +143,7 @@ public class CancelledProducerConsumerLoops { if (!future.isCancelled()) throw new AssertionError("not cancelled"); try { - future.get(10L, TimeUnit.SECONDS); + future.get(LONG_DELAY_MS, MILLISECONDS); throw new AssertionError("should throw CancellationException"); } catch (CancellationException success) {} } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java index f3f130bb2c7..9677ea5d2e6 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/Interrupt.java @@ -26,10 +26,10 @@ * @bug 6384064 * @summary Check proper handling of interrupts * @author Martin Buchholz + * @library /lib/testlibrary/ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; import java.util.List; @@ -41,8 +41,10 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.Executor; import java.util.concurrent.ScheduledThreadPoolExecutor; +import jdk.testlibrary.Utils; public class Interrupt { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void checkInterrupted0(Iterable fs, Executor ex) { for (Fun f : fs) { @@ -71,7 +73,7 @@ public class Interrupt { checkInterrupted0(fs, immediateExecutor); checkInterrupted0(fs, delayedExecutor); stpe.shutdown(); - check(stpe.awaitTermination(10L, SECONDS)); + check(stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } static void testQueue(final BlockingQueue q) { @@ -82,12 +84,12 @@ public class Interrupt { q.clear(); List fs = new ArrayList(); fs.add(() -> q.take()); - fs.add(() -> q.poll(60, SECONDS)); + fs.add(() -> q.poll(LONG_DELAY_MS, MILLISECONDS)); if (deq != null) { fs.add(() -> deq.takeFirst()); fs.add(() -> deq.takeLast()); - fs.add(() -> deq.pollFirst(7, SECONDS)); - fs.add(() -> deq.pollLast(7, SECONDS)); + fs.add(() -> deq.pollFirst(LONG_DELAY_MS, MILLISECONDS)); + fs.add(() -> deq.pollLast(LONG_DELAY_MS, MILLISECONDS)); } checkInterrupted(fs); @@ -99,12 +101,12 @@ public class Interrupt { fs.clear(); fs.add(() -> q.put(1)); - fs.add(() -> q.offer(1, 7, SECONDS)); + fs.add(() -> q.offer(1, LONG_DELAY_MS, MILLISECONDS)); if (deq != null) { fs.add(() -> deq.putFirst(1)); fs.add(() -> deq.putLast(1)); - fs.add(() -> deq.offerFirst(1, 7, SECONDS)); - fs.add(() -> deq.offerLast(1, 7, SECONDS)); + fs.add(() -> deq.offerFirst(1, LONG_DELAY_MS, MILLISECONDS)); + fs.add(() -> deq.offerLast(1, LONG_DELAY_MS, MILLISECONDS)); } checkInterrupted(fs); } catch (Throwable t) { diff --git a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java index 6fafe5453c2..076521266d0 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/MultipleProducersSingleConsumerLoops.java @@ -35,10 +35,11 @@ * @test * @bug 4486658 * @summary multiple producers and single consumer using blocking queues + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -51,8 +52,10 @@ import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class MultipleProducersSingleConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -77,7 +80,7 @@ public class MultipleProducersSingleConsumerLoops { } pool.shutdown(); - if (! pool.awaitTermination(10L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java index 6cc57e7f319..454a58facef 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/ProducerConsumerLoops.java @@ -35,10 +35,11 @@ * @test * @bug 4486658 * @summary multiple producers and consumers using blocking queues + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -51,8 +52,10 @@ import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class ProducerConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -77,7 +80,7 @@ public class ProducerConsumerLoops { run(new ArrayBlockingQueue(100, true), i, 100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java index 662b6b277aa..d1810680dd9 100644 --- a/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java +++ b/jdk/test/java/util/concurrent/BlockingQueue/SingleProducerMultipleConsumerLoops.java @@ -35,10 +35,11 @@ * @test * @bug 4486658 * @summary check ordering for blocking queues with 1 producer and multiple consumers + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; @@ -50,8 +51,10 @@ import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.PriorityBlockingQueue; import java.util.concurrent.SynchronousQueue; +import jdk.testlibrary.Utils; public class SingleProducerMultipleConsumerLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; public static void main(String[] args) throws Exception { @@ -75,7 +78,7 @@ public class SingleProducerMultipleConsumerLoops { run(new ArrayBlockingQueue(100, true), i, 100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java index 4470604b3f0..9b6773d4a8e 100644 --- a/jdk/test/java/util/concurrent/CompletableFuture/Basic.java +++ b/jdk/test/java/util/concurrent/CompletableFuture/Basic.java @@ -34,15 +34,17 @@ /* * @test * @bug 8005696 + * @summary Basic tests for CompletableFuture + * @library /lib/testlibrary/ * @run main Basic * @run main/othervm -Djava.util.concurrent.ForkJoinPool.common.parallelism=0 Basic - * @summary Basic tests for CompletableFuture * @author Chris Hegarty */ import static java.util.concurrent.CompletableFuture.runAsync; import static java.util.concurrent.CompletableFuture.supplyAsync; import static java.util.concurrent.ForkJoinPool.commonPool; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.lang.reflect.Array; @@ -54,8 +56,10 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void checkCompletedNormally(CompletableFuture cf, Object value) { checkCompletedNormally(cf, value == null ? null : new Object[] { value }); @@ -109,12 +113,13 @@ public class Basic { } private static void realMain(String[] args) throws Throwable { - ExecutorService executor = Executors.newFixedThreadPool(2); + ExecutorService pool = Executors.newFixedThreadPool(2); try { - test(executor); + test(pool); } finally { - executor.shutdown(); - executor.awaitTermination(30L, SECONDS); + pool.shutdown(); + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) + throw new Error(); } } diff --git a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java index 767f035ab62..6ce67ccf8ff 100644 --- a/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java +++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/MapLoops.java @@ -34,7 +34,6 @@ /* * @test * @bug 4486658 - * @run main/timeout=1600 MapLoops * @summary Exercise multithreaded maps, by default ConcurrentHashMap. * Multithreaded hash table test. Each thread does a random walk * though elements of "key" array. On each iteration, it checks if @@ -42,9 +41,11 @@ * inserts it, and if present, with probability premove it removes * it. (pinsert and premove are expressed as percentages to simplify * parsing from command line.) + * @library /lib/testlibrary/ + * @run main/timeout=1600 MapLoops */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.List; import java.util.Map; @@ -53,8 +54,10 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class MapLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static int nkeys = 1000; // 10_000 static int pinsert = 60; static int premove = 2; @@ -126,7 +129,7 @@ public class MapLoops { i = k; } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); if (! throwables.isEmpty()) diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java index 8b7511f71e9..8ecc8f84f5e 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/ConcurrentQueueLoops.java @@ -34,11 +34,12 @@ /* * @test * @bug 4486658 6785442 - * @run main ConcurrentQueueLoops 8 123456 * @summary Checks that a set of threads can repeatedly get and modify items + * @library /lib/testlibrary/ + * @run main ConcurrentQueueLoops 8 123456 */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.ArrayList; import java.util.Collection; @@ -57,8 +58,10 @@ import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class ConcurrentQueueLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); ExecutorService pool; AtomicInteger totalItems; boolean print; @@ -106,16 +109,14 @@ public class ConcurrentQueueLoops { print = false; System.out.println("Warmup..."); oneRun(1, items, q); - //Thread.sleep(100); oneRun(3, items, q); - Thread.sleep(100); print = true; for (int i = 1; i <= maxStages; i += (i+1) >>> 1) { oneRun(i, items, q); } pool.shutdown(); - check(pool.awaitTermination(60L, SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } class Stage implements Callable { diff --git a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java index befc8ad11f4..314166b8689 100644 --- a/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java +++ b/jdk/test/java/util/concurrent/ConcurrentQueues/GCRetention.java @@ -38,10 +38,14 @@ * @run main GCRetention 12345 */ +import static java.util.concurrent.TimeUnit.SECONDS; + +import java.lang.ref.WeakReference; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedDeque; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedTransferQueue; @@ -59,6 +63,25 @@ public class GCRetention { // Suitable for benchmarking. Overridden by args[0] for testing. int count = 1024 * 1024; + /** No guarantees, but effective in practice. */ + static void forceFullGc() { + CountDownLatch finalizeDone = new CountDownLatch(1); + WeakReference ref = new WeakReference(new Object() { + protected void finalize() { finalizeDone.countDown(); }}); + try { + for (int i = 0; i < 10; i++) { + System.gc(); + if (finalizeDone.await(1L, SECONDS) && ref.get() == null) { + System.runFinalization(); // try to pick up stragglers + return; + } + } + } catch (InterruptedException unexpected) { + throw new AssertionError("unexpected InterruptedException"); + } + throw new AssertionError("failed to do a \"full\" gc"); + } + final Map results = new ConcurrentHashMap(); Collection> queues() { @@ -117,8 +140,8 @@ public class GCRetention { long t0 = System.nanoTime(); for (int i = 0; i < count; i++) check(q.add(Boolean.TRUE)); - System.gc(); - System.gc(); + forceFullGc(); + // forceFullGc(); Boolean x; while ((x = q.poll()) != null) equal(x, Boolean.TRUE); diff --git a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java index da62643e5d5..146347ed502 100644 --- a/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java +++ b/jdk/test/java/util/concurrent/CyclicBarrier/Basic.java @@ -25,11 +25,11 @@ * @test * @bug 6253848 6366811 * @summary Basic tests for CyclicBarrier + * @library /lib/testlibrary/ * @author Martin Buchholz, David Holmes */ import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; import java.util.Iterator; @@ -39,8 +39,10 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.TimeoutException; import java.util.concurrent.atomic.AtomicInteger; +import jdk.testlibrary.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); private static void checkBroken(final CyclicBarrier barrier) { check(barrier.isBroken()); @@ -77,7 +79,7 @@ public class Basic { private static final CyclicBarrier atTheStartingGate = new CyclicBarrier(3); private static void toTheStartingGate() { - try { atTheStartingGate.await(10, SECONDS); pass(); } + try { atTheStartingGate.await(LONG_DELAY_MS, MILLISECONDS); pass(); } catch (Throwable t) { unexpected(t); reset(atTheStartingGate); @@ -314,13 +316,13 @@ public class Basic { Throwable throwable() { return this.throwable; } boolean interruptBit() { return this.interrupted; } void realRun() throws Throwable { - startingGate.await(10, SECONDS); + startingGate.await(LONG_DELAY_MS, MILLISECONDS); try { - if (timed) barrier.await(10, SECONDS); + if (timed) barrier.await(LONG_DELAY_MS, MILLISECONDS); else barrier.await(); } catch (Throwable throwable) { this.throwable = throwable; } - try { doneSignal.await(10, SECONDS); } + try { doneSignal.await(LONG_DELAY_MS, MILLISECONDS); } catch (InterruptedException e) { interrupted = true; } } } @@ -354,7 +356,7 @@ public class Basic { waiter.start(); waiters.add(waiter); } - startingGate.await(10, SECONDS); + startingGate.await(LONG_DELAY_MS, MILLISECONDS); while (barrier.getNumberWaiting() < N) Thread.yield(); barrier.await(); doneSignal.countDown(); @@ -383,7 +385,7 @@ public class Basic { waiter.start(); waiters.add(waiter); } - startingGate.await(10, SECONDS); + startingGate.await(LONG_DELAY_MS, MILLISECONDS); while (barrier.getNumberWaiting() < N) Thread.yield(); for (int i = 0; i < N/2; i++) waiters.get(i).interrupt(); diff --git a/jdk/test/java/util/concurrent/DelayQueue/Stress.java b/jdk/test/java/util/concurrent/DelayQueue/Stress.java index 8d6145819e2..5a25b077521 100644 --- a/jdk/test/java/util/concurrent/DelayQueue/Stress.java +++ b/jdk/test/java/util/concurrent/DelayQueue/Stress.java @@ -26,6 +26,7 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; +import java.util.concurrent.TimeUnit; /** * This is not a regression test, but a stress benchmark test for diff --git a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java index 8af16e2955c..5a20b6b9e2f 100644 --- a/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java +++ b/jdk/test/java/util/concurrent/Exchanger/ExchangeLoops.java @@ -34,18 +34,20 @@ /* * @test * @bug 4486658 - * @run main/timeout=720 ExchangeLoops * @summary checks to make sure a pipeline of exchangers passes data. + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.Exchanger; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class ExchangeLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static boolean print = false; @@ -56,14 +58,14 @@ public class ExchangeLoops { public static void main(String[] args) throws Exception { int maxStages = 5; - int iters = 10000; + int iters = 2000; if (args.length > 0) maxStages = Integer.parseInt(args[0]); print = false; System.out.println("Warmup..."); - oneRun(2, 100000); + oneRun(2, iters); print = true; for (int i = 2; i <= maxStages; i += (i+1) >>> 1) { @@ -71,7 +73,7 @@ public class ExchangeLoops { oneRun(i, iters); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java index 1da7f2335c7..79dc0392f8a 100644 --- a/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java +++ b/jdk/test/java/util/concurrent/ExecutorCompletionService/ExecutorCompletionServiceLoops.java @@ -34,19 +34,21 @@ /* * @test * @bug 4965960 - * @run main/timeout=3600 ExecutorCompletionServiceLoops - * @summary Exercise ExecutorCompletionServiceLoops + * @summary Exercise ExecutorCompletionService + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorCompletionService; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class ExecutorCompletionServiceLoops { - static final int POOLSIZE = 100; + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static final int POOLSIZE = 10; static final ExecutorService pool = Executors.newFixedThreadPool(POOLSIZE); static final ExecutorCompletionService ecs = @@ -55,23 +57,21 @@ public class ExecutorCompletionServiceLoops { public static void main(String[] args) throws Exception { int max = 8; - int base = 10000; + int base = 2000; if (args.length > 0) max = Integer.parseInt(args[0]); System.out.println("Warmup..."); oneTest(base); - Thread.sleep(100); print = true; for (int i = 1; i <= max; i += (i+1) >>> 1) { System.out.print("n: " + i * base); oneTest(i * base); - Thread.sleep(100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java index cbec012cbb9..7e34e28bded 100644 --- a/jdk/test/java/util/concurrent/Executors/AutoShutdown.java +++ b/jdk/test/java/util/concurrent/Executors/AutoShutdown.java @@ -24,26 +24,32 @@ /* * @test * @bug 6399443 - * @run main/othervm/timeout=1000 AutoShutdown * @summary Check for auto-shutdown and gc of singleThreadExecutors + * @library /lib/testlibrary/ + * @run main/othervm/timeout=1000 AutoShutdown * @author Martin Buchholz */ +import static java.util.concurrent.Executors.defaultThreadFactory; +import static java.util.concurrent.Executors.newFixedThreadPool; +import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; +import static java.util.concurrent.Executors.newSingleThreadExecutor; + +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executor; import java.util.concurrent.TimeUnit; -import static java.util.concurrent.Executors.defaultThreadFactory; -import static java.util.concurrent.Executors.newFixedThreadPool; -import static java.util.concurrent.Executors.newSingleThreadScheduledExecutor; -import static java.util.concurrent.Executors.newSingleThreadExecutor; +import jdk.testlibrary.Utils; public class AutoShutdown { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void await(CountDownLatch latch) throws InterruptedException { - if (!latch.await(100L, TimeUnit.SECONDS)) + if (!latch.await(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out waiting for latch"); } diff --git a/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java b/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java index 12a26b84302..b6c645e6018 100644 --- a/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java +++ b/jdk/test/java/util/concurrent/FutureTask/CancelledFutureLoops.java @@ -34,13 +34,14 @@ /* * @test * @bug 4486658 - * @run main/timeout=2000 CancelledFutureLoops * @summary Checks for responsiveness of futures to cancellation. * Runs under the assumption that ITERS computations require more than * TIMEOUT msecs to complete. + * @library /lib/testlibrary/ + * @run main/timeout=2000 CancelledFutureLoops */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.BrokenBarrierException; @@ -51,8 +52,10 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class CancelledFutureLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; @@ -80,7 +83,7 @@ public final class CancelledFutureLoops { Thread.sleep(TIMEOUT); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(6 * LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java index b35de7a3782..7874107d40a 100644 --- a/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java +++ b/jdk/test/java/util/concurrent/FutureTask/DoneMeansDone.java @@ -36,8 +36,11 @@ * @bug 8073704 * @summary Checks that once isDone() returns true, * get() never throws InterruptedException or TimeoutException + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.ArrayList; import java.util.concurrent.Callable; import java.util.concurrent.CountDownLatch; @@ -49,8 +52,11 @@ import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; +import jdk.testlibrary.Utils; public class DoneMeansDone { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + public static void main(String[] args) throws Throwable { final int iters = 1000; final int nThreads = 2; @@ -92,7 +98,7 @@ public class DoneMeansDone { } done.set(true); pool.shutdown(); - if (!pool.awaitTermination(10L, TimeUnit.SECONDS)) + if (!pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError(); for (Future future : futures) future.get(); diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java index 36af2e10e5a..071f7b51b15 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/DelayOverflow.java @@ -35,14 +35,21 @@ * @test * @bug 6725789 * @summary Check for long overflow in task time comparison. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.DAYS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledThreadPoolExecutor; -import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class DelayOverflow { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static void waitForNanoTimeTick() { for (long t0 = System.nanoTime(); t0 == System.nanoTime(); ) ; @@ -52,16 +59,16 @@ public class DelayOverflow { Runnable r, int how) { switch (how) { case 0: - pool.schedule(r, 0, TimeUnit.MILLISECONDS); + pool.schedule(r, 0, MILLISECONDS); break; case 1: - pool.schedule(Executors.callable(r), 0, TimeUnit.DAYS); + pool.schedule(Executors.callable(r), 0, DAYS); break; case 2: - pool.scheduleWithFixedDelay(r, 0, 1000, TimeUnit.NANOSECONDS); + pool.scheduleWithFixedDelay(r, 0, 1000, NANOSECONDS); break; case 3: - pool.scheduleAtFixedRate(r, 0, 1000, TimeUnit.MILLISECONDS); + pool.scheduleAtFixedRate(r, 0, 1000, MILLISECONDS); break; default: fail(String.valueOf(how)); @@ -72,16 +79,16 @@ public class DelayOverflow { Runnable r, int how) { switch (how) { case 0: - pool.schedule(r, Long.MAX_VALUE, TimeUnit.MILLISECONDS); + pool.schedule(r, Long.MAX_VALUE, MILLISECONDS); break; case 1: - pool.schedule(Executors.callable(r), Long.MAX_VALUE, TimeUnit.DAYS); + pool.schedule(Executors.callable(r), Long.MAX_VALUE, DAYS); break; case 2: - pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, TimeUnit.NANOSECONDS); + pool.scheduleWithFixedDelay(r, Long.MAX_VALUE, 1000, NANOSECONDS); break; case 3: - pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, TimeUnit.MILLISECONDS); + pool.scheduleAtFixedRate(r, Long.MAX_VALUE, 1000, MILLISECONDS); break; default: fail(String.valueOf(how)); @@ -114,14 +121,14 @@ public class DelayOverflow { proceedLatch.await(); } catch (Throwable t) { unexpected(t); } }}; - pool.schedule(keepPoolBusy, 0, TimeUnit.SECONDS); + pool.schedule(keepPoolBusy, 0, DAYS); busyLatch.await(); scheduleNow(pool, notifier, nowHow); waitForNanoTimeTick(); scheduleAtTheEndOfTime(pool, neverRuns, thenHow); proceedLatch.countDown(); - check(runLatch.await(10L, TimeUnit.SECONDS)); + check(runLatch.await(LONG_DELAY_MS, MILLISECONDS)); equal(runLatch.getCount(), 0L); pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); @@ -142,10 +149,9 @@ public class DelayOverflow { } catch (Throwable t) { unexpected(t); } }}; pool.scheduleWithFixedDelay(scheduleNowScheduler, - 0, Long.MAX_VALUE, - TimeUnit.NANOSECONDS); + 0, Long.MAX_VALUE, NANOSECONDS); - check(runLatch.await(10L, TimeUnit.SECONDS)); + check(runLatch.await(LONG_DELAY_MS, MILLISECONDS)); equal(runLatch.getCount(), 0L); pool.setExecuteExistingDelayedTasksAfterShutdownPolicy(false); diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java index c39fcc07cf3..76e5eb9a5f8 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/GCRetention.java @@ -34,8 +34,11 @@ /* * @test * @summary Ensure that waiting pool threads don't retain refs to tasks. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.lang.ref.WeakReference; import java.util.concurrent.Delayed; import java.util.concurrent.ExecutionException; @@ -44,8 +47,11 @@ import java.util.concurrent.RunnableScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; +import jdk.testlibrary.Utils; public class GCRetention { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + /** * A custom thread pool with a custom RunnableScheduledFuture, for the * sole purpose of ensuring that the task retains a strong reference to @@ -116,7 +122,7 @@ public class GCRetention { Thread.sleep(10); } pool.shutdown(); - pool.awaitTermination(10L, TimeUnit.SECONDS); + pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); if (cleared < size) throw new Error(String.format ("references to %d/%d tasks retained (\"leaked\")", diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java index fefb46747d4..4aff18e2a25 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCorePoolSize.java @@ -26,16 +26,21 @@ * @bug 7091003 * @summary ScheduledExecutorService never executes Runnable * with corePoolSize of zero + * @library /lib/testlibrary/ * @author Chris Hegarty */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; /** * Verify that tasks can be run even with a core pool size of 0. */ public class ZeroCorePoolSize { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); volatile boolean taskRun; @@ -49,10 +54,10 @@ public class ZeroCorePoolSize { }; check(pool.getCorePoolSize() == 0); - pool.schedule(task, 1, TimeUnit.SECONDS); + pool.schedule(task, 12L, MILLISECONDS); pool.shutdown(); - check(pool.awaitTermination(20L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); check(pool.getCorePoolSize() == 0); check(taskRun); } diff --git a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java index 2a610edbf22..f78c8d854d3 100644 --- a/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java +++ b/jdk/test/java/util/concurrent/ScheduledThreadPoolExecutor/ZeroCoreThreads.java @@ -35,9 +35,11 @@ * @test * @bug 8022642 8065320 8129861 * @summary Ensure relative sanity when zero core threads + * @library /lib/testlibrary/ */ import static java.util.concurrent.TimeUnit.HOURS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.lang.reflect.Field; @@ -45,8 +47,28 @@ import java.util.concurrent.BlockingQueue; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BooleanSupplier; +import jdk.testlibrary.Utils; public class ZeroCoreThreads { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); + } + + static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) { + long startTime = -1L; + while (!predicate.getAsBoolean()) { + if (startTime == -1L) + startTime = System.nanoTime(); + else if (millisElapsedSince(startTime) > timeoutMillis) + throw new AssertionError( + String.format("timed out after %s ms", timeoutMillis)); + Thread.yield(); + } + } + static boolean hasWaiters(ReentrantLock lock, Condition condition) { lock.lock(); try { @@ -56,6 +78,11 @@ public class ZeroCoreThreads { } } + static void awaitHasWaiters(ReentrantLock lock, Condition condition, + long timeoutMillis) { + spinWaitUntil(() -> hasWaiters(lock, condition), timeoutMillis); + } + static T getField(Object x, String fieldName) { try { Field field = x.getClass().getDeclaredField(fieldName); @@ -72,7 +99,7 @@ public class ZeroCoreThreads { test(p); } finally { p.shutdownNow(); - check(p.awaitTermination(10L, SECONDS)); + check(p.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } } @@ -89,13 +116,7 @@ public class ZeroCoreThreads { equal(0L, p.getCompletedTaskCount()); p.schedule(dummy, 1L, HOURS); // Ensure one pool thread actually waits in timed queue poll - long t0 = System.nanoTime(); - while (!hasWaiters(lock, available)) { - if (System.nanoTime() - t0 > SECONDS.toNanos(10L)) - throw new AssertionError - ("timed out waiting for a waiter to show up"); - Thread.yield(); - } + awaitHasWaiters(lock, available, LONG_DELAY_MS); equal(1, p.getPoolSize()); equal(1, p.getLargestPoolSize()); equal(1L, p.getTaskCount()); diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java index 8b80814e1d7..088907cae77 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/CoreThreadTimeOut.java @@ -25,17 +25,22 @@ * @test * @bug 6233235 6268386 * @summary Test allowsCoreThreadTimeOut + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class CoreThreadTimeOut { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class IdentifiableThreadFactory implements ThreadFactory { static ThreadFactory defaultThreadFactory @@ -60,8 +65,8 @@ public class CoreThreadTimeOut { return count; } - static long millisElapsedSince(long t0) { - return (System.nanoTime() - t0) / (1000L * 1000L); + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); } void test(String[] args) throws Throwable { @@ -89,7 +94,7 @@ public class CoreThreadTimeOut { equal(countExecutorThreads(), 0); tpe.shutdown(); check(tpe.allowsCoreThreadTimeOut()); - check(tpe.awaitTermination(10L, TimeUnit.SECONDS)); + check(tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java index 9fded6a58d4..a1a21655b88 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/Custom.java @@ -25,9 +25,12 @@ * @test * @bug 6277663 * @summary Test TPE extensibility framework + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.FutureTask; @@ -37,8 +40,11 @@ import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; +import java.util.function.BooleanSupplier; +import jdk.testlibrary.Utils; public class Custom { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static volatile int passed = 0, failed = 0; static void pass() { passed++; } static void fail() { failed++; Thread.dumpStack(); } @@ -97,6 +103,22 @@ public class Custom { private static final int threadCount = 10; + static long millisElapsedSince(long startTime) { + return (System.nanoTime() - startTime) / (1000L * 1000L); + } + + static void spinWaitUntil(BooleanSupplier predicate, long timeoutMillis) { + long startTime = -1L; + while (!predicate.getAsBoolean()) { + if (startTime == -1L) + startTime = System.nanoTime(); + else if (millisElapsedSince(startTime) > timeoutMillis) + throw new AssertionError( + String.format("timed out after %s ms", timeoutMillis)); + Thread.yield(); + } + } + public static void main(String[] args) throws Throwable { CustomTPE tpe = new CustomTPE(); equal(tpe.getCorePoolSize(), threadCount); @@ -106,9 +128,8 @@ public class Custom { equal(countExecutorThreads(), threadCount); equal(CustomTask.births.get(), threadCount); tpe.shutdown(); - tpe.awaitTermination(120L, TimeUnit.SECONDS); - Thread.sleep(1000); - equal(countExecutorThreads(), 0); + tpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS); + spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS); CustomSTPE stpe = new CustomSTPE(); for (int i = 0; i < threadCount; i++) @@ -116,9 +137,8 @@ public class Custom { equal(CustomSTPE.decorations.get(), threadCount); equal(countExecutorThreads(), threadCount); stpe.shutdown(); - stpe.awaitTermination(120L, TimeUnit.SECONDS); - Thread.sleep(1000); - equal(countExecutorThreads(), 0); + stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS); + spinWaitUntil(() -> countExecutorThreads() == 0, LONG_DELAY_MS); System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed); if (failed > 0) throw new Exception("Some tests failed"); diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java index 325ecef58a2..bb327e817c2 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/FlakyThreadFactory.java @@ -35,14 +35,20 @@ /* * @test * @summary Should be able to shutdown a pool when worker creation failed. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class FlakyThreadFactory { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + void test(String[] args) throws Throwable { test(NullPointerException.class, new ThreadFactory() { @@ -89,7 +95,7 @@ public class FlakyThreadFactory { check(exceptionClass.isInstance(t)); } pool.shutdown(); - check(pool.awaitTermination(10L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } //--------------------- Infrastructure --------------------------- diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java index 9211ff28d95..c93ed9bf4f9 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/SelfInterrupt.java @@ -25,14 +25,20 @@ * @test * @bug 6576792 * @summary non-idle worker threads should not be interrupted + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.CountDownLatch; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class SelfInterrupt { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + void test(String[] args) throws Throwable { final int n = 100; final ThreadPoolExecutor pool = @@ -58,7 +64,7 @@ public class SelfInterrupt { } catch (Throwable t) { unexpected(t); }}}); finishLine.await(); pool.shutdown(); - check(pool.awaitTermination(1000L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } //--------------------- Infrastructure --------------------------- diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java index 1b485867ce2..5d10213dc99 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/ThreadRestarts.java @@ -36,6 +36,7 @@ * @test * @summary Only one thread should be created when a thread needs to * be kept alive to service a delayed task waiting in the queue. + * @library /lib/testlibrary/ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; @@ -44,8 +45,12 @@ import static java.util.concurrent.TimeUnit.SECONDS; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicLong; +import jdk.testlibrary.Utils; public class ThreadRestarts { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static final long FAR_FUTURE_MS = 10 * LONG_DELAY_MS; + public static void main(String[] args) throws Exception { test(false); test(true); @@ -56,14 +61,15 @@ public class ThreadRestarts { ScheduledThreadPoolExecutor stpe = new ScheduledThreadPoolExecutor(10, ctf); try { + // schedule a dummy task in the "far future" Runnable nop = new Runnable() { public void run() {}}; - stpe.schedule(nop, 10*1000L, MILLISECONDS); + stpe.schedule(nop, FAR_FUTURE_MS, MILLISECONDS); stpe.setKeepAliveTime(1L, MILLISECONDS); stpe.allowCoreThreadTimeOut(allowTimeout); - MILLISECONDS.sleep(100L); + MILLISECONDS.sleep(12L); } finally { stpe.shutdownNow(); - if (!stpe.awaitTermination(60L, SECONDS)) + if (!stpe.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new AssertionError("timed out"); } if (ctf.count.get() > 1) @@ -76,8 +82,9 @@ public class ThreadRestarts { final AtomicLong count = new AtomicLong(0L); public Thread newThread(Runnable r) { - Thread t = new Thread(r); count.getAndIncrement(); + Thread t = new Thread(r); + t.setDaemon(true); return t; } } diff --git a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java index 8778b401d27..463d388b5da 100644 --- a/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java +++ b/jdk/test/java/util/concurrent/ThreadPoolExecutor/TimeOutShrink.java @@ -25,15 +25,22 @@ * @test * @bug 6458662 * @summary poolSize might shrink below corePoolSize after timeout + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.concurrent.CyclicBarrier; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; +import jdk.testlibrary.Utils; public class TimeOutShrink { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static final long KEEPALIVE_MS = 12L; + static void checkPoolSizes(ThreadPoolExecutor pool, int size, int core, int max) { equal(pool.getPoolSize(), size); @@ -45,7 +52,8 @@ public class TimeOutShrink { final int n = 4; final CyclicBarrier barrier = new CyclicBarrier(2*n+1); final ThreadPoolExecutor pool - = new ThreadPoolExecutor(n, 2*n, 1L, TimeUnit.SECONDS, + = new ThreadPoolExecutor(n, 2*n, + KEEPALIVE_MS, MILLISECONDS, new SynchronousQueue()); final Runnable r = new Runnable() { public void run() { try { @@ -58,12 +66,16 @@ public class TimeOutShrink { barrier.await(); checkPoolSizes(pool, 2*n, n, 2*n); barrier.await(); - while (pool.getPoolSize() > n) - Thread.sleep(100); - Thread.sleep(100); + long nap = KEEPALIVE_MS + (KEEPALIVE_MS >> 2); + for (long sleepyTime = 0L; pool.getPoolSize() > n; ) { + check((sleepyTime += nap) <= LONG_DELAY_MS); + Thread.sleep(nap); + } + checkPoolSizes(pool, n, n, 2*n); + Thread.sleep(nap); checkPoolSizes(pool, n, n, 2*n); pool.shutdown(); - check(pool.awaitTermination(60L, TimeUnit.SECONDS)); + check(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } //--------------------- Infrastructure --------------------------- diff --git a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java index a8f7bbe5daf..2e3d4b28e12 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java +++ b/jdk/test/java/util/concurrent/locks/Lock/CheckedLockLoops.java @@ -35,9 +35,10 @@ * @test * @bug 4486658 * @summary basic safety and liveness of ReentrantLocks, and other locks based on them + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; @@ -47,8 +48,10 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import jdk.testlibrary.Utils; public final class CheckedLockLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static ExecutorService pool; static final SplittableRandom rnd = new SplittableRandom(); @@ -63,7 +66,7 @@ public final class CheckedLockLoops { oneTest(i, iters / i); } pool.shutdown(); - if (! pool.awaitTermination(10L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); pool = null; } diff --git a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java index cf1605197cf..82f9ead09f5 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java +++ b/jdk/test/java/util/concurrent/locks/Lock/FlakyMutex.java @@ -25,9 +25,12 @@ * @test * @bug 6503247 6574123 * @summary Test resilience to tryAcquire methods that throw + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.Random; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; @@ -36,6 +39,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.AbstractQueuedLongSynchronizer; import java.util.concurrent.locks.Condition; import java.util.concurrent.locks.Lock; +import jdk.testlibrary.Utils; /** * This uses a variant of the standard Mutex demo, except with a @@ -44,6 +48,7 @@ import java.util.concurrent.locks.Lock; */ @SuppressWarnings("serial") public class FlakyMutex implements Lock { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static class MyError extends Error {} static class MyException extends Exception {} static class MyRuntimeException extends RuntimeException {} @@ -91,7 +96,7 @@ public class FlakyMutex implements Lock { } catch (Throwable t) { unexpected(t); }}});} barrier.await(); es.shutdown(); - check(es.awaitTermination(30L, TimeUnit.SECONDS)); + check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } private static class FlakySync extends AbstractQueuedLongSynchronizer { diff --git a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java index a3440ec8b8d..7d6da0b255e 100644 --- a/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java +++ b/jdk/test/java/util/concurrent/locks/Lock/TimedAcquireLeak.java @@ -25,9 +25,11 @@ * @test * @bug 6460501 6236036 6500694 6490770 * @summary Repeated failed timed waits shouldn't leak memory + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; @@ -54,8 +56,11 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; import java.util.regex.Matcher; import java.util.regex.Pattern; +import jdk.testlibrary.Utils; public class TimedAcquireLeak { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); + static String javahome() { String jh = System.getProperty("java.home"); return (jh.endsWith("jre")) ? jh.substring(0, jh.length() - 4) : jh; @@ -191,7 +196,7 @@ public class TimedAcquireLeak { final String[] jobCmd = { java, "-Xmx8m", "-XX:+UsePerfData", - "-classpath", System.getProperty("test.classes", "."), + "-classpath", System.getProperty("test.class.path"), childClassName, uniqueID }; final Process p = new ProcessBuilder(jobCmd).start(); @@ -219,7 +224,7 @@ public class TimedAcquireLeak { check(Math.abs(n1 - n0) < 10); check(n1 < 25); drainers.shutdown(); - if (!drainers.awaitTermination(10L, SECONDS)) { + if (!drainers.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) { drainers.shutdownNow(); // last resort throw new AssertionError("thread pool did not terminate"); } diff --git a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java index 1b098ea953e..5a078a83ea5 100644 --- a/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java +++ b/jdk/test/java/util/concurrent/locks/LockSupport/ParkLoops.java @@ -35,11 +35,12 @@ * @test * @bug 8074773 * @summary Stress test looks for lost unparks + * @library /lib/testlibrary/ * @modules java.management - * @run main/timeout=1200 ParkLoops */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.lang.management.ManagementFactory; import java.lang.management.ThreadInfo; import java.util.SplittableRandom; @@ -49,13 +50,12 @@ import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicLong; import java.util.concurrent.atomic.AtomicReferenceArray; import java.util.concurrent.locks.LockSupport; +import jdk.testlibrary.Utils; public final class ParkLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int THREADS = 4; - // static final int ITERS = 2_000_000; - // static final int TIMEOUT = 3500; // in seconds - static final int ITERS = 100_000; - static final int TIMEOUT = 1000; // in seconds + static final int ITERS = 30_000; static class Parker implements Runnable { static { @@ -130,13 +130,13 @@ public final class ParkLoops { pool.submit(unparker); } try { - if (!done.await(TIMEOUT, SECONDS)) { + if (!done.await(LONG_DELAY_MS, MILLISECONDS)) { dumpAllStacks(); throw new AssertionError("lost unpark"); } } finally { pool.shutdown(); - pool.awaitTermination(10L, SECONDS); + pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS); } } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java index b8d49c73863..de9f765b733 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/LockOncePerThreadLoops.java @@ -34,25 +34,27 @@ /* * @test * @bug 4486658 - * @run main/timeout=15000 LockOncePerThreadLoops * @summary Checks for missed signals by locking and unlocking each of an array of locks once per thread + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class LockOncePerThreadLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; - static int nlocks = 50000; - static int nthreads = 100; - static int replications = 5; + static int nlocks = 20_000; + static int nthreads = 20; + static int replications = 3; public static void main(String[] args) throws Exception { if (args.length > 0) @@ -66,10 +68,9 @@ public final class LockOncePerThreadLoops { for (int i = 0; i < replications; ++i) { System.out.print("Iteration: " + i); new ReentrantLockLoop().test(); - Thread.sleep(100); } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java index 9e6ed4533f7..8534a391594 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/SimpleReentrantLockLoops.java @@ -34,23 +34,25 @@ /* * @test * @bug 4486658 - * @run main/timeout=4500 SimpleReentrantLockLoops * @summary multiple threads using a single lock + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class SimpleReentrantLockLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; - static int iters = 1000000; + static int iters = 100_000; public static void main(String[] args) throws Exception { int maxThreads = 5; @@ -66,11 +68,10 @@ public final class SimpleReentrantLockLoops { while (n-- > 0) { System.out.print("Threads: " + i); new ReentrantLockLoop(i).test(); - Thread.sleep(100); } } pool.shutdown(); - if (! pool.awaitTermination(60L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java index 3e4e0cfb059..8dc02e4f570 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantLock/TimeoutLockLoops.java @@ -34,18 +34,22 @@ /* * @test * @bug 4486658 5031862 8140471 - * @run main TimeoutLockLoops * @summary Checks for responsiveness of locks to timeouts. + * @library /lib/testlibrary/ */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; +import jdk.testlibrary.Utils; public final class TimeoutLockLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final ExecutorService pool = Executors.newCachedThreadPool(); static final SplittableRandom rnd = new SplittableRandom(); static boolean print = false; @@ -63,7 +67,7 @@ public final class TimeoutLockLoops { new ReentrantLockLoop(i).test(); } pool.shutdown(); - if (! pool.awaitTermination(60L, TimeUnit.SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java index 6341a817257..e6e094ac76b 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/Count.java @@ -25,9 +25,12 @@ * @test * @bug 6207928 6328220 6378321 6625723 * @summary Recursive lock invariant sanity checks + * @library /lib/testlibrary/ * @author Martin Buchholz */ +import static java.util.concurrent.TimeUnit.MILLISECONDS; + import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -42,9 +45,11 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantReadWriteLock; +import jdk.testlibrary.Utils; // I am the Cownt, and I lahve to cownt. public class Count { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); final Random rnd = new Random(); void lock(Lock lock) { @@ -102,7 +107,7 @@ public class Count { barrier.await(); } catch (Throwable t) { unexpected(t); }}});} es.shutdown(); - check(es.awaitTermination(10L, TimeUnit.SECONDS)); + check(es.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); } void testReentrantLocks(final boolean fair, diff --git a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java index f82327ac8a4..4c44f6a2dbe 100644 --- a/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java +++ b/jdk/test/java/util/concurrent/locks/ReentrantReadWriteLock/MapLoops.java @@ -41,17 +41,20 @@ * inserts it, and if present, with probability premove it removes * it. (pinsert and premove are expressed as percentages to simplify * parsing from command line.) + * @library /lib/testlibrary/ */ -import static java.util.concurrent.TimeUnit.SECONDS; +import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.Map; import java.util.SplittableRandom; import java.util.concurrent.CyclicBarrier; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; +import jdk.testlibrary.Utils; public class MapLoops { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static final int NKEYS = 100000; static int pinsert = 60; static int premove = 2; @@ -125,7 +128,7 @@ public class MapLoops { map.clear(); } pool.shutdown(); - if (! pool.awaitTermination(10L, SECONDS)) + if (! pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)) throw new Error(); } diff --git a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java index dde4fed0030..ea90f3c03de 100644 --- a/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java +++ b/jdk/test/java/util/concurrent/locks/StampedLock/Basic.java @@ -35,6 +35,7 @@ * @test * @bug 8005697 * @summary Basic tests for StampedLock + * @library /lib/testlibrary/ * @author Chris Hegarty */ @@ -49,8 +50,10 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.StampedLock; +import jdk.testlibrary.Utils; public class Basic { + static final long LONG_DELAY_MS = Utils.adjustTimeout(10_000); static void checkResult(Locker l, Class c) { Throwable t = l.thrown(); @@ -268,7 +271,7 @@ public class Basic { case 2: case 5: return interruptibleReader(sl, -1, SECONDS, gate, view ^= true); default: - return interruptibleReader(sl, 30, SECONDS, gate, view ^= true); }} + return interruptibleReader(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; } @@ -286,7 +289,7 @@ public class Basic { case 2: case 5: return interruptibleWriter(sl, -1, SECONDS, gate, view ^= true); default: - return interruptibleWriter(sl, 30, SECONDS, gate, view ^= true); }} + return interruptibleWriter(sl, LONG_DELAY_MS, MILLISECONDS, gate, view ^= true); }} public void remove() {throw new UnsupportedOperationException();}}; } @@ -454,13 +457,13 @@ public class Basic { // We test interrupting both before and after trying to acquire boolean view = false; StampedLock sl = new StampedLock(); - for (long timeout : new long[] { -1L, 30L, -1L, 30L }) { + for (long timeout : new long[] { -1L, LONG_DELAY_MS, -1L, LONG_DELAY_MS }) { long stamp; Thread.State state; stamp = sl.writeLock(); try { - Reader r = interruptibleReader(sl, timeout, SECONDS, null, view); + Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view); r.start(); r.interrupt(); r.join(); @@ -471,7 +474,7 @@ public class Basic { stamp = sl.writeLock(); try { - Reader r = interruptibleReader(sl, timeout, SECONDS, null, view); + Reader r = interruptibleReader(sl, timeout, MILLISECONDS, null, view); r.start(); waitForThreadToBlock(r); r.interrupt(); @@ -483,7 +486,7 @@ public class Basic { stamp = sl.readLock(); try { - Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view); + Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view); w.start(); w.interrupt(); w.join(); @@ -494,7 +497,7 @@ public class Basic { stamp = sl.readLock(); try { - Writer w = interruptibleWriter(sl, timeout, SECONDS, null, view); + Writer w = interruptibleWriter(sl, timeout, MILLISECONDS, null, view); w.start(); waitForThreadToBlock(w); w.interrupt(); @@ -509,7 +512,7 @@ public class Basic { check(!sl.tryUnlockRead()); check(!sl.tryUnlockWrite()); check(sl.tryOptimisticRead() != 0L); - if (timeout == 30L) + if (timeout == LONG_DELAY_MS) view = true; } } catch (Throwable t) { unexpected(t); } diff --git a/jdk/test/java/util/concurrent/tck/Collection8Test.java b/jdk/test/java/util/concurrent/tck/Collection8Test.java index 1a10b280228..36f99e157dc 100644 --- a/jdk/test/java/util/concurrent/tck/Collection8Test.java +++ b/jdk/test/java/util/concurrent/tck/Collection8Test.java @@ -37,6 +37,7 @@ import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; @@ -98,26 +99,29 @@ public class Collection8Test extends JSR166TestCase { public void testForEachConcurrentStressTest() throws Throwable { if (!impl.isConcurrent()) return; final Collection c = impl.emptyCollection(); - final long testDurationMillis = SHORT_DELAY_MS; + final long testDurationMillis = timeoutMillis(); final AtomicBoolean done = new AtomicBoolean(false); final Object elt = impl.makeElement(1); - ExecutorService pool = Executors.newCachedThreadPool(); - Runnable checkElt = () -> { - while (!done.get()) - c.stream().forEach((x) -> { assertSame(x, elt); }); }; - Runnable addRemove = () -> { - while (!done.get()) { - assertTrue(c.add(elt)); - assertTrue(c.remove(elt)); - }}; - Future f1 = pool.submit(checkElt); - Future f2 = pool.submit(addRemove); - Thread.sleep(testDurationMillis); - done.set(true); - pool.shutdown(); - assertTrue(pool.awaitTermination(LONG_DELAY_MS, MILLISECONDS)); - assertNull(f1.get(LONG_DELAY_MS, MILLISECONDS)); - assertNull(f2.get(LONG_DELAY_MS, MILLISECONDS)); + final Future f1, f2; + final ExecutorService pool = Executors.newCachedThreadPool(); + try (PoolCleaner cleaner = cleaner(pool, done)) { + final CountDownLatch threadsStarted = new CountDownLatch(2); + Runnable checkElt = () -> { + threadsStarted.countDown(); + while (!done.get()) + c.stream().forEach((x) -> { assertSame(x, elt); }); }; + Runnable addRemove = () -> { + threadsStarted.countDown(); + while (!done.get()) { + assertTrue(c.add(elt)); + assertTrue(c.remove(elt)); + }}; + f1 = pool.submit(checkElt); + f2 = pool.submit(addRemove); + Thread.sleep(testDurationMillis); + } + assertNull(f1.get(0L, MILLISECONDS)); + assertNull(f2.get(0L, MILLISECONDS)); } // public void testCollection8DebugFail() { fail(); } diff --git a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java index 69b2c93d0af..78e7d684046 100644 --- a/jdk/test/java/util/concurrent/tck/JSR166TestCase.java +++ b/jdk/test/java/util/concurrent/tck/JSR166TestCase.java @@ -88,6 +88,7 @@ import java.util.concurrent.Semaphore; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -210,11 +211,31 @@ public class JSR166TestCase extends TestCase { private static final int suiteRuns = Integer.getInteger("jsr166.suiteRuns", 1); + private static float systemPropertyValue(String name, float defaultValue) { + String floatString = System.getProperty(name); + if (floatString == null) + return defaultValue; + try { + return Float.parseFloat(floatString); + } catch (NumberFormatException ex) { + throw new IllegalArgumentException( + String.format("Bad float value in system property %s=%s", + name, floatString)); + } + } + /** * The scaling factor to apply to standard delays used in tests. */ - private static final int delayFactor = - Integer.getInteger("jsr166.delay.factor", 1); + private static final float delayFactor = + systemPropertyValue("jsr166.delay.factor", 1.0f); + + /** + * The timeout factor as used in the jtreg test harness. + * See: http://openjdk.java.net/jtreg/tag-spec.html + */ + private static final float jtregTestTimeoutFactor + = systemPropertyValue("test.timeout.factor", 1.0f); public JSR166TestCase() { super(); } public JSR166TestCase(String name) { super(name); } @@ -590,10 +611,12 @@ public class JSR166TestCase extends TestCase { /** * Returns the shortest timed delay. This can be scaled up for - * slow machines using the jsr166.delay.factor system property. + * slow machines using the jsr166.delay.factor system property, + * or via jtreg's -timeoutFactor: flag. + * http://openjdk.java.net/jtreg/command-help.html */ protected long getShortDelay() { - return 50 * delayFactor; + return (long) (50 * delayFactor * jtregTestTimeoutFactor); } /** @@ -906,6 +929,14 @@ public class JSR166TestCase extends TestCase { }}; } + PoolCleaner cleaner(ExecutorService pool, AtomicBoolean flag) { + return new PoolCleanerWithReleaser(pool, releaser(flag)); + } + + Runnable releaser(final AtomicBoolean flag) { + return new Runnable() { public void run() { flag.set(true); }}; + } + /** * Waits out termination of a thread pool or fails doing so. */ @@ -1462,16 +1493,20 @@ public class JSR166TestCase extends TestCase { return new LatchAwaiter(latch); } - public void await(CountDownLatch latch) { + public void await(CountDownLatch latch, long timeoutMillis) { try { - if (!latch.await(LONG_DELAY_MS, MILLISECONDS)) + if (!latch.await(timeoutMillis, MILLISECONDS)) fail("timed out waiting for CountDownLatch for " - + (LONG_DELAY_MS/1000) + " sec"); + + (timeoutMillis/1000) + " sec"); } catch (Throwable fail) { threadUnexpectedException(fail); } } + public void await(CountDownLatch latch) { + await(latch, LONG_DELAY_MS); + } + public void await(Semaphore semaphore) { try { if (!semaphore.tryAcquire(LONG_DELAY_MS, MILLISECONDS)) diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java index 50b7b171140..ead869ed648 100644 --- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorSubclassTest.java @@ -32,6 +32,7 @@ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; @@ -55,7 +56,9 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import junit.framework.Test; import junit.framework.TestSuite; @@ -226,52 +229,75 @@ public class ScheduledExecutorSubclassTest extends JSR166TestCase { } /** - * scheduleAtFixedRate executes series of tasks at given rate + * scheduleAtFixedRate executes series of tasks at given rate. + * Eventually, it must hold that: + * cycles - 1 <= elapsedMillis/delay < cycles */ public void testFixedRateSequence() throws InterruptedException { final CustomExecutor p = new CustomExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { + final Runnable task = new CheckedRunnable() { public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final ScheduledFuture periodicTask = p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (elapsedMillis <= cycles * delay) return; + // else retry with longer delay } fail("unexpected execution rate"); } } /** - * scheduleWithFixedDelay executes series of tasks with given period + * scheduleWithFixedDelay executes series of tasks with given period. + * Eventually, it must hold that each task starts at least delay and at + * most 2 * delay after the termination of the previous task. */ public void testFixedDelaySequence() throws InterruptedException { final CustomExecutor p = new CustomExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final AtomicLong previous = new AtomicLong(startTime); + final AtomicBoolean tryLongerDelay = new AtomicBoolean(false); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { - public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final int d = delay; + final Runnable task = new CheckedRunnable() { + public void realRun() { + long now = System.nanoTime(); + long elapsedMillis + = NANOSECONDS.toMillis(now - previous.get()); + if (done.getCount() == cycles) { // first execution + if (elapsedMillis >= d) + tryLongerDelay.set(true); + } else { + assertTrue(elapsedMillis >= d); + if (elapsedMillis >= 2 * d) + tryLongerDelay.set(true); + } + previous.set(now); + done.countDown(); + }}; + final ScheduledFuture periodicTask = p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + cycles * LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (!tryLongerDelay.get()) return; + // else retry with longer delay } fail("unexpected execution rate"); } diff --git a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java index 797dee3a845..53ebc5ea179 100644 --- a/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java +++ b/jdk/test/java/util/concurrent/tck/ScheduledExecutorTest.java @@ -34,6 +34,7 @@ */ import static java.util.concurrent.TimeUnit.MILLISECONDS; +import static java.util.concurrent.TimeUnit.NANOSECONDS; import static java.util.concurrent.TimeUnit.SECONDS; import java.util.ArrayList; @@ -52,7 +53,9 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; import junit.framework.Test; import junit.framework.TestSuite; @@ -170,52 +173,75 @@ public class ScheduledExecutorTest extends JSR166TestCase { } /** - * scheduleAtFixedRate executes series of tasks at given rate + * scheduleAtFixedRate executes series of tasks at given rate. + * Eventually, it must hold that: + * cycles - 1 <= elapsedMillis/delay < cycles */ public void testFixedRateSequence() throws InterruptedException { final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { + final Runnable task = new CheckedRunnable() { public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final ScheduledFuture periodicTask = p.scheduleAtFixedRate(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (elapsedMillis <= cycles * delay) return; + // else retry with longer delay } fail("unexpected execution rate"); } } /** - * scheduleWithFixedDelay executes series of tasks with given period + * scheduleWithFixedDelay executes series of tasks with given period. + * Eventually, it must hold that each task starts at least delay and at + * most 2 * delay after the termination of the previous task. */ public void testFixedDelaySequence() throws InterruptedException { final ScheduledThreadPoolExecutor p = new ScheduledThreadPoolExecutor(1); try (PoolCleaner cleaner = cleaner(p)) { for (int delay = 1; delay <= LONG_DELAY_MS; delay *= 3) { - long startTime = System.nanoTime(); - int cycles = 10; + final long startTime = System.nanoTime(); + final AtomicLong previous = new AtomicLong(startTime); + final AtomicBoolean tryLongerDelay = new AtomicBoolean(false); + final int cycles = 8; final CountDownLatch done = new CountDownLatch(cycles); - Runnable task = new CheckedRunnable() { - public void realRun() { done.countDown(); }}; - ScheduledFuture h = + final int d = delay; + final Runnable task = new CheckedRunnable() { + public void realRun() { + long now = System.nanoTime(); + long elapsedMillis + = NANOSECONDS.toMillis(now - previous.get()); + if (done.getCount() == cycles) { // first execution + if (elapsedMillis >= d) + tryLongerDelay.set(true); + } else { + assertTrue(elapsedMillis >= d); + if (elapsedMillis >= 2 * d) + tryLongerDelay.set(true); + } + previous.set(now); + done.countDown(); + }}; + final ScheduledFuture periodicTask = p.scheduleWithFixedDelay(task, 0, delay, MILLISECONDS); - await(done); - h.cancel(true); - double normalizedTime = - (double) millisElapsedSince(startTime) / delay; - if (normalizedTime >= cycles - 1 && - normalizedTime <= cycles) + final int totalDelayMillis = (cycles - 1) * delay; + await(done, totalDelayMillis + cycles * LONG_DELAY_MS); + periodicTask.cancel(true); + final long elapsedMillis = millisElapsedSince(startTime); + assertTrue(elapsedMillis >= totalDelayMillis); + if (!tryLongerDelay.get()) return; + // else retry with longer delay } fail("unexpected execution rate"); } diff --git a/jdk/test/java/util/concurrent/tck/ThreadTest.java b/jdk/test/java/util/concurrent/tck/ThreadTest.java index 939d590beb9..92b2aca52a6 100644 --- a/jdk/test/java/util/concurrent/tck/ThreadTest.java +++ b/jdk/test/java/util/concurrent/tck/ThreadTest.java @@ -77,7 +77,7 @@ public class ThreadTest extends JSR166TestCase { */ public void testGetAndSetDefaultUncaughtExceptionHandler() { assertEquals(null, Thread.getDefaultUncaughtExceptionHandler()); - // failure due to securityException is OK. + // failure due to SecurityException is OK. // Would be nice to explicitly test both ways, but cannot yet. Thread.UncaughtExceptionHandler defaultHandler = Thread.getDefaultUncaughtExceptionHandler(); diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java new file mode 100644 index 00000000000..a520d316a58 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarAPI.java @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the extended API and the aliasing additions in JarFile that + * support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarAPI + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Arrays; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import jdk.Version; + +import static java.util.jar.JarFile.Release; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + + +public class MultiReleaseJarAPI { + + static final int MAJOR_VERSION = Version.current().major(); + + String userdir = System.getProperty("user.dir","."); + File unversioned = new File(userdir, "unversioned.jar"); + File multirelease = new File(userdir, "multi-release.jar"); + File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + Release[] values = JarFile.Release.values(); + + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildUnversionedJar(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(unversioned.toPath()); + Files.delete(multirelease.toPath()); + Files.delete(signedmultirelease.toPath()); + } + + @Test + public void isMultiReleaseJar() throws Exception { + try (JarFile jf = new JarFile(unversioned)) { + Assert.assertFalse(jf.isMultiRelease()); + } + + try (JarFile jf = new JarFile(multirelease)) { + Assert.assertTrue(jf.isMultiRelease()); + } + } + + @Test + public void testVersioning() throws Exception { + // multi-release jar + JarFile jar = new JarFile(multirelease); + Assert.assertEquals(Release.BASE, jar.getVersion()); + jar.close(); + + for (Release value : values) { + System.err.println("test versioning for Release " + value); + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, value)) { + Assert.assertEquals(value, jf.getVersion()); + } + } + + // regular, unversioned, jar + for (Release value : values) { + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, value)) { + Assert.assertEquals(Release.BASE, jf.getVersion()); + } + } + + // assure that we have a Release object corresponding to the actual runtime version + String version = "VERSION_" + MAJOR_VERSION; + boolean runtimeVersionExists = false; + for (Release value : values) { + if (version.equals(value.name())) runtimeVersionExists = true; + } + Assert.assertTrue(runtimeVersionExists); + } + + @Test + public void testAliasing() throws Exception { + for (Release value : values) { + System.err.println("test aliasing for Release " + value); + String name = value.name(); + String prefix; + if (name.equals("BASE")) { + prefix = ""; + } else if (name.equals("RUNTIME")) { + prefix = "META-INF/versions/" + MAJOR_VERSION + "/"; + } else { + prefix = "META-INF/versions/" + name.substring(8) + "/"; + } + // test both multi-release jars + readAndCompare(multirelease, value, "README", prefix + "README"); + readAndCompare(multirelease, value, "version/Version.class", prefix + "version/Version.class"); + // and signed multi-release jars + readAndCompare(signedmultirelease, value, "README", prefix + "README"); + readAndCompare(signedmultirelease, value, "version/Version.class", prefix + "version/Version.class"); + } + } + + private void readAndCompare(File jar, Release version, String name, String realName) throws Exception { + byte[] baseBytes; + byte[] versionedBytes; + try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, Release.BASE)) { + ZipEntry ze = jf.getEntry(realName); + try (InputStream is = jf.getInputStream(ze)) { + baseBytes = is.readAllBytes(); + } + } + assert baseBytes.length > 0; + + try (JarFile jf = new JarFile(jar, true, ZipFile.OPEN_READ, version)) { + ZipEntry ze = jf.getEntry(name); + try (InputStream is = jf.getInputStream(ze)) { + versionedBytes = is.readAllBytes(); + } + } + assert versionedBytes.length > 0; + + Assert.assertTrue(Arrays.equals(baseBytes, versionedBytes)); + } + + @Test + public void testNames() throws Exception { + String rname = "version/Version.class"; + String vname = "META-INF/versions/9/version/Version.class"; + ZipEntry ze1; + ZipEntry ze2; + try (JarFile jf = new JarFile(multirelease)) { + ze1 = jf.getEntry(vname); + } + Assert.assertEquals(ze1.getName(), vname); + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + ze2 = jf.getEntry(rname); + } + Assert.assertEquals(ze2.getName(), rname); + Assert.assertNotEquals(ze1.getName(), ze2.getName()); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java new file mode 100644 index 00000000000..f80991d09d5 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarHttpProperties.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the System properties for JarFile that support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarHttpProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarHttpProperties + */ + +import com.sun.net.httpserver.*; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarHttpProperties extends MultiReleaseJarProperties { + private SimpleHttpServer server; + + @BeforeClass + public void initialize() throws Exception { + server = new SimpleHttpServer(); + server.start(); + super.initialize(); + } + + @Override + protected void initializeClassLoader() throws Exception { + URL[] urls = new URL[]{ + new URL("http://localhost:" + server.getPort() + "/multi-release-jar") + }; + cldr = new URLClassLoader(urls); + // load any class, Main is convenient and in the root entries + rootClass = cldr.loadClass("version.Main"); + } + + @AfterClass + public void close() throws IOException { + // Windows requires server to stop before file is deleted + if (server != null) + server.stop(); + super.close(); + } + + /* + * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader + */ + + @Test + public void testURLClassLoader() throws Throwable { + Class vcls = cldr.loadClass("version.Version"); + invokeMethod(vcls, rtVersion); + } + + @Test + public void testGetResourceAsStream() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResourceAsStream(rootClass, resource); + } + + @Test + public void testGetResource() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResource(rootClass, resource); + } +} + +/** + * Extremely simple server that only performs one task. The server listens for + * requests on the ephemeral port. If it sees a request that begins with + * "/multi-release-jar", it consumes the request and returns a stream of bytes + * representing the jar file multi-release.jar found in "userdir". + */ +class SimpleHttpServer { + private static final String userdir = System.getProperty("user.dir", "."); + private static final Path multirelease = Paths.get(userdir, "multi-release.jar"); + + private final HttpServer server; + + public SimpleHttpServer() throws IOException { + server = HttpServer.create(); + } + + public void start() throws IOException { + server.bind(new InetSocketAddress(0), 0); + server.createContext("/multi-release-jar", t -> { + try (InputStream is = t.getRequestBody()) { + is.readAllBytes(); // probably not necessary to consume request + byte[] bytes = Files.readAllBytes(multirelease); + t.sendResponseHeaders(200, bytes.length); + try (OutputStream os = t.getResponseBody()) { + os.write(bytes); + } + } + }); + server.setExecutor(null); // creates a default executor + server.start(); + } + + public void stop() { + server.stop(0); + } + + int getPort() { + return server.getAddress().getPort(); + } +} + diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java new file mode 100644 index 00000000000..59900cf3f7a --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarIterators.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the extended API and the aliasing additions in JarFile that + * support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarIterators + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.util.Enumeration; +import java.util.HashMap; +import java.util.Map; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.stream.Collectors; +import java.util.zip.ZipFile; +import jdk.Version; + +import static java.util.jar.JarFile.Release; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + + +public class MultiReleaseJarIterators { + + static final int MAJOR_VERSION = Version.current().major(); + + String userdir = System.getProperty("user.dir", "."); + File unversioned = new File(userdir, "unversioned.jar"); + File multirelease = new File(userdir, "multi-release.jar"); + Map uvEntries = new HashMap<>(); + Map mrEntries = new HashMap<>(); + Map baseEntries = new HashMap<>(); + Map v9Entries = new HashMap<>(); + Map v10Entries = new HashMap<>(); + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildUnversionedJar(); + creator.buildMultiReleaseJar(); + + try (JarFile jf = new JarFile(multirelease)) { + for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { + JarEntry je = e.nextElement(); + String name = je.getName(); + mrEntries.put(name, je); + if (name.startsWith("META-INF/versions/")) { + if (name.startsWith("META-INF/versions/9/")) { + v9Entries.put(name.substring(20), je); + } else if (name.startsWith("META-INF/versions/10/")) { + v10Entries.put(name.substring(21), je); + } + } else { + baseEntries.put(name, je); + } + } + } + Assert.assertEquals(mrEntries.size(), 14); + Assert.assertEquals(baseEntries.size(), 6); + Assert.assertEquals(v9Entries.size(), 5); + Assert.assertEquals(v10Entries.size(), 3); + + try (JarFile jf = new JarFile(unversioned)) { + jf.entries().asIterator().forEachRemaining(je -> uvEntries.put(je.getName(), je)); + } + Assert.assertEquals(uvEntries.size(), 6); + } + + @AfterClass + public void close() throws IOException { + Files.delete(unversioned.toPath()); + Files.delete(multirelease.toPath()); + } + + @Test + public void testMultiReleaseJar() throws IOException { + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ)) { + testEnumeration(jf, mrEntries); + testStream(jf, mrEntries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.BASE)) { + testEnumeration(jf, baseEntries); + testStream(jf, baseEntries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + testEnumeration(jf, v9Entries); + testStream(jf, v9Entries); + } + + try (JarFile jf = new JarFile(multirelease, true, ZipFile.OPEN_READ, Release.RUNTIME)) { + Map expectedEntries; + switch (MAJOR_VERSION) { + case 9: + expectedEntries = v9Entries; + break; + case 10: // won't get here until JDK 10 + expectedEntries = v10Entries; + break; + default: + expectedEntries = baseEntries; + break; + } + + testEnumeration(jf, expectedEntries); + testStream(jf, expectedEntries); + } + } + + @Test + public void testUnversionedJar() throws IOException { + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.BASE)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.VERSION_9)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + + try (JarFile jf = new JarFile(unversioned, true, ZipFile.OPEN_READ, Release.RUNTIME)) { + testEnumeration(jf, uvEntries); + testStream(jf, uvEntries); + } + } + + private void testEnumeration(JarFile jf, Map expectedEntries) { + Map actualEntries = new HashMap<>(); + for (Enumeration e = jf.entries(); e.hasMoreElements(); ) { + JarEntry je = e.nextElement(); + actualEntries.put(je.getName(), je); + } + + testEntries(jf, actualEntries, expectedEntries); + } + + + private void testStream(JarFile jf, Map expectedEntries) { + Map actualEntries = jf.stream().collect(Collectors.toMap(je -> je.getName(), je -> je)); + + testEntries(jf, actualEntries, expectedEntries); + } + + private void testEntries(JarFile jf, Map actualEntries, Map expectedEntries) { + /* For multi-release jar files constructed with a Release object, + * actualEntries contain versionedEntries that are considered part of the + * public API. They have a 1-1 correspondence with baseEntries, + * so entries that are not part of the public API won't be present, + * i.e. those entries with a name that starts with version/PackagePrivate + * in this particular jar file (multi-release.jar) + */ + + Map entries; + if (expectedEntries == mrEntries) { + Assert.assertEquals(actualEntries.size(), mrEntries.size()); + entries = mrEntries; + } else if (expectedEntries == uvEntries) { + Assert.assertEquals(actualEntries.size(), uvEntries.size()); + entries = uvEntries; + } else { + Assert.assertEquals(actualEntries.size(), baseEntries.size()); // this is correct + entries = baseEntries; + } + + entries.keySet().forEach(name -> { + JarEntry ee = expectedEntries.get(name); + if (ee == null) ee = entries.get(name); + JarEntry ae = actualEntries.get(name); + try { + compare(jf, ae, ee); + } catch (IOException x) { + throw new RuntimeException(x); + } + }); + } + + private void compare(JarFile jf, JarEntry actual, JarEntry expected) throws IOException { + byte[] abytes; + byte[] ebytes; + + try (InputStream is = jf.getInputStream(actual)) { + abytes = is.readAllBytes(); + } + + try (InputStream is = jf.getInputStream(expected)) { + ebytes = is.readAllBytes(); + } + + Assert.assertEquals(abytes, ebytes); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java new file mode 100644 index 00000000000..6bf059fb8ea --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarProperties.java @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test the System properties for JarFile that support multi-release jar files + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=0 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=100 MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=8 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=9 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.version=10 -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=false MultiReleaseJarProperties + * @run testng/othervm -Djdk.util.jar.enableMultiRelease=force MultiReleaseJarProperties + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; +import java.net.URL; +import java.net.URLClassLoader; +import java.nio.file.Files; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import jdk.Version; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarProperties { + + static final int MAJOR_VERSION = Version.current().major(); + + final static int ROOTVERSION = 8; // magic number from knowledge of internals + final static String userdir = System.getProperty("user.dir", "."); + final static File multirelease = new File(userdir, "multi-release.jar"); + protected int rtVersion; + boolean force; + protected ClassLoader cldr; + protected Class rootClass; + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + + rtVersion = Integer.getInteger("jdk.util.jar.version", MAJOR_VERSION); + String mrprop = System.getProperty("jdk.util.jar.enableMultiRelease", ""); + if (mrprop.equals("false")) { + rtVersion = ROOTVERSION; + } else if (rtVersion < ROOTVERSION) { + rtVersion = ROOTVERSION; + } else if (rtVersion > MAJOR_VERSION) { + rtVersion = MAJOR_VERSION; + } + force = mrprop.equals("force"); + + initializeClassLoader(); + } + + protected void initializeClassLoader() throws Exception { + URL[] urls = new URL[]{multirelease.toURI().toURL()}; + cldr = new URLClassLoader(urls); + // load any class, Main is convenient and in the root entries + rootClass = cldr.loadClass("version.Main"); + } + + @AfterClass + public void close() throws IOException { + ((URLClassLoader)cldr).close(); + Files.delete(multirelease.toPath()); + } + + /* + * jdk.util.jar.enableMultiRelease=force is a no-op for URLClassLoader + */ + @Test + public void testURLClassLoader() throws Throwable { + Class vcls = cldr.loadClass("version.Version"); + invokeMethod(vcls, rtVersion); + } + + protected void invokeMethod(Class vcls, int expected) throws Throwable { + MethodType mt = MethodType.methodType(int.class); + MethodHandle mh = MethodHandles.lookup().findVirtual(vcls, "getVersion", mt); + Assert.assertEquals(expected, (int) mh.invoke(vcls.newInstance())); + } + + /* + * jdk.util.jar.enableMultiRelease=force should affect a custom class loader + */ + @Test + public void testClassLoader() throws Throwable { + try (JarFile jf = new JarFile(multirelease)) { // do not set runtime versioning + ClassLoader cldr = new CustomClassLoader(jf); + Class vcls = cldr.loadClass("version.Version"); + if (rtVersion == 9) { + try { + cldr.loadClass("version.PackagePrivate"); + } catch (ClassNotFoundException x) { + if (force) throw x; + } + } + invokeMethod(vcls, force ? rtVersion : ROOTVERSION); + } + } + + private static class CustomClassLoader extends ClassLoader { + private final JarFile jf; + + CustomClassLoader(JarFile jf) throws Exception { + super(null); + this.jf = jf; + } + + protected Class findClass(String name) throws ClassNotFoundException { + try { + byte[] b; + String entryName = name.replace(".", "/") + ".class"; + JarEntry je = jf.getJarEntry(entryName); + if (je != null) { + try (InputStream is = jf.getInputStream(je)) { + b = new byte[(int) je.getSize()]; + is.read(b); + } + return defineClass(name, b, 0, b.length); + } + throw new ClassNotFoundException(name); + } catch (IOException x) { + throw new ClassNotFoundException(x.getMessage()); + } + } + } + + @Test + public void testGetResourceAsStream() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use fileRootClass as a base for getting resources + getResourceAsStream(rootClass, resource); + } + + protected void getResourceAsStream(Class rootClass, String resource) throws Exception { + try (InputStream is = rootClass.getResourceAsStream(resource)) { + byte[] bytes = is.readAllBytes(); + resource = new String(bytes); + } + String match = "return " + rtVersion + ";"; + Assert.assertTrue(resource.contains(match)); + } + + @Test + public void testGetResource() throws Exception { + String resource = rtVersion == 9 ? "/version/PackagePrivate.java" : "/version/Version.java"; + // use rootClass as a base for getting resources + getResource(rootClass, resource); + } + + protected void getResource(Class rootClass, String resource) throws Exception { + URL url = rootClass.getResource(resource); + try (InputStream is = url.openStream()) { + byte[] bytes = is.readAllBytes(); + resource = new String(bytes); + } + String match = "return " + rtVersion + ";"; + Assert.assertTrue(resource.contains(match)); + } +} diff --git a/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java new file mode 100644 index 00000000000..348194a3be3 --- /dev/null +++ b/jdk/test/java/util/jar/JarFile/MultiReleaseJarSecurity.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test potential security related issues + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarSecurity + */ + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.security.CodeSigner; +import java.security.cert.Certificate; +import java.util.Arrays; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; +import java.util.zip.ZipFile; +import jdk.Version; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class MultiReleaseJarSecurity { + + static final int MAJOR_VERSION = Version.current().major(); + + String userdir = System.getProperty("user.dir","."); + File multirelease = new File(userdir, "multi-release.jar"); + File signedmultirelease = new File(userdir, "signed-multi-release.jar"); + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(multirelease.toPath()); + Files.delete(signedmultirelease.toPath()); + } + + @Test + public void testCertsAndSigners() throws IOException { + try (JarFile jf = new JarFile(signedmultirelease, true, ZipFile.OPEN_READ, JarFile.Release.RUNTIME)) { + CertsAndSigners vcas = new CertsAndSigners(jf, jf.getJarEntry("version/Version.class")); + CertsAndSigners rcas = new CertsAndSigners(jf, jf.getJarEntry("META-INF/versions/" + MAJOR_VERSION + "/version/Version.class")); + Assert.assertTrue(Arrays.equals(rcas.getCertificates(), vcas.getCertificates())); + Assert.assertTrue(Arrays.equals(rcas.getCodeSigners(), vcas.getCodeSigners())); + } + } + + private static class CertsAndSigners { + final private JarFile jf; + final private JarEntry je; + private boolean readComplete; + + CertsAndSigners(JarFile jf, JarEntry je) { + this.jf = jf; + this.je = je; + } + + Certificate[] getCertificates() throws IOException { + readEntry(); + return je.getCertificates(); + } + + CodeSigner[] getCodeSigners() throws IOException { + readEntry(); + return je.getCodeSigners(); + } + + private void readEntry() throws IOException { + if (!readComplete) { + try (InputStream is = jf.getInputStream(je)) { + is.readAllBytes(); + } + readComplete = true; + } + } + } +} diff --git a/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java b/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java index 2f1641f49e3..f54eb2a7a5c 100644 --- a/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java +++ b/jdk/test/java/util/logging/LogManagerAppContextDeadlock.java @@ -141,6 +141,7 @@ public class LogManagerAppContextDeadlock { t1.setDaemon(true); t1.start(); Thread t2 = new Thread() { + public Object logger; public void run() { sem3.release(); try { @@ -151,7 +152,10 @@ public class LogManagerAppContextDeadlock { Thread.interrupted(); } System.out.println("Logger.getLogger(name).info(name)"); - Logger.getLogger(test.name());//.info(name); + // stick the logger in an instance variable to prevent it + // from being garbage collected before the main thread + // calls LogManager.getLogger() below. + logger = Logger.getLogger(test.name());//.info(name); System.out.println("Done: Logger.getLogger(name).info(name)"); } }; diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java index d9a87bb8115..1b987485aca 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/DoubleStreamTestDataProvider.java @@ -126,6 +126,9 @@ public class DoubleStreamTestDataProvider { () -> Spliterators.spliterator(isl.iterator(), doubles.length, 0))); spliterators.add(splitDescr("Primitives.s(SpinedBuffer.iterator()):" + name, () -> Spliterators.spliteratorUnknownSize(isl.iterator(), 0))); + spliterators.add(splitDescr("DoubleStream.iterate(0,x->xx+1):" + name, + () -> DoubleStream.iterate(0.0, x -> x < doubles.length, x -> x + 1.0) + .spliterator())); // Need more! } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java index 945cd9580e5..9afbaf76276 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/IntStreamTestDataProvider.java @@ -136,6 +136,8 @@ public class IntStreamTestDataProvider { () -> IntStream.range(0, ints.length).spliterator())); spliterators.add(splitDescr("IntStream.intRangeClosed(0,l):" + name, () -> IntStream.rangeClosed(0, ints.length).spliterator())); + spliterators.add(splitDescr("IntStream.iterate(0,x->xx+1): " + name, + () -> IntStream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator())); // Need more! } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java index 80b1dcc1019..17fd8185a20 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/LongStreamTestDataProvider.java @@ -136,6 +136,9 @@ public class LongStreamTestDataProvider { () -> LongStream.range(0, longs.length).spliterator())); spliterators.add(splitDescr("LongStream.longRangeClosed(0,l):" + name, () -> LongStream.rangeClosed(0, longs.length).spliterator())); + spliterators.add(splitDescr("LongStream.iterate(0,x->xx+1):" + name, + () -> LongStream.iterate(0L, x -> x < longs.length, x -> x + 1L) + .spliterator())); // Need more! } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java index b3aa58ac842..05312b44a34 100644 --- a/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java +++ b/jdk/test/java/util/stream/bootlib/java.base/java/util/stream/StreamTestDataProvider.java @@ -171,6 +171,8 @@ public class StreamTestDataProvider { () -> Spliterators.spliterator(Arrays.asList(ints).iterator(), ints.length, 0))); spliterators.add(splitDescr("Iterators.s(Arrays.s(array).iterator()):" + name, () -> Spliterators.spliteratorUnknownSize(Arrays.asList(ints).iterator(), 0))); + spliterators.add(splitDescr("Stream.iterate(0,x->xx+1): " + name, + () -> Stream.iterate(0, x -> x < ints.length, x -> x + 1).spliterator())); // @@@ Add map and collection spliterators when spliterator() is exposed on Collection or Iterable } spliteratorTestData = spliterators.toArray(new Object[0][]); diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java new file mode 100644 index 00000000000..7843f22563f --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8072727 + */ + +package org.openjdk.tests.java.util.stream; + +import java.util.List; +import java.util.Objects; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; +import java.util.stream.TestData; +import java.util.stream.TestData.Factory; + +import static java.util.stream.ThowableHelper.checkNPE; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +@Test +public class IterateTest extends OpTestCase { + + @DataProvider(name = "IterateStreamsData") + public static Object[][] makeIterateStreamsTestData() { + Object[][] data = { + {List.of(), + Factory.ofSupplier("ref.empty", () -> Stream.iterate(1, x -> x < 0, x -> x * 2))}, + {List.of(1), + Factory.ofSupplier("ref.one", () -> Stream.iterate(1, x -> x < 2, x -> x * 2))}, + {List.of(1, 2, 4, 8, 16, 32, 64, 128, 256, 512), + Factory.ofSupplier("ref.ten", () -> Stream.iterate(1, x -> x < 1000, x -> x * 2))}, + {List.of(10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0), + Factory.ofSupplier("ref.nullCheck", () -> Stream.iterate(10, Objects::nonNull, x -> x > 0 ? x - 1 : null))}, + {List.of(), + Factory.ofIntSupplier("int.empty", () -> IntStream.iterate(1, x -> x < 0, x -> x + 1))}, + {List.of(1), + Factory.ofIntSupplier("int.one", () -> IntStream.iterate(1, x -> x < 2, x -> x + 1))}, + {List.of(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), + Factory.ofIntSupplier("int.ten", () -> IntStream.iterate(1, x -> x <= 10, x -> x + 1))}, + {List.of(5, 4, 3, 2, 1), + Factory.ofIntSupplier("int.divZero", () -> IntStream.iterate(5, x -> x != 0, x -> x - 1/x/2 - 1))}, + {List.of(), + Factory.ofLongSupplier("long.empty", () -> LongStream.iterate(1L, x -> x < 0, x -> x + 1))}, + {List.of(1L), + Factory.ofLongSupplier("long.one", () -> LongStream.iterate(1L, x -> x < 2, x -> x + 1))}, + {List.of(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L), + Factory.ofLongSupplier("long.ten", () -> LongStream.iterate(1L, x -> x <= 10, x -> x + 1))}, + {List.of(), + Factory.ofDoubleSupplier("double.empty", () -> DoubleStream.iterate(1.0, x -> x < 0, x -> x + 1))}, + {List.of(1.0), + Factory.ofDoubleSupplier("double.one", () -> DoubleStream.iterate(1.0, x -> x < 2, x -> x + 1))}, + {List.of(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0), + Factory.ofDoubleSupplier("double.ten", () -> DoubleStream.iterate(1.0, x -> x <= 10, x -> x + 1))} + }; + return data; + } + + @Test(dataProvider = "IterateStreamsData") + public void testIterate(List expected, TestData data) { + withData(data).stream(s -> s).expectedResult(expected).exercise(); + } + + @Test + public void testNPE() { + checkNPE(() -> Stream.iterate("", null, x -> x + "a")); + checkNPE(() -> Stream.iterate("", String::isEmpty, null)); + checkNPE(() -> IntStream.iterate(0, null, x -> x + 1)); + checkNPE(() -> IntStream.iterate(0, x -> x < 10, null)); + checkNPE(() -> LongStream.iterate(0, null, x -> x + 1)); + checkNPE(() -> LongStream.iterate(0, x -> x < 10, null)); + checkNPE(() -> DoubleStream.iterate(0, null, x -> x + 1)); + checkNPE(() -> DoubleStream.iterate(0, x -> x < 10, null)); + } +} diff --git a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java index 6fd24a9816a..d20a6670dac 100644 --- a/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ /* * @test * @summary close handlers and closing streams - * @bug 8044047 + * @bug 8044047 8147505 */ package org.openjdk.tests.java.util.stream; @@ -37,6 +37,7 @@ import org.testng.annotations.Test; import static java.util.stream.LambdaTestHelpers.countTo; import static java.util.stream.ThowableHelper.checkNPE; +import static java.util.stream.ThowableHelper.checkISE; @Test(groups = { "serialization-hostile" }) public class StreamCloseTest extends OpTestCase { @@ -170,4 +171,21 @@ public class StreamCloseTest extends OpTestCase { for (int i=0; i s = countTo(100).stream()) { + s.forEach(i -> {}); + // Adding onClose handler when stream is consumed is illegal + // handler must not be registered + checkISE(() -> s.onClose(() -> fail("1"))); + } + + // close() must be idempotent: + // second close() invoked at the end of try-with-resources must have no effect + try(Stream s = countTo(100).stream()) { + s.close(); + // Adding onClose handler when stream is closed is also illegal + checkISE(() -> s.onClose(() -> fail("3"))); + } + } } diff --git a/jdk/test/java/util/zip/TestLocalTime.java b/jdk/test/java/util/zip/TestLocalTime.java index 93770ef2f3b..d4b669a1033 100644 --- a/jdk/test/java/util/zip/TestLocalTime.java +++ b/jdk/test/java/util/zip/TestLocalTime.java @@ -24,7 +24,6 @@ /* * @test * @bug 8075526 8135108 - * @key intermittent * @summary Test timestamp via ZipEntry.get/setTimeLocal() */ diff --git a/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java new file mode 100644 index 00000000000..fdfa76de068 --- /dev/null +++ b/jdk/test/javax/crypto/JceSecurity/FinalRestricted.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8149417 + * @summary Use final restricted flag + */ + +import java.security.*; +import java.lang.reflect.*; + +public class FinalRestricted { + + public static void main(String[] args) throws Exception { + + int modifiers = Class.forName("javax.crypto.JceSecurity") + .getDeclaredField("isRestricted").getModifiers(); + if (!(Modifier.isFinal(modifiers) && Modifier.isStatic(modifiers) && + Modifier.isPrivate(modifiers))) { + throw new Exception("JceSecurity.isRestricted is not " + + "a private static final field!"); + } + } +} diff --git a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java index 699260777d1..2dd9abdaaa6 100644 --- a/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java +++ b/jdk/test/javax/management/mxbean/MXBeanLoadingTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,6 @@ import java.lang.ref.WeakReference; import java.net.URL; -import java.net.URLClassLoader; import java.util.Arrays; import java.util.Map; import javax.management.Attribute; @@ -70,16 +69,16 @@ public class MXBeanLoadingTest1 { + " some little extra check of Descriptors, MBean*Info."); ClassLoader myClassLoader = MXBeanLoadingTest1.class.getClassLoader(); + if(myClassLoader == null) + throw new RuntimeException("Test Failed : Null Classloader for test"); + URL url = myClassLoader.getResource( + MXBeanLoadingTest1.class.getCanonicalName() + .replace(".", "/") + ".class"); + String clsLoadPath = url.toURI().toString(). + replaceAll(MXBeanLoadingTest1.class.getSimpleName() + + ".class", ""); - if (!(myClassLoader instanceof URLClassLoader)) { - String message = "(ERROR) Test's class loader is not " + - "a URLClassLoader"; - System.out.println(message); - throw new RuntimeException(message); - } - - URLClassLoader myURLClassLoader = (URLClassLoader) myClassLoader; - URL[] urls = myURLClassLoader.getURLs(); + URL[] urls = new URL[]{new URL(clsLoadPath)}; PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(TestMXBean.class.getName()); diff --git a/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java b/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java new file mode 100644 index 00000000000..7dece5ba724 --- /dev/null +++ b/jdk/test/javax/net/ssl/Stapling/StapleEnableProps.java @@ -0,0 +1,721 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8145854 + * @summary SSLContextImpl.statusResponseManager should be generated if required + * @library ../../../../java/security/testlibrary + * @build CertificateBuilder SimpleOCSPServer + * @run main/othervm StapleEnableProps + */ + +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.math.BigInteger; +import java.security.*; +import java.nio.*; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.TimeUnit; + +import sun.security.testlibrary.SimpleOCSPServer; +import sun.security.testlibrary.CertificateBuilder; + +public class StapleEnableProps { + + /* + * Enables logging of the SSLEngine operations. + */ + private static final boolean logging = true; + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + + // These two ByteBuffer references will be used to hang onto ClientHello + // messages with and without the status_request[_v2] extensions. These + // will be used in the server-side stapling tests. + private static ByteBuffer cHelloStaple; + private static ByteBuffer cHelloNoStaple; + + // The following items are used to set up the keystores. + private static final String passwd = "passphrase"; + private static final String ROOT_ALIAS = "root"; + private static final String INT_ALIAS = "intermediate"; + private static final String SSL_ALIAS = "ssl"; + + // PKI components we will need for this test + private static KeyManagerFactory kmf; + private static TrustManagerFactory tmf; + private static KeyStore rootKeystore; // Root CA Keystore + private static KeyStore intKeystore; // Intermediate CA Keystore + private static KeyStore serverKeystore; // SSL Server Keystore + private static KeyStore trustStore; // SSL Client trust store + private static SimpleOCSPServer rootOcsp; // Root CA OCSP Responder + private static int rootOcspPort; // Port for root OCSP + private static SimpleOCSPServer intOcsp; // Intermediate CA OCSP server + private static int intOcspPort; // Port for intermediate OCSP + + // A few helpful TLS definitions to make it easier + private static final int HELLO_EXT_STATUS_REQ = 5; + private static final int HELLO_EXT_STATUS_REQ_V2 = 17; + + /* + * Main entry point for this test. + */ + public static void main(String args[]) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl"); + } + + // Create the PKI we will use for the test and start the OCSP servers + createPKI(); + + // Set up the KeyManagerFactory and TrustManagerFactory + kmf = KeyManagerFactory.getInstance("PKIX"); + kmf.init(serverKeystore, passwd.toCharArray()); + tmf = TrustManagerFactory.getInstance("PKIX"); + tmf.init(trustStore); + + // Run the client and server property tests + testClientProp(); + testServerProp(); + + } + + private static void testClientProp() throws Exception { + SSLEngineResult clientResult; + + // Test with the client-side enable property set to true + System.out.println("========================================="); + System.out.println("Client Test 1: " + + "jdk.tls.client.enableStatusRequestExtension = true"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.client.enableStatusRequestExtension", + "true"); + SSLContext ctxStaple = SSLContext.getInstance("TLS"); + ctxStaple.init(null, tmf.getTrustManagers(), null); + SSLEngine engine = ctxStaple.createSSLEngine(); + engine.setUseClientMode(true); + SSLSession session = engine.getSession(); + ByteBuffer clientOut = ByteBuffer.wrap("I'm a Client".getBytes()); + ByteBuffer cTOs = + ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Create and check the ClientHello message + clientResult = engine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + if (clientResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + clientResult.getStatus()); + } + cTOs.flip(); + System.out.println(dumpHexBytes(cTOs)); + checkClientHello(cTOs, true, true); + cHelloStaple = cTOs; + + // Test with the property set to false + System.out.println("========================================="); + System.out.println("Client Test 2: " + + "jdk.tls.client.enableStatusRequestExtension = false"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.client.enableStatusRequestExtension", + "false"); + SSLContext ctxNoStaple = SSLContext.getInstance("TLS"); + ctxNoStaple.init(null, tmf.getTrustManagers(), null); + engine = ctxNoStaple.createSSLEngine(); + engine.setUseClientMode(true); + session = engine.getSession(); + cTOs = ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Create and check the ClientHello message + clientResult = engine.wrap(clientOut, cTOs); + log("client wrap: ", clientResult); + if (clientResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + clientResult.getStatus()); + } + cTOs.flip(); + System.out.println(dumpHexBytes(cTOs)); + checkClientHello(cTOs, false, false); + cHelloNoStaple = cTOs; + } + + private static void testServerProp() throws Exception { + SSLEngineResult serverResult; + HandshakeStatus hsStat; + + // Test with the server-side enable property set to true + System.out.println("========================================="); + System.out.println("Server Test 1: " + + "jdk.tls.server.enableStatusRequestExtension = true"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.server.enableStatusRequestExtension", + "true"); + SSLContext ctxStaple = SSLContext.getInstance("TLS"); + ctxStaple.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + SSLEngine engine = ctxStaple.createSSLEngine(); + engine.setUseClientMode(false); + SSLSession session = engine.getSession(); + ByteBuffer serverOut = ByteBuffer.wrap("I'm a Server".getBytes()); + ByteBuffer serverIn = + ByteBuffer.allocate(session.getApplicationBufferSize() + 50); + ByteBuffer sTOc = + ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Consume the client hello + serverResult = engine.unwrap(cHelloStaple, serverIn); + log("server unwrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Server unwrap got status: " + + serverResult.getStatus()); + } else if (serverResult.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new SSLException("Server unwrap expected NEED_TASK, got: " + + serverResult.getHandshakeStatus()); + } + runDelegatedTasks(serverResult, engine); + if (engine.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_WRAP) { + throw new SSLException("Expected NEED_WRAP, got: " + + engine.getHandshakeStatus()); + } + + // Generate a TLS record with the ServerHello + serverResult = engine.wrap(serverOut, sTOc); + log("client wrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + serverResult.getStatus()); + } + sTOc.flip(); + System.out.println(dumpHexBytes(sTOc)); + checkServerHello(sTOc, false, true); + + // Flip the client hello so we can reuse it in the next test. + cHelloStaple.flip(); + + // Test with the server-side enable property set to false + System.out.println("========================================="); + System.out.println("Server Test 2: " + + "jdk.tls.server.enableStatusRequestExtension = false"); + System.out.println("========================================="); + + System.setProperty("jdk.tls.server.enableStatusRequestExtension", + "false"); + SSLContext ctxNoStaple = SSLContext.getInstance("TLS"); + ctxNoStaple.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); + engine = ctxNoStaple.createSSLEngine(); + engine.setUseClientMode(false); + session = engine.getSession(); + serverIn = ByteBuffer.allocate(session.getApplicationBufferSize() + 50); + sTOc = ByteBuffer.allocateDirect(session.getPacketBufferSize()); + + // Consume the client hello + serverResult = engine.unwrap(cHelloStaple, serverIn); + log("server unwrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Server unwrap got status: " + + serverResult.getStatus()); + } else if (serverResult.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_TASK) { + throw new SSLException("Server unwrap expected NEED_TASK, got: " + + serverResult.getHandshakeStatus()); + } + runDelegatedTasks(serverResult, engine); + if (engine.getHandshakeStatus() != + SSLEngineResult.HandshakeStatus.NEED_WRAP) { + throw new SSLException("Expected NEED_WRAP, got: " + + engine.getHandshakeStatus()); + } + + // Generate a TLS record with the ServerHello + serverResult = engine.wrap(serverOut, sTOc); + log("client wrap: ", serverResult); + if (serverResult.getStatus() != SSLEngineResult.Status.OK) { + throw new SSLException("Client wrap got status: " + + serverResult.getStatus()); + } + sTOc.flip(); + System.out.println(dumpHexBytes(sTOc)); + checkServerHello(sTOc, false, false); + } + + /* + * If the result indicates that we have outstanding tasks to do, + * go ahead and run them in this thread. + */ + private static void runDelegatedTasks(SSLEngineResult result, + SSLEngine engine) throws Exception { + + if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + HandshakeStatus hsStatus = engine.getHandshakeStatus(); + if (hsStatus == HandshakeStatus.NEED_TASK) { + throw new Exception( + "handshake shouldn't need additional tasks"); + } + log("\tnew HandshakeStatus: " + hsStatus); + } + } + + private static void log(String str, SSLEngineResult result) { + if (!logging) { + return; + } + HandshakeStatus hsStatus = result.getHandshakeStatus(); + log(str + + result.getStatus() + "/" + hsStatus + ", " + + result.bytesConsumed() + "/" + result.bytesProduced() + + " bytes"); + if (hsStatus == HandshakeStatus.FINISHED) { + log("\t...ready for application data"); + } + } + + private static void log(String str) { + if (logging) { + System.out.println(str); + } + } + + /** + * Dump a ByteBuffer as a hexdump to stdout. The dumping routine will + * start at the current position of the buffer and run to its limit. + * After completing the dump, the position will be returned to its + * starting point. + * + * @param data the ByteBuffer to dump to stdout. + * + * @return the hexdump of the byte array. + */ + private static String dumpHexBytes(ByteBuffer data) { + StringBuilder sb = new StringBuilder(); + if (data != null) { + int i = 0; + data.mark(); + while (data.hasRemaining()) { + if (i % 16 == 0 && i != 0) { + sb.append("\n"); + } + sb.append(String.format("%02X ", data.get())); + i++; + } + data.reset(); + } + + return sb.toString(); + } + + /** + * Tests the ClientHello for the presence (or not) of the status_request + * and status_request_v2 hello extensions. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the TLS record + * containing the ClientHello and contains the entire hello message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. If an exception is + * thrown the position at the time of the exception will be preserved. + * + * @param data the ByteBuffer containing the ClientHello bytes + * @param statReqPresent true if the status_request hello extension should + * be present. + * @param statReqV2Present true if the status_request_v2 hello extension + * should be present. + * + * @throws SSLException if the presence or lack of either the + * status_request or status_request_v2 extensions is inconsistent with + * the expected settings in the statReqPresent or statReqV2Present + * parameters. + */ + private static void checkClientHello(ByteBuffer data, + boolean statReqPresent, boolean statReqV2Present) + throws SSLException { + boolean hasV1 = false; + boolean hasV2 = false; + Objects.requireNonNull(data); + data.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(data.get()); + int ver_major = Byte.toUnsignedInt(data.get()); + int ver_minor = Byte.toUnsignedInt(data.get()); + int recLen = Short.toUnsignedInt(data.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > data.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + data.remaining()); + } + + // Grab the handshake message header. + int msgHdr = data.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + // More simple sanity checks + if (msgType != 1) { + throw new SSLException("Not a ClientHello: Type = " + msgType); + } + + // Skip over the protocol version and client random + data.position(data.position() + 34); + + // Jump past the session ID (if there is one) + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Jump past the cipher suites + int csLen = Short.toUnsignedInt(data.getShort()); + if (csLen != 0) { + data.position(data.position() + csLen); + } + + // ...and the compression + int compLen = Byte.toUnsignedInt(data.get()); + if (compLen != 0) { + data.position(data.position() + compLen); + } + + // Now for the fun part. Go through the extensions and look + // for the two status request exts. + int extsLen = Short.toUnsignedInt(data.getShort()); + while (data.hasRemaining()) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + hasV1 |= (extType == HELLO_EXT_STATUS_REQ); + hasV2 |= (extType == HELLO_EXT_STATUS_REQ_V2); + data.position(data.position() + extLen); + } + + if (hasV1 != statReqPresent) { + throw new SSLException("The status_request extension is " + + "inconsistent with the expected result: expected = " + + statReqPresent + ", actual = " + hasV1); + } else if (hasV2 != statReqV2Present) { + throw new SSLException("The status_request_v2 extension is " + + "inconsistent with the expected result: expected = " + + statReqV2Present + ", actual = " + hasV2); + } + + // We should be at the end of the ClientHello + data.reset(); + } + + /** + * Tests the ServerHello for the presence (or not) of the status_request + * or status_request_v2 hello extension. It is assumed that the provided + * ByteBuffer has its position set at the first byte of the TLS record + * containing the ServerHello and contains the entire hello message. Upon + * successful completion of this method the ByteBuffer will have its + * position reset to the initial offset in the buffer. If an exception is + * thrown the position at the time of the exception will be preserved. + * + * @param statReqPresent true if the status_request hello extension should + * be present. + * @param statReqV2Present true if the status_request_v2 hello extension + * should be present. + * + * @throws SSLException if the presence or lack of either the + * status_request or status_request_v2 extensions is inconsistent with + * the expected settings in the statReqPresent or statReqV2Present + * parameters. + */ + private static void checkServerHello(ByteBuffer data, + boolean statReqPresent, boolean statReqV2Present) + throws SSLException { + boolean hasV1 = false; + boolean hasV2 = false; + Objects.requireNonNull(data); + int startPos = data.position(); + data.mark(); + + // Process the TLS record header + int type = Byte.toUnsignedInt(data.get()); + int ver_major = Byte.toUnsignedInt(data.get()); + int ver_minor = Byte.toUnsignedInt(data.get()); + int recLen = Short.toUnsignedInt(data.getShort()); + + // Simple sanity checks + if (type != 22) { + throw new SSLException("Not a handshake: Type = " + type); + } else if (recLen > data.remaining()) { + throw new SSLException("Incomplete record in buffer: " + + "Record length = " + recLen + ", Remaining = " + + data.remaining()); + } + + // Grab the handshake message header. + int msgHdr = data.getInt(); + int msgType = (msgHdr >> 24) & 0x000000FF; + int msgLen = msgHdr & 0x00FFFFFF; + + // More simple sanity checks + if (msgType != 2) { + throw new SSLException("Not a ServerHello: Type = " + msgType); + } + + // Skip over the protocol version and server random + data.position(data.position() + 34); + + // Jump past the session ID + int sessLen = Byte.toUnsignedInt(data.get()); + if (sessLen != 0) { + data.position(data.position() + sessLen); + } + + // Skip the cipher suite and compression method + data.position(data.position() + 3); + + // Go through the extensions and look for the request extension + // expected by the caller. + int extsLen = Short.toUnsignedInt(data.getShort()); + while (data.position() < recLen + startPos + 5) { + int extType = Short.toUnsignedInt(data.getShort()); + int extLen = Short.toUnsignedInt(data.getShort()); + hasV1 |= (extType == HELLO_EXT_STATUS_REQ); + hasV2 |= (extType == HELLO_EXT_STATUS_REQ_V2); + data.position(data.position() + extLen); + } + + if (hasV1 != statReqPresent) { + throw new SSLException("The status_request extension is " + + "inconsistent with the expected result: expected = " + + statReqPresent + ", actual = " + hasV1); + } else if (hasV2 != statReqV2Present) { + throw new SSLException("The status_request_v2 extension is " + + "inconsistent with the expected result: expected = " + + statReqV2Present + ", actual = " + hasV2); + } + + // Reset the position to the initial spot at the start of this method. + data.reset(); + } + + /** + * Creates the PKI components necessary for this test, including + * Root CA, Intermediate CA and SSL server certificates, the keystores + * for each entity, a client trust store, and starts the OCSP responders. + */ + private static void createPKI() throws Exception { + CertificateBuilder cbld = new CertificateBuilder(); + KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); + keyGen.initialize(2048); + KeyStore.Builder keyStoreBuilder = + KeyStore.Builder.newInstance("PKCS12", null, + new KeyStore.PasswordProtection(passwd.toCharArray())); + + // Generate Root, IntCA, EE keys + KeyPair rootCaKP = keyGen.genKeyPair(); + log("Generated Root CA KeyPair"); + KeyPair intCaKP = keyGen.genKeyPair(); + log("Generated Intermediate CA KeyPair"); + KeyPair sslKP = keyGen.genKeyPair(); + log("Generated SSL Cert KeyPair"); + + // Set up the Root CA Cert + cbld.setSubjectName("CN=Root CA Cert, O=SomeCompany"); + cbld.setPublicKey(rootCaKP.getPublic()); + cbld.setSerialNumber(new BigInteger("1")); + // Make a 3 year validity starting from 60 days ago + long start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(60); + long end = start + TimeUnit.DAYS.toMillis(1085); + cbld.setValidity(new Date(start), new Date(end)); + addCommonExts(cbld, rootCaKP.getPublic(), rootCaKP.getPublic()); + addCommonCAExts(cbld); + // Make our Root CA Cert! + X509Certificate rootCert = cbld.build(null, rootCaKP.getPrivate(), + "SHA256withRSA"); + log("Root CA Created:\n" + certInfo(rootCert)); + + // Now build a keystore and add the keys and cert + rootKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] rootChain = {rootCert}; + rootKeystore.setKeyEntry(ROOT_ALIAS, rootCaKP.getPrivate(), + passwd.toCharArray(), rootChain); + + // Now fire up the OCSP responder + rootOcsp = new SimpleOCSPServer(rootKeystore, passwd, ROOT_ALIAS, null); + rootOcsp.enableLog(logging); + rootOcsp.setNextUpdateInterval(3600); + rootOcsp.start(); + Thread.sleep(1000); // Give the server a second to start up + rootOcspPort = rootOcsp.getPort(); + String rootRespURI = "http://localhost:" + rootOcspPort; + log("Root OCSP Responder URI is " + rootRespURI); + + // Now that we have the root keystore and OCSP responder we can + // create our intermediate CA. + cbld.reset(); + cbld.setSubjectName("CN=Intermediate CA Cert, O=SomeCompany"); + cbld.setPublicKey(intCaKP.getPublic()); + cbld.setSerialNumber(new BigInteger("100")); + // Make a 2 year validity starting from 30 days ago + start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(30); + end = start + TimeUnit.DAYS.toMillis(730); + cbld.setValidity(new Date(start), new Date(end)); + addCommonExts(cbld, intCaKP.getPublic(), rootCaKP.getPublic()); + addCommonCAExts(cbld); + cbld.addAIAExt(Collections.singletonList(rootRespURI)); + // Make our Intermediate CA Cert! + X509Certificate intCaCert = cbld.build(rootCert, rootCaKP.getPrivate(), + "SHA256withRSA"); + log("Intermediate CA Created:\n" + certInfo(intCaCert)); + + // Provide intermediate CA cert revocation info to the Root CA + // OCSP responder. + Map revInfo = + new HashMap<>(); + revInfo.put(intCaCert.getSerialNumber(), + new SimpleOCSPServer.CertStatusInfo( + SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)); + rootOcsp.updateStatusDb(revInfo); + + // Now build a keystore and add the keys, chain and root cert as a TA + intKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] intChain = {intCaCert, rootCert}; + intKeystore.setKeyEntry(INT_ALIAS, intCaKP.getPrivate(), + passwd.toCharArray(), intChain); + intKeystore.setCertificateEntry(ROOT_ALIAS, rootCert); + + // Now fire up the Intermediate CA OCSP responder + intOcsp = new SimpleOCSPServer(intKeystore, passwd, + INT_ALIAS, null); + intOcsp.enableLog(logging); + intOcsp.setNextUpdateInterval(3600); + intOcsp.start(); + Thread.sleep(1000); + intOcspPort = intOcsp.getPort(); + String intCaRespURI = "http://localhost:" + intOcspPort; + log("Intermediate CA OCSP Responder URI is " + intCaRespURI); + + // Last but not least, let's make our SSLCert and add it to its own + // Keystore + cbld.reset(); + cbld.setSubjectName("CN=SSLCertificate, O=SomeCompany"); + cbld.setPublicKey(sslKP.getPublic()); + cbld.setSerialNumber(new BigInteger("4096")); + // Make a 1 year validity starting from 7 days ago + start = System.currentTimeMillis() - TimeUnit.DAYS.toMillis(7); + end = start + TimeUnit.DAYS.toMillis(365); + cbld.setValidity(new Date(start), new Date(end)); + + // Add extensions + addCommonExts(cbld, sslKP.getPublic(), intCaKP.getPublic()); + boolean[] kuBits = {true, false, true, false, false, false, + false, false, false}; + cbld.addKeyUsageExt(kuBits); + List ekuOids = new ArrayList<>(); + ekuOids.add("1.3.6.1.5.5.7.3.1"); + ekuOids.add("1.3.6.1.5.5.7.3.2"); + cbld.addExtendedKeyUsageExt(ekuOids); + cbld.addSubjectAltNameDNSExt(Collections.singletonList("localhost")); + cbld.addAIAExt(Collections.singletonList(intCaRespURI)); + // Make our SSL Server Cert! + X509Certificate sslCert = cbld.build(intCaCert, intCaKP.getPrivate(), + "SHA256withRSA"); + log("SSL Certificate Created:\n" + certInfo(sslCert)); + + // Provide SSL server cert revocation info to the Intermeidate CA + // OCSP responder. + revInfo = new HashMap<>(); + revInfo.put(sslCert.getSerialNumber(), + new SimpleOCSPServer.CertStatusInfo( + SimpleOCSPServer.CertStatus.CERT_STATUS_GOOD)); + intOcsp.updateStatusDb(revInfo); + + // Now build a keystore and add the keys, chain and root cert as a TA + serverKeystore = keyStoreBuilder.getKeyStore(); + java.security.cert.Certificate[] sslChain = {sslCert, intCaCert, rootCert}; + serverKeystore.setKeyEntry(SSL_ALIAS, sslKP.getPrivate(), + passwd.toCharArray(), sslChain); + serverKeystore.setCertificateEntry(ROOT_ALIAS, rootCert); + + // And finally a Trust Store for the client + trustStore = keyStoreBuilder.getKeyStore(); + trustStore.setCertificateEntry(ROOT_ALIAS, rootCert); + } + + private static void addCommonExts(CertificateBuilder cbld, + PublicKey subjKey, PublicKey authKey) throws IOException { + cbld.addSubjectKeyIdExt(subjKey); + cbld.addAuthorityKeyIdExt(authKey); + } + + private static void addCommonCAExts(CertificateBuilder cbld) + throws IOException { + cbld.addBasicConstraintsExt(true, true, -1); + // Set key usage bits for digitalSignature, keyCertSign and cRLSign + boolean[] kuBitSettings = {true, false, false, false, false, true, + true, false, false}; + cbld.addKeyUsageExt(kuBitSettings); + } + + /** + * Helper routine that dumps only a few cert fields rather than + * the whole toString() output. + * + * @param cert an X509Certificate to be displayed + * + * @return the String output of the issuer, subject and + * serial number + */ + private static String certInfo(X509Certificate cert) { + StringBuilder sb = new StringBuilder(); + sb.append("Issuer: ").append(cert.getIssuerX500Principal()). + append("\n"); + sb.append("Subject: ").append(cert.getSubjectX500Principal()). + append("\n"); + sb.append("Serial: ").append(cert.getSerialNumber()).append("\n"); + return sb.toString(); + } +} diff --git a/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java new file mode 100644 index 00000000000..e32e7723db5 --- /dev/null +++ b/jdk/test/javax/sound/sampled/AudioInputStream/FrameLengthAfterConversion.java @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.List; + +import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.UnsupportedAudioFileException; +import javax.sound.sampled.spi.AudioFileWriter; +import javax.sound.sampled.spi.FormatConversionProvider; + +import static java.util.ServiceLoader.load; +import static javax.sound.sampled.AudioFileFormat.Type.AIFC; +import static javax.sound.sampled.AudioFileFormat.Type.AIFF; +import static javax.sound.sampled.AudioFileFormat.Type.AU; +import static javax.sound.sampled.AudioFileFormat.Type.SND; +import static javax.sound.sampled.AudioFileFormat.Type.WAVE; +import static javax.sound.sampled.AudioSystem.NOT_SPECIFIED; + +/** + * @test + * @bug 8038139 + */ +public final class FrameLengthAfterConversion { + + /** + * We will try to use all formats, in this case all our providers will be + * covered by supported/unsupported formats. + */ + private static final List formats = new ArrayList<>(23000); + + private static final AudioFormat.Encoding[] encodings = { + AudioFormat.Encoding.ALAW, AudioFormat.Encoding.ULAW, + AudioFormat.Encoding.PCM_SIGNED, AudioFormat.Encoding.PCM_UNSIGNED, + AudioFormat.Encoding.PCM_FLOAT, new AudioFormat.Encoding("Test") + }; + + private static final int[] sampleBits = { + 1, 4, 8, 11, 16, 20, 24, 32 + }; + + private static final int[] channels = { + 1, 2, 3, 4, 5 + }; + + private static final AudioFileFormat.Type[] types = { + WAVE, AU, AIFF, AIFC, SND, + new AudioFileFormat.Type("TestName", "TestExt") + }; + + private static final int FRAME_LENGTH = 10; + + static { + for (final int sampleSize : sampleBits) { + for (final int channel : channels) { + for (final AudioFormat.Encoding enc : encodings) { + final int frameSize = ((sampleSize + 7) / 8) * channel; + formats.add(new AudioFormat(enc, 44100, sampleSize, channel, + frameSize, 44100, true)); + formats.add(new AudioFormat(enc, 44100, sampleSize, channel, + frameSize, 44100, false)); + } + } + } + } + + public static void main(final String[] args) { + for (final FormatConversionProvider fcp : load( + FormatConversionProvider.class)) { + System.out.println("fcp = " + fcp); + for (final AudioFormat from : formats) { + for (final AudioFormat to : formats) { + testAfterConversion(fcp, to, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToStream(afw, type, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToFile(afw, type, getStream(from, true)); + } + } + } + + for (final AudioFileWriter afw : load(AudioFileWriter.class)) { + System.out.println("afw = " + afw); + for (final AudioFileFormat.Type type : types) { + for (final AudioFormat from : formats) { + testAfterSaveToFile(afw, type, getStream(from, false)); + } + } + } + } + + /** + * Verifies the frame length after the stream was saved/read to/from + * stream. + */ + private static void testAfterSaveToStream(final AudioFileWriter afw, + final AudioFileFormat.Type type, + final AudioInputStream ais) { + try { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + afw.write(ais, type, out); + final InputStream input = new ByteArrayInputStream( + out.toByteArray()); + validate(AudioSystem.getAudioInputStream(input).getFrameLength()); + } catch (IllegalArgumentException | UnsupportedAudioFileException + | IOException ignored) { + } + } + + /** + * Verifies the frame length after the stream was saved/read to/from file. + */ + private static void testAfterSaveToFile(final AudioFileWriter afw, + final AudioFileFormat.Type type, + AudioInputStream ais) { + try { + final File temp = File.createTempFile("sound", ".tmp"); + temp.deleteOnExit(); + afw.write(ais, type, temp); + ais = AudioSystem.getAudioInputStream(temp); + final long frameLength = ais.getFrameLength(); + ais.close(); + temp.delete(); + validate(frameLength); + } catch (IllegalArgumentException | UnsupportedAudioFileException + | IOException ignored) { + } + } + + /** + * Verifies the frame length after the stream was converted to other + * stream. + * + * @see FormatConversionProvider#getAudioInputStream(AudioFormat, + * AudioInputStream) + */ + private static void testAfterConversion(final FormatConversionProvider fcp, + final AudioFormat to, + final AudioInputStream ais) { + if (fcp.isConversionSupported(to, ais.getFormat())) { + validate(fcp.getAudioInputStream(to, ais).getFrameLength()); + } + } + + /** + * Throws an exception if the frameLength is specified and is not equal to + * the gold value. + */ + private static void validate(final long frameLength) { + if (frameLength != FRAME_LENGTH) { + System.err.println("Expected: " + FRAME_LENGTH); + System.err.println("Actual: " + frameLength); + throw new RuntimeException(); + } + } + + private static AudioInputStream getStream(final AudioFormat format, + final boolean frameLength) { + final int dataSize = FRAME_LENGTH * format.getFrameSize(); + final InputStream in = new ByteArrayInputStream(new byte[dataSize]); + if (frameLength) { + return new AudioInputStream(in, format, FRAME_LENGTH); + } else { + return new AudioInputStream(in, format, NOT_SPECIFIED); + } + } +} diff --git a/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java new file mode 100644 index 00000000000..0892b5e2090 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/ShellFolderQueries/ShellFolderQueriesTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8081722 + * @summary Provide public API for file hierarchy provided by + * sun.awt.shell.ShellFolder + * @author Semyon Sadetsky + * @run main ShellFolderQueriesTest + */ + +import sun.awt.OSInfo; + +import javax.swing.filechooser.FileSystemView; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; + +public class ShellFolderQueriesTest { + static final String HOME = System.getProperty("user.home"); + static final FileSystemView fsv = FileSystemView.getFileSystemView(); + + + static String scriptBeg = + "set WshShell = WScript.CreateObject(\"WScript.Shell\")\n" + + "set oShellLink = WshShell.CreateShortcut(\"shortcut.lnk\")\n" + + "oShellLink.TargetPath = \""; + static String scriptEnd = "\"\noShellLink.WindowStyle = 1\noShellLink.Save"; + + public static void main(String[] args) throws Exception { + if(OSInfo.getOSType() == OSInfo.OSType.WINDOWS) { + testGet(); + testLink(); + } else { + testGet(); + } + System.out.println("ok"); + } + + private static void testLink() throws IOException, InterruptedException { + // Create and execute VBS script to create a link + File file = createVbsScript(scriptBeg + HOME + scriptEnd); + Runtime.getRuntime().exec("cscript " + file.getName(), null, + file.getParentFile()).waitFor(); + file.delete(); + + File link = new File(file.getParentFile(), "shortcut.lnk"); + if (!fsv.isLink(link)) { + link.delete(); + throw new RuntimeException("Link is not detected"); + } + + File location = fsv.getLinkLocation(link); + if (!location.getAbsolutePath().equals(HOME)) { + link.delete(); + throw new RuntimeException("Link location " + location + + " is wrong"); + } + link.delete(); + + + link = File.createTempFile("test", ".tst"); + + if (fsv.isLink(link)) { + link.delete(); + throw new RuntimeException("File is not a link"); + } + + try { + location = fsv.getLinkLocation(link); + if (location != null) { + link.delete(); + throw new RuntimeException("Not a link, should return null"); + } + } + catch (FileNotFoundException e) { + } + link.delete(); + } + + private static File createVbsScript(String script) throws IOException { + File file = File.createTempFile("test", ".vbs"); + file.deleteOnExit(); + FileOutputStream fos = new FileOutputStream(file); + fos.write(script.getBytes()); + fos.close(); + return file; + } + + private static void testGet() { + File[] files = fsv.getChooserComboBoxFiles(); + for (File file : files) { + if (fsv.isLink(file)) { + throw new RuntimeException( + "Link shouldn't be in FileChooser combobox, " + + file.getPath()); + } + } + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java new file mode 100644 index 00000000000..4ff95c5bc30 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/8146321/JInternalFrameIconTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8146321 + * @summary verifies JInternalFrame Icon and ImageIcon + * @library ../../regtesthelpers + * @build Util + * @run main JInternalFrameIconTest + */ +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.image.BufferedImage; +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; + +public class JInternalFrameIconTest { + + private static JFrame frame; + private static JDesktopPane desktopPane; + private static JInternalFrame internalFrame; + private static ImageIcon titleImageIcon; + private static Icon titleIcon; + private static BufferedImage imageIconImage; + private static BufferedImage iconImage; + + private static Robot robot; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.delay(2000); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + executeCase(lookAndFeelItem.getClassName()); + } + + } + + private static void executeCase(String lookAndFeelString) throws Exception { + if (tryLookAndFeel(lookAndFeelString)) { + createImageIconUI(lookAndFeelString); + robot.delay(1000); + getImageIconBufferedImage(); + robot.waitForIdle(); + cleanUp(); + robot.waitForIdle(); + + createIconUI(lookAndFeelString); + robot.delay(1000); + getIconBufferedImage(); + robot.waitForIdle(); + cleanUp(); + robot.waitForIdle(); + testIfSame(); + robot.waitForIdle(); + } + + } + + private static void createImageIconUI(final String lookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + desktopPane = new JDesktopPane(); + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setTitle(lookAndFeelString); + titleImageIcon = new ImageIcon() { + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + + @Override + public void paintIcon( + Component c, Graphics g, int x, int y) { + g.setColor(java.awt.Color.black); + g.fillRect(x, y, 16, 16); + } + }; + internalFrame.setFrameIcon(titleImageIcon); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void createIconUI(final String lookAndFeelString) + throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + desktopPane = new JDesktopPane(); + internalFrame = new JInternalFrame(); + frame = new JFrame(); + internalFrame.setTitle(lookAndFeelString); + titleIcon = new Icon() { + @Override + public int getIconWidth() { + return 16; + } + + @Override + public int getIconHeight() { + return 16; + } + + @Override + public void paintIcon( + Component c, Graphics g, int x, int y) { + g.setColor(java.awt.Color.black); + g.fillRect(x, y, 16, 16); + } + }; + internalFrame.setFrameIcon(titleIcon); + internalFrame.setSize(500, 200); + internalFrame.setVisible(true); + desktopPane.add(internalFrame); + + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.getContentPane().setLayout(new BorderLayout()); + frame.getContentPane().add(desktopPane, "Center"); + frame.setSize(500, 500); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + frame.toFront(); + } + }); + } + + private static void getImageIconBufferedImage() throws Exception { + Point point = internalFrame.getLocationOnScreen(); + Rectangle rect = internalFrame.getBounds(); + Rectangle captureRect = new Rectangle( + point.x + internalFrame.getInsets().left, + point.y, + rect.width, + internalFrame.getInsets().top); + imageIconImage + = robot.createScreenCapture(captureRect); + } + + private static void getIconBufferedImage() throws Exception { + Point point = internalFrame.getLocationOnScreen(); + Rectangle rect = internalFrame.getBounds(); + Rectangle captureRect = new Rectangle( + point.x + internalFrame.getInsets().left, + point.y, + rect.width, + internalFrame.getInsets().top); + iconImage + = robot.createScreenCapture(captureRect); + } + + private static void testIfSame() throws Exception { + if (!bufferedImagesEqual(imageIconImage, iconImage)) { + System.err.println("ERROR: icon and imageIcon not same."); + } else { + System.out.println("SUCCESS: icon and imageIcon same."); + } + } + + private static boolean bufferedImagesEqual( + BufferedImage bufferedImage1, BufferedImage bufferedImage2) { + boolean flag = true; + + if (bufferedImage1.getWidth() == bufferedImage2.getWidth() + && bufferedImage1.getHeight() == bufferedImage2.getHeight()) { + final int colorTolerance = 25; + final int mismatchTolerance = (int) (0.1 + * bufferedImage1.getWidth() * bufferedImage1.getHeight()); + int mismatchCounter = 0; + for (int x = 0; x < bufferedImage1.getWidth(); x++) { + for (int y = 0; y < bufferedImage1.getHeight(); y++) { + + int color1 = bufferedImage1.getRGB(x, y); + int red1 = (color1 >> 16) & 0x000000FF; + int green1 = (color1 >> 8) & 0x000000FF; + int blue1 = (color1) & 0x000000FF; + + int color2 = bufferedImage2.getRGB(x, y); + int red2 = (color2 >> 16) & 0x000000FF; + int green2 = (color2 >> 8) & 0x000000FF; + int blue2 = (color2) & 0x000000FF; + if (red1 != red2 || green1 != green2 || blue1 != blue2) { + ++mismatchCounter; + if ((Math.abs(red1 - red2) > colorTolerance) + || (Math.abs(green1 - green2) > colorTolerance) + || (Math.abs(blue1 - blue2) > colorTolerance)) { + + flag = false; + } + } + } + } + if (mismatchCounter > mismatchTolerance) { + flag = false; + } + } else { + System.err.println("ERROR: size is different"); + flag = false; + } + return flag; + } + + private static void cleanUp() throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + frame.dispose(); + } + }); + } + + private static boolean tryLookAndFeel(String lookAndFeelString) + throws Exception { + try { + UIManager.setLookAndFeel( + lookAndFeelString); + + } catch (UnsupportedLookAndFeelException + | ClassNotFoundException + | InstantiationException + | IllegalAccessException e) { + return false; + } + return true; + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java b/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java new file mode 100644 index 00000000000..2a6d7f998a9 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/NormalBoundsTest.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + /* + @test + @bug 7126823 + @summary Verify NormalBounds upon iconify/deiconify sequence + @run main NormalBoundsTest + */ +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.beans.PropertyVetoException; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.WindowConstants; + +public class NormalBoundsTest { + + private static JFrame mainFrame; + private static JInternalFrame internalFrame; + private static Rectangle bounds; + + private static void createUI(String lookAndFeelString) { + internalFrame = new JInternalFrame("Internal", true, true, true, true); + internalFrame.setDefaultCloseOperation( + WindowConstants.DO_NOTHING_ON_CLOSE); + internalFrame.setSize(200, 200); + + JDesktopPane desktopPane = new JDesktopPane(); + desktopPane.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE); + desktopPane.add(internalFrame); + + mainFrame = new JFrame(lookAndFeelString); + mainFrame.setSize(640, 480); + mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + mainFrame.setContentPane(desktopPane); + + mainFrame.setVisible(true); + internalFrame.setVisible(true); + + } + + private static int signWOZero(int i) { + return (i > 0) ? 1 : -1; + } + + private static void mouseMove(Robot robot, Point startPt, Point endPt) { + int dx = endPt.x - startPt.x; + int dy = endPt.y - startPt.y; + + int ax = Math.abs(dx) * 2; + int ay = Math.abs(dy) * 2; + + int sx = signWOZero(dx); + int sy = signWOZero(dy); + + int x = startPt.x; + int y = startPt.y; + + int d = 0; + + if (ax > ay) { + d = ay - ax / 2; + while (true) { + robot.mouseMove(x, y); + robot.delay(50); + + if (x == endPt.x) { + return; + } + if (d >= 0) { + y = y + sy; + d = d - ax; + } + x = x + sx; + d = d + ay; + } + } else { + d = ax - ay / 2; + while (true) { + robot.mouseMove(x, y); + robot.delay(50); + + if (y == endPt.y) { + return; + } + if (d >= 0) { + x = x + sx; + d = d - ay; + } + y = y + sy; + d = d + ax; + } + } + } + + private static void drag(Robot r, Point startPt, Point endPt, int button) { + if (!(button == InputEvent.BUTTON1_MASK + || button == InputEvent.BUTTON2_MASK + || button == InputEvent.BUTTON3_MASK)) { + throw new IllegalArgumentException("invalid mouse button"); + } + + r.mouseMove(startPt.x, startPt.y); + r.mousePress(button); + try { + mouseMove(r, startPt, endPt); + } finally { + r.mouseRelease(button); + } + } + + private static boolean tryLookAndFeel(String lookAndFeelString) { + try { + UIManager.setLookAndFeel(lookAndFeelString); + return true; + } catch (UnsupportedLookAndFeelException | ClassNotFoundException | + InstantiationException | IllegalAccessException e) { + return false; + } + } + + public static void executeTest(Robot robot) throws Exception { + + // Iconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Iconize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // Deiconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Deiconize InternalFrame" + + " Failed"); + } + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + Point loc = internalFrame.getLocationOnScreen(); + // Drag Frame + drag(robot, + new Point((int) loc.x + 80, (int) loc.y + 12), + new Point((int) loc.x + 100, (int) loc.y + 40), + InputEvent.BUTTON1_MASK); + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + bounds = internalFrame.getBounds(); + if (!internalFrame.getNormalBounds().equals(bounds)) { + mainFrame.dispose(); + throw new RuntimeException("Invalid NormalBounds"); + } + } + }); + robot.waitForIdle(); + + // Regression Test Bug ID: 4424247 + // Maximize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setMaximum(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Maximize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // Iconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(true); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Iconize InternalFrame Failed"); + } + } + }); + robot.waitForIdle(); + + // DeIconize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setIcon(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("DeIcoize InternalFrame " + + " Failed"); + } + } + }); + robot.waitForIdle(); + + // Restore/Undo Maximize JInternalFrame + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + try { + internalFrame.setMaximum(false); + } catch (PropertyVetoException ex) { + mainFrame.dispose(); + throw new RuntimeException("Restore InternalFrame " + + " Failed"); + } + } + }); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + if (!internalFrame.getBounds().equals(bounds)) { + mainFrame.dispose(); + throw new RuntimeException("Regression Test Failed"); + } + } + }); + robot.waitForIdle(); + + mainFrame.dispose(); + } + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + if (tryLookAndFeel(lookAndFeelString)) { + // create UI + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createUI(lookAndFeelString); + } + }); + + robot.waitForIdle(); + executeTest(robot); + } else { + throw new RuntimeException("Setting Look and Feel Failed"); + } + } + + } +} diff --git a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java similarity index 78% rename from jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java rename to jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java index 4e5d23149ab..b8120b9e910 100644 --- a/jdk/test/javax/swing/JScrollPane/8033000/bug8033000.java +++ b/jdk/test/javax/swing/JScrollPane/HorizontalMouseWheelOnShiftPressed/HorizontalMouseWheelOnShiftPressed.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -20,6 +20,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + import java.awt.BorderLayout; import java.awt.Point; import java.awt.Robot; @@ -29,24 +30,25 @@ import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextArea; import javax.swing.SwingUtilities; -import javax.swing.UIManager; + import jdk.testlibrary.OSInfo; /** * @test - * @bug 8033000 + * @bug 8033000 8147994 * @author Alexander Scherbatiy * @summary No Horizontal Mouse Wheel Support In BasicScrollPaneUI * @library ../../../../lib/testlibrary * @build jdk.testlibrary.OSInfo - * @run main bug8033000 + * @run main HorizontalMouseWheelOnShiftPressed */ -public class bug8033000 { +public class HorizontalMouseWheelOnShiftPressed { private static JScrollPane scrollPane; private static JTextArea textArea; private static Point point; private static final int delta; + private static JFrame frame; static { delta = OSInfo.getOSType().equals(OSInfo.OSType.MACOSX) ? -30 : 30; @@ -57,9 +59,17 @@ public class bug8033000 { Robot robot = new Robot(); robot.setAutoDelay(50); - SwingUtilities.invokeAndWait(bug8033000::createAndShowGUI); + SwingUtilities.invokeAndWait( + HorizontalMouseWheelOnShiftPressed::createAndShowGUI); robot.waitForIdle(); + try { + test(robot); + } finally { + frame.dispose(); + } + } + private static void test(Robot robot) throws Exception { SwingUtilities.invokeAndWait(() -> { Point locationOnScreen = scrollPane.getLocationOnScreen(); point = new Point( @@ -75,7 +85,7 @@ public class bug8033000 { robot.waitForIdle(); robot.mouseWheel(delta); robot.waitForIdle(); - checkScrollPane(true); + checkScrollPane(true, false); // vertical scroll bar is enabled + shift initScrollPane(true, false); @@ -84,14 +94,14 @@ public class bug8033000 { robot.mouseWheel(delta); robot.keyRelease(KeyEvent.VK_SHIFT); robot.waitForIdle(); - checkScrollPane(true); + checkScrollPane(false, false); // horizontal scroll bar is enabled initScrollPane(false, true); robot.waitForIdle(); robot.mouseWheel(delta); robot.waitForIdle(); - checkScrollPane(false); + checkScrollPane(false, true); // horizontal scroll bar is enabled + shift initScrollPane(false, true); @@ -100,14 +110,14 @@ public class bug8033000 { robot.mouseWheel(delta); robot.keyRelease(KeyEvent.VK_SHIFT); robot.waitForIdle(); - checkScrollPane(false); + checkScrollPane(false, true); // both scroll bars are enabled initScrollPane(true, true); robot.waitForIdle(); robot.mouseWheel(delta); robot.waitForIdle(); - checkScrollPane(true); + checkScrollPane(true, false); // both scroll bars are enabled + shift initScrollPane(true, true); @@ -116,7 +126,7 @@ public class bug8033000 { robot.mouseWheel(delta); robot.keyRelease(KeyEvent.VK_SHIFT); robot.waitForIdle(); - checkScrollPane(false); + checkScrollPane(false, true); } static void initScrollPane(boolean vVisible, boolean hVisible) throws Exception { @@ -131,17 +141,25 @@ public class bug8033000 { }); } - static void checkScrollPane(boolean verticalScrolled) throws Exception { + static void checkScrollPane(boolean verticalScrolled, + boolean horizontalScrolled) throws Exception { SwingUtilities.invokeAndWait(() -> { if (verticalScrolled) { - if (scrollPane.getVerticalScrollBar().getValue() == 0 - || scrollPane.getHorizontalScrollBar().getValue() != 0) { + if (scrollPane.getVerticalScrollBar().getValue() == 0) { throw new RuntimeException("Wrong vertical scrolling!"); } + } else{ + if (scrollPane.getVerticalScrollBar().getValue() != 0) { + throw new RuntimeException("Wrong vertical scrolling!"); + } + } + if (horizontalScrolled) { + if (scrollPane.getHorizontalScrollBar().getValue() == 0) { + throw new RuntimeException("Wrong horizontal scrolling!"); + } } else { - if (scrollPane.getVerticalScrollBar().getValue() != 0 - || scrollPane.getHorizontalScrollBar().getValue() == 0) { + if (scrollPane.getHorizontalScrollBar().getValue() != 0) { throw new RuntimeException("Wrong horizontal scrolling!"); } } @@ -149,9 +167,10 @@ public class bug8033000 { } static void createAndShowGUI() { - JFrame frame = new JFrame(); + frame = new JFrame(); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(300, 300); + frame.setLocationRelativeTo(null); textArea = new JTextArea("Hello World!"); scrollPane = new JScrollPane(textArea); JPanel panel = new JPanel(new BorderLayout()); diff --git a/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java b/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java new file mode 100644 index 00000000000..54ac5fd2619 --- /dev/null +++ b/jdk/test/javax/swing/JTableHeader/8020039/TableHeaderRendererExceptionTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.UIManager; +import javax.swing.table.JTableHeader; + +/** + * @test + * @summary Tests whether getTableCellRendererComponent() method handles + * null table parameter + * @bug 8020039 + * @run main TableHeaderRendererExceptionTest + */ +public class TableHeaderRendererExceptionTest { + + public static void main(String[] args) throws Throwable { + //Execute test for all supported look and feels + UIManager.LookAndFeelInfo[] lookAndFeelArray + = UIManager.getInstalledLookAndFeels(); + + for (UIManager.LookAndFeelInfo lookAndFeelItem : lookAndFeelArray) { + String lookAndFeelString = lookAndFeelItem.getClassName(); + + UIManager.setLookAndFeel(lookAndFeelString); + + // Test getTableCellRendererComponent method by passing null table + JTableHeader header = new JTableHeader(); + + header.getDefaultRenderer().getTableCellRendererComponent(null, + " test ", true, true, -1, 0); + } + } +} diff --git a/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java b/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java index 0ef16996cf5..71a2e6f4b58 100644 --- a/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java +++ b/jdk/test/javax/swing/plaf/gtk/crash/RenderBadPictureCrash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,16 +23,15 @@ /* @test - @bug 8056151 + @bug 8056151 8131751 @summary Switching to GTK L&F on-the-fly leads to X Window System error RenderBadPicture @run main/othervm -Dswing.defaultlaf=javax.swing.plaf.metal.MetalLookAndFeel -Dsun.java2d.xrender=T RenderBadPictureCrash */ - import java.awt.Color; +import java.awt.GraphicsDevice; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.SwingUtilities; - import javax.swing.UIManager; public class RenderBadPictureCrash { @@ -41,7 +40,10 @@ public class RenderBadPictureCrash { SwingUtilities.invokeAndWait(() -> { JFrame f = new JFrame(); f.setUndecorated(true); - f.setBackground(new Color(0, 0, 0, 0)); + GraphicsDevice gd = f.getGraphicsConfiguration().getDevice(); + if (gd.isWindowTranslucencySupported(GraphicsDevice.WindowTranslucency.PERPIXEL_TRANSLUCENT)) { + f.setBackground(new Color(0, 0, 0, 0)); + } f.setSize(200, 300); f.setVisible(true); diff --git a/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java new file mode 100644 index 00000000000..ba61e23fcc9 --- /dev/null +++ b/jdk/test/jdk/internal/misc/Unsafe/CopySwap.java @@ -0,0 +1,711 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.internal.misc.Unsafe; +import java.lang.reflect.Field; + +/* + * @test + * @summary Test Unsafe.copySwapMemory + * @modules java.base/jdk.internal.misc + */ +public class CopySwap { + private static final boolean DEBUG = Boolean.getBoolean("CopySwap.DEBUG"); + + public static final long KB = 1024; + public static final long MB = KB * 1024; + public static final long GB = MB * 1024; + + private static final Unsafe UNSAFE; + private static final int SMALL_COPY_SIZE = 32; + private static final int BASE_ALIGNMENT = 16; + + static { + try { + Field f = jdk.internal.misc.Unsafe.class.getDeclaredField("theUnsafe"); + f.setAccessible(true); + UNSAFE = (jdk.internal.misc.Unsafe) f.get(null); + } catch (Exception e) { + throw new RuntimeException("Unable to get Unsafe instance.", e); + } + } + + private static long alignDown(long value, long alignment) { + return value & ~(alignment - 1); + } + + private static long alignUp(long value, long alignment) { + return (value + alignment - 1) & ~(alignment - 1); + } + + private static boolean isAligned(long value, long alignment) { + return value == alignDown(value, alignment); + } + + private CopySwap() { + } + + /** + * Generate verification data for a given offset + * + * The verification data is used to verify that the correct bytes + * have indeed been copied and byte swapped. + * + * The data is generated based on the offset (in bytes) into the + * source buffer. For a native buffer the offset is relative to + * the base pointer. For a heap array it is relative to the + * address of the first array element. + * + * This method will return the result of doing an elementSize byte + * read starting at offset (in bytes). + * + * @param offset offset into buffer + * @param elemSize size (in bytes) of the element + * + * @return the verification data, only the least significant + * elemSize*8 bits are set, zero extended + */ + private long getVerificationDataForOffset(long offset, long elemSize) { + byte[] bytes = new byte[(int)elemSize]; + + for (long i = 0; i < elemSize; i++) { + bytes[(int)i] = (byte)(offset + i); + } + + long o = UNSAFE.arrayBaseOffset(byte[].class); + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(bytes, o)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(bytes, o)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(bytes, o)); + case 8: return UNSAFE.getLongUnaligned(bytes, o); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Verify byte swapped data + * + * @param ptr the data to verify + * @param srcOffset the srcOffset (in bytes) from which the copy started, + * used as key to regenerate the verification data + * @param dstOffset the offset (in bytes) in the array at which to start + * the verification, relative to the first element in the array + * @param size size (in bytes) of data to to verify + * @param elemSize size (in bytes) of the individual array elements + * + * @throws RuntimeException if an error is found + */ + private void verifySwappedData(GenericPointer ptr, long srcOffset, long dstOffset, long size, long elemSize) { + for (long offset = 0; offset < size; offset += elemSize) { + long expectedUnswapped = getVerificationDataForOffset(srcOffset + offset, elemSize); + long expected = byteSwap(expectedUnswapped, elemSize); + + long actual = getArrayElem(ptr, dstOffset + offset, elemSize); + + if (expected != actual) { + throw new RuntimeException("srcOffset: 0x" + Long.toHexString(srcOffset) + + " dstOffset: 0x" + Long.toHexString(dstOffset) + + " size: 0x" + Long.toHexString(size) + + " offset: 0x" + Long.toHexString(offset) + + " expectedUnswapped: 0x" + Long.toHexString(expectedUnswapped) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + /** + * Initialize an array with verification friendly data + * + * @param ptr pointer to the data to initialize + * @param size size (in bytes) of the data + * @param elemSize size (in bytes) of the individual elements + */ + private void initVerificationData(GenericPointer ptr, long size, long elemSize) { + for (long offset = 0; offset < size; offset++) { + byte data = (byte)getVerificationDataForOffset(offset, 1); + + if (ptr.isOnHeap()) { + UNSAFE.putByte(ptr.getObject(), ptr.getOffset() + offset, data); + } else { + UNSAFE.putByte(ptr.getOffset() + offset, data); + } + } + } + + /** + * Allocate a primitive array + * + * @param size size (in bytes) of all the array elements (elemSize * length) + * @param elemSize the size of the array elements + * + * @return a newly allocated primitive array + */ + Object allocArray(long size, long elemSize) { + int length = (int)(size / elemSize); + + switch ((int)elemSize) { + case 2: return new short[length]; + case 4: return new int[length]; + case 8: return new long[length]; + default: + throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the value of a primitive array entry + * + * @param ptr pointer to the data + * @param offset offset (in bytes) of the array element, relative to the first element in the array + * + * @return the array element, as an unsigned long + */ + private long getArrayElem(GenericPointer ptr, long offset, long elemSize) { + if (ptr.isOnHeap()) { + Object o = ptr.getObject(); + int index = (int)(offset / elemSize); + + if (o instanceof short[]) { + short[] arr = (short[])o; + return Short.toUnsignedLong(arr[index]); + } else if (o instanceof int[]) { + int[] arr = (int[])o; + return Integer.toUnsignedLong(arr[index]); + } else if (o instanceof long[]) { + long[] arr = (long[])o; + return arr[index]; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } else { + long addr = ptr.getOffset() + offset; + + switch ((int)elemSize) { + case 1: return Byte.toUnsignedLong(UNSAFE.getByte(addr)); + case 2: return Short.toUnsignedLong(UNSAFE.getShortUnaligned(null, addr)); + case 4: return Integer.toUnsignedLong(UNSAFE.getIntUnaligned(null, addr)); + case 8: return UNSAFE.getLongUnaligned(null, addr); + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + } + + private void putValue(long addr, long elemSize, long value) { + switch ((int)elemSize) { + case 1: UNSAFE.putByte(addr, (byte)value); break; + case 2: UNSAFE.putShortUnaligned(null, addr, (short)value); break; + case 4: UNSAFE.putIntUnaligned(null, addr, (int)value); break; + case 8: UNSAFE.putLongUnaligned(null, addr, value); break; + default: throw new IllegalArgumentException("Invalid element size: " + elemSize); + } + } + + /** + * Get the size of the elements for an array + * + * @param o a primitive heap array + * + * @return the size (in bytes) of the individual array elements + */ + private long getArrayElemSize(Object o) { + if (o instanceof short[]) { + return 2; + } else if (o instanceof int[]) { + return 4; + } else if (o instanceof long[]) { + return 8; + } else { + throw new IllegalArgumentException("Invalid object type: " + o.getClass().getName()); + } + } + + /** + * Byte swap a value + * + * @param value the value to swap, only the bytes*8 least significant bits are used + * @param size size (in bytes) of the value + * + * @return the byte swapped value in the bytes*8 least significant bits + */ + private long byteSwap(long value, long size) { + switch ((int)size) { + case 2: return Short.toUnsignedLong(Short.reverseBytes((short)value)); + case 4: return Integer.toUnsignedLong(Integer.reverseBytes((int)value)); + case 8: return Long.reverseBytes(value); + default: throw new IllegalArgumentException("Invalid element size: " + size); + } + } + + /** + * Verify data in a heap array which has *not* been byte swapped + * + * @param ptr the data to verify + * @param startOffset the offset (in bytes) at which to start the verification + * @param size size (in bytes) of the data to verify + * + * @throws RuntimeException if an error is found + */ + private void verifyUnswappedData(GenericPointer ptr, long startOffset, long size) { + for (long elemOffset = startOffset; elemOffset < startOffset + size; elemOffset++) { + byte expected = (byte)getVerificationDataForOffset(elemOffset, 1); + + byte actual; + if (ptr.isOnHeap()) { + actual = UNSAFE.getByte(ptr.getObject(), ptr.getOffset() + elemOffset); + } else { + actual = UNSAFE.getByte(ptr.getOffset() + elemOffset); + } + + if (expected != actual) { + throw new RuntimeException("startOffset: 0x" + Long.toHexString(startOffset) + + " size: 0x" + Long.toHexString(size) + + " elemOffset: 0x" + Long.toHexString(elemOffset) + + " expected: 0x" + Long.toHexString(expected) + + " != actual: 0x" + Long.toHexString(actual)); + } + } + } + + + /** + * Copy and byte swap data from the source to the destination + * + * This method will pre-populate the whole source and destination + * buffers with verification friendly data. It will then use + * copySwapMemory to fill part of the destination buffer with + * swapped data from the source. Some space (padding) will be + * left before and after the data in the destination buffer, which + * should not be touched/overwritten by the copy call. + * + * Note: Both source and destination buffers will be overwritten! + * + * @param src source buffer to copy from + * @param srcOffset the offset (in bytes) in the source buffer, relative to + * the first array element, at which to start reading data + * @param dst destination buffer to copy to + * @param dstOffset the offset (in bytes) in the destination + * buffer, relative to the first array element, at which to + * start writing data + * @param bufSize the size (in bytes) of the src and dst arrays + * @param copyBytes the size (in bytes) of the copy to perform, + * must be a multiple of elemSize + * @param elemSize the size (in bytes) of the elements to byte swap + * + * @throws RuntimeException if an error is found + */ + private void testCopySwap(GenericPointer src, long srcOffset, + GenericPointer dst, long dstOffset, + long bufSize, long copyBytes, long elemSize) { + if (!isAligned(copyBytes, elemSize)) { + throw new IllegalArgumentException( + "copyBytes (" + copyBytes + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (src.isOnHeap() && !isAligned(srcOffset, elemSize)) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (dst.isOnHeap() && !isAligned(dstOffset, elemSize)) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") must be a multiple of elemSize (" + elemSize + ")"); + } + if (srcOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "srcOffset (" + srcOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + if (dstOffset + copyBytes > bufSize) { + throw new IllegalArgumentException( + "dstOffset (" + dstOffset + ") + copyBytes (" + copyBytes + ") > bufSize (" + bufSize + ")"); + } + + // Initialize the whole source buffer with a verification friendly pattern (no 0x00 bytes) + initVerificationData(src, bufSize, elemSize); + if (!src.equals(dst)) { + initVerificationData(dst, bufSize, elemSize); + } + + if (DEBUG) { + System.out.println("===before==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Copy & swap data into the middle of the destination buffer + UNSAFE.copySwapMemory(src.getObject(), + src.getOffset() + srcOffset, + dst.getObject(), + dst.getOffset() + dstOffset, + copyBytes, + elemSize); + + if (DEBUG) { + System.out.println("===after==="); + for (int offset = 0; offset < bufSize; offset += elemSize) { + long srcValue = getArrayElem(src, offset, elemSize); + long dstValue = getArrayElem(dst, offset, elemSize); + + System.out.println("offs=0x" + Long.toHexString(Integer.toUnsignedLong(offset)) + + " src=0x" + Long.toHexString(srcValue) + + " dst=0x" + Long.toHexString(dstValue)); + } + } + + // Verify the the front padding is unchanged + verifyUnswappedData(dst, 0, dstOffset); + + // Verify swapped data + verifySwappedData(dst, srcOffset, dstOffset, copyBytes, elemSize); + + // Verify that the back back padding is unchanged + long frontAndDataBytes = dstOffset + copyBytes; + long trailingBytes = bufSize - frontAndDataBytes; + verifyUnswappedData(dst, frontAndDataBytes, trailingBytes); + } + + /** + * Test various configurations copy-swapping from one buffer to the other + * + * @param src the source buffer to copy from + * @param dst the destination buffer to copy to + * @param size size (in bytes) of the buffers + * @param elemSize size (in bytes) of the individual elements + * + * @throws RuntimeException if an error is found + */ + public void testBufferPair(GenericPointer src, GenericPointer dst, long size, long elemSize) { + // offset in source from which to start reading data + for (long srcOffset = 0; srcOffset < size; srcOffset += (src.isOnHeap() ? elemSize : 1)) { + + // offset in destination at which to start writing data + for (int dstOffset = 0; dstOffset < size; dstOffset += (dst.isOnHeap() ? elemSize : 1)) { + + // number of bytes to copy + long maxCopyBytes = Math.min(size - srcOffset, size - dstOffset); + for (long copyBytes = 0; copyBytes < maxCopyBytes; copyBytes += elemSize) { + try { + testCopySwap(src, srcOffset, dst, dstOffset, size, copyBytes, elemSize); + } catch (RuntimeException e) { + // Wrap the exception in another exception to catch the relevant configuration data + throw new RuntimeException("testBufferPair: " + + "src=" + src + + " dst=" + dst + + " elemSize=0x" + Long.toHexString(elemSize) + + " copyBytes=0x" + Long.toHexString(copyBytes) + + " srcOffset=0x" + Long.toHexString(srcOffset) + + " dstOffset=0x" + Long.toHexString(dstOffset), + e); + } + } + } + } + } + + /** + * Test copying between various permutations of buffers + * + * @param buffers buffers to permute (src x dst) + * @param size size (in bytes) of buffers + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + public void testPermuteBuffers(GenericPointer[] buffers, long size, long elemSize) { + for (int srcIndex = 0; srcIndex < buffers.length; srcIndex++) { + for (int dstIndex = 0; dstIndex < buffers.length; dstIndex++) { + testBufferPair(buffers[srcIndex], buffers[dstIndex], size, elemSize); + } + } + } + + /** + * Test copying of a specific element size + * + * @param size size (in bytes) of buffers to allocate + * @param elemSize size (in bytes) of individual elements + * + * @throws RuntimeException if an error is found + */ + private void testElemSize(long size, long elemSize) { + long buf1Raw = 0; + long buf2Raw = 0; + + try { + buf1Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf1 = alignUp(buf1Raw, BASE_ALIGNMENT); + + buf2Raw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + long buf2 = alignUp(buf2Raw, BASE_ALIGNMENT); + + GenericPointer[] buffers = { + new GenericPointer(buf1), + new GenericPointer(buf2), + new GenericPointer(allocArray(size, elemSize)), + new GenericPointer(allocArray(size, elemSize)) + }; + + testPermuteBuffers(buffers, size, elemSize); + } finally { + if (buf1Raw != 0) { + UNSAFE.freeMemory(buf1Raw); + } + if (buf2Raw != 0) { + UNSAFE.freeMemory(buf2Raw); + } + } + } + + /** + * Verify that small copy swaps work + */ + private void testSmallCopy() { + int smallBufSize = SMALL_COPY_SIZE; + + // Test various element types and heap/native combinations + for (long elemSize = 2; elemSize <= 8; elemSize <<= 1) { + testElemSize(smallBufSize, elemSize); + } + } + + + /** + * Verify that large copy swaps work + */ + private void testLargeCopy() { + long size = 2 * GB + 8; + long bufRaw = 0; + + // Check that a large native copy succeeds + try { + try { + bufRaw = UNSAFE.allocateMemory(size + BASE_ALIGNMENT); + } catch (OutOfMemoryError e) { + // Accept failure, skip test + return; + } + + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + + UNSAFE.copySwapMemory(null, buf, null, buf, size, 8); + } catch (Exception e) { + throw new RuntimeException("copySwapMemory of large buffer failed"); + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Run positive tests + * + * @throws RuntimeException if an error is found + */ + private void testPositive() { + testSmallCopy(); + testLargeCopy(); + } + + /** + * Run negative tests, testing corner cases and the various exceptions + * + * @throws RuntimeException if an error is found + */ + private void testNegative() { + long bufRaw = 0; + + try { + bufRaw = UNSAFE.allocateMemory(1024); + long buf = alignUp(bufRaw, BASE_ALIGNMENT); + short[] arr = new short[16]; + + // Check various illegal element sizes + for (int elemSize = 2; elemSize <= 8; elemSize <<= 1) { + long[] illegalSizes = { -1, 1, elemSize - 1, elemSize + 1, elemSize * 2 - 1 }; + for (long size : illegalSizes) { + try { + // Check that illegal elemSize throws an IAE + UNSAFE.copySwapMemory(null, buf, null, buf, size, elemSize); + throw new RuntimeException("copySwapMemory failed to throw IAE for size=" + size + " elemSize=" + elemSize); + } catch (IllegalArgumentException e) { + // good + } + } + } + + try { + // Check that negative srcOffset throws an IAE + UNSAFE.copySwapMemory(arr, -1, arr, UNSAFE.arrayBaseOffset(arr.getClass()), 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset=-1"); + } catch (IllegalArgumentException e) { + // good + } + + try { + // Check that negative dstOffset throws an IAE + UNSAFE.copySwapMemory(arr, UNSAFE.arrayBaseOffset(arr.getClass()), arr, -1, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset=-1"); + } catch (IllegalArgumentException e) { + // good + } + + long illegalElemSizes[] = { 0, 1, 3, 5, 6, 7, 9, 10, -1 }; + for (long elemSize : illegalElemSizes) { + try { + // Check that elemSize 1 throws an IAE + UNSAFE.copySwapMemory(null, buf, null, buf, 16, elemSize); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (IllegalArgumentException e) { + // good + } + } + + try { + // Check that a NULL source throws NPE + UNSAFE.copySwapMemory(null, 0, null, buf, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (NullPointerException e) { + // good + } + + try { + // Check that a NULL destination throws NPE + UNSAFE.copySwapMemory(null, buf, null, 0, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (NullPointerException e) { + // good + } + + try { + // Check that a reference array destination throws IAE + UNSAFE.copySwapMemory(null, buf, new Object[16], UNSAFE.arrayBaseOffset(Object[].class), 16, 8); + throw new RuntimeException("copySwapMemory failed to throw NPE"); + } catch (IllegalArgumentException e) { + // good + } + + // Check that invalid source & dest pointers throw IAEs (only relevant on 32-bit platforms) + if (UNSAFE.addressSize() == 4) { + long invalidPtr = (long)1 << 35; // Pick a random bit in upper 32 bits + + try { + // Check that an invalid (not 32-bit clean) source pointer throws IAE + UNSAFE.copySwapMemory(null, invalidPtr, null, buf, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for srcOffset 0x" + + Long.toHexString(invalidPtr)); + } catch (IllegalArgumentException e) { + // good + } + + try { + // Check that an invalid (not 32-bit clean) source pointer throws IAE + UNSAFE.copySwapMemory(null, buf, null, invalidPtr, 16, 2); + throw new RuntimeException("copySwapMemory failed to throw IAE for destOffset 0x" + + Long.toHexString(invalidPtr)); + } catch (IllegalArgumentException e) { + // good + } + } + } finally { + if (bufRaw != 0) { + UNSAFE.freeMemory(bufRaw); + } + } + } + + /** + * Run all tests + * + * @throws RuntimeException if an error is found + */ + private void test() { + testPositive(); + testNegative(); + } + + public static void main(String[] args) { + CopySwap cs = new CopySwap(); + cs.test(); + } + + /** + * Helper class to represent a "pointer" - either a heap array or + * a pointer to a native buffer. + * + * In the case of a native pointer, the Object is null and the offset is + * the absolute address of the native buffer. + * + * In the case of a heap object, the Object is a primitive array, and + * the offset will be set to the base offset to the first element, meaning + * the object and the offset together form a double-register pointer. + */ + static class GenericPointer { + private final Object o; + private final long offset; + + private GenericPointer(Object o, long offset) { + this.o = o; + this.offset = offset; + } + + public String toString() { + return "GenericPointer(o={" + o + "}, offset=0x" + Long.toHexString(offset) + ")"; + } + + public boolean equals(Object other) { + if (!(other instanceof GenericPointer)) { + return false; + } + + GenericPointer otherp = (GenericPointer)other; + + return o == otherp.o && offset == otherp.offset; + } + + GenericPointer(Object o) { + this(o, UNSAFE.arrayBaseOffset(o.getClass())); + } + + GenericPointer(long offset) { + this(null, offset); + } + + public boolean isOnHeap() { + return o != null; + } + + public Object getObject() { + return o; + } + + public long getOffset() { + return offset; + } + } +} diff --git a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java index f409e2b4cd5..6f87dc68813 100644 --- a/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java +++ b/jdk/test/jdk/nio/zipfs/MultiReleaseJarTest.java @@ -44,7 +44,7 @@ import org.testng.Assert; import org.testng.annotations.*; public class MultiReleaseJarTest { - final private int MAJOR_VERSION= Version.current().major(); + final private int MAJOR_VERSION = Version.current().major(); final private String userdir = System.getProperty("user.dir","."); final private Map stringEnv = new HashMap<>(); diff --git a/jdk/test/sample/TEST.properties b/jdk/test/sample/TEST.properties new file mode 100644 index 00000000000..8e5f78afde3 --- /dev/null +++ b/jdk/test/sample/TEST.properties @@ -0,0 +1 @@ +external.lib.roots = ../../ diff --git a/jdk/test/sample/chatserver/ChatTest.java b/jdk/test/sample/chatserver/ChatTest.java index 654819b9fa5..dcfe4d3dd6c 100644 --- a/jdk/test/sample/chatserver/ChatTest.java +++ b/jdk/test/sample/chatserver/ChatTest.java @@ -25,9 +25,9 @@ /* @test * @summary Test chat server chatserver test * - * @library ../../../src/sample/share/nio/chatserver + * @library /src/sample/share/nio/chatserver * @build ChatTest ChatServer Client ClientReader DataReader MessageReader NameReader - * @run main ChatTest + * @run testng ChatTest */ import java.io.*; @@ -38,10 +38,13 @@ import java.util.Collections; import java.util.List; import java.util.concurrent.CyclicBarrier; +import org.testng.annotations.Test; + public class ChatTest { public static int listeningPort = 0; - public static void main(String[] args) throws Throwable { + @Test + public static void doTest() throws Throwable { testStartStop(); testPortOpen(); testAsksForName(); diff --git a/jdk/test/sample/mergesort/MergeSortTest.java b/jdk/test/sample/mergesort/MergeSortTest.java index e38a0e03413..fb082c21a56 100644 --- a/jdk/test/sample/mergesort/MergeSortTest.java +++ b/jdk/test/sample/mergesort/MergeSortTest.java @@ -25,14 +25,16 @@ /* @test * @summary Test MergeSort * - * @library ../../../src/sample/share/forkjoin/mergesort + * @library /src/sample/share/forkjoin/mergesort * @build MergeSortTest MergeDemo MergeSort - * @run main MergeSortTest + * @run testng MergeSortTest */ import java.util.Arrays; import java.util.Random; +import org.testng.annotations.Test; + public class MergeSortTest { private Random random; private MergeSort target; @@ -42,7 +44,8 @@ public class MergeSortTest { this.target = target; } - public static void main(String[] args) { + @Test + public static void doTest() { MergeSortTest test = new MergeSortTest(new Random(), new MergeSort(Runtime.getRuntime().availableProcessors() * 4)); test.run(); } diff --git a/jdk/test/sun/java2d/marlin/CrashNaNTest.java b/jdk/test/sun/java2d/marlin/CrashNaNTest.java new file mode 100644 index 00000000000..01e32dd6c11 --- /dev/null +++ b/jdk/test/sun/java2d/marlin/CrashNaNTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.RenderingHints; +import java.awt.geom.Path2D; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import static java.lang.Double.NaN; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8149338 + * @summary Verifies that Marlin supports NaN coordinates and no JVM crash happens ! + * @run main CrashNaNTest + */ +public class CrashNaNTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(String argv[]) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + final int width = 400; + final int height = 400; + + final BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setBackground(Color.WHITE); + g2d.clearRect(0, 0, width, height); + + final Path2D.Double path = new Path2D.Double(); + path.moveTo(30, 30); + path.lineTo(100, 100); + + for (int i = 0; i < 20000; i++) { + path.lineTo(110 + 0.01 * i, 110); + path.lineTo(111 + 0.01 * i, 100); + } + + path.lineTo(NaN, 200); + path.lineTo(200, 200); + path.lineTo(200, NaN); + path.lineTo(300, 300); + path.lineTo(NaN, NaN); + path.lineTo(100, 100); + path.closePath(); + + final Path2D.Double path2 = new Path2D.Double(); + path2.moveTo(0,0); + path2.lineTo(width,height); + path2.lineTo(10, 10); + path2.closePath(); + + for (int i = 0; i < 1; i++) { + final long start = System.nanoTime(); + g2d.setColor(Color.BLUE); + g2d.fill(path); + + g2d.fill(path2); + + final long time = System.nanoTime() - start; + System.out.println("paint: duration= " + (1e-6 * time) + " ms."); + } + + if (SAVE_IMAGE) { + try { + final File file = new File("CrashNaNTest.png"); + System.out.println("Writing file: " + + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + System.out.println("Writing file failure:"); + ex.printStackTrace(); + } + } + } finally { + g2d.dispose(); + } + } +} diff --git a/jdk/test/sun/java2d/marlin/CrashPaintTest.java b/jdk/test/sun/java2d/marlin/CrashPaintTest.java new file mode 100644 index 00000000000..cf710bc83a5 --- /dev/null +++ b/jdk/test/sun/java2d/marlin/CrashPaintTest.java @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Color; +import java.awt.Graphics2D; +import java.awt.Paint; +import java.awt.PaintContext; +import java.awt.Rectangle; +import java.awt.RenderingHints; +import java.awt.TexturePaint; +import java.awt.geom.AffineTransform; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Rectangle2D; +import java.awt.image.BufferedImage; +import java.awt.image.ColorModel; +import java.awt.image.Raster; +import java.io.File; +import java.io.IOException; +import java.util.Locale; +import java.util.logging.Handler; +import java.util.logging.LogRecord; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8148886 + * @summary Verifies that Marlin supports reentrant operations (ThreadLocal) + * like in custom Paint or custom Composite + * @run main CrashPaintTest + */ +public class CrashPaintTest { + + static final boolean SAVE_IMAGE = false; + + public static void main(String argv[]) { + Locale.setDefault(Locale.US); + + // initialize j.u.l Looger: + final Logger log = Logger.getLogger("sun.java2d.marlin"); + log.addHandler(new Handler() { + @Override + public void publish(LogRecord record) { + Throwable th = record.getThrown(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); + + throw new RuntimeException("Test failed: ", th); + } + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + } + }); + + // enable Marlin logging & internal checks: + System.setProperty("sun.java2d.renderer.log", "true"); + System.setProperty("sun.java2d.renderer.useLogger", "true"); + System.setProperty("sun.java2d.renderer.doChecks", "true"); + + // Force using thread-local storage: + System.setProperty("sun.java2d.renderer.useThreadLocal", "true"); + // Force smaller pixelsize to force using array caches: + System.setProperty("sun.java2d.renderer.pixelsize", "256"); + + final int width = 300; + final int height = 300; + + final BufferedImage image = new BufferedImage(width, height, + BufferedImage.TYPE_INT_ARGB); + + final Graphics2D g2d = (Graphics2D) image.getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + + g2d.setBackground(Color.WHITE); + g2d.clearRect(0, 0, width, height); + + final Ellipse2D.Double ellipse + = new Ellipse2D.Double(0, 0, width, height); + + final Paint paint = new CustomPaint(100); + + for (int i = 0; i < 20; i++) { + final long start = System.nanoTime(); + g2d.setPaint(paint); + g2d.fill(ellipse); + + g2d.setColor(Color.GREEN); + g2d.draw(ellipse); + + final long time = System.nanoTime() - start; + System.out.println("paint: duration= " + (1e-6 * time) + " ms."); + } + + if (SAVE_IMAGE) { + try { + final File file = new File("CrashPaintTest.png"); + System.out.println("Writing file: " + + file.getAbsolutePath()); + ImageIO.write(image, "PNG", file); + } catch (IOException ex) { + System.out.println("Writing file failure:"); + ex.printStackTrace(); + } + } + + // Check image on few pixels: + final Raster raster = image.getData(); + + // 170, 175 = blue + checkPixel(raster, 170, 175, Color.BLUE.getRGB()); + // 50, 50 = blue + checkPixel(raster, 50, 50, Color.BLUE.getRGB()); + + // 190, 110 = pink + checkPixel(raster, 190, 110, Color.PINK.getRGB()); + // 280, 210 = pink + checkPixel(raster, 280, 210, Color.PINK.getRGB()); + + } finally { + g2d.dispose(); + } + } + + private static void checkPixel(final Raster raster, + final int x, final int y, + final int expected) { + + final int[] rgb = (int[]) raster.getDataElements(x, y, null); + + if (rgb[0] != expected) { + throw new IllegalStateException("bad pixel at (" + x + ", " + y + + ") = " + rgb[0] + " expected: " + expected); + } + } + + private static class CustomPaint extends TexturePaint { + private int size; + + CustomPaint(final int size) { + super(new BufferedImage(size, size, + BufferedImage.TYPE_INT_ARGB), + new Rectangle2D.Double(0, 0, size, size) + ); + this.size = size; + } + + @Override + public PaintContext createContext(ColorModel cm, + Rectangle deviceBounds, + Rectangle2D userBounds, + AffineTransform at, + RenderingHints hints) { + + // Fill bufferedImage using + final Graphics2D g2d = (Graphics2D) getImage().getGraphics(); + try { + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, + RenderingHints.VALUE_ANTIALIAS_ON); + g2d.setBackground(Color.PINK); + g2d.clearRect(0, 0, size, size); + + g2d.setColor(Color.BLUE); + g2d.drawRect(0, 0, size, size); + + g2d.fillOval(size / 10, size / 10, + size * 8 / 10, size * 8 / 10); + + } finally { + g2d.dispose(); + } + + return super.createContext(cm, deviceBounds, userBounds, at, hints); + } + } +} diff --git a/jdk/test/sun/java2d/marlin/TextClipErrorTest.java b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java index efce137256c..c6d42ceb305 100644 --- a/jdk/test/sun/java2d/marlin/TextClipErrorTest.java +++ b/jdk/test/sun/java2d/marlin/TextClipErrorTest.java @@ -69,24 +69,12 @@ public class TextClipErrorTest { @Override public void publish(LogRecord record) { Throwable th = record.getThrown(); - // detect potential Throwable thrown by XxxArrayCache.check(): - if (th != null && th.getClass() == Throwable.class) { - StackTraceElement[] stackElements = th.getStackTrace(); + // detect any Throwable: + if (th != null) { + System.out.println("Test failed:\n" + record.getMessage()); + th.printStackTrace(System.out); - for (int i = 0; i < stackElements.length; i++) { - StackTraceElement e = stackElements[i]; - - if (e.getClassName().startsWith("sun.java2d.marlin") - && e.getClassName().contains("ArrayCache") - && "check".equals(e.getMethodName())) - { - System.out.println("Test failed:\n" - + record.getMessage()); - th.printStackTrace(System.out); - - throw new RuntimeException("Test failed: ", th); - } - } + throw new RuntimeException("Test failed: ", th); } } diff --git a/jdk/test/sun/misc/SunMiscSignalTest.java b/jdk/test/sun/misc/SunMiscSignalTest.java index 4179b000b85..3dbab4f6cc0 100644 --- a/jdk/test/sun/misc/SunMiscSignalTest.java +++ b/jdk/test/sun/misc/SunMiscSignalTest.java @@ -180,6 +180,12 @@ public class SunMiscSignalTest { return newArray; } + // Return true if the signal is one of the shutdown signals known to the VM + private static boolean isShutdownSignal(Signal signal) { + String name = signal.getName(); + return name.equals("INT") || name.equals("HUP") || name.equals("TERM"); + } + /** * Quick verification of supported signals using sun.misc.Signal. * @@ -201,14 +207,24 @@ public class SunMiscSignalTest { Assert.assertEquals(signal.toString(), "SIG" + name, "toString() mismatch, "); try { - SignalHandler old = Signal.handle(signal, h); + orig = Signal.handle(signal, h); + printf("oldHandler: %s%n", orig); Assert.assertEquals(CanRegister.YES, register, "Unexpected handle succeeded " + name); try { Signal.raise(signal); Assert.assertEquals(CanRaise.YES, raise, "Unexpected raise success for " + name); Invoked inv = h.semaphore().tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS) ? Invoked.YES : Invoked.NO; - Assert.assertEquals(inv, invoked, "handler not invoked;"); + if (!isShutdownSignal(signal)) { + // Normal case + Assert.assertEquals(inv, invoked, "handler not invoked;"); + } else { + if (orig == SignalHandler.SIG_IGN) { + Assert.assertEquals(inv, Invoked.NO, "handler should not be invoked"); + } else { + Assert.assertEquals(inv, invoked, "handler not invoked;"); + } + } } catch (IllegalArgumentException uoe3) { Assert.assertNotEquals(CanRaise.YES, raise, "raise failed for " + name + ": " + uoe3.getMessage()); @@ -270,14 +286,22 @@ public class SunMiscSignalTest { } // Test expected exception when raising a signal when no handler defined - @Test(expectedExceptions = IllegalArgumentException.class) + @Test static void testRaiseNoConsumer() { Signal signal = new Signal("INT"); SignalHandler orig = null; try { - Signal.handle(signal, SignalHandler.SIG_DFL); + orig = Signal.handle(signal, SignalHandler.SIG_DFL); + printf("oldHandler: %s%n", orig); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for TERM means it cannot be handled + return; + } Signal.raise(signal); - } finally { + Assert.fail("Should have thrown IllegalArgumentException"); + } catch (IllegalArgumentException iae) { + printf("IAE message: %s%n", iae.getMessage()); + } finally { // Restore original signal handler if (orig != null && signal != null) { Signal.handle(signal, orig); @@ -296,7 +320,13 @@ public class SunMiscSignalTest { } Handler handler = new Handler(); Signal signal = new Signal("INT"); - Signal.handle(signal, handler); + SignalHandler orig = Signal.handle(signal, handler); + printf("oldHandler: %s%n", orig); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for INT means it cannot be handled + return; + } + Signal.raise(signal); boolean handled = handler.semaphore() .tryAcquire(Utils.adjustTimeout(100L), TimeUnit.MILLISECONDS); @@ -332,6 +362,10 @@ public class SunMiscSignalTest { Handler h1 = new Handler(); Handler h2 = new Handler(); SignalHandler orig = Signal.handle(signal, h1); + if (orig == SignalHandler.SIG_IGN) { + // SIG_IGN for TERM means it cannot be handled + return; + } try { SignalHandler prev = Signal.handle(signal, h2); diff --git a/jdk/test/sun/misc/Version/Version.java b/jdk/test/sun/misc/Version/Version.java deleted file mode 100644 index a2b11242bfc..00000000000 --- a/jdk/test/sun/misc/Version/Version.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. - * 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 6994413 8134365 - * @summary Check the JDK and JVM version returned by sun.misc.Version - * matches the versions defined in the system properties. - * Should use the API described in JDK-8136651 when available - * @modules java.base/sun.misc - * @compile -XDignore.symbol.file Version.java - * @run main Version - */ - -import static sun.misc.Version.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class Version { - - public static void main(String[] args) throws Exception { - VersionInfo jdk = newVersionInfo(System.getProperty("java.runtime.version")); - VersionInfo v1 = new VersionInfo(jdkMajorVersion(), - jdkMinorVersion(), - jdkSecurityVersion(), - jdkPatchVersion(), - jdkBuildNumber()); - System.out.println("JDK version = " + jdk + " " + v1); - if (!jdk.equals(v1)) { - throw new RuntimeException("Unmatched version: " + jdk + " vs " + v1); - } - VersionInfo jvm = newVersionInfo(System.getProperty("java.vm.version")); - VersionInfo v2 = new VersionInfo(jvmMajorVersion(), - jvmMinorVersion(), - jvmSecurityVersion(), - jvmPatchVersion(), - jvmBuildNumber()); - System.out.println("JVM version = " + jvm + " " + v2); - if (!jvm.equals(v2)) { - throw new RuntimeException("Unmatched version: " + jvm + " vs " + v2); - } - } - - static class VersionInfo { - final int major; - final int minor; - final int security; - final int patch; - final int build; - VersionInfo(int major, int minor, int security, - int patch, int build) { - this.major = major; - this.minor = minor; - this.security = security; - this.patch = patch; - this.build = build; - } - - VersionInfo(int[] fields) { - this.major = fields[0]; - this.minor = fields[1]; - this.security = fields[2]; - this.patch = fields[3]; - this.build = fields[4]; - } - - public boolean equals(VersionInfo v) { - return (this.major == v.major && this.minor == v.minor && - this.security == v.security && this.patch == v.patch && - this.build == v.build); - } - - public String toString() { - StringBuilder sb = new StringBuilder(); - // Do not include trailing zeros - if (patch > 0) { - sb.insert(0, "." + patch); - } - if (security > 0 || sb.length() > 0) { - sb.insert(0, "." + security); - } - if (minor > 0 || sb.length() > 0) { - sb.insert(0, "." + minor); - } - sb.insert(0, major); - - if (build >= 0) - sb.append("+" + build); - - return sb.toString(); - } - } - - private static VersionInfo newVersionInfo(String version) throws Exception { - // Version string fromat as defined by JEP-223 - String jep223Pattern = - "^([0-9]+)(\\.([0-9]+))?(\\.([0-9]+))?(\\.([0-9]+))?" + // $VNUM - "(-([a-zA-Z]+))?(\\.([a-zA-Z]+))?" + // $PRE - "(\\+([0-9]+))?" + // Build Number - "(([-a-zA-Z0-9.]+))?$"; // $OPT - - // Pattern group index for: Major, Minor, Security, Patch, Build - int[] groups = {1, 3, 5, 7, 13}; - // Default values for Major, Minor, Security, Patch, Build - int[] versionFields = {0, 0, 0, 0, 0}; - - Pattern pattern = Pattern.compile(jep223Pattern); - Matcher matcher = pattern.matcher(version); - if (matcher.matches()) { - for (int i = 0; i < versionFields.length; i++) { - String field = matcher.group(groups[i]); - versionFields[i] = (field != null) ? Integer.parseInt(field) : 0; - } - } - - VersionInfo vi = new VersionInfo(versionFields); - System.out.printf("newVersionInfo: input=%s output=%s\n", version, vi); - return vi; - } -} diff --git a/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java new file mode 100644 index 00000000000..aeca6c6b50d --- /dev/null +++ b/jdk/test/sun/net/www/protocol/jar/MultiReleaseJarURLConnection.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * 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 8132734 + * @summary Test that URL connections to multi-release jars can be runtime versioned + * @library /lib/testlibrary/java/util/jar + * @build Compiler JarBuilder CreateMultiReleaseTestJars + * @run testng MultiReleaseJarURLConnection + */ + +import java.io.IOException; +import java.io.InputStream; +import java.net.JarURLConnection; +import java.net.URL; +import java.net.URLConnection; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.jar.JarFile; + +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +public class MultiReleaseJarURLConnection { + String userdir = System.getProperty("user.dir","."); + String file = userdir + "/signed-multi-release.jar"; + + @BeforeClass + public void initialize() throws Exception { + CreateMultiReleaseTestJars creator = new CreateMultiReleaseTestJars(); + creator.compileEntries(); + creator.buildMultiReleaseJar(); + creator.buildSignedMultiReleaseJar(); + } + + @AfterClass + public void close() throws IOException { + Files.delete(Paths.get(userdir, "multi-release.jar")); + Files.delete(Paths.get(userdir, "signed-multi-release.jar")); + } + + @DataProvider(name = "data") + public Object[][] createData() { + return new Object[][]{ + {"unsigned file", userdir + "/multi-release.jar"}, + {"signed file", userdir + "/signed-multi-release.jar"}, + }; + } + + @Test(dataProvider = "data") + public void testRuntimeVersioning(String ignore, String file) throws Exception { + String urlFile = "jar:file:" + file + "!/"; + String urlEntry = urlFile + "version/Version.java"; + + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + // #runtime is "magic" + Assert.assertTrue(readAndCompare(new URL(urlEntry + "#runtime"), "return 9")); + // #fragment or any other fragment is not magic + Assert.assertTrue(readAndCompare(new URL(urlEntry + "#fragment"), "return 8")); + // cached entities not affected + Assert.assertTrue(readAndCompare(new URL(urlEntry), "return 8")); + } + + @Test(dataProvider = "data") + public void testCachedJars(String ignore, String file) throws Exception { + String urlFile = "jar:file:" + file + "!/"; + + URL rootUrl = new URL(urlFile); + JarURLConnection juc = (JarURLConnection)rootUrl.openConnection(); + JarFile rootJar = juc.getJarFile(); + JarFile.Release root = rootJar.getVersion(); + + URL runtimeUrl = new URL(urlFile + "#runtime"); + juc = (JarURLConnection)runtimeUrl.openConnection(); + JarFile runtimeJar = juc.getJarFile(); + JarFile.Release runtime = runtimeJar.getVersion(); + Assert.assertNotEquals(root, runtime); + + juc = (JarURLConnection)rootUrl.openConnection(); + JarFile jar = juc.getJarFile(); + Assert.assertEquals(jar.getVersion(), root); + Assert.assertEquals(jar, rootJar); + + juc = (JarURLConnection)runtimeUrl.openConnection(); + jar = juc.getJarFile(); + Assert.assertEquals(jar.getVersion(), runtime); + Assert.assertEquals(jar, runtimeJar); + + rootJar.close(); + runtimeJar.close(); + jar.close(); // probably not needed + } + + private boolean readAndCompare(URL url, String match) throws Exception { + boolean result; + // necessary to do it this way, instead of openStream(), so we can + // close underlying JarFile, otherwise windows can't delete the file + URLConnection conn = url.openConnection(); + try (InputStream is = conn.getInputStream()) { + byte[] bytes = is.readAllBytes(); + result = (new String(bytes)).contains(match); + } + if (conn instanceof JarURLConnection) { + ((JarURLConnection)conn).getJarFile().close(); + } + return result; + } +} diff --git a/jdk/test/sun/security/mscapi/SignatureOffsets.java b/jdk/test/sun/security/mscapi/SignatureOffsets.java index 4c710396840..128cc00ca04 100644 --- a/jdk/test/sun/security/mscapi/SignatureOffsets.java +++ b/jdk/test/sun/security/mscapi/SignatureOffsets.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.security.SignatureException; /* * @test * @bug 8050374 - * @key randomness + * @key randomness intermittent * @summary This test validates signature verification * Signature.verify(byte[], int, int). The test uses RandomFactory to * get random set of clear text data to sign. After the signature diff --git a/jdk/test/sun/security/pkcs11/PKCS11Test.java b/jdk/test/sun/security/pkcs11/PKCS11Test.java index 46621e1ae2e..bd85ea6058f 100644 --- a/jdk/test/sun/security/pkcs11/PKCS11Test.java +++ b/jdk/test/sun/security/pkcs11/PKCS11Test.java @@ -380,7 +380,9 @@ public abstract class PKCS11Test { } static double getNSSInfo(String library) { - String nssHeader = "$Header: NSS"; + // look for two types of headers in NSS libraries + String nssHeader1 = "$Header: NSS"; + String nssHeader2 = "Version: NSS"; boolean found = false; String s = null; int i = 0; @@ -408,7 +410,8 @@ public abstract class PKCS11Test { } s = new String(data, 0, read); - if ((i = s.indexOf(nssHeader)) > 0) { + i = s.indexOf(nssHeader1); + if (i > 0 || (i = s.indexOf(nssHeader2)) > 0) { found = true; // If the nssHeader is before 920 we can break, otherwise // we may not have the whole header so do another read. If diff --git a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java index 43a857f0c26..bd2fcdadc31 100644 --- a/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java +++ b/jdk/test/sun/security/provider/NSASuiteB/TestDSAGenParameterSpec.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import java.util.List; /* * @test * @bug 8075286 + * @key intermittent * @summary Verify that DSAGenParameterSpec can and can only be used to generate * DSA within some certain range of key sizes as described in the class * specification (L, N) as (1024, 160), (2048, 224), (2048, 256) and diff --git a/jdk/test/sun/security/rsa/SpecTest.java b/jdk/test/sun/security/rsa/SpecTest.java index d2ab0a8e79f..c13f1d91989 100644 --- a/jdk/test/sun/security/rsa/SpecTest.java +++ b/jdk/test/sun/security/rsa/SpecTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ import java.security.spec.RSAKeyGenParameterSpec; /** * @test * @bug 8044199 + * @key intermittent * @summary Check same KeyPair's private key and public key have same modulus. * also check public key's public exponent equals to given spec's public * exponent. diff --git a/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java b/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java new file mode 100644 index 00000000000..76f6a7b949a --- /dev/null +++ b/jdk/test/sun/security/ssl/DHKeyExchange/LegacyDHEKeyExchange.java @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8148108 + * @summary Disable Diffie-Hellman keys less than 1024 bits + * @run main/othervm -Djdk.tls.ephemeralDHKeySize=legacy LegacyDHEKeyExchange + */ + +import java.io.*; +import javax.net.ssl.*; + +public class LegacyDHEKeyExchange { + + /* + * ============================================================= + * Set the various variables needed for the tests, then + * specify what tests to run on each side. + */ + + /* + * Should we run the client or server in a separate thread? + * Both sides can throw exceptions, but do you have a preference + * as to which side should be the main thread. + */ + static boolean separateServerThread = false; + + /* + * Where do we find the keystores? + */ + static String pathToStores = "../../../../javax/net/ssl/etc"; + static String keyStoreFile = "keystore"; + static String trustStoreFile = "truststore"; + static String passwd = "passphrase"; + + /* + * Is the server ready to serve? + */ + volatile static boolean serverReady = false; + + /* + * Turn on SSL debugging? + */ + static boolean debug = false; + + /* + * If the client or server is doing some kind of object creation + * that the other side depends on, and that thread prematurely + * exits, you may experience a hang. The test harness will + * terminate all hung threads after its timeout has expired, + * currently 3 minutes by default, but you might try to be + * smart about it.... + */ + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault(); + SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket(serverPort); + + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + try (SSLSocket sslSocket = (SSLSocket)sslServerSocket.accept()) { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + throw new Exception( + "Leagcy DH keys (< 1024) should be restricted"); + } catch (SSLHandshakeException she) { + // ignore, client should terminate the connection + } finally { + sslServerSocket.close(); + } + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + while (!serverReady) { + Thread.sleep(50); + } + + SSLSocketFactory sslsf = + (SSLSocketFactory) SSLSocketFactory.getDefault(); + SSLSocket sslSocket = (SSLSocket) + sslsf.createSocket("localhost", serverPort); + + String[] suites = new String [] {"TLS_DHE_RSA_WITH_AES_128_CBC_SHA"}; + sslSocket.setEnabledCipherSuites(suites); + + try { + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + throw new Exception("Leagcy DH keys (< 1024) should be restricted"); + } catch (SSLHandshakeException she) { + // ignore, should be caused by algorithm constraints + } finally { + sslSocket.close(); + } + } + + /* + * ============================================================= + * The remainder is just support stuff + */ + + // use any free port by default + volatile int serverPort = 0; + + volatile Exception serverException = null; + volatile Exception clientException = null; + + public static void main(String[] args) throws Exception { + String keyFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + keyStoreFile; + String trustFilename = + System.getProperty("test.src", ".") + "/" + pathToStores + + "/" + trustStoreFile; + + System.setProperty("javax.net.ssl.keyStore", keyFilename); + System.setProperty("javax.net.ssl.keyStorePassword", passwd); + System.setProperty("javax.net.ssl.trustStore", trustFilename); + System.setProperty("javax.net.ssl.trustStorePassword", passwd); + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + + /* + * Start the tests. + */ + new LegacyDHEKeyExchange(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + LegacyDHEKeyExchange() throws Exception { + Exception startException = null; + try { + if (separateServerThread) { + startServer(true); + startClient(false); + } else { + startClient(true); + startServer(false); + } + } catch (Exception e) { + startException = e; + } + + /* + * Wait for other side to close down. + */ + if (separateServerThread) { + if (serverThread != null) { + serverThread.join(); + } + } else { + if (clientThread != null) { + clientThread.join(); + } + } + + /* + * When we get here, the test is pretty much over. + * Which side threw the error? + */ + Exception local; + Exception remote; + + if (separateServerThread) { + remote = serverException; + local = clientException; + } else { + remote = clientException; + local = serverException; + } + + Exception exception = null; + + /* + * Check various exception conditions. + */ + if ((local != null) && (remote != null)) { + // If both failed, return the curthread's exception. + local.initCause(remote); + exception = local; + } else if (local != null) { + exception = local; + } else if (remote != null) { + exception = remote; + } else if (startException != null) { + exception = startException; + } + + /* + * If there was an exception *AND* a startException, + * output it. + */ + if (exception != null) { + if (exception != startException && startException != null) { + exception.addSuppressed(startException); + } + throw exception; + } + + // Fall-through: no exception to throw! + } + + void startServer(boolean newThread) throws Exception { + if (newThread) { + serverThread = new Thread() { + @Override + public void run() { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Release the client, if not active already... + */ + System.err.println("Server died..."); + serverReady = true; + serverException = e; + } + } + }; + serverThread.start(); + } else { + try { + doServerSide(); + } catch (Exception e) { + serverException = e; + } finally { + serverReady = true; + } + } + } + + void startClient(boolean newThread) throws Exception { + if (newThread) { + clientThread = new Thread() { + @Override + public void run() { + try { + doClientSide(); + } catch (Exception e) { + /* + * Our client thread just died. + */ + System.err.println("Client died..."); + clientException = e; + } + } + }; + clientThread.start(); + } else { + try { + doClientSide(); + } catch (Exception e) { + clientException = e; + } + } + } +} diff --git a/jdk/test/tools/jar/JarEntryTime.java b/jdk/test/tools/jar/JarEntryTime.java index 701779c2828..1985bb1ab66 100644 --- a/jdk/test/tools/jar/JarEntryTime.java +++ b/jdk/test/tools/jar/JarEntryTime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.File; import java.io.PrintWriter; import java.nio.file.attribute.FileTime; +import java.util.Date; +import java.util.TimeZone; import sun.tools.jar.Main; public class JarEntryTime { @@ -39,6 +41,9 @@ public class JarEntryTime { // allow for e.g. rounding/truncation and networked/samba drives. static final long PRECISION = 10000L; + static final TimeZone TZ = TimeZone.getDefault(); + static final boolean DST = TZ.inDaylightTime(new Date()); + static boolean cleanup(File dir) throws Throwable { boolean rc = true; File[] x = dir.listFiles(); @@ -75,11 +80,13 @@ public class JarEntryTime { File dirOuter = new File("outer"); File dirInner = new File(dirOuter, "inner"); File jarFile = new File("JarEntryTime.jar"); + File testFile = new File("JarEntryTimeTest.txt"); // Remove any leftovers from prior run cleanup(dirInner); cleanup(dirOuter); jarFile.delete(); + testFile.delete(); /* Create a directory structure * outer/ @@ -129,23 +136,39 @@ public class JarEntryTime { check(cleanup(dirInner)); check(cleanup(dirOuter)); + try (PrintWriter pw = new PrintWriter(testFile)) { + pw.println("hello, world"); + } + final long start = testFile.lastModified(); + // Extract and check the last modified values are the current times. // See sun.tools.jar.Main extractJar(jarFile, true); + + try (PrintWriter pw = new PrintWriter(testFile)) { + pw.println("hello, world"); + } + final long end = testFile.lastModified(); + check(dirOuter.exists()); check(dirInner.exists()); check(fileInner.exists()); - checkFileTime(dirOuter.lastModified(), now); - checkFileTime(dirInner.lastModified(), now); - checkFileTime(fileInner.lastModified(), now); + checkFileTime(start, dirOuter.lastModified(), end); + checkFileTime(start, dirInner.lastModified(), end); + checkFileTime(start, fileInner.lastModified(), end); check(cleanup(dirInner)); check(cleanup(dirOuter)); check(jarFile.delete()); + check(testFile.delete()); } static void checkFileTime(long now, long original) { + if (isTimeSettingChanged()) { + return; + } + if (Math.abs(now - original) > PRECISION) { System.out.format("Extracted to %s, expected to be close to %s%n", FileTime.fromMillis(now), FileTime.fromMillis(original)); @@ -153,6 +176,27 @@ public class JarEntryTime { } } + static void checkFileTime(long start, long now, long end) { + if (isTimeSettingChanged()) { + return; + } + + if (now < start || now > end) { + System.out.format("Extracted to %s, " + + "expected to be after %s and before %s%n", + FileTime.fromMillis(now), + FileTime.fromMillis(start), + FileTime.fromMillis(end)); + fail(); + } + } + + private static boolean isTimeSettingChanged() { + TimeZone currentTZ = TimeZone.getDefault(); + boolean currentDST = currentTZ.inDaylightTime(new Date()); + return (!currentTZ.equals(TZ) || currentDST != DST); + } + //--------------------- Infrastructure --------------------------- static volatile int passed = 0, failed = 0; static void pass() {passed++;} diff --git a/jdk/test/tools/pack200/Pack200Test.java b/jdk/test/tools/pack200/Pack200Test.java index 9298e9723a8..fb6d9b1f83d 100644 --- a/jdk/test/tools/pack200/Pack200Test.java +++ b/jdk/test/tools/pack200/Pack200Test.java @@ -81,7 +81,9 @@ public class Pack200Test { System.out.println("Packing [" + in.toString() + "]"); // Call the packer Utils.pack(jarFile, packFile); + System.out.println("Done Packing [" + in.toString() + "]"); jarFile.close(); + System.out.println("Start leak check"); leakCheck(); System.out.println(" Unpacking using java unpacker"); diff --git a/jdk/test/tools/pack200/Utils.java b/jdk/test/tools/pack200/Utils.java index f0c29a597b5..60f2d0c50bc 100644 --- a/jdk/test/tools/pack200/Utils.java +++ b/jdk/test/tools/pack200/Utils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -324,6 +324,9 @@ class Utils { private static void findFiles0(File startDir, List list, FileFilter filter) throws IOException { File[] foundFiles = startDir.listFiles(filter); + if (foundFiles == null) { + return; + } list.addAll(Arrays.asList(foundFiles)); File[] dirs = startDir.listFiles(DIR_FILTER); for (File dir : dirs) { diff --git a/langtools/.hgtags b/langtools/.hgtags index c6a2d3a75cd..5fb34d8884a 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -349,3 +349,6 @@ cb73b474703e2de266542b505cffd658bcc052da jdk-9+99 3f60a4808377a276f6398ff19e61c1b9086f4d97 jdk-9+104 81bd82222f8a1f2b291a44a49e063973caa4e73b jdk-9+105 dd05d3761a341143ef4a6b1a245e0960cc125b76 jdk-9+106 +7a0c343551497bd0e38ad69a77cc57d9f396615a jdk-9+107 +fd18a155ad22f62e06a9b74850ab8609d415c752 jdk-9+108 +f5991c73ed73b9a355a090b65c8d7fb9a1901f89 jdk-9+109 diff --git a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java index 950daf73328..447c9647b1a 100644 --- a/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java +++ b/langtools/src/java.compiler/share/classes/javax/tools/ToolProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,12 +28,7 @@ package javax.tools; import java.lang.ref.Reference; import java.lang.ref.WeakReference; import java.util.HashMap; -import java.util.Locale; import java.util.Map; -import java.util.logging.Logger; -import java.util.logging.Level; - -import static java.util.logging.Level.*; /** * Provides methods for locating tool providers, for example, @@ -45,47 +40,6 @@ import static java.util.logging.Level.*; */ public class ToolProvider { - private static final String propertyName = "sun.tools.ToolProvider"; - private static final String loggerName = "javax.tools"; - - /* - * Define the system property "sun.tools.ToolProvider" to enable - * debugging: - * - * java ... -Dsun.tools.ToolProvider ... - */ - static T trace(Level level, Object reason) { - // NOTE: do not make this method private as it affects stack traces - try { - if (System.getProperty(propertyName) != null) { - StackTraceElement[] st = Thread.currentThread().getStackTrace(); - String method = "???"; - String cls = ToolProvider.class.getName(); - if (st.length > 2) { - StackTraceElement frame = st[2]; - method = String.format((Locale)null, "%s(%s:%s)", - frame.getMethodName(), - frame.getFileName(), - frame.getLineNumber()); - cls = frame.getClassName(); - } - Logger logger = Logger.getLogger(loggerName); - if (reason instanceof Throwable) { - logger.logp(level, cls, method, - reason.getClass().getName(), (Throwable)reason); - } else { - logger.logp(level, cls, method, String.valueOf(reason)); - } - } - } catch (SecurityException ex) { - System.err.format((Locale)null, "%s: %s; %s%n", - ToolProvider.class.getName(), - reason, - ex.getLocalizedMessage()); - } - return null; - } - private static final String systemJavaCompilerName = "com.sun.tools.javac.api.JavacTool"; @@ -153,7 +107,7 @@ public class ToolProvider { try { return c.asSubclass(clazz).newInstance(); } catch (InstantiationException | IllegalAccessException | RuntimeException | Error e) { - return trace(WARNING, e); + throw new Error(e); } } @@ -164,7 +118,7 @@ public class ToolProvider { try { c = Class.forName(name, false, ClassLoader.getSystemClassLoader()); } catch (ClassNotFoundException | RuntimeException | Error e) { - return trace(WARNING, e); + throw new Error(e); } toolClasses.put(name, new WeakReference<>(c)); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java index 0c602c4c16a..466a41d7635 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/code/ClassFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ package com.sun.tools.javac.code; import java.io.IOException; -import java.io.File; +import java.nio.file.Path; import java.util.EnumSet; import java.util.HashMap; import java.util.Map; @@ -45,7 +45,6 @@ import com.sun.tools.javac.code.Symbol.CompletionFailure; import com.sun.tools.javac.code.Symbol.PackageSymbol; import com.sun.tools.javac.code.Symbol.TypeSymbol; import com.sun.tools.javac.comp.Annotate; -import com.sun.tools.javac.comp.Enter; import com.sun.tools.javac.file.JRTIndex; import com.sun.tools.javac.file.JavacFileManager; import com.sun.tools.javac.jvm.ClassReader; @@ -535,25 +534,25 @@ public class ClassFinder { if (fileManager instanceof StandardJavaFileManager) { StandardJavaFileManager fm = (StandardJavaFileManager)fileManager; if (haveSourcePath && wantSourceFiles) { - List path = List.nil(); - for (File file : fm.getLocation(SOURCE_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path sourcePath : fm.getLocationAsPaths(SOURCE_PATH)) { + path = path.prepend(sourcePath); } log.printVerbose("sourcepath", path.reverse().toString()); } else if (wantSourceFiles) { - List path = List.nil(); - for (File file : fm.getLocation(CLASS_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { + path = path.prepend(classPath); } log.printVerbose("sourcepath", path.reverse().toString()); } if (wantClassFiles) { - List path = List.nil(); - for (File file : fm.getLocation(PLATFORM_CLASS_PATH)) { - path = path.prepend(file); + List path = List.nil(); + for (Path platformPath : fm.getLocationAsPaths(PLATFORM_CLASS_PATH)) { + path = path.prepend(platformPath); } - for (File file : fm.getLocation(CLASS_PATH)) { - path = path.prepend(file); + for (Path classPath : fm.getLocationAsPaths(CLASS_PATH)) { + path = path.prepend(classPath); } log.printVerbose("classpath", path.reverse().toString()); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index f62d866bacb..efa57d8b854 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -155,8 +155,6 @@ public class Attr extends JCTree.Visitor { allowDefaultMethods = source.allowDefaultMethods(); allowStaticInterfaceMethods = source.allowStaticInterfaceMethods(); sourceName = source.name; - relax = (options.isSet("-retrofit") || - options.isSet("-relax")); useBeforeDeclarationWarning = options.isSet("useBeforeDeclarationWarning"); statInfo = new ResultInfo(KindSelector.NIL, Type.noType); @@ -168,10 +166,6 @@ public class Attr extends JCTree.Visitor { recoveryInfo = new RecoveryInfo(deferredAttr.emptyDeferredAttrContext); } - /** Switch: relax some constraints for retrofit mode. - */ - boolean relax; - /** Switch: support target-typing inference */ boolean allowPoly; @@ -1025,8 +1019,7 @@ public class Attr extends JCTree.Visitor { log.error(tree.pos(), "default.allowed.in.intf.annotation.member"); } - if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0 && - !relax) + if (isDefaultMethod || (tree.sym.flags() & (ABSTRACT | NATIVE)) == 0) log.error(tree.pos(), "missing.meth.body.or.decl.abstract"); } else if ((tree.sym.flags() & (ABSTRACT|DEFAULT|PRIVATE)) == ABSTRACT) { if ((owner.flags() & INTERFACE) != 0) { @@ -4384,8 +4377,7 @@ public class Attr extends JCTree.Visitor { // If this is a non-abstract class, check that it has no abstract // methods or unimplemented methods of an implemented interface. if ((c.flags() & (ABSTRACT | INTERFACE)) == 0) { - if (!relax) - chk.checkAllDefined(tree.pos(), c); + chk.checkAllDefined(tree.pos(), c); } if ((c.flags() & ANNOTATION) != 0) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index a130f220926..4b0b3a1a42c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -81,8 +81,6 @@ public class Check { private final Types types; private final TypeAnnotations typeAnnotations; private final JCDiagnostic.Factory diags; - private boolean warnOnSyntheticConflicts; - private boolean suppressAbortOnBadClassFile; private final JavaFileManager fileManager; private final Source source; private final Profile profile; @@ -130,8 +128,6 @@ public class Check { allowStrictMethodClashCheck = source.allowStrictMethodClashCheck(); allowPrivateSafeVarargs = source.allowPrivateSafeVarargs(); allowDiamondWithAnonymousClassCreation = source.allowDiamondWithAnonymousClassCreation(); - warnOnSyntheticConflicts = options.isSet("warnOnSyntheticConflicts"); - suppressAbortOnBadClassFile = options.isSet("suppressAbortOnBadClassFile"); warnOnAccessToSensitiveMembers = options.isSet("warnOnAccessToSensitiveMembers"); Target target = Target.instance(context); @@ -269,8 +265,7 @@ public class Check { */ public Type completionError(DiagnosticPosition pos, CompletionFailure ex) { log.error(JCDiagnostic.DiagnosticFlag.NON_DEFERRABLE, pos, "cant.access", ex.sym, ex.getDetailValue()); - if (ex instanceof ClassFinder.BadClassFile - && !suppressAbortOnBadClassFile) throw new Abort(); + if (ex instanceof ClassFinder.BadClassFile) throw new Abort(); else return syms.errType; } @@ -2006,10 +2001,11 @@ public class Check { } } + final boolean explicitOverride = m.attribute(syms.overrideType.tsym) != null; // Check if this method must override a super method due to being annotated with @Override // or by virtue of being a member of a diamond inferred anonymous class. Latter case is to // be treated "as if as they were annotated" with @Override. - boolean mustOverride = m.attribute(syms.overrideType.tsym) != null || + boolean mustOverride = explicitOverride || (env.info.isAnonymousDiamond && !m.isConstructor() && !m.isPrivate()); if (mustOverride && !isOverrider(m)) { DiagnosticPosition pos = tree.pos(); @@ -2019,7 +2015,9 @@ public class Check { break; } } - log.error(pos, "method.does.not.override.superclass"); + log.error(pos, + explicitOverride ? Errors.MethodDoesNotOverrideSuperclass : + Errors.AnonymousDiamondMethodDoesNotOverrideSuperclass(Fragments.DiamondAnonymousMethodsImplicitlyOverride)); } } @@ -2632,12 +2630,7 @@ public class Check { */ private void syntheticError(DiagnosticPosition pos, Symbol sym) { if (!sym.type.isErroneous()) { - if (warnOnSyntheticConflicts) { - log.warning(pos, "synthetic.name.conflict", sym, sym.location()); - } - else { - log.error(pos, "synthetic.name.conflict", sym, sym.location()); - } + log.error(pos, "synthetic.name.conflict", sym, sym.location()); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java index 9f30e750db3..190c0e6e623 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Infer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,9 +44,11 @@ import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph.Node; import com.sun.tools.javac.comp.Resolve.InapplicableMethodException; import com.sun.tools.javac.comp.Resolve.VerboseResolutionMode; -import java.io.File; -import java.io.FileWriter; import java.io.IOException; +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -353,9 +355,9 @@ public class Infer { rsContext.attrMode(), rsContext.step, round); - File dotFile = new File(dependenciesFolder, filename); - try (FileWriter fw = new FileWriter(dotFile)) { - fw.append(graph); + Path dotFile = Paths.get(dependenciesFolder, filename); + try (Writer w = Files.newBufferedWriter(dotFile)) { + w.append(graph); } round++; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 00783594e26..38a941b6312 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -4043,7 +4043,12 @@ public class Resolve { found = false; break; } - allThrown = chk.intersect(allThrown, mt2.getThrownTypes()); + List thrownTypes2 = mt2.getThrownTypes(); + if (mt.hasTag(FORALL) && mt2.hasTag(FORALL)) { + // if both are generic methods, adjust thrown types ahead of intersection computation + thrownTypes2 = types.subst(thrownTypes2, mt2.getTypeArguments(), mt.getTypeArguments()); + } + allThrown = chk.intersect(allThrown, thrownTypes2); } if (found) { //all ambiguous methods were abstract and one method had diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java index 42603b462ca..caf3dc32546 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/BaseFileManager.java @@ -267,7 +267,14 @@ public abstract class BaseFileManager implements JavaFileManager { * @return true if successful, and false otherwise */ public boolean handleOption(Option option, String value) { - return locations.handleOption(option, value); + switch (option) { + case ENCODING: + encodingName = value; + return true; + + default: + return locations.handleOption(option, value); + } } /** @@ -285,6 +292,7 @@ public abstract class BaseFileManager implements JavaFileManager { // // + private String encodingName; private String defaultEncodingName; private String getDefaultEncodingName() { if (defaultEncodingName == null) { @@ -295,11 +303,7 @@ public abstract class BaseFileManager implements JavaFileManager { } public String getEncodingName() { - String encName = options.get(Option.ENCODING); - if (encName == null) - return getDefaultEncodingName(); - else - return encName; + return (encodingName != null) ? encodingName : getDefaultEncodingName(); } @SuppressWarnings("cast") diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java index 091ef22661c..1fc2fa1ac6d 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/JavacFileManager.java @@ -425,7 +425,7 @@ public class JavacFileManager extends BaseFileManager implements StandardJavaFil if (container.endsWith("bootmodules.jimage")) { System.err.println("Warning: reference to bootmodules.jimage replaced by jrt:"); container = Locations.JRT_MARKER_FILE; - } else if (container.getFileName().toString().endsWith(".jimage")) { + } else if (container.getNameCount() > 0 && container.getFileName().toString().endsWith(".jimage")) { System.err.println("Warning: reference to " + container + " ignored"); return; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java index 59d79df9ac1..3e541b884f1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/file/RelativePath.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,6 @@ package com.sun.tools.javac.file; -import java.io.File; import java.nio.file.FileSystem; import java.nio.file.FileSystems; import java.nio.file.InvalidPathException; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 1b1f8a15457..aa161b5ec76 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,18 +72,6 @@ public class ClassWriter extends ClassFile { */ private boolean verbose; - /** Switch: scramble private field names. - */ - private boolean scramble; - - /** Switch: scramble all field names. - */ - private boolean scrambleAll; - - /** Switch: retrofit mode. - */ - private boolean retrofit; - /** Switch: emit source file attribute. */ private boolean emitSourceFile; @@ -184,9 +172,6 @@ public class ClassWriter extends ClassFile { signatureGen = new CWSignatureGenerator(types); verbose = options.isSet(VERBOSE); - scramble = options.isSet("-scramble"); - scrambleAll = options.isSet("-scrambleAll"); - retrofit = options.isSet("-retrofit"); genCrt = options.isSet(XJCOV); debugstackmap = options.isSet("debugstackmap"); @@ -491,26 +476,11 @@ public class ClassWriter extends ClassFile { putChar(poolbuf, poolCountIdx, pool.pp); } - /** Given a field, return its name. - */ - Name fieldName(Symbol sym) { - if (scramble && (sym.flags() & PRIVATE) != 0 || - scrambleAll && (sym.flags() & (PROTECTED | PUBLIC)) == 0) - return names.fromString("_$" + sym.name.getIndex()); - else - return sym.name; - } - /** Given a symbol, return its name-and-type. */ NameAndType nameType(Symbol sym) { - return new NameAndType(fieldName(sym), - retrofit - ? sym.erasure(types) - : sym.externalType(types), types); - // if we retrofit, then the NameAndType has been read in as is - // and no change is necessary. If we compile normally, the - // NameAndType is generated from a symbol reference, and the + return new NameAndType(sym.name, sym.externalType(types), types); + // the NameAndType is generated from a symbol reference, and the // adjustment of adding an additional this$n parameter needs to be made. } @@ -1055,10 +1025,10 @@ public class ClassWriter extends ClassFile { databuf.appendChar(flags); if (dumpFieldModifiers) { PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); - pw.println("FIELD " + fieldName(v)); + pw.println("FIELD " + v.name); pw.println("---" + flagNames(v.flags())); } - databuf.appendChar(pool.put(fieldName(v))); + databuf.appendChar(pool.put(v.name)); databuf.appendChar(pool.put(typeSig(v.erasure(types)))); int acountIdx = beginAttrs(); int acount = 0; @@ -1079,10 +1049,10 @@ public class ClassWriter extends ClassFile { databuf.appendChar(flags); if (dumpMethodModifiers) { PrintWriter pw = log.getWriter(Log.WriterKind.ERROR); - pw.println("METHOD " + fieldName(m)); + pw.println("METHOD " + m.name); pw.println("---" + flagNames(m.flags())); } - databuf.appendChar(pool.put(fieldName(m))); + databuf.appendChar(pool.put(m.name)); databuf.appendChar(pool.put(typeSig(m.externalType(types)))); int acountIdx = beginAttrs(); int acount = 0; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index 83ed8adbef5..b551b61e8d9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -80,6 +80,11 @@ public class Gen extends JCTree.Visitor { */ private final Type methodType; + /** + * Are we presently traversing a let expression ? Yes if depth != 0 + */ + private int letExprDepth; + public static Gen instance(Context context) { Gen instance = context.get(genKey); if (instance == null) @@ -120,25 +125,11 @@ public class Gen extends JCTree.Visitor { : options.isSet(G_CUSTOM, "vars"); genCrt = options.isSet(XJCOV); debugCode = options.isSet("debugcode"); - allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic"); allowBetterNullChecks = target.hasObjects(); pool = new Pool(types); // ignore cldc because we cannot have both stackmap formats this.stackMap = StackMapFormat.JSR202; - - // by default, avoid jsr's for simple finalizers - int setjsrlimit = 50; - String jsrlimitString = options.get("jsrlimit"); - if (jsrlimitString != null) { - try { - setjsrlimit = Integer.parseInt(jsrlimitString); - } catch (NumberFormatException ex) { - // ignore ill-formed numbers for jsrlimit - } - } - this.jsrlimit = setjsrlimit; - this.useJsrLocally = false; // reset in visitTry annotate = Annotate.instance(context); } @@ -148,19 +139,8 @@ public class Gen extends JCTree.Visitor { private final boolean varDebugInfo; private final boolean genCrt; private final boolean debugCode; - private final boolean allowInvokedynamic; private final boolean allowBetterNullChecks; - /** Default limit of (approximate) size of finalizer to inline. - * Zero means always use jsr. 100 or greater means never use - * jsr. - */ - private final int jsrlimit; - - /** True if jsr is used. - */ - private boolean useJsrLocally; - /** Code buffer, set by genMethod. */ private Code code; @@ -1031,8 +1011,10 @@ public class Gen extends JCTree.Visitor { if (tree.init != null) { checkStringConstant(tree.init.pos(), v.getConstValue()); if (v.getConstValue() == null || varDebugInfo) { + Assert.check(letExprDepth != 0 || code.state.stacksize == 0); genExpr(tree.init, v.erasure(types)).load(); items.makeLocalItem(v).store(); + Assert.check(letExprDepth != 0 || code.state.stacksize == 0); } } checkDimension(tree.pos(), v.type); @@ -1087,12 +1069,14 @@ public class Gen extends JCTree.Visitor { CondItem c; if (cond != null) { code.statBegin(cond.pos); + Assert.check(code.state.stacksize == 0); c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER); } else { c = items.makeCondItem(goto_); } Chain loopDone = c.jumpFalse(); code.resolve(c.trueJumps); + Assert.check(code.state.stacksize == 0); genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); code.resolve(loopEnv.info.cont); genStats(step, loopEnv); @@ -1105,11 +1089,13 @@ public class Gen extends JCTree.Visitor { CondItem c; if (cond != null) { code.statBegin(cond.pos); + Assert.check(code.state.stacksize == 0); c = genCond(TreeInfo.skipParens(cond), CRT_FLOW_CONTROLLER); } else { c = items.makeCondItem(goto_); } code.resolve(c.jumpTrue(), startpc); + Assert.check(code.state.stacksize == 0); code.resolve(c.falseJumps); } Chain exit = loopEnv.info.exit; @@ -1137,6 +1123,7 @@ public class Gen extends JCTree.Visitor { int limit = code.nextreg; Assert.check(!tree.selector.type.hasTag(CLASS)); int startpcCrt = genCrt ? code.curCP() : 0; + Assert.check(code.state.stacksize == 0); Item sel = genExpr(tree.selector, syms.intType); List cases = tree.cases; if (cases.isEmpty()) { @@ -1305,6 +1292,7 @@ public class Gen extends JCTree.Visitor { int limit = code.nextreg; // Generate code to evaluate lock and save in temporary variable. final LocalItem lockVar = makeTemp(syms.objectType); + Assert.check(code.state.stacksize == 0); genExpr(tree.lock, tree.lock.type).load().duplicate(); lockVar.store(); @@ -1339,31 +1327,11 @@ public class Gen extends JCTree.Visitor { // in a new environment which calls the finally block if there is one. final Env tryEnv = env.dup(tree, new GenContext()); final Env oldEnv = env; - if (!useJsrLocally) { - useJsrLocally = - (stackMap == StackMapFormat.NONE) && - (jsrlimit <= 0 || - jsrlimit < 100 && - estimateCodeComplexity(tree.finalizer)>jsrlimit); - } tryEnv.info.finalize = new GenFinalizer() { void gen() { - if (useJsrLocally) { - if (tree.finalizer != null) { - Code.State jsrState = code.state.dup(); - jsrState.push(Code.jsrReturnValue); - tryEnv.info.cont = - new Chain(code.emitJump(jsr), - tryEnv.info.cont, - jsrState); - } - Assert.check(tryEnv.info.gaps.length() % 2 == 0); - tryEnv.info.gaps.append(code.curCP()); - } else { - Assert.check(tryEnv.info.gaps.length() % 2 == 0); - tryEnv.info.gaps.append(code.curCP()); - genLast(); - } + Assert.check(tryEnv.info.gaps.length() % 2 == 0); + tryEnv.info.gaps.append(code.curCP()); + genLast(); } void genLast() { if (tree.finalizer != null) @@ -1568,99 +1536,14 @@ public class Gen extends JCTree.Visitor { } } - /** Very roughly estimate the number of instructions needed for - * the given tree. - */ - int estimateCodeComplexity(JCTree tree) { - if (tree == null) return 0; - class ComplexityScanner extends TreeScanner { - int complexity = 0; - public void scan(JCTree tree) { - if (complexity > jsrlimit) return; - super.scan(tree); - } - public void visitClassDef(JCClassDecl tree) {} - public void visitDoLoop(JCDoWhileLoop tree) - { super.visitDoLoop(tree); complexity++; } - public void visitWhileLoop(JCWhileLoop tree) - { super.visitWhileLoop(tree); complexity++; } - public void visitForLoop(JCForLoop tree) - { super.visitForLoop(tree); complexity++; } - public void visitSwitch(JCSwitch tree) - { super.visitSwitch(tree); complexity+=5; } - public void visitCase(JCCase tree) - { super.visitCase(tree); complexity++; } - public void visitSynchronized(JCSynchronized tree) - { super.visitSynchronized(tree); complexity+=6; } - public void visitTry(JCTry tree) - { super.visitTry(tree); - if (tree.finalizer != null) complexity+=6; } - public void visitCatch(JCCatch tree) - { super.visitCatch(tree); complexity+=2; } - public void visitConditional(JCConditional tree) - { super.visitConditional(tree); complexity+=2; } - public void visitIf(JCIf tree) - { super.visitIf(tree); complexity+=2; } - // note: for break, continue, and return we don't take unwind() into account. - public void visitBreak(JCBreak tree) - { super.visitBreak(tree); complexity+=1; } - public void visitContinue(JCContinue tree) - { super.visitContinue(tree); complexity+=1; } - public void visitReturn(JCReturn tree) - { super.visitReturn(tree); complexity+=1; } - public void visitThrow(JCThrow tree) - { super.visitThrow(tree); complexity+=1; } - public void visitAssert(JCAssert tree) - { super.visitAssert(tree); complexity+=5; } - public void visitApply(JCMethodInvocation tree) - { super.visitApply(tree); complexity+=2; } - public void visitNewClass(JCNewClass tree) - { scan(tree.encl); scan(tree.args); complexity+=2; } - public void visitNewArray(JCNewArray tree) - { super.visitNewArray(tree); complexity+=5; } - public void visitAssign(JCAssign tree) - { super.visitAssign(tree); complexity+=1; } - public void visitAssignop(JCAssignOp tree) - { super.visitAssignop(tree); complexity+=2; } - public void visitUnary(JCUnary tree) - { complexity+=1; - if (tree.type.constValue() == null) super.visitUnary(tree); } - public void visitBinary(JCBinary tree) - { complexity+=1; - if (tree.type.constValue() == null) super.visitBinary(tree); } - public void visitTypeTest(JCInstanceOf tree) - { super.visitTypeTest(tree); complexity+=1; } - public void visitIndexed(JCArrayAccess tree) - { super.visitIndexed(tree); complexity+=1; } - public void visitSelect(JCFieldAccess tree) - { super.visitSelect(tree); - if (tree.sym.kind == VAR) complexity+=1; } - public void visitIdent(JCIdent tree) { - if (tree.sym.kind == VAR) { - complexity+=1; - if (tree.type.constValue() == null && - tree.sym.owner.kind == TYP) - complexity+=1; - } - } - public void visitLiteral(JCLiteral tree) - { complexity+=1; } - public void visitTree(JCTree tree) {} - public void visitWildcard(JCWildcard tree) { - throw new AssertionError(this.getClass().getName()); - } - } - ComplexityScanner scanner = new ComplexityScanner(); - tree.accept(scanner); - return scanner.complexity; - } - public void visitIf(JCIf tree) { int limit = code.nextreg; Chain thenExit = null; + Assert.check(code.state.stacksize == 0); CondItem c = genCond(TreeInfo.skipParens(tree.cond), CRT_FLOW_CONTROLLER); Chain elseChain = c.jumpFalse(); + Assert.check(code.state.stacksize == 0); if (!c.isFalse()) { code.resolve(c.trueJumps); genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET); @@ -1674,6 +1557,7 @@ public class Gen extends JCTree.Visitor { } code.resolve(thenExit); code.endScopes(limit); + Assert.check(code.state.stacksize == 0); } public void visitExec(JCExpressionStatement tree) { @@ -1687,7 +1571,9 @@ public class Gen extends JCTree.Visitor { ((JCUnary) e).setTag(PREDEC); break; } + Assert.check(code.state.stacksize == 0); genExpr(tree.expr, tree.expr.type).drop(); + Assert.check(code.state.stacksize == 0); } public void visitBreak(JCBreak tree) { @@ -1713,6 +1599,7 @@ public class Gen extends JCTree.Visitor { */ int tmpPos = code.pendingStatPos; if (tree.expr != null) { + Assert.check(code.state.stacksize == 0); Item r = genExpr(tree.expr, pt).load(); if (hasFinally(env.enclMethod, env)) { r = makeTemp(pt); @@ -1732,8 +1619,10 @@ public class Gen extends JCTree.Visitor { } public void visitThrow(JCThrow tree) { + Assert.check(code.state.stacksize == 0); genExpr(tree.expr, tree.expr.type).load(); code.emitop0(athrow); + Assert.check(code.state.stacksize == 0); } /* ************************************************************************ @@ -2233,10 +2122,12 @@ public class Gen extends JCTree.Visitor { } public void visitLetExpr(LetExpr tree) { + letExprDepth++; int limit = code.nextreg; genStats(tree.defs, env); result = genExpr(tree.expr, tree.expr.type).load(); code.endScopes(limit); + letExprDepth--; } private void generateReferencesToPrunedTree(ClassSymbol classSymbol, Pool pool) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java index bb5436bd96c..80cee302dec 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/StringConcat.java @@ -33,8 +33,7 @@ import com.sun.tools.javac.tree.TreeMaker; import com.sun.tools.javac.util.*; import static com.sun.tools.javac.code.Kinds.Kind.MTH; -import static com.sun.tools.javac.code.TypeTag.DOUBLE; -import static com.sun.tools.javac.code.TypeTag.LONG; +import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.jvm.ByteCodes.*; import static com.sun.tools.javac.tree.JCTree.Tag.PLUS; import com.sun.tools.javac.jvm.Items.*; @@ -142,6 +141,25 @@ public abstract class StringConcat { return res.append(tree); } + /** + * If the type is not accessible from current context, try to figure out the + * sharpest accessible supertype. + * + * @param originalType type to sharpen + * @return sharped type + */ + Type sharpestAccessible(Type originalType) { + if (originalType.hasTag(ARRAY)) { + return types.makeArrayType(sharpestAccessible(types.elemtype(originalType))); + } + + Type type = originalType; + while (!rs.isAccessible(gen.getAttrEnv(), type.asElement())) { + type = types.supertype(type); + } + return type; + } + /** * "Legacy" bytecode flavor: emit the StringBuilder.append chains for string * concatenation. @@ -314,7 +332,7 @@ public abstract class StringConcat { if (arg.type == syms.botType) { dynamicArgs.add(types.boxedClass(syms.voidType).type); } else { - dynamicArgs.add(arg.type); + dynamicArgs.add(sharpestAccessible(arg.type)); } gen.genExpr(arg, arg.type).load(); } @@ -415,7 +433,7 @@ public abstract class StringConcat { } else { // Ordinary arguments come through the dynamic arguments. recipe.append(TAG_ARG); - dynamicArgs.add(arg.type); + dynamicArgs.add(sharpestAccessible(arg.type)); gen.genExpr(arg, arg.type).load(); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java index af02f2261d0..5d79556b3b9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Arguments.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,10 @@ package com.sun.tools.javac.main; -import java.io.File; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collection; import java.util.Collections; import java.util.Iterator; @@ -73,7 +74,7 @@ public class Arguments { private String ownName; private Set classNames; - private Set files; + private Set files; private Map deferredFileManagerOptions; private Set fileObjects; private final Options options; @@ -153,8 +154,8 @@ public class Arguments { } @Override - public void addFile(File f) { - files.add(f); + public void addFile(Path p) { + files.add(p); } @Override @@ -252,7 +253,7 @@ public class Arguments { } else { fileObjects = new LinkedHashSet<>(); JavacFileManager jfm = (JavacFileManager) getFileManager(); - for (JavaFileObject fo: jfm.getJavaFileObjectsFromFiles(files)) + for (JavaFileObject fo: jfm.getJavaFileObjectsFromPaths(files)) fileObjects.add(fo); } } @@ -583,8 +584,8 @@ public class Arguments { if (value == null) { return true; } - File file = new File(value); - if (file.exists() && !file.isDirectory()) { + Path file = Paths.get(value); + if (Files.exists(file) && !Files.isDirectory(file)) { error("err.file.not.directory", value); return false; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java index d770176e797..546f64d6a86 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/CommandLine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,9 +27,10 @@ package com.sun.tools.javac.main; import java.io.IOException; import java.io.Reader; -import java.io.FileReader; -import java.io.BufferedReader; import java.io.StreamTokenizer; +import java.nio.file.Files; +import java.nio.file.Paths; + import com.sun.tools.javac.util.ListBuffer; /** @@ -73,7 +74,7 @@ public class CommandLine { private static void loadCmdFile(String name, ListBuffer args) throws IOException { - try (Reader r = new BufferedReader(new FileReader(name))) { + try (Reader r = Files.newBufferedReader(Paths.get(name))) { StreamTokenizer st = new StreamTokenizer(r); st.resetSyntax(); st.wordChars(' ', 255); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 40ca702ba82..4d3bc8bb8ff 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -389,10 +389,6 @@ public class JavaCompiler { verbose = options.isSet(VERBOSE); sourceOutput = options.isSet(PRINTSOURCE); // used to be -s - stubOutput = options.isSet("-stubs"); - relax = options.isSet("-relax"); - printFlat = options.isSet("-printflat"); - encoding = options.get(ENCODING); lineDebugInfo = options.isUnset(G_CUSTOM) || options.isSet(G_CUSTOM, "lines"); genEndPos = options.isSet(XJCOV) || @@ -447,21 +443,6 @@ public class JavaCompiler { */ public boolean sourceOutput; - /** Emit stub source files rather than class files. - */ - public boolean stubOutput; - - /** Switch: relax some constraints for producing the jsr14 prototype. - */ - boolean relax; - - /** Debug switch: Emit Java sources after inner class flattening. - */ - public boolean printFlat; - - /** The encoding to be used for source input. - */ - public String encoding; /** Generate code with the LineNumberTable attribute for debugging */ @@ -611,7 +592,7 @@ public class JavaCompiler { // where public boolean keepComments = false; protected boolean keepComments() { - return keepComments || sourceOutput || stubOutput; + return keepComments || sourceOutput; } @@ -676,30 +657,6 @@ public class JavaCompiler { } } - /** Emit plain Java source for a class. - * @param env The attribution environment of the outermost class - * containing this class. - * @param cdef The class definition to be printed. - */ - JavaFileObject printSource(Env env, JCClassDecl cdef) throws IOException { - JavaFileObject outFile - = fileManager.getJavaFileForOutput(CLASS_OUTPUT, - cdef.sym.flatname.toString(), - JavaFileObject.Kind.SOURCE, - null); - if (inputFiles.contains(outFile)) { - log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); - return null; - } else { - try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) { - new Pretty(out, true).printUnit(env.toplevel, cdef); - if (verbose) - log.printVerbose("wrote.file", outFile); - } - return outFile; - } - } - /** Generate code and emit a class file for a given class * @param env The attribution environment of the outermost class * containing this class. @@ -720,6 +677,30 @@ public class JavaCompiler { return null; } + /** Emit plain Java source for a class. + * @param env The attribution environment of the outermost class + * containing this class. + * @param cdef The class definition to be printed. + */ + JavaFileObject printSource(Env env, JCClassDecl cdef) throws IOException { + JavaFileObject outFile + = fileManager.getJavaFileForOutput(CLASS_OUTPUT, + cdef.sym.flatname.toString(), + JavaFileObject.Kind.SOURCE, + null); + if (inputFiles.contains(outFile)) { + log.error(cdef.pos(), "source.cant.overwrite.input.file", outFile); + return null; + } else { + try (BufferedWriter out = new BufferedWriter(outFile.openWriter())) { + new Pretty(out, true).printUnit(env.toplevel, cdef); + if (verbose) + log.printVerbose("wrote.file", outFile); + } + return outFile; + } + } + /** Compile a source file that has been accessed by the class finder. * @param c The class the source file of which needs to be compiled. */ @@ -897,12 +878,6 @@ public class JavaCompiler { throw new AssertionError("attempt to reuse JavaCompiler"); } - /** - * Set needRootClasses to true, in JavaCompiler subclass constructor - * that want to collect public apis of classes supplied on the command line. - */ - protected boolean needRootClasses = false; - /** * The list of classes explicitly supplied on the command line for compilation. * Not always populated. @@ -966,7 +941,7 @@ public class JavaCompiler { // If generating source, or if tracking public apis, // then remember the classes declared in // the original compilation units listed on the command line. - if (needRootClasses || sourceOutput || stubOutput) { + if (sourceOutput) { ListBuffer cdefs = new ListBuffer<>(); for (JCCompilationUnit unit : roots) { for (List defs = unit.defs; @@ -1275,11 +1250,6 @@ public class JavaCompiler { if (shouldStop(CompileState.FLOW)) return; - if (relax) { - results.add(env); - return; - } - if (verboseCompilePolicy) printNote("[flow " + env.enclClass.sym + "]"); JavaFileObject prev = log.useSource( @@ -1419,9 +1389,9 @@ public class JavaCompiler { TreeMaker localMake = make.forToplevel(env.toplevel); if (env.tree.hasTag(JCTree.Tag.PACKAGEDEF)) { - if (!(stubOutput || sourceOutput || printFlat)) { + if (!(sourceOutput)) { if (shouldStop(CompileState.LOWER)) - return; + return; List pdef = lower.translateTopLevelClass(env, env.tree, localMake); if (pdef.head != null) { Assert.check(pdef.tail.isEmpty()); @@ -1431,19 +1401,6 @@ public class JavaCompiler { return; } - if (stubOutput) { - //emit stub Java source file, only for compilation - //units enumerated explicitly on the command line - JCClassDecl cdef = (JCClassDecl)env.tree; - if (untranslated instanceof JCClassDecl && - rootClasses.contains((JCClassDecl)untranslated) && - ((cdef.mods.flags & (Flags.PROTECTED|Flags.PUBLIC)) != 0 || - cdef.sym.packge().getQualifiedName() == names.java_lang)) { - results.add(new Pair<>(env, removeMethodBodies(cdef))); - } - return; - } - if (shouldStop(CompileState.TRANSTYPES)) return; @@ -1504,16 +1461,12 @@ public class JavaCompiler { if (shouldStop(CompileState.GENERATE)) return; - boolean usePrintSource = (stubOutput || sourceOutput || printFlat); - for (Pair, JCClassDecl> x: queue) { Env env = x.fst; JCClassDecl cdef = x.snd; if (verboseCompilePolicy) { - printNote("[generate " - + (usePrintSource ? " source" : "code") - + " " + cdef.sym + "]"); + printNote("[generate " + (sourceOutput ? " source" : "code") + " " + cdef.sym + "]"); } if (!taskListener.isEmpty()) { @@ -1526,9 +1479,9 @@ public class JavaCompiler { env.toplevel.sourcefile); try { JavaFileObject file; - if (usePrintSource) + if (sourceOutput) { file = printSource(env, cdef); - else { + } else { if (fileManager.hasLocation(StandardLocation.NATIVE_HEADER_OUTPUT) && jniWriter.needsHeader(cdef.sym)) { jniWriter.write(cdef.sym); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java index 0a291db707f..b48f51632f2 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/Option.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,11 @@ package com.sun.tools.javac.main; -import java.io.File; import java.io.FileWriter; import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Collections; import java.util.EnumSet; import java.util.LinkedHashMap; @@ -238,13 +240,7 @@ public enum Option { IMPLICIT("-implicit:", "opt.implicit", STANDARD, BASIC, ONEOF, "none", "class"), - ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER) { - @Override - public boolean process(OptionHelper helper, String option, String operand) { - return super.process(helper, option, operand); - } - - }, + ENCODING("-encoding", "opt.arg.encoding", "opt.encoding", STANDARD, FILEMANAGER), SOURCE("-source", "opt.arg.release", "opt.source", STANDARD, BASIC) { @Override @@ -537,16 +533,16 @@ public enum Option { @Override public boolean process(OptionHelper helper, String option) { if (option.endsWith(".java") ) { - File f = new File(option); - if (!f.exists()) { - helper.error("err.file.not.found", f); + Path p = Paths.get(option); + if (!Files.exists(p)) { + helper.error("err.file.not.found", p); return true; } - if (!f.isFile()) { - helper.error("err.file.not.file", f); + if (!Files.isRegularFile(p)) { + helper.error("err.file.not.file", p); return true; } - helper.addFile(f); + helper.addFile(p); } else { helper.addClassName(option); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java index cf6479238d1..149576f0029 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/main/OptionHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,9 +25,10 @@ package com.sun.tools.javac.main; +import java.nio.file.Path; + import com.sun.tools.javac.util.Log; import com.sun.tools.javac.util.Log.PrefixKind; -import java.io.File; /** * Helper object to be used by {@link Option#process}, providing access to @@ -63,7 +64,7 @@ public abstract class OptionHelper { abstract void error(String key, Object... args); /** Record a file to be compiled. */ - abstract void addFile(File f); + abstract void addFile(Path p); /** Record the name of a class for annotation processing. */ abstract void addClassName(String s); @@ -112,8 +113,8 @@ public abstract class OptionHelper { } @Override - public void addFile(File f) { - throw new IllegalArgumentException(f.getPath()); + public void addFile(Path p) { + throw new IllegalArgumentException(p.toString()); } @Override diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java index 94ed6da8d11..9165f9b2cb9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java @@ -31,6 +31,7 @@ import java.io.PrintWriter; import java.io.StringWriter; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Path; import java.util.*; import java.util.regex.*; import java.util.stream.Collectors; @@ -42,6 +43,7 @@ import javax.lang.model.util.*; import javax.tools.JavaFileManager; import javax.tools.JavaFileObject; import javax.tools.StandardJavaFileManager; + import static javax.tools.StandardLocation.*; import com.sun.source.util.TaskEvent; @@ -79,6 +81,7 @@ import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.ServiceLoader; + import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.main.Option.*; @@ -317,9 +320,9 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea if (fileManager instanceof JavacFileManager) { StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager; - Iterable workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) - ? standardFileManager.getLocation(ANNOTATION_PROCESSOR_PATH) - : standardFileManager.getLocation(CLASS_PATH); + Iterable workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH) + ? standardFileManager.getLocationAsPaths(ANNOTATION_PROCESSOR_PATH) + : standardFileManager.getLocationAsPaths(CLASS_PATH); if (needClassLoader(options.get(PROCESSOR), workingPath) ) handleException(key, e); @@ -1298,14 +1301,14 @@ public class JavacProcessingEnvironment implements ProcessingEnvironment, Closea * Called retroactively to determine if a class loader was required, * after we have failed to create one. */ - private boolean needClassLoader(String procNames, Iterable workingpath) { + private boolean needClassLoader(String procNames, Iterable workingpath) { if (procNames != null) return true; URL[] urls = new URL[1]; - for(File pathElement : workingpath) { + for(Path pathElement : workingpath) { try { - urls[0] = pathElement.toURI().toURL(); + urls[0] = pathElement.toUri().toURL(); if (ServiceProxy.hasService(Processor.class, urls)) return true; } catch (MalformedURLException ex) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 795f38032f7..21945462c6f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -214,6 +214,11 @@ compiler.err.bad.functional.intf.anno.1=\ Unexpected @FunctionalInterface annotation\n\ {0} +# 0: message segment +compiler.err.anonymous.diamond.method.does.not.override.superclass=\ + method does not override or implement a method from a supertype\n\ + {0} + # 0: symbol compiler.misc.not.a.functional.intf=\ {0} is not a functional interface @@ -981,10 +986,6 @@ compiler.err.string.const.req=\ compiler.err.synthetic.name.conflict=\ the symbol {0} conflicts with a compiler-synthesized symbol in {1} -# 0: symbol, 1: symbol -compiler.warn.synthetic.name.conflict=\ - the symbol {0} conflicts with a compiler-synthesized symbol in {1} - compiler.err.throws.not.allowed.in.intf.annotation=\ throws clause not allowed in @interface members @@ -1200,6 +1201,9 @@ compiler.misc.fatal.err.cant.close=\ ## miscellaneous strings ## +compiler.misc.diamond.anonymous.methods.implicitly.override=\ + (due to <>, every non-private method declared in this anonymous class must override or implement a method from a supertype) + compiler.misc.source.unavailable=\ (source unavailable) @@ -1334,16 +1338,6 @@ compiler.misc.verbose.total=\ compiler.misc.verbose.wrote.file=\ [wrote {0}] -## extra output when using -verbose (Retro) -compiler.misc.verbose.retro=\ - [retrofitting {0}] - -compiler.misc.verbose.retro.with=\ - \tretrofitting {0} with {1} - -compiler.misc.verbose.retro.with.list=\ - \tretrofitting {0} with type parameters {1}, supertype {2}, interfaces {3} - ## extra output when using -verbose (code/ClassReader) # 0: string compiler.misc.verbose.loading=\ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties index 135646a3fdb..b94ead7665b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/ct.properties @@ -1,6 +1,5 @@ apple.laf.*: hidden apple.security.*: hidden -com.apple.concurrent.*: hidden com.apple.eawt.*: hidden com.apple.eawt.event.*: hidden com.apple.eio.*: hidden diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties index d64280ab946..7246acf194f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac.properties @@ -124,20 +124,12 @@ javac.opt.nogj=\ Don't accept generics in the language javac.opt.moreinfo=\ Print extended information for type variables -javac.opt.printflat=\ - Print abstract syntax tree after inner class conversion javac.opt.printsearch=\ Print information where classfiles are searched javac.opt.prompt=\ Stop after each error -javac.opt.retrofit=\ - Retrofit existing classfiles with generic types javac.opt.s=\ Emit java sources instead of classfiles -javac.opt.scramble=\ - Scramble private identifiers in bytecode -javac.opt.scrambleall=\ - Scramble package visible identifiers in bytecode javac.opt.version=\ Version information javac.opt.arg.pathname=\ diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java index 3b5e0832372..56298136002 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/DocTreeMaker.java @@ -50,6 +50,7 @@ import com.sun.tools.javac.api.JavacTrees; import com.sun.tools.javac.parser.ParserFactory; import com.sun.tools.javac.parser.ReferenceParser; import com.sun.tools.javac.parser.Tokens.Comment; +import com.sun.tools.javac.parser.Tokens.Comment.CommentStyle; import com.sun.tools.javac.tree.DCTree.DCAttribute; import com.sun.tools.javac.tree.DCTree.DCAuthor; import com.sun.tools.javac.tree.DCTree.DCComment; @@ -206,7 +207,31 @@ public class DocTreeMaker implements DocTreeFactory { lb.addAll(cast(firstSentence)); lb.addAll(cast(body)); List fullBody = lb.toList(); - DCDocComment tree = new DCDocComment(null, fullBody, cast(firstSentence), cast(body), cast(tags)); + + // A dummy comment to keep the diagnostics logic happy. + Comment c = new Comment() { + @Override + public String getText() { + return null; + } + + @Override + public int getSourcePos(int index) { + return Position.NOPOS; + } + + @Override + public CommentStyle getStyle() { + return CommentStyle.JAVADOC; + } + + @Override + public boolean isDeprecated() { + return false; + } + }; + + DCDocComment tree = new DCDocComment(c, fullBody, cast(firstSentence), cast(body), cast(tags)); return tree; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java index 56b369c8082..789069b49ed 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/javah/JavahTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -170,12 +170,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { } }, - new HiddenOption(false, "-stubs") { - void process(JavahTask task, String opt, String arg) { - // ignored; for backwards compatibility - } - }, - new Option(false, "-v", "-verbose") { void process(JavahTask task, String opt, String arg) { task.verbose = true; @@ -454,8 +448,6 @@ public class JavahTask implements NativeHeaderTool.NativeHeaderTask { if (llni) g = new LLNI(doubleAlign, util); else { -// if (stubs) -// throw new BadArgs("jni.no.stubs"); g = new JNI(util); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java index 03f02d8e42c..ef1602eb396 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java @@ -75,9 +75,7 @@ public class CleanProperties implements Transformer { Map dependencyPublicApis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err) { + int numCores) { boolean rc = true; for (String pkgName : pkgSrcs.keySet()) { String pkgNameF = pkgName.replace('.',File.separatorChar); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java index 14fc859048b..f6ac5d2ad44 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java @@ -42,6 +42,8 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; +import java.util.regex.Pattern; +import java.util.stream.Stream; import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; @@ -89,9 +91,7 @@ public class CompileJavaPackages implements Transformer { final Map dependencyPubapis, int debugLevel, boolean incremental, - int numCores, - final Writer out, - final Writer err) { + int numCores) { Log.debug("Performing CompileJavaPackages transform..."); @@ -219,7 +219,9 @@ public class CompileJavaPackages implements Transformer { } String chunkId = id + "-" + String.valueOf(i); + Log log = Log.get(); compilationCalls.add(() -> { + Log.setLogForCurrentThread(log); CompilationSubResult result = sjavac.compile("n/a", chunkId, args.prepJavacArgs(), @@ -227,8 +229,8 @@ public class CompileJavaPackages implements Transformer { cc.srcs, visibleSources); synchronized (lock) { - safeWrite(result.stdout, out); - safeWrite(result.stderr, err); + Util.getLines(result.stdout).forEach(Log::info); + Util.getLines(result.stderr).forEach(Log::error); } return result; }); @@ -246,8 +248,10 @@ public class CompileJavaPackages implements Transformer { subResults.add(fut.get()); } catch (ExecutionException ee) { Log.error("Compilation failed: " + ee.getMessage()); - } catch (InterruptedException ee) { - Log.error("Compilation interrupted: " + ee.getMessage()); + Log.error(ee); + } catch (InterruptedException ie) { + Log.error("Compilation interrupted: " + ie.getMessage()); + Log.error(ie); Thread.currentThread().interrupt(); } } @@ -292,16 +296,6 @@ public class CompileJavaPackages implements Transformer { return rc; } - private void safeWrite(String str, Writer w) { - if (str.length() > 0) { - try { - w.write(str); - } catch (IOException e) { - Log.error("Could not print compilation output."); - } - } - } - /** * Split up the sources into compile chunks. If old package dependents information * is available, sort the order of the chunks into the most dependent first! diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java index 3ca37b547f6..7045bc14afd 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java @@ -83,9 +83,7 @@ public class CompileProperties implements Transformer { Map dependencyPublicApis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err) { + int numCores) { boolean rc = true; for (String pkgName : pkgSrcs.keySet()) { String pkgNameF = Util.toFileSystemPath(pkgName); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java index 5ab8d22fc7a..d3685eacfc6 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java @@ -70,9 +70,7 @@ public class CopyFile implements Transformer { Map dependencyPubapis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err) + int numCores) { boolean rc = true; String dest_filename; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java index 114d1282fc1..93749f61676 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java @@ -123,16 +123,11 @@ public class JavacState { // Setup transform that always exist. private CompileJavaPackages compileJavaPackages = new CompileJavaPackages(); - // Where to send stdout and stderr. - private Writer out, err; - // Command line options. private Options options; - JavacState(Options op, boolean removeJavacState, Writer o, Writer e) { + JavacState(Options op, boolean removeJavacState) { options = op; - out = o; - err = e; numCores = options.getNumCores(); theArgs = options.getStateArgsString(); binDir = Util.pathToFile(options.getDestDir()); @@ -294,8 +289,8 @@ public class JavacState { /** * Load a javac_state file. */ - public static JavacState load(Options options, Writer out, Writer err) { - JavacState db = new JavacState(options, false, out, err); + public static JavacState load(Options options) { + JavacState db = new JavacState(options, false); Module lastModule = null; Package lastPackage = null; Source lastSource = null; @@ -367,22 +362,22 @@ public class JavacState { noFileFound = true; } catch (IOException e) { Log.info("Dropping old javac_state because of errors when reading it."); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); foundCorrectVerNr = true; newCommandLine = false; syntaxError = false; } if (foundCorrectVerNr == false && !noFileFound) { Log.info("Dropping old javac_state since it is of an old version."); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); } else if (newCommandLine == true && !noFileFound) { Log.info("Dropping old javac_state since a new command line is used!"); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); } else if (syntaxError == true) { Log.info("Dropping old javac_state since it contains syntax errors."); - db = new JavacState(options, true, out, err); + db = new JavacState(options, true); } db.prev.calculateDependents(); return db; @@ -812,9 +807,7 @@ public class JavacState { dependencyPublicApis, 0, isIncremental(), - numCores, - out, - err); + numCores); if (!r) rc = false; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java index 60f513fc80c..39788ebba6b 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,24 @@ package com.sun.tools.sjavac; import java.io.PrintWriter; +import java.io.StringWriter; import java.io.Writer; +import java.util.Locale; /** * Utility class only for sjavac logging. - * The log level can be set using for example --log=DEBUG on the sjavac command line. + * + * Logging in sjavac has special requirements when running in server/client + * mode. Most of the log messages is generated server-side, but the server + * is typically spawned by the client in the background, so the user usually + * does not see the server stdout/stderr. For this reason log messages needs + * to relayed back to the client that performed the request that generated the + * log message. To support this use case this class maintains a per-thread log + * instance so that each connected client can have its own instance that + * relays messages back to the requesting client. + * + * On the client-side (or when running sjavac without server-mode) there will + * typically just be one Log instance. * *

    This is NOT part of any supported API. * If you write code that depends on this, you do so at your own risk. @@ -38,61 +51,94 @@ import java.io.Writer; * deletion without notice. */ public class Log { - private static PrintWriter out, err; - public final static int WARN = 1; - public final static int INFO = 2; - public final static int DEBUG = 3; - public final static int TRACE = 4; - private static int level = WARN; + public enum Level { + ERROR, + WARN, + INFO, + DEBUG, + TRACE; + } + + private static Log stdOutErr = new Log(new PrintWriter(System.out), new PrintWriter(System.err)); + private static ThreadLocal loggers = new ThreadLocal<>(); + + protected PrintWriter err; // Used for error and warning messages + protected PrintWriter out; // Used for other messages + protected Level level = Level.INFO; + + public Log(Writer out, Writer err) { + this.out = out == null ? null : new PrintWriter(out, true); + this.err = err == null ? null : new PrintWriter(err, true); + } + + public static void setLogForCurrentThread(Log log) { + loggers.set(log); + } + + public static void setLogLevel(String l) { + setLogLevel(Level.valueOf(l.toUpperCase(Locale.US))); + } + + public static void setLogLevel(Level l) { + get().level = l; + } static public void trace(String msg) { - if (level >= TRACE) { - out.println(msg); - } + log(Level.TRACE, msg); } static public void debug(String msg) { - if (level >= DEBUG) { - out.println(msg); - } + log(Level.DEBUG, msg); } static public void info(String msg) { - if (level >= INFO) { - out.println(msg); - } + log(Level.INFO, msg); } static public void warn(String msg) { - err.println(msg); + log(Level.WARN, msg); } static public void error(String msg) { - err.println(msg); + log(Level.ERROR, msg); } - static public void initializeLog(Writer o, Writer e) { - out = new PrintWriter(o); - err = new PrintWriter(e); + static public void error(Throwable t) { + log(Level.ERROR, t); } - static public void setLogLevel(String l) { - switch (l) { - case "warn": level = WARN; break; - case "info": level = INFO; break; - case "debug": level = DEBUG; break; - case "trace": level = TRACE; break; - default: - throw new IllegalArgumentException("No such log level \"" + l + "\""); - } + static public void log(Level l, String msg) { + get().printLogMsg(l, msg); } - static public boolean isTracing() { - return level >= TRACE; + public static void debug(Throwable t) { + log(Level.DEBUG, t); + } + + public static void log(Level l, Throwable t) { + StringWriter sw = new StringWriter(); + t.printStackTrace(new PrintWriter(sw, true)); + log(l, sw.toString()); } static public boolean isDebugging() { - return level >= DEBUG; + return get().isLevelLogged(Level.DEBUG); + } + + protected boolean isLevelLogged(Level l) { + return l.ordinal() <= level.ordinal(); + } + + public static Log get() { + Log log = loggers.get(); + return log != null ? log : stdOutErr; + } + + protected void printLogMsg(Level msgLevel, String msg) { + if (isLevelLogged(msgLevel)) { + PrintWriter pw = msgLevel.ordinal() <= Level.WARN.ordinal() ? err : out; + pw.println(msg); + } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java index 7fcac272176..c9e2c62865c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java @@ -95,9 +95,7 @@ public interface Transformer { Map dependencyApis, int debugLevel, boolean incremental, - int numCores, - Writer out, - Writer err); + int numCores); void setExtra(String e); void setExtra(Options args); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java index d010cfa7b82..1bcad774b24 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Util.java @@ -36,7 +36,9 @@ import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.function.Function; +import java.util.regex.Pattern; import java.util.stream.Collectors; +import java.util.stream.Stream; /** * Utilities. @@ -236,4 +238,10 @@ public class Util { int dotIndex = fileNameStr.indexOf('.'); return dotIndex == -1 ? "" : fileNameStr.substring(dotIndex); } + + public static Stream getLines(String str) { + return str.isEmpty() + ? Stream.empty() + : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java index 0e62feaed2d..54c1e51952f 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java @@ -51,7 +51,7 @@ public class ClientMain { public static int run(String[] args, Writer out, Writer err) { - Log.initializeLog(out, err); + Log.setLogForCurrentThread(new Log(out, err)); Options options; try { @@ -61,6 +61,8 @@ public class ClientMain { return -1; } + Log.setLogLevel(options.getLogLevel()); + Log.debug("=========================================================="); Log.debug("Launching sjavac client with the following parameters:"); Log.debug(" " + options.getStateArgsString()); @@ -68,24 +70,15 @@ public class ClientMain { // Prepare sjavac object boolean useServer = options.getServerConf() != null; - Sjavac sjavac; - // Create an sjavac implementation to be used for compilation - if (useServer) { - try { - sjavac = new SjavacClient(options); - } catch (PortFileInaccessibleException e) { - Log.error("Port file inaccessible."); - return -1; - } - } else { - sjavac = new SjavacImpl(); - } + Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl(); - int rc = sjavac.compile(args, out, err); + // Perform compilation + int rc = sjavac.compile(args); // If sjavac is running in the foreground we should shut it down at this point - if (!useServer) + if (!useServer) { sjavac.shutdown(); + } return rc; } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java index e13c9455ff9..b9b039354d4 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; +import java.io.Reader; import java.io.Writer; import java.net.InetAddress; import java.net.InetSocketAddress; @@ -40,6 +41,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; +import java.util.stream.Stream; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; @@ -50,6 +52,8 @@ import com.sun.tools.sjavac.server.PortFile; import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.SjavacServer; +import static java.util.stream.Collectors.joining; + /** * Sjavac implementation that delegates requests to a SjavacServer. * @@ -64,8 +68,6 @@ public class SjavacClient implements Sjavac { // JavaCompiler instance for several compiles using the same id. private final String id; private final PortFile portFile; - private final String logfile; - private final String stdouterrfile; // Default keepalive for server is 120 seconds. // I.e. it will accept 120 seconds of inactivity before quitting. @@ -86,7 +88,7 @@ public class SjavacClient implements Sjavac { // Store the server conf settings here. private final String settings; - public SjavacClient(Options options) throws PortFileInaccessibleException { + public SjavacClient(Options options) { String tmpServerConf = options.getServerConf(); String serverConf = (tmpServerConf!=null)? tmpServerConf : ""; String tmpId = Util.extractStringOption("id", serverConf); @@ -96,14 +98,7 @@ public class SjavacClient implements Sjavac { .toAbsolutePath() .toString(); String portfileName = Util.extractStringOption("portfile", serverConf, defaultPortfile); - try { - portFile = SjavacServer.getPortFile(portfileName); - } catch (PortFileInaccessibleException e) { - Log.error("Port file inaccessable: " + e); - throw e; - } - logfile = Util.extractStringOption("logfile", serverConf, portfileName + ".javaclog"); - stdouterrfile = Util.extractStringOption("stdouterrfile", serverConf, portfileName + ".stdouterr"); + portFile = SjavacServer.getPortFile(portfileName); sjavacForkCmd = Util.extractStringOption("sjavac", serverConf, "sjavac"); int poolsize = Util.extractIntOption("poolsize", serverConf); keepalive = Util.extractIntOption("keepalive", serverConf, 120); @@ -121,7 +116,7 @@ public class SjavacClient implements Sjavac { } @Override - public int compile(String[] args, Writer stdout, Writer stderr) { + public int compile(String[] args) { int result = -1; try (Socket socket = tryConnect()) { PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); @@ -136,32 +131,36 @@ public class SjavacClient implements Sjavac { // Read server response line by line String line; while (null != (line = in.readLine())) { + if (!line.contains(":")) { + throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<"); + } String[] typeAndContent = line.split(":", 2); String type = typeAndContent[0]; String content = typeAndContent[1]; - switch (type) { - case SjavacServer.LINE_TYPE_STDOUT: - stdout.write(content); - stdout.write('\n'); - break; - case SjavacServer.LINE_TYPE_STDERR: - stderr.write(content); - stderr.write('\n'); - break; - case SjavacServer.LINE_TYPE_RC: + + try { + Log.log(Log.Level.valueOf(type), "[server] " + content); + continue; + } catch (IllegalArgumentException e) { + // Parsing of 'type' as log level failed. + } + + if (type.equals(SjavacServer.LINE_TYPE_RC)) { result = Integer.parseInt(content); - break; } } - } catch (IOException ioe) { - Log.error("[CLIENT] Exception caught: " + ioe); + } catch (PortFileInaccessibleException e) { + Log.error("Port file inaccessible."); + result = CompilationSubResult.ERROR_FATAL; + } catch (IOException ioe) { + Log.error("IOException caught during compilation: " + ioe.getMessage()); + Log.debug(ioe); result = CompilationSubResult.ERROR_FATAL; - ioe.printStackTrace(new PrintWriter(stderr)); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Restore interrupt - Log.error("[CLIENT] compile interrupted."); + Log.error("Compilation interrupted."); + Log.debug(ie); result = CompilationSubResult.ERROR_FATAL; - ie.printStackTrace(new PrintWriter(stderr)); } return result; } @@ -203,23 +202,22 @@ public class SjavacClient implements Sjavac { private void makeSureServerIsRunning(PortFile portFile) throws IOException, InterruptedException { - portFile.lock(); - portFile.getValues(); - portFile.unlock(); + if (portFile.exists()) { + portFile.lock(); + portFile.getValues(); + portFile.unlock(); - if (portFile.containsPortInfo()) { - // Server seems to already be running - return; + if (portFile.containsPortInfo()) { + // Server seems to already be running + return; + } } // Fork a new server and wait for it to start SjavacClient.fork(sjavacForkCmd, portFile, - logfile, poolsize, - keepalive, - System.err, - stdouterrfile); + keepalive); } @Override @@ -230,51 +228,53 @@ public class SjavacClient implements Sjavac { /* * Fork a server process process and wait for server to come around */ - public static void fork(String sjavacCmd, - PortFile portFile, - String logfile, - int poolsize, - int keepalive, - final PrintStream err, - String stdouterrfile) - throws IOException, InterruptedException { + public static void fork(String sjavacCmd, PortFile portFile, int poolsize, int keepalive) + throws IOException, InterruptedException { List cmd = new ArrayList<>(); cmd.addAll(Arrays.asList(OptionHelper.unescapeCmdArg(sjavacCmd).split(" "))); cmd.add("--startserver:" + "portfile=" + portFile.getFilename() - + ",logfile=" + logfile - + ",stdouterrfile=" + stdouterrfile + ",poolsize=" + poolsize + ",keepalive="+ keepalive); - Process p = null; + Process serverProcess; Log.info("Starting server. Command: " + String.join(" ", cmd)); try { - // If the cmd for some reason can't be executed (file not found, or - // is not executable) this will throw an IOException with a decent - // error message. - p = new ProcessBuilder(cmd) - .redirectErrorStream(true) - .redirectOutput(new File(stdouterrfile)) - .start(); + // If the cmd for some reason can't be executed (file is not found, + // or is not executable for instance) this will throw an + // IOException and p == null. + serverProcess = new ProcessBuilder(cmd) + .redirectErrorStream(true) + .start(); + } catch (IOException ex) { + // Message is typically something like: + // Cannot run program "xyz": error=2, No such file or directory + Log.error("Failed to create server process: " + ex.getMessage()); + Log.debug(ex); + throw new IOException(ex); + } + // serverProcess != null at this point. + try { // Throws an IOException if no valid values materialize portFile.waitForValidValues(); - } catch (IOException ex) { - // Log and rethrow exception - Log.error("Faild to launch server."); - Log.error(" Message: " + ex.getMessage()); - String rc = p == null || p.isAlive() ? "n/a" : "" + p.exitValue(); - Log.error(" Server process exit code: " + rc); - Log.error("Server log:"); - Log.error("------- Server log start -------"); - try (Scanner s = new Scanner(new File(stdouterrfile))) { - while (s.hasNextLine()) - Log.error(s.nextLine()); + // Process was started, but server failed to initialize. This could + // for instance be due to the JVM not finding the server class, + // or the server running in to some exception early on. + Log.error("Sjavac server failed to initialize: " + ex.getMessage()); + Log.error("Process output:"); + Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream()); + try (BufferedReader br = new BufferedReader(serverStdoutStderr)) { + br.lines().forEach(Log::error); } - Log.error("------- Server log end ---------"); - throw ex; + Log.error(""); + try { + Log.error("Process exit code: " + serverProcess.exitValue()); + } catch (IllegalThreadStateException e) { + // Server is presumably still running. + } + throw new IOException("Server failed to initialize: " + ex.getMessage(), ex); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java index 6569e28c076..0eb4f7e2358 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -95,11 +95,8 @@ public class CompilationService { for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH)); - // Create a new logger - StringWriter stdoutLog = new StringWriter(); + // Create a log to capture compiler output StringWriter stderrLog = new StringWriter(); - PrintWriter stdout = new PrintWriter(stdoutLog); - PrintWriter stderr = new PrintWriter(stderrLog); com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs); PathAndPackageVerifier papVerifier = new PathAndPackageVerifier(); @@ -108,11 +105,10 @@ public class CompilationService { if (explicitJFOs.size() > 0) { sfm.setVisibleSources(visibleSources); sfm.cleanArtifacts(); - sfm.setLog(stdout); // Do the compilation! JavacTaskImpl task = - (JavacTaskImpl) compiler.getTask(stderr, + (JavacTaskImpl) compiler.getTask(new PrintWriter(stderrLog), sfm, null, Arrays.asList(args), @@ -144,7 +140,6 @@ public class CompilationService { compilationResult.packagePubapis = pubApiCollector.getPubApis(true); compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); - compilationResult.stdout = stdoutLog.toString(); compilationResult.stderr = stderrLog.toString(); compilationResult.returnCode = rc.exitCode; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java index caabc38df1d..82be0ae3b16 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,15 +25,14 @@ package com.sun.tools.sjavac.comp; -import java.io.Writer; +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.server.Sjavac; + import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import com.sun.tools.sjavac.Log; -import com.sun.tools.sjavac.server.Sjavac; - /** * An sjavac implementation that limits the number of concurrent calls by * wrapping invocations in Callables and delegating them to a FixedThreadPool. @@ -55,10 +54,12 @@ public class PooledSjavac implements Sjavac { } @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { + Log log = Log.get(); try { return pool.submit(() -> { - return delegate.compile(args, out, err); + Log.setLogForCurrentThread(log); + return delegate.compile(args); }).get(); } catch (Exception e) { e.printStackTrace(); diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java index 79835ab6c28..b1b77150364 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java @@ -27,7 +27,7 @@ package com.sun.tools.sjavac.comp; import java.io.IOException; import java.io.PrintWriter; -import java.io.Writer; +import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -68,7 +68,7 @@ import javax.tools.JavaFileManager; public class SjavacImpl implements Sjavac { @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { Options options; try { options = Options.parseArgs(args); @@ -77,11 +77,13 @@ public class SjavacImpl implements Sjavac { return RC_FATAL; } - Log.setLogLevel(options.getLogLevel()); - if (!validateOptions(options)) return RC_FATAL; + if (srcDstOverlap(options.getSources(), options.getDestDir())) { + return RC_FATAL; + } + if (!createIfMissing(options.getDestDir())) return RC_FATAL; @@ -100,18 +102,21 @@ public class SjavacImpl implements Sjavac { if (stateDir == null) { // Prepare context. Direct logging to our byte array stream. Context context = new Context(); - PrintWriter writer = new PrintWriter(err); - com.sun.tools.javac.util.Log.preRegister(context, writer); + StringWriter strWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(strWriter); + com.sun.tools.javac.util.Log.preRegister(context, printWriter); JavacFileManager.preRegister(context); // Prepare arguments String[] passThroughArgs = Stream.of(args) .filter(arg -> !arg.startsWith(Option.SERVER.arg)) .toArray(String[]::new); - // Compile - com.sun.tools.javac.main.Main compiler = new com.sun.tools.javac.main.Main("javac", writer); - Main.Result result = compiler.compile(passThroughArgs, context); + Main.Result result = new Main("javac", printWriter).compile(passThroughArgs, context); + + // Process compiler output (which is always errors) + printWriter.flush(); + Util.getLines(strWriter.toString()).forEach(Log::error); // Clean up JavaFileManager fileManager = context.get(JavaFileManager.class); @@ -126,7 +131,7 @@ public class SjavacImpl implements Sjavac { } else { // Load the prev build state database. - JavacState javac_state = JavacState.load(options, out, err); + JavacState javac_state = JavacState.load(options); // Setup the suffix rules from the command line. Map suffixRules = new HashMap<>(); @@ -288,10 +293,12 @@ public class SjavacImpl implements Sjavac { return rc[0] ? RC_OK : RC_FATAL; } catch (ProblemException e) { + // For instance make file list mismatch. Log.error(e.getMessage()); + Log.debug(e); return RC_FATAL; } catch (Exception e) { - e.printStackTrace(new PrintWriter(err)); + Log.error(e); return RC_FATAL; } } @@ -326,6 +333,22 @@ public class SjavacImpl implements Sjavac { } + private static boolean srcDstOverlap(List locs, Path dest) { + for (SourceLocation loc : locs) { + if (isOverlapping(loc.getPath(), dest)) { + Log.error("Source location " + loc.getPath() + " overlaps with destination " + dest); + return true; + } + } + return false; + } + + private static boolean isOverlapping(Path p1, Path p2) { + p1 = p1.toAbsolutePath().normalize(); + p2 = p2.toAbsolutePath().normalize(); + return p1.startsWith(p2) || p2.startsWith(p1); + } + private static boolean createIfMissing(Path dir) { if (Files.isDirectory(dir)) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java index db66e4ab59f..496f039eb9a 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,8 +63,6 @@ public class SmartFileManager extends ForwardingJavaFileManager Set visibleSources = new HashSet<>(); // Map from modulename:packagename to artifacts. Map> packageArtifacts = new HashMap<>(); - // Where to print informational messages. - PrintWriter stdout; public SmartFileManager(JavaFileManager fileManager) { super(fileManager); @@ -78,10 +76,6 @@ public class SmartFileManager extends ForwardingJavaFileManager packageArtifacts = new HashMap<>(); } - public void setLog(PrintWriter pw) { - stdout = pw; - } - /** * Set whether or not to use ct.sym as an alternate to rt.jar. */ @@ -188,7 +182,7 @@ public class SmartFileManager extends ForwardingJavaFileManager if (file == null) return file; if (location.equals(StandardLocation.NATIVE_HEADER_OUTPUT) && superFile instanceof JavaFileObject) { - file = new SmartFileObject((JavaFileObject) file, stdout); + file = new SmartFileObject((JavaFileObject) file); packageName = ":" + packageNameFromFileName(relativeName); } if (packageName.equals("")) { diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java index c7ac09d5868..e5295a16eb1 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartFileObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -49,11 +49,9 @@ import com.sun.tools.javac.util.DefinedBy.Api; public class SmartFileObject implements JavaFileObject { JavaFileObject file; - PrintWriter stdout; - public SmartFileObject(JavaFileObject r, PrintWriter pw) { + public SmartFileObject(JavaFileObject r) { file = r; - stdout = pw; } @Override @@ -113,7 +111,7 @@ public class SmartFileObject implements JavaFileObject { } catch (FileNotFoundException | NoSuchFileException e) { // Perfectly ok. } - return new SmartWriter(file, s.toString(), file.getName(), stdout); + return new SmartWriter(file, s.toString(), file.getName()); } @DefinedBy(Api.COMPILER) diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java index 0aabb65f4ce..2d1fa389858 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SmartWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.tools.sjavac.comp; +import com.sun.tools.sjavac.Log; + import java.io.*; import javax.tools.JavaFileObject; @@ -45,19 +47,17 @@ public class SmartWriter extends Writer { JavaFileObject file; String oldContent; StringWriter newContent = new StringWriter(); - PrintWriter stdout; boolean closed; - public SmartWriter(JavaFileObject f, String s, String n, PrintWriter pw) { + + public SmartWriter(JavaFileObject f, String s, String n) { name = n; file = f; oldContent = s; newContent = new StringWriter(); - stdout = pw; closed = false; } - public void write(char[] chars, int i, int i1) - { + public void write(char[] chars, int i, int i1) { newContent.write(chars, i, i1); } @@ -70,7 +70,7 @@ public class SmartWriter extends Writer { try (Writer writer = file.openWriter()) { writer.write(s); } - stdout.println("Writing "+file.getName().substring(p+1)); + Log.debug("Writing " + file.getName().substring(p + 1)); } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java index 111d9c9ff32..8b7d17b0c0c 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,10 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.sjavac.Log; + +import java.io.FileWriter; +import java.io.IOException; import java.io.Writer; import java.util.Timer; import java.util.TimerTask; @@ -53,8 +57,8 @@ public class IdleResetSjavac implements Sjavac { private TimerTask idlenessTimerTask; public IdleResetSjavac(Sjavac delegate, - Terminable toShutdown, - long idleTimeout) { + Terminable toShutdown, + long idleTimeout) { this.delegate = delegate; this.toShutdown = toShutdown; this.idleTimeout = idleTimeout; @@ -62,10 +66,10 @@ public class IdleResetSjavac implements Sjavac { } @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { startCall(); try { - return delegate.compile(args, out, err); + return delegate.compile(args); } finally { endCall(); } @@ -95,6 +99,7 @@ public class IdleResetSjavac implements Sjavac { throw new IllegalStateException("Idle timeout already scheduled"); idlenessTimerTask = new TimerTask() { public void run() { + Log.setLogForCurrentThread(ServerMain.getErrorLog()); toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds."); } }; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java deleted file mode 100644 index 0cdc2cc7dfa..00000000000 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/LinePrefixFilterWriter.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.tools.sjavac.server; - -import java.io.FilterWriter; -import java.io.IOException; -import java.io.Writer; - -/** - * Inserts {@literal prefix} in front of each line written. - * - * A line is considered to be terminated by any one of a line feed, a carriage - * return, or a carriage return followed immediately by a line feed. - */ -public class LinePrefixFilterWriter extends FilterWriter { - - private final String prefix; - private boolean atBeginningOfLine = true; - private char lastChar = '\0'; - - protected LinePrefixFilterWriter(Writer out, String prefix) { - super(out); - this.prefix = prefix; - } - - @Override - public void write(String str, int off, int len) throws IOException { - for (int i = 0; i < len; i++) { - write(str.charAt(off + i)); - } - } - - @Override - public void write(char[] cbuf, int off, int len) throws IOException { - for (int i = 0; i < len; i++) { - write(cbuf[off + i]); - } - } - - @Override - public void write(int c) throws IOException { - if (lastChar == '\r' && c == '\n') { - // Second character of CR+LF sequence. - // Do nothing. We already started a new line on last character. - } else { - if (atBeginningOfLine) { - super.write(prefix, 0, prefix.length()); - } - super.write(c); - atBeginningOfLine = c == '\r' || c == '\n'; - } - lastChar = (char) c; - } -} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java index d1a290adade..3bbdca22c4e 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java @@ -81,10 +81,15 @@ public class PortFile { * Create a new portfile. * @param fn is the path to the file. */ - public PortFile(String fn) throws PortFileInaccessibleException { + public PortFile(String fn) { filename = fn; file = new File(filename); stopFile = new File(filename+".stop"); + containsPortInfo = false; + lock = null; + } + + private void initializeChannel() throws PortFileInaccessibleException { try { rwfile = new RandomAccessFile(file, "rw"); } catch (FileNotFoundException e) { @@ -94,14 +99,15 @@ public class PortFile { // The rwfile should only be readable by the owner of the process // and no other! How do we do that on a RandomAccessFile? channel = rwfile.getChannel(); - containsPortInfo = false; - lock = null; } /** * Lock the port file. */ public void lock() throws IOException, InterruptedException { + if (channel == null) { + initializeChannel(); + } lockSem.acquire(); lock = channel.lock(); } @@ -204,8 +210,8 @@ public class PortFile { if (stopFile.exists()) { try { stopFile.delete(); - } catch (Exception e) - {} + } catch (Exception e) { + } return true; } return false; @@ -215,7 +221,9 @@ public class PortFile { * Unlock the port file. */ public void unlock() throws IOException { - Assert.check(lock != null); + if (lock == null) { + return; + } lock.release(); lock = null; lockSem.release(); @@ -230,9 +238,11 @@ public class PortFile { long timeout = startTime + getServerStartupTimeoutSeconds() * 1000; while (true) { Log.debug("Looking for valid port file values..."); - lock(); - getValues(); - unlock(); + if (exists()) { + lock(); + getValues(); + unlock(); + } if (containsPortInfo) { Log.debug("Valid port file values found after " + (System.currentTimeMillis() - startTime) + " ms"); return; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java index d3e68565533..7b37d3753ae 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFileMonitor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.tools.sjavac.server; +import com.sun.tools.sjavac.Log; + import java.io.IOException; import java.util.Timer; import java.util.TimerTask; @@ -56,8 +58,11 @@ public class PortFileMonitor { } public void start() { + Log log = Log.get(); TimerTask shutdownCheck = new TimerTask() { public void run() { + Log.setLogForCurrentThread(log); + Log.debug("Checking port file status..."); try { if (!portFile.exists()) { // Time to quit because the portfile was deleted by another @@ -74,12 +79,11 @@ public class PortFileMonitor { server.shutdown("Quitting because portfile is now owned by another javac server!"); } } catch (IOException e) { - e.printStackTrace(server.theLog); - server.flushLog(); + Log.error("IOException caught in PortFileMonitor."); + Log.debug(e); } catch (InterruptedException e) { Thread.currentThread().interrupt(); - e.printStackTrace(server.theLog); - server.flushLog(); + Log.error(e); } } }; diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java index 253c1724a26..62ba3b995a9 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,16 @@ package com.sun.tools.sjavac.server; -import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC; -import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDERR; -import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_STDOUT; +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.Util; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Writer; import java.net.Socket; +import java.nio.file.Path; -import com.sun.tools.sjavac.AutoFlushWriter; -import com.sun.tools.sjavac.Log; +import static com.sun.tools.sjavac.server.SjavacServer.LINE_TYPE_RC; /** @@ -56,7 +53,7 @@ import com.sun.tools.sjavac.Log; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class RequestHandler implements Runnable { +public class RequestHandler extends Thread { private final Socket socket; private final Sjavac sjavac; @@ -68,9 +65,30 @@ public class RequestHandler implements Runnable { @Override public void run() { + try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { + // Set up logging for this thread. Stream back logging messages to + // client on the format format "level:msg". + Log.setLogForCurrentThread(new Log(out, out) { + @Override + protected boolean isLevelLogged(Level l) { + // Make sure it is up to the client to decide whether or + // not this message should be displayed. + return true; + } + + @Override + protected void printLogMsg(Level msgLevel, String msg) { + // Follow sjavac server/client protocol: Send one line + // at a time and prefix with message with "level:". + Util.getLines(msg) + .map(line -> msgLevel + ":" + line) + .forEach(line -> super.printLogMsg(msgLevel, line)); + } + }); + // Read argument array int n = Integer.parseInt(in.readLine()); String[] args = new String[n]; @@ -78,23 +96,32 @@ public class RequestHandler implements Runnable { args[i] = in.readLine(); } + // If there has been any internal errors, notify client + checkInternalErrorLog(); + // Perform compilation - Writer stdout = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDOUT + ":"); - Writer stderr = new LinePrefixFilterWriter(new AutoFlushWriter(out), LINE_TYPE_STDERR + ":"); - int rc = sjavac.compile(args, stdout, stderr); - stdout.flush(); - stderr.flush(); + int rc = sjavac.compile(args); // Send return code back to client out.println(LINE_TYPE_RC + ":" + rc); + // Check for internal errors again. + checkInternalErrorLog(); } catch (Exception ex) { // Not much to be done at this point. The client side request // code will most likely throw an IOException and the // compilation will fail. - StringWriter sw = new StringWriter(); - ex.printStackTrace(new PrintWriter(sw)); - Log.error(sw.toString()); + Log.error(ex); + } finally { + Log.setLogForCurrentThread(null); + } + } + + private void checkInternalErrorLog() { + Path errorLog = ServerMain.getErrorLog().getLogDestination(); + if (errorLog != null) { + Log.error("Server has encountered an internal error. See " + errorLog.toAbsolutePath() + + " for details."); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java index aab5ada4ae2..6690c3ece70 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/ServerMain.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,10 +25,20 @@ package com.sun.tools.sjavac.server; +import java.io.FileWriter; +import java.io.FilterOutputStream; +import java.io.FilterWriter; import java.io.IOException; -import java.io.OutputStreamWriter; +import java.io.PrintStream; +import java.lang.Thread.UncaughtExceptionHandler; import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.Log.Level; +import com.sun.tools.sjavac.server.log.LazyInitFileLog; +import com.sun.tools.sjavac.server.log.LoggingOutputStream; + +import static com.sun.tools.sjavac.Log.Level.ERROR; +import static com.sun.tools.sjavac.Log.Level.INFO; /** *

    This is NOT part of any supported API. @@ -37,20 +47,40 @@ import com.sun.tools.sjavac.Log; * deletion without notice. */ public class ServerMain { + + // For logging server internal (non request specific) errors. + private static LazyInitFileLog errorLog; + public static int run(String[] args) { - Log.initializeLog(new OutputStreamWriter(System.out), - new OutputStreamWriter(System.err)); + // Under normal operation, all logging messages generated server-side + // are due to compilation requests. These logging messages should + // be relayed back to the requesting client rather than written to the + // server log. The only messages that should be written to the server + // log (in production mode) should be errors, + Log.setLogForCurrentThread(errorLog = new LazyInitFileLog("server.log")); + Log.setLogLevel(ERROR); // should be set to ERROR. + + // Make sure no exceptions go under the radar + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + Log.setLogForCurrentThread(errorLog); + Log.error(e); + }); + + // Inevitably someone will try to print messages using System.{out,err}. + // Make sure this output also ends up in the log. + System.setOut(new PrintStream(new LoggingOutputStream(System.out, INFO, "[stdout] "))); + System.setErr(new PrintStream(new LoggingOutputStream(System.err, ERROR, "[stderr] "))); // Any options other than --startserver? if (args.length > 1) { - System.err.println("When spawning a background server, only a single --startserver argument is allowed."); + Log.error("When spawning a background server, only a single --startserver argument is allowed."); return 1; } int exitCode; try { - SjavacServer server = new SjavacServer(args[0], System.err); + SjavacServer server = new SjavacServer(args[0]); exitCode = server.startServer(); } catch (IOException | InterruptedException ex) { ex.printStackTrace(); @@ -59,4 +89,8 @@ public class ServerMain { return exitCode; } + + public static LazyInitFileLog getErrorLog() { + return errorLog; + } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java index 837fb633b33..91063c5a809 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,6 @@ public interface Sjavac { final static int RC_FATAL = -1; final static int RC_OK = 0; - int compile(String[] args, Writer stdout, Writer stderr); + int compile(String[] args); void shutdown(); } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java index 1f9ec7504d4..ea9720886bf 100644 --- a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java @@ -26,6 +26,7 @@ package com.sun.tools.sjavac.server; import java.io.FileNotFoundException; +import java.io.FileWriter; import java.io.IOException; import java.io.PrintStream; import java.io.PrintWriter; @@ -39,6 +40,7 @@ import java.util.Map; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; +import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.client.PortFileInaccessibleException; import com.sun.tools.sjavac.comp.PooledSjavac; @@ -54,17 +56,12 @@ import com.sun.tools.sjavac.comp.SjavacImpl; */ public class SjavacServer implements Terminable { - // Used in protocol to tell the content of each line + // Prefix of line containing return code. public final static String LINE_TYPE_RC = "RC"; - public final static String LINE_TYPE_STDOUT = "STDOUT"; - public final static String LINE_TYPE_STDERR = "STDERR"; final private String portfilename; - final private String logfile; - final private String stdouterrfile; final private int poolsize; final private int keepalive; - final private PrintStream err; // The secret cookie shared between server and client through the port file. // Used to prevent clients from believing that they are communicating with @@ -75,9 +72,6 @@ public class SjavacServer implements Terminable { // Accumulated build time, not counting idle time, used for logging purposes private long totalBuildTime; - // The javac server specific log file. - PrintWriter theLog; - // The sjavac implementation to delegate requests to Sjavac sjavac; @@ -92,40 +86,28 @@ public class SjavacServer implements Terminable { // For the client, all port files fetched, one per started javac server. // Though usually only one javac server is started by a client. private static Map allPortFiles; - private static Map maxServerMemory; - public SjavacServer(String settings, PrintStream err) throws FileNotFoundException { + public SjavacServer(String settings) throws FileNotFoundException { this(Util.extractStringOption("portfile", settings), - Util.extractStringOption("logfile", settings), - Util.extractStringOption("stdouterrfile", settings), Util.extractIntOption("poolsize", settings, Runtime.getRuntime().availableProcessors()), - Util.extractIntOption("keepalive", settings, 120), - err); + Util.extractIntOption("keepalive", settings, 120)); } public SjavacServer(String portfilename, - String logfile, - String stdouterrfile, int poolsize, - int keepalive, - PrintStream err) + int keepalive) throws FileNotFoundException { this.portfilename = portfilename; - this.logfile = logfile; - this.stdouterrfile = stdouterrfile; this.poolsize = poolsize; this.keepalive = keepalive; - this.err = err; - - myCookie = new Random().nextLong(); - theLog = new PrintWriter(logfile); + this.myCookie = new Random().nextLong(); } /** * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. */ - public static synchronized PortFile getPortFile(String filename) throws PortFileInaccessibleException { + public static synchronized PortFile getPortFile(String filename) { if (allPortFiles == null) { allPortFiles = new HashMap<>(); } @@ -169,26 +151,6 @@ public class SjavacServer implements Terminable { totalBuildTime += inc; } - /** - * Log this message. - */ - public void log(String msg) { - if (theLog != null) { - theLog.println(msg); - } else { - System.err.println(msg); - } - } - - /** - * Make sure the log is flushed. - */ - public void flushLog() { - if (theLog != null) { - theLog.flush(); - } - } - /** * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" * is sent as the settings parameter. Returns 0 on success, -1 on failure. @@ -203,7 +165,7 @@ public class SjavacServer implements Terminable { portFile.lock(); portFile.getValues(); if (portFile.containsPortInfo()) { - err.println("Javac server not started because portfile exists!"); + Log.info("Javac server not started because portfile exists!"); portFile.unlock(); return -1; } @@ -230,23 +192,23 @@ public class SjavacServer implements Terminable { portFileMonitor = new PortFileMonitor(portFile, this); portFileMonitor.start(); - log("Sjavac server started. Accepting connections..."); - log(" port: " + getPort()); - log(" time: " + new java.util.Date()); - log(" poolsize: " + poolsize); - flushLog(); + Log.info("Sjavac server started. Accepting connections..."); + Log.info(" port: " + getPort()); + Log.info(" time: " + new java.util.Date()); + Log.info(" poolsize: " + poolsize); + keepAcceptingRequests.set(true); do { try { Socket socket = serverSocket.accept(); - new Thread(new RequestHandler(socket, sjavac)).start(); + new RequestHandler(socket, sjavac).start(); } catch (SocketException se) { // Caused by serverSocket.close() and indicates shutdown } } while (keepAcceptingRequests.get()); - log("Shutting down."); + Log.info("Shutting down."); // No more connections accepted. If any client managed to connect after // the accept() was interrupted but before the server socket is closed @@ -254,8 +216,7 @@ public class SjavacServer implements Terminable { // IOException on the client side. long realTime = System.currentTimeMillis() - serverStart; - log("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); - flushLog(); + Log.info("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); // Shut down sjavac.shutdown(); @@ -270,8 +231,7 @@ public class SjavacServer implements Terminable { return; } - log("Quitting: " + quitMsg); - flushLog(); + Log.info("Quitting: " + quitMsg); portFileMonitor.shutdown(); // No longer any need to monitor port file @@ -280,12 +240,12 @@ public class SjavacServer implements Terminable { try { portFile.delete(); } catch (IOException | InterruptedException e) { - e.printStackTrace(theLog); + Log.error(e); } try { serverSocket.close(); } catch (IOException e) { - e.printStackTrace(theLog); + Log.error(e); } } } diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java new file mode 100644 index 00000000000..2b6cf9cee65 --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LazyInitFileLog.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.sjavac.server.log; + +import com.sun.tools.sjavac.Log; + +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class LazyInitFileLog extends Log { + + String baseFilename; + Path destination = null; + + public LazyInitFileLog(String baseFilename) { + super(null, null); + this.baseFilename = baseFilename; + } + + protected void printLogMsg(Level msgLevel, String msg) { + try { + // Lazily initialize out/err + if (out == null && isLevelLogged(msgLevel)) { + destination = getAvailableDestination(); + out = err = new PrintWriter(new FileWriter(destination.toFile()), true); + } + // Proceed to log the message + super.printLogMsg(msgLevel, msg); + } catch (IOException e) { + // This could be bad. We might have run into an error and we can't + // log it. Resort to printing on stdout. + System.out.println("IO error occurred: " + e.getMessage()); + System.out.println("Original message: [" + msgLevel + "] " + msg); + } + } + + /** + * @return The first available path of baseFilename, baseFilename.1, + * basefilename.2, ... + */ + private Path getAvailableDestination() { + Path p = Paths.get(baseFilename); + int i = 1; + while (Files.exists(p)) { + p = Paths.get(baseFilename + "." + i++); + } + return p; + } + + public Path getLogDestination() { + return destination; + } +} diff --git a/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java new file mode 100644 index 00000000000..56b048376ce --- /dev/null +++ b/langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/log/LoggingOutputStream.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.sjavac.server.log; + +import com.sun.tools.sjavac.Log; + +import java.io.ByteArrayOutputStream; +import java.io.FilterOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class LoggingOutputStream extends FilterOutputStream { + + private static final byte[] LINE_SEP = System.lineSeparator().getBytes(); + + private final Log.Level level; + private final String linePrefix; + private EolTrackingByteArrayOutputStream buf = new EolTrackingByteArrayOutputStream(); + + public LoggingOutputStream(OutputStream out, Log.Level level, String linePrefix) { + super(out); + this.level = level; + this.linePrefix = linePrefix; + } + + @Override + public void write(int b) throws IOException { + super.write(b); + buf.write(b); + if (buf.isLineComplete()) { + String line = new String(buf.toByteArray(), 0, buf.size() - LINE_SEP.length); + Log.log(level, linePrefix + line); + buf = new EolTrackingByteArrayOutputStream(); + } + } + + private static class EolTrackingByteArrayOutputStream extends ByteArrayOutputStream { + private static final byte[] EOL = System.lineSeparator().getBytes(); + private boolean isLineComplete() { + if (count < EOL.length) { + return false; + } + for (int i = 0; i < EOL.length; i++) { + if (buf[count - EOL.length + i] != EOL[i]) { + return false; + } + } + return true; + } + } +} diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java index 037d7fa77eb..66408158a9b 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/FrameOutputWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -96,6 +96,7 @@ public class FrameOutputWriter extends HtmlDocletWriter { protected void generateFrameFile() throws IOException { Content frame = getFrameDetails(); HtmlTree body = new HtmlTree(HtmlTag.BODY); + body.addAttr(HtmlAttr.ONLOAD, "loadFrames()"); if (configuration.allowTag(HtmlTag.MAIN)) { HtmlTree main = HtmlTree.MAIN(frame); body.addContent(main); diff --git a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 5c5d65b3585..2107273913f 100644 --- a/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -423,6 +423,10 @@ public class HtmlWriter { " }" + DocletConstants.NL + " }" + DocletConstants.NL + " return true;" + DocletConstants.NL + + " }" + DocletConstants.NL + + " function loadFrames() {" + DocletConstants.NL + + " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL + + " top.classFrame.location = top.targetPage;" + DocletConstants.NL + " }" + DocletConstants.NL; RawHtml scriptContent = new RawHtml(scriptCode); script.addContent(scriptContent); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java index d82da4653cd..44977bfb71a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractExecutableMemberWriter.java @@ -104,11 +104,11 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite sb.append(utils.getFullyQualifiedName(member)); if (!utils.isConstructor(member)) { sb.append("."); - sb.append(member.getSimpleName().toString()); + sb.append(member.getSimpleName()); } sb.append(utils.flatSignature((ExecutableElement) member)); - return writer.getDocLink(MEMBER, member, sb.toString()); + return writer.getDocLink(MEMBER, member, sb); } /** @@ -204,7 +204,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite htmltree.addContent("("); String sep = ""; List parameters = member.getParameters(); - String indent = makeSpace(indentSize + 1); + CharSequence indent = makeSpace(indentSize + 1); TypeMirror rcvrType = member.getReceiverType(); if (includeAnnotations && rcvrType != null && utils.isAnnotated(rcvrType)) { List annotationMirrors = rcvrType.getAnnotationMirrors(); @@ -260,7 +260,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite protected void addExceptions(ExecutableElement member, Content htmltree, int indentSize) { List exceptions = member.getThrownTypes(); if (!exceptions.isEmpty()) { - String indent = makeSpace(indentSize + 1 - 7); + CharSequence indent = makeSpace(indentSize + 1 - 7); htmltree.addContent(DocletConstants.NL); htmltree.addContent(indent); htmltree.addContent("throws "); @@ -336,7 +336,7 @@ public abstract class AbstractExecutableMemberWriter extends AbstractMemberWrite @Override @DefinedBy(Api.LANGUAGE_MODEL) protected Boolean defaultAction(TypeMirror e, Void p) { - buf.append(e.toString()); + buf.append(e); return foundTypeVariable; } }; diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java index aa04f515ea1..50f4c099807 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/AbstractMemberWriter.java @@ -223,26 +223,6 @@ public abstract class AbstractMemberWriter { htmltree.addContent(name); } - protected String typeString(Element member) { - return new SimpleElementVisitor9() { - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public String visitExecutable(ExecutableElement e, Void p) { - return utils.isMethod(e) ? e.getReturnType().toString() : ""; - } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - public String visitVariable(VariableElement e, Void p) { - return e.toString(); - } - - @Override @DefinedBy(Api.LANGUAGE_MODEL) - protected String defaultAction(Element e, Void p) { - return ""; - } - }.visit(member); - } - /** * Add the modifier for the member. The modifiers are ordered as specified * by The Java Language Specification. @@ -282,7 +262,7 @@ public abstract class AbstractMemberWriter { } } - protected String makeSpace(int len) { + protected CharSequence makeSpace(int len) { if (len <= 0) { return ""; } @@ -290,7 +270,7 @@ public abstract class AbstractMemberWriter { for (int i = 0; i < len; i++) { sb.append(' '); } - return sb.toString(); + return sb; } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java index 37bc63c57e6..17efe9c9c52 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ClassWriterImpl.java @@ -196,8 +196,11 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite div.addStyle(HtmlStyle.header); PackageElement pkg = utils.containingPackage(typeElement); if (!pkg.isUnnamed()) { - Content pkgNameContent = new StringContent(utils.getPackageName(pkg)); - Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, pkgNameContent); + Content classPackageLabel = HtmlTree.SPAN(HtmlStyle.packageLabelInClass, packageLabel); + Content pkgNameDiv = HtmlTree.DIV(HtmlStyle.subTitle, classPackageLabel); + pkgNameDiv.addContent(getSpace()); + Content pkgNameContent = getPackageLink(pkg, new StringContent(pkg.getQualifiedName())); + pkgNameDiv.addContent(pkgNameContent); div.addContent(pkgNameDiv); } LinkInfoImpl linkInfo = new LinkInfoImpl(configuration, @@ -391,10 +394,10 @@ public class ClassWriterImpl extends SubWriterHolderWriter implements ClassWrite new LinkInfoImpl(configuration, LinkInfoImpl.Kind.TREE, typeElement)); if (configuration.shouldExcludeQualifier(utils.containingPackage(typeElement).toString())) { - li.addContent(utils.asTypeElement(type).getSimpleName().toString()); + li.addContent(utils.asTypeElement(type).getSimpleName()); li.addContent(typeParameters); } else { - li.addContent(utils.asTypeElement(type).getQualifiedName().toString()); + li.addContent(utils.asTypeElement(type).getQualifiedName()); li.addContent(typeParameters); } } else { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java index 2b993595998..70f4a0fdd5a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/ConstantsSummaryWriterImpl.java @@ -244,7 +244,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons PackageElement enclosingPackage = utils.containingPackage(typeElement); if (!enclosingPackage.isUnnamed()) { Content cb = new ContentBuilder(); - cb.addContent(enclosingPackage.getQualifiedName().toString()); + cb.addContent(enclosingPackage.getQualifiedName()); cb.addContent("."); cb.addContent(classlink); return getClassName(cb); @@ -332,7 +332,7 @@ public class ConstantsSummaryWriterImpl extends HtmlDocletWriter implements Cons */ private Content getNameColumn(VariableElement member) { Content nameContent = getDocLink(LinkInfoImpl.Kind.CONSTANT_SUMMARY, - member, member.getSimpleName().toString(), false); + member, member.getSimpleName(), false); Content code = HtmlTree.CODE(nameContent); return HtmlTree.TD(code); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java index 69be1be292e..fa8e8ee3d92 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/FrameOutputWriter.java @@ -27,6 +27,7 @@ package jdk.javadoc.internal.doclets.formats.html; import java.io.*; +import jdk.javadoc.internal.doclets.formats.html.markup.HtmlAttr; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlStyle; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTag; import jdk.javadoc.internal.doclets.formats.html.markup.HtmlTree; @@ -102,6 +103,7 @@ public class FrameOutputWriter extends HtmlDocletWriter { protected void generateFrameFile() throws IOException { Content frame = getFrameDetails(); HtmlTree body = new HtmlTree(HtmlTag.BODY); + body.addAttr(HtmlAttr.ONLOAD, "loadFrames()"); if (configuration.allowTag(HtmlTag.MAIN)) { HtmlTree main = HtmlTree.MAIN(frame); body.addContent(main); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java index c5daf0fa50b..294bc605891 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDocletWriter.java @@ -166,6 +166,8 @@ public class HtmlDocletWriter extends HtmlDocWriter { HtmlTree fixedNavDiv = new HtmlTree(HtmlTag.DIV); + final static Pattern IMPROPER_HTML_CHARS = Pattern.compile(".*[&<>].*"); + /** * Constructor to construct the HtmlStandardWriter object. * @@ -945,7 +947,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { public Content getPackageName(PackageElement packageElement) { return packageElement == null || packageElement.isUnnamed() ? defaultPackageLabel - : getPackageLabel(packageElement.getQualifiedName().toString()); + : getPackageLabel(packageElement.getQualifiedName()); } /** @@ -954,7 +956,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param packageName the package name * @return the package name content */ - public Content getPackageLabel(String packageName) { + public Content getPackageLabel(CharSequence packageName) { return new StringContent(packageName); } @@ -1038,7 +1040,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param label the label for the link. * @return a content tree for the package link. */ - public Content getPackageLink(PackageElement packageElement, String label) { + public Content getPackageLink(PackageElement packageElement, CharSequence label) { return getPackageLink(packageElement, new StringContent(label)); } @@ -1081,7 +1083,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { public Content interfaceName(TypeElement typeElement, boolean qual) { Content name = new StringContent((qual) - ? typeElement.getQualifiedName().toString() + ? typeElement.getQualifiedName() : utils.getSimpleName(typeElement)); return (utils.isInterface(typeElement)) ? HtmlTree.SPAN(HtmlStyle.interfaceName, name) : name; } @@ -1279,7 +1281,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param label the label for the link * @return a content tree for the element link */ - public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label) { + public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, new StringContent(label)); } @@ -1293,7 +1295,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @param strong true if the link should be strong. * @return the link for the given member. */ - public Content getDocLink(LinkInfoImpl.Kind context, Element element, String label, + public Content getDocLink(LinkInfoImpl.Kind context, Element element, CharSequence label, boolean strong) { return getDocLink(context, utils.getEnclosingTypeElement(element), element, label, strong); } @@ -1311,7 +1313,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @return the link for the given member. */ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, - String label, boolean strong) { + CharSequence label, boolean strong) { return getDocLink(context, typeElement, element, label, strong, false); } @@ -1334,13 +1336,14 @@ public class HtmlDocletWriter extends HtmlDocWriter { * @return the link for the given member. */ public Content getDocLink(LinkInfoImpl.Kind context, TypeElement typeElement, Element element, - String label, boolean strong, boolean isProperty) { + CharSequence label, boolean strong, boolean isProperty) { return getDocLink(context, typeElement, element, new StringContent(check(label)), strong, isProperty); } - String check(String s) { - if (s.matches(".*[&<>].*")) { - throw new IllegalArgumentException(s); + CharSequence check(CharSequence s) { + Matcher m = IMPROPER_HTML_CHARS.matcher(s); + if (m.matches()) { + throw new IllegalArgumentException(s.toString()); } return s; } @@ -1426,7 +1429,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { CommentHelper ch = utils.getCommentHelper(element); String tagName = ch.getTagName(see); - String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see))); + String seetext = replaceDocRootDir(utils.normalizeNewlines(ch.getText(see)).toString()); // Check if @see is an href or "string" if (seetext.startsWith("<") || seetext.startsWith("\"")) { return new RawHtml(seetext); @@ -1452,7 +1455,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { //@see is referencing an included package if (label.isEmpty()) label = plainOrCode(isLinkPlain, - new StringContent(refPackage.getQualifiedName().toString())); + new StringContent(refPackage.getQualifiedName())); return getPackageLink(refPackage, label); } else { // @see is not referencing an included class or package. Check for cross links. @@ -1695,7 +1698,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { final Content result = new ContentBuilder() { @Override - public void addContent(String text) { + public void addContent(CharSequence text) { super.addContent(utils.normalizeNewlines(text)); } }; @@ -1741,7 +1744,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { public Boolean visitAttribute(AttributeTree node, Content c) { StringBuilder sb = new StringBuilder(SPACER).append(node.getName()); if (node.getValueKind() == ValueKind.EMPTY) { - result.addContent(sb.toString()); + result.addContent(sb); return false; } sb.append("="); @@ -1758,7 +1761,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { break; } sb.append(quote); - result.addContent(sb.toString()); + result.addContent(sb); Content docRootContent = new ContentBuilder(); for (DocTree dt : node.getValue()) { @@ -1767,16 +1770,15 @@ public class HtmlDocletWriter extends HtmlDocWriter { if (text.startsWith("/..") && !configuration.docrootparent.isEmpty()) { result.addContent(configuration.docrootparent); docRootContent = new ContentBuilder(); - text = textCleanup(text.substring(3), isLast(node)); + result.addContent(textCleanup(text.substring(3), isLast(node))); } else { if (!docRootContent.isEmpty()) { docRootContent = copyDocRootContent(docRootContent); } else { text = redirectRelativeLinks(element, (TextTree) dt); } - text = textCleanup(text, isLast(node)); + result.addContent(textCleanup(text, isLast(node))); } - result.addContent(text); } else { docRootContent = copyDocRootContent(docRootContent); dt.accept(this, docRootContent); @@ -1889,8 +1891,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { @Override @DefinedBy(Api.COMPILER_TREE) public Boolean visitStartElement(StartElementTree node, Content c) { String text = "<" + node.getName(); - text = utils.normalizeNewlines(text); - RawHtml rawHtml = new RawHtml(text); + RawHtml rawHtml = new RawHtml(utils.normalizeNewlines(text)); result.addContent(rawHtml); for (DocTree dt : node.getAttributes()) { @@ -1900,11 +1901,11 @@ public class HtmlDocletWriter extends HtmlDocWriter { return false; } - private String textCleanup(String text, boolean isLast) { + private CharSequence textCleanup(String text, boolean isLast) { return textCleanup(text, isLast, false); } - private String textCleanup(String text, boolean isLast, boolean trimLeader) { + private CharSequence textCleanup(String text, boolean isLast, boolean trimLeader) { if (trimLeader) { text = removeLeadingWhitespace(text); } @@ -1912,16 +1913,14 @@ public class HtmlDocletWriter extends HtmlDocWriter { text = removeTrailingWhitespace(text); } text = utils.replaceTabs(text); - text = utils.normalizeNewlines(text); - return text; + return utils.normalizeNewlines(text); } @Override @DefinedBy(Api.COMPILER_TREE) public Boolean visitText(TextTree node, Content c) { String text = node.getBody(); - text = textCleanup(text, isLast(node), commentRemoved); + result.addContent(new RawHtml(textCleanup(text, isLast(node), commentRemoved))); commentRemoved = false; - result.addContent(new RawHtml(text)); return false; } @@ -2358,7 +2357,8 @@ public class HtmlDocletWriter extends HtmlDocWriter { private void addAnnotations(TypeElement annotationDoc, LinkInfoImpl linkInfo, ContentBuilder annotation, Mapmap, int indent, boolean linkBreak) { - linkInfo.label = new StringContent("@" + annotationDoc.getSimpleName().toString()); + linkInfo.label = new StringContent("@"); + linkInfo.label.addContent(annotationDoc.getSimpleName()); annotation.addContent(getLink(linkInfo)); if (!map.isEmpty()) { annotation.addContent("("); @@ -2372,7 +2372,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { annotation.addContent(","); if (linkBreak) { annotation.addContent(DocletConstants.NL); - int spaces = annotationDoc.getSimpleName().toString().length() + 2; + int spaces = annotationDoc.getSimpleName().length() + 2; for (int k = 0; k < (spaces + indent); k++) { annotation.addContent(" "); } @@ -2496,7 +2496,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { @Override @DefinedBy(Api.LANGUAGE_MODEL) public Content visitEnumConstant(VariableElement c, Void p) { return getDocLink(LinkInfoImpl.Kind.ANNOTATION, - c, c.getSimpleName().toString(), false); + c, c.getSimpleName(), false); } @Override @DefinedBy(Api.LANGUAGE_MODEL) public Content visitArray(List vals, Void p) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java index 01cd9508a1a..30801a6bbc9 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/LinkInfoImpl.java @@ -294,7 +294,7 @@ public class LinkInfoImpl extends LinkInfo { * Set the label for the link. * @param label plain-text label for the link */ - public LinkInfoImpl label(String label) { + public LinkInfoImpl label(CharSequence label) { this.label = new StringContent(label); return this; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java index 40b00cdd1fd..68648d4aaaa 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/MethodWriterImpl.java @@ -356,11 +356,10 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter Content overriddenTypeLink = writer.getLink(new LinkInfoImpl(writer.configuration, context, overriddenType)); Content codeOverridenTypeLink = HtmlTree.CODE(overriddenTypeLink); - String name = method.getSimpleName().toString(); Content methlink = writer.getLink( new LinkInfoImpl(writer.configuration, LinkInfoImpl.Kind.MEMBER, holder) - .where(writer.getName(writer.getAnchor(method))).label(name)); + .where(writer.getName(writer.getAnchor(method))).label(method.getSimpleName())); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); dd.addContent(writer.getSpace()); @@ -395,7 +394,7 @@ public class MethodWriterImpl extends AbstractExecutableMemberWriter dl.addContent(dt); Content methlink = writer.getDocLink( LinkInfoImpl.Kind.MEMBER, implementedMeth, - implementedMeth.getSimpleName().toString(), false); + implementedMeth.getSimpleName(), false); Content codeMethLink = HtmlTree.CODE(methlink); Content dd = HtmlTree.DD(codeMethLink); dd.addContent(writer.getSpace()); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java index 064a93ce9d2..94170a334fb 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PackageIndexFrameWriter.java @@ -123,7 +123,7 @@ public class PackageIndexFrameWriter extends AbstractPackageIndexWriter { packageLinkContent = getHyperLink(DocPaths.PACKAGE_FRAME, packageLabel, "", "packageFrame"); } else { - packageLabel = getPackageLabel(pe.getQualifiedName().toString()); + packageLabel = getPackageLabel(pe.getQualifiedName()); packageLinkContent = getHyperLink(pathString(pe, DocPaths.PACKAGE_FRAME), packageLabel, "", "packageFrame"); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java index 3a1eebc23cf..9b7ca5da8ed 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/PropertyWriterImpl.java @@ -158,7 +158,7 @@ public class PropertyWriterImpl extends AbstractMemberWriter writer.getDocLink(LinkInfoImpl.Kind.PROPERTY_COPY, holder, property, utils.isIncluded(holder) - ? holder.toString() : utils.getFullyQualifiedName(holder), + ? holder.getSimpleName() : holder.getQualifiedName(), false); Content codeLink = HtmlTree.CODE(link); Content descfrmLabel = HtmlTree.SPAN(HtmlStyle.descfrmTypeLabel, diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java index 1ae644233b2..80a4cccf532 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/TagletWriterImpl.java @@ -91,8 +91,7 @@ public class TagletWriterImpl extends TagletWriter { */ protected Content codeTagOutput(Element element, DocTree tag) { CommentHelper ch = utils.getCommentHelper(element); - String str = utils.normalizeNewlines(ch.getText(tag)); - StringContent content = new StringContent(str); + StringContent content = new StringContent(utils.normalizeNewlines(ch.getText(tag))); Content result = HtmlTree.CODE(content); return result; } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java index 0adfc088106..32c5cc6c5b3 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/Comment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,8 @@ public class Comment extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java index 64ceef82473..e4a9265cbbd 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/ContentBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,8 +50,8 @@ public class ContentBuilder extends Content { } @Override - public void addContent(String text) { - if (text.isEmpty()) + public void addContent(CharSequence text) { + if (text.length() == 0) return; ensureMutableContents(); Content c = contents.isEmpty() ? null : contents.get(contents.size() - 1); diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java index 469ee40743f..cd6739d3f1f 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/DocType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -89,7 +89,8 @@ public class DocType extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java index 8f995c7c772..73da0086ab1 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlDocument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,7 +90,8 @@ public class HtmlDocument extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java index ccaf4769276..f55de090491 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -84,6 +84,7 @@ public enum HtmlStyle { overrideSpecifyLabel, overviewSummary, packageHierarchyLabel, + packageLabelInClass, paramLabel, returnLabel, rightContainer, diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java index 93b9071dcf7..a3a40f4391e 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlTree.java @@ -132,7 +132,8 @@ public class HtmlTree extends Content { * * @param stringContent string content that needs to be added */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { if (!content.isEmpty()) { Content lastContent = content.get(content.size() - 1); if (lastContent instanceof StringContent) diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java index 589f342ef79..dce9fd720a7 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/HtmlWriter.java @@ -401,6 +401,10 @@ public class HtmlWriter { " }" + DocletConstants.NL + " }" + DocletConstants.NL + " return true;" + DocletConstants.NL + + " }" + DocletConstants.NL + + " function loadFrames() {" + DocletConstants.NL + + " if (targetPage != \"\" && targetPage != \"undefined\")" + DocletConstants.NL + + " top.classFrame.location = top.targetPage;" + DocletConstants.NL + " }" + DocletConstants.NL; RawHtml scriptContent = new RawHtml(scriptCode); script.addContent(scriptContent); @@ -471,7 +475,7 @@ public class HtmlWriter { addStyles(HtmlStyle.rowColor, vars); addStyles(HtmlStyle.tableTab, vars); addStyles(HtmlStyle.activeTableTab, vars); - script.addContent(new RawHtml(vars.toString())); + script.addContent(new RawHtml(vars)); } /** diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java index fe425dd743a..ca621a4c75a 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/RawHtml.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,8 +53,8 @@ public class RawHtml extends Content { * * @param rawHtml raw HTML text to be added */ - public RawHtml(String rawHtml) { - rawHtmlContent = nullCheck(rawHtml); + public RawHtml(CharSequence rawHtml) { + rawHtmlContent = rawHtml.toString(); } /** @@ -77,7 +77,8 @@ public class RawHtml extends Content { * DocletAbortException because it * is not supported. */ - public void addContent(String stringContent) { + @Override + public void addContent(CharSequence stringContent) { throw new DocletAbortException("not supported"); } @@ -103,7 +104,7 @@ public class RawHtml extends Content { return charCount(rawHtmlContent); } - static int charCount(String htmlText) { + static int charCount(CharSequence htmlText) { State state = State.TEXT; int count = 0; for (int i = 0; i < htmlText.length(); i++) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java index 6b7c7dde2ed..cececf6b991 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/markup/StringContent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ public class StringContent extends Content { * * @param initialContent initial content for the object */ - public StringContent(String initialContent) { + public StringContent(CharSequence initialContent) { stringContent = new StringBuilder(); appendChars(initialContent); } @@ -83,7 +83,7 @@ public class StringContent extends Content { * @param strContent string content to be added */ @Override - public void addContent(String strContent) { + public void addContent(CharSequence strContent) { appendChars(strContent); } @@ -118,7 +118,7 @@ public class StringContent extends Content { return s.endsWith(DocletConstants.NL); } - private void appendChars(String s) { + private void appendChars(CharSequence s) { for (int i = 0; i < s.length(); i++) { char ch = s.charAt(i); switch (ch) { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java index 3d2e664a3e0..7efd4250504 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/Content.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -74,7 +74,7 @@ public abstract class Content { * * @param stringContent the string content to be added */ - public abstract void addContent(String stringContent); + public abstract void addContent(CharSequence stringContent); /** * Writes content to a writer. diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css index 076087c92f4..4a0e575f59b 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/stylesheet.css @@ -610,8 +610,9 @@ h1.hidden { color:#474747; } .deprecatedLabel, .descfrmTypeLabel, .memberNameLabel, .memberNameLink, -.overrideSpecifyLabel, .packageHierarchyLabel, .paramLabel, .returnLabel, -.seeLabel, .simpleTagLabel, .throwsLabel, .typeNameLabel, .typeNameLink, .searchTagLink { +.overrideSpecifyLabel, .packageLabelInClass, .packageHierarchyLabel, +.paramLabel, .returnLabel, .seeLabel, .simpleTagLabel, .throwsLabel, +.typeNameLabel, .typeNameLink, .searchTagLink { font-weight:bold; } .deprecationComment, .emphasizedPhrase, .interfaceName { diff --git a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java index 5914a2e6013..fa2c90f1efe 100644 --- a/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java +++ b/langtools/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/util/Utils.java @@ -1356,7 +1356,7 @@ public class Utils { return result.toString(); } - public String normalizeNewlines(String text) { + public CharSequence normalizeNewlines(CharSequence text) { StringBuilder sb = new StringBuilder(); final int textLength = text.length(); final String NL = DocletConstants.NL; @@ -1379,7 +1379,7 @@ public class Utils { } } sb.append(text, pos, textLength); - return sb.toString(); + return sb; } /** @@ -1746,6 +1746,8 @@ public class Utils { * A generic utility which returns the fully qualified names of an entity, * if the entity is not qualifiable then its enclosing entity, it is upto * the caller to add the elements name as required. + * @param e the element to get FQN for. + * @return the name */ public String getFullyQualifiedName(Element e) { return getFullyQualifiedName(e, true); diff --git a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java index bd70ec841b1..1c45a2fd54f 100644 --- a/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java +++ b/langtools/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/Profile.java @@ -38,7 +38,7 @@ enum Profile { "jdk.httpserver", "jdk.security.auth", "jdk.naming.dns", "jdk.naming.rmi", "jdk.management"), - FULL_JRE("Full JRE", 4, "java.se", "jdk.deploy.osx", "jdk.charsets", + FULL_JRE("Full JRE", 4, "java.se", "jdk.charsets", "jdk.crypto.ec", "jdk.crypto.pkcs11", "jdk.crypto.mscapi", "jdk.crypto.ucrypto", "jdk.jvmstat", "jdk.localedata", "jdk.scripting.nashorn", "jdk.zipfs"); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java new file mode 100644 index 00000000000..2e86d9de290 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ArgTokenizer.java @@ -0,0 +1,271 @@ +/* + * Copyright (c) 1995, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.jshell.tool; + +import java.util.Arrays; +import java.util.stream.Stream; + +/** + * Parse command arguments, derived from StreamTokenizer by + * @author James Gosling + */ +class ArgTokenizer { + + private final String str; + private final int length; + private int next = 0; + private char buf[] = new char[20]; + private int mark; + + private final byte ctype[] = new byte[256]; + private static final byte CT_ALPHA = 0; + private static final byte CT_WHITESPACE = 1; + private static final byte CT_QUOTE = 8; + + private String sval; + private boolean isQuoted = false; + + ArgTokenizer(String arg) { + this.str = arg; + this.length = arg.length(); + quoteChar('"'); + quoteChar('\''); + whitespaceChars(0x09, 0x0D); + whitespaceChars(0x1C, 0x20); + whitespaceChars(0x85, 0x85); + whitespaceChars(0xA0, 0xA0); + } + + String next() { + nextToken(); + return sval; + } + + String[] next(String... strings) { + return next(Arrays.stream(strings)); + } + + String[] next(Stream stream) { + nextToken(); + if (sval == null) { + return null; + } + String[] matches = stream + .filter(s -> s.startsWith(sval)) + .toArray(size -> new String[size]); + return matches; + } + + String val() { + return sval; + } + + boolean isQuoted() { + return isQuoted; + } + + String whole() { + return str; + } + + void mark() { + mark = next; + } + + void rewind() { + next = mark; + } + + /** + * Reads a single character. + * + * @return The character read, or -1 if the end of the stream has been + * reached + */ + private int read() { + if (next >= length) { + return -1; + } + return str.charAt(next++); + } + + /** + * Specifies that all characters c in the range + * low <= c <= high + * are white space characters. White space characters serve only to + * separate tokens in the input stream. + * + *

    Any other attribute settings for the characters in the specified + * range are cleared. + * + * @param low the low end of the range. + * @param hi the high end of the range. + */ + private void whitespaceChars(int low, int hi) { + if (low < 0) + low = 0; + if (hi >= ctype.length) + hi = ctype.length - 1; + while (low <= hi) + ctype[low++] = CT_WHITESPACE; + } + + /** + * Specifies that matching pairs of this character delimit string + * constants in this tokenizer. + *

    + * If a string quote character is encountered, then a string is + * recognized, consisting of all characters after (but not including) + * 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 "\u005Cn"} and {@code "\u005Ct"} are recognized and + * converted to single characters as the string is parsed. + * + *

    Any other attribute settings for the specified character are cleared. + * + * @param ch the character. + */ + private void quoteChar(int ch) { + if (ch >= 0 && ch < ctype.length) + ctype[ch] = CT_QUOTE; + } + + private int unicode2ctype(int c) { + switch (c) { + case 0x1680: + case 0x180E: + case 0x200A: + case 0x202F: + case 0x205F: + case 0x3000: + return CT_WHITESPACE; + default: + return CT_ALPHA; + } + } + + /** + * Parses the next token of this tokenizer. + */ + public void nextToken() { + byte ct[] = ctype; + int c; + int lctype; + sval = null; + isQuoted = false; + + do { + c = read(); + if (c < 0) { + return; + } + lctype = (c < 256) ? ct[c] : unicode2ctype(c); + } while (lctype == CT_WHITESPACE); + + if (lctype == CT_ALPHA) { + int i = 0; + do { + if (i >= buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[i++] = (char) c; + c = read(); + lctype = c < 0 ? CT_WHITESPACE : (c < 256)? ct[c] : unicode2ctype(c); + } while (lctype == CT_ALPHA); + if (c >= 0) --next; // push last back + sval = String.copyValueOf(buf, 0, i); + return; + } + + if (lctype == CT_QUOTE) { + int quote = c; + int i = 0; + /* Invariants (because \Octal needs a lookahead): + * (i) c contains char value + * (ii) d contains the lookahead + */ + int d = read(); + while (d >= 0 && d != quote) { + if (d == '\\') { + c = read(); + int first = c; /* To allow \377, but not \477 */ + if (c >= '0' && c <= '7') { + c = c - '0'; + int c2 = read(); + if ('0' <= c2 && c2 <= '7') { + c = (c << 3) + (c2 - '0'); + c2 = read(); + if ('0' <= c2 && c2 <= '7' && first <= '3') { + c = (c << 3) + (c2 - '0'); + d = read(); + } else + d = c2; + } else + d = c2; + } else { + switch (c) { + case 'a': + c = 0x7; + break; + case 'b': + c = '\b'; + break; + case 'f': + c = 0xC; + break; + case 'n': + c = '\n'; + break; + case 'r': + c = '\r'; + break; + case 't': + c = '\t'; + break; + case 'v': + c = 0xB; + break; + } + d = read(); + } + } else { + c = d; + d = read(); + } + if (i >= buf.length) { + buf = Arrays.copyOf(buf, buf.length * 2); + } + buf[i++] = (char)c; + } + + if (d == quote) { + isQuoted = true; + } + sval = String.copyValueOf(buf, 0, i); + } + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java index ebc11be5b75..d86319f7254 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/ConsoleIOContext.java @@ -26,6 +26,7 @@ package jdk.internal.jshell.tool; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; +import jdk.jshell.SourceCodeAnalysis.QualifiedNames; import jdk.jshell.SourceCodeAnalysis.Suggestion; import java.awt.event.ActionListener; @@ -34,8 +35,12 @@ import java.io.InputStream; import java.io.PrintStream; import java.io.UncheckedIOException; import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Locale; +import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.function.Supplier; @@ -43,6 +48,7 @@ import java.util.function.Supplier; import jdk.internal.jline.NoInterruptUnixTerminal; import jdk.internal.jline.Terminal; import jdk.internal.jline.TerminalFactory; +import jdk.internal.jline.UnsupportedTerminal; import jdk.internal.jline.WindowsTerminal; import jdk.internal.jline.console.ConsoleReader; import jdk.internal.jline.console.KeyMap; @@ -63,7 +69,9 @@ class ConsoleIOContext extends IOContext { this.repl = repl; this.input = new StopDetectingInputStream(() -> repl.state.stop(), ex -> repl.hard("Error on input: %s", ex)); Terminal term; - if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { + if (System.getProperty("test.jdk") != null) { + term = new UnsupportedTerminal(); + } else if (System.getProperty("os.name").toLowerCase(Locale.US).contains(TerminalFactory.WINDOWS)) { term = new JShellWindowsTerminal(input); } else { term = new JShellUnixTerminal(input); @@ -144,6 +152,11 @@ class ConsoleIOContext extends IOContext { bind(DOCUMENTATION_SHORTCUT, (ActionListener) evt -> documentation(repl)); bind(CTRL_UP, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::previousSnippet)); bind(CTRL_DOWN, (ActionListener) evt -> moveHistoryToSnippet(((EditingHistory) in.getHistory())::nextSnippet)); + for (FixComputer computer : FIX_COMPUTERS) { + for (String shortcuts : SHORTCUT_FIXES) { + bind(shortcuts + computer.shortcut, (ActionListener) evt -> fixes(computer)); + } + } } @Override @@ -216,6 +229,11 @@ class ConsoleIOContext extends IOContext { private static final String DOCUMENTATION_SHORTCUT = "\033\133\132"; //Shift-TAB private static final String CTRL_UP = "\033\133\061\073\065\101"; //Ctrl-UP private static final String CTRL_DOWN = "\033\133\061\073\065\102"; //Ctrl-DOWN + private static final String[] SHORTCUT_FIXES = { + "\033\015", //Alt-Enter (Linux) + "\033\133\061\067\176", //F6/Alt-F1 (Mac) + "\u001BO3P" //Alt-F1 (Linux) + }; private void documentation(JShellTool repl) { String buffer = in.getCursorBuffer().buffer.toString(); @@ -290,6 +308,185 @@ class ConsoleIOContext extends IOContext { history.fullHistoryReplace(source); } + //compute possible options/Fixes based on the selected FixComputer, present them to the user, + //and perform the selected one: + private void fixes(FixComputer computer) { + String input = prefix + in.getCursorBuffer().toString(); + int cursor = prefix.length() + in.getCursorBuffer().cursor; + FixResult candidates = computer.compute(repl, input, cursor); + + try { + final boolean printError = candidates.error != null && !candidates.error.isEmpty(); + if (printError) { + in.println(candidates.error); + } + if (candidates.fixes.isEmpty()) { + in.beep(); + if (printError) { + in.redrawLine(); + in.flush(); + } + } else if (candidates.fixes.size() == 1 && !computer.showMenu) { + if (printError) { + in.redrawLine(); + in.flush(); + } + candidates.fixes.get(0).perform(in); + } else { + List fixes = new ArrayList<>(candidates.fixes); + fixes.add(0, new Fix() { + @Override + public String displayName() { + return "Do nothing"; + } + + @Override + public void perform(ConsoleReader in) throws IOException { + in.redrawLine(); + } + }); + + Map char2Fix = new HashMap<>(); + in.println(); + for (int i = 0; i < fixes.size(); i++) { + Fix fix = fixes.get(i); + char2Fix.put((char) ('0' + i), fix); + in.println("" + i + ": " + fixes.get(i).displayName()); + } + in.print("Choice: "); + in.flush(); + int read; + + read = in.readCharacter(); + + Fix fix = char2Fix.get((char) read); + + if (fix == null) { + in.beep(); + fix = fixes.get(0); + } + + in.println(); + + fix.perform(in); + + in.flush(); + } + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + /** + * A possible action which the user can choose to perform. + */ + public interface Fix { + /** + * A name that should be shown to the user. + */ + public String displayName(); + /** + * Perform the given action. + */ + public void perform(ConsoleReader in) throws IOException; + } + + /** + * A factory for {@link Fix}es. + */ + public abstract static class FixComputer { + private final char shortcut; + private final boolean showMenu; + + /** + * Construct a new FixComputer. {@code shortcut} defines the key which should trigger this FixComputer. + * If {@code showMenu} is {@code false}, and this computer returns exactly one {@code Fix}, + * no options will be show to the user, and the given {@code Fix} will be performed. + */ + public FixComputer(char shortcut, boolean showMenu) { + this.shortcut = shortcut; + this.showMenu = showMenu; + } + + /** + * Compute possible actions for the given code. + */ + public abstract FixResult compute(JShellTool repl, String code, int cursor); + } + + /** + * A list of {@code Fix}es with a possible error that should be shown to the user. + */ + public static class FixResult { + public final List fixes; + public final String error; + + public FixResult(List fixes, String error) { + this.fixes = fixes; + this.error = error; + } + } + + private static final FixComputer[] FIX_COMPUTERS = new FixComputer[] { + new FixComputer('v', false) { //compute "Introduce variable" Fix: + @Override + public FixResult compute(JShellTool repl, String code, int cursor) { + String type = repl.analysis.analyzeType(code, cursor); + if (type == null) { + return new FixResult(Collections.emptyList(), null); + } + return new FixResult(Collections.singletonList(new Fix() { + @Override + public String displayName() { + return "Create variable"; + } + @Override + public void perform(ConsoleReader in) throws IOException { + in.redrawLine(); + in.setCursorPosition(0); + in.putString(type + " = "); + in.setCursorPosition(in.getCursorBuffer().cursor - 3); + in.flush(); + } + }), null); + } + }, + new FixComputer('i', true) { //compute "Add import" Fixes: + @Override + public FixResult compute(JShellTool repl, String code, int cursor) { + QualifiedNames res = repl.analysis.listQualifiedNames(code, cursor); + List fixes = new ArrayList<>(); + for (String fqn : res.getNames()) { + fixes.add(new Fix() { + @Override + public String displayName() { + return "import: " + fqn; + } + @Override + public void perform(ConsoleReader in) throws IOException { + repl.state.eval("import " + fqn + ";"); + in.println("Imported: " + fqn); + in.redrawLine(); + } + }); + } + if (res.isResolvable()) { + return new FixResult(Collections.emptyList(), + "\nThe identifier is resolvable in this context."); + } else { + String error = ""; + if (fixes.isEmpty()) { + error = "\nNo candidate fully qualified names found to import."; + } + if (!res.isUpToDate()) { + error += "\nResults may be incomplete; try again later for complete results."; + } + return new FixResult(fixes, error); + } + } + } + }; + private static final class JShellUnixTerminal extends NoInterruptUnixTerminal { private final StopDetectingInputStream input; diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java new file mode 100644 index 00000000000..9089dfc86aa --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/Feedback.java @@ -0,0 +1,1049 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.internal.jshell.tool; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.EnumMap; +import java.util.EnumSet; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.Set; +import java.util.function.Function; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * Feedback customization support + * + * @author Robert Field + */ +class Feedback { + + // Patern for substituted fields within a customized format string + private static final Pattern FIELD_PATTERN = Pattern.compile("\\{(.*?)\\}"); + + // Current mode + private Mode mode = new Mode("", false); // initial value placeholder during start-up + + // Mapping of mode names to mode modes + private final Map modeMap = new HashMap<>(); + + public boolean shouldDisplayCommandFluff() { + return mode.commandFluff; + } + + public String getPre() { + return mode.pre; + } + + public String getPost() { + return mode.post; + } + + public String getErrorPre() { + return mode.errorPre; + } + + public String getErrorPost() { + return mode.errorPost; + } + + public String getFormat(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + return mode.getFormat(fc, fw, fa, fr, hasName, hasType, hasResult); + } + + public String getPrompt(String nextId) { + return mode.getPrompt(nextId); + } + + public String getContinuationPrompt(String nextId) { + return mode.getContinuationPrompt(nextId); + } + + public boolean setFeedback(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setFeedback(); + } + + public boolean setField(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setField(); + } + + public boolean setFormat(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setFormat(); + } + + public boolean setNewMode(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setNewMode(); + } + + public boolean setPrompt(JShellTool tool, ArgTokenizer at) { + return new FormatSetter(tool, at).setPrompt(); + } + + public void printFeedbackHelp(JShellTool tool) { + new FormatSetter(tool, null).printFeedbackHelp(); + } + + public void printFieldHelp(JShellTool tool) { + new FormatSetter(tool, null).printFieldHelp(); + } + + public void printFormatHelp(JShellTool tool) { + new FormatSetter(tool, null).printFormatHelp(); + } + + public void printNewModeHelp(JShellTool tool) { + new FormatSetter(tool, null).printNewModeHelp(); + } + + public void printPromptHelp(JShellTool tool) { + new FormatSetter(tool, null).printPromptHelp(); + } + + /** + * Holds all the context of a mode mode + */ + private class Mode { + + // Use name of mode mode + + final String name; + + // Display command verification/information + final boolean commandFluff; + + // event cases: class, method + final EnumMap>> cases; + + // action names: add. modified, replaced, ... + final EnumMap> actions; + + // resolution status description format with %s for unresolved + final EnumMap> resolves; + + // primary snippet vs update + final EnumMap whens; + + // fixed map of how to get format string for a field, given a specific formatting contet + final EnumMap> fields; + + // format wrappers for name, type, and result + String fname = "%s"; + String ftype = "%s"; + String fresult = "%s"; + + // start and end, also used by hard-coded output + String pre = "| "; + String post = "\n"; + String errorPre = "| Error: "; + String errorPost = "\n"; + + String prompt = "\n-> "; + String continuationPrompt = ">> "; + + /** + * The context of a specific mode to potentially display. + */ + class Context { + + final FormatCase fc; + final FormatAction fa; + final FormatResolve fr; + final FormatWhen fw; + final boolean hasName; + final boolean hasType; + final boolean hasResult; + + Context(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + this.fc = fc; + this.fa = fa; + this.fr = fr; + this.fw = fw; + this.hasName = hasName; + this.hasType = hasType; + this.hasResult = hasResult; + } + + String when() { + return whens.get(fw); + } + + String action() { + return actions.get(fa).get(fw); + } + + String resolve() { + return String.format(resolves.get(fr).get(fw), FormatField.RESOLVE.form); + } + + String name() { + return hasName + ? String.format(fname, FormatField.NAME.form) + : ""; + } + + String type() { + return hasType + ? String.format(ftype, FormatField.TYPE.form) + : ""; + } + + String result() { + return hasResult + ? String.format(fresult, FormatField.RESULT.form) + : ""; + } + + /** + * Lookup format based on case, action, and whether it update. + * Replace fields with context specific formats. + * + * @return format string + */ + String format() { + String format = cases.get(fc).get(fa).get(fw); + if (format == null) { + return ""; + } + Matcher m = FIELD_PATTERN.matcher(format); + StringBuffer sb = new StringBuffer(format.length()); + while (m.find()) { + String fieldName = m.group(1).toUpperCase(Locale.US); + String sub = null; + for (FormatField f : FormatField.values()) { + if (f.name().startsWith(fieldName)) { + sub = fields.get(f).apply(this); + break; + } + } + if (sub != null) { + m.appendReplacement(sb, Matcher.quoteReplacement(sub)); + } + } + m.appendTail(sb); + return sb.toString(); + } + } + + { + // set fixed mappings of fields + fields = new EnumMap<>(FormatField.class); + fields.put(FormatField.WHEN, c -> c.when()); + fields.put(FormatField.ACTION, c -> c.action()); + fields.put(FormatField.RESOLVE, c -> c.resolve()); + fields.put(FormatField.NAME, c -> c.name()); + fields.put(FormatField.TYPE, c -> c.type()); + fields.put(FormatField.RESULT, c -> c.result()); + fields.put(FormatField.PRE, c -> pre); + fields.put(FormatField.POST, c -> post); + fields.put(FormatField.ERRORPRE, c -> errorPre); + fields.put(FormatField.ERRORPOST, c -> errorPost); + } + + /** + * Set up an empty mode. + * + * @param name + * @param commandFluff True if should display command fluff messages + */ + Mode(String name, boolean commandFluff) { + this.name = name; + this.commandFluff = commandFluff; + cases = new EnumMap<>(FormatCase.class); + for (FormatCase fc : FormatCase.values()) { + EnumMap> ac = new EnumMap<>(FormatAction.class); + cases.put(fc, ac); + for (FormatAction fa : FormatAction.values()) { + EnumMap aw = new EnumMap<>(FormatWhen.class); + ac.put(fa, aw); + for (FormatWhen fw : FormatWhen.values()) { + aw.put(fw, ""); + } + } + } + + actions = new EnumMap<>(FormatAction.class); + for (FormatAction fa : FormatAction.values()) { + EnumMap afw = new EnumMap<>(FormatWhen.class); + actions.put(fa, afw); + for (FormatWhen fw : FormatWhen.values()) { + afw.put(fw, fa.name() + "-" + fw.name()); + } + } + + resolves = new EnumMap<>(FormatResolve.class); + for (FormatResolve fr : FormatResolve.values()) { + EnumMap arw = new EnumMap<>(FormatWhen.class); + resolves.put(fr, arw); + for (FormatWhen fw : FormatWhen.values()) { + arw.put(fw, fr.name() + "-" + fw.name() + ": %s"); + } + } + + whens = new EnumMap<>(FormatWhen.class); + for (FormatWhen fw : FormatWhen.values()) { + whens.put(fw, fw.name()); + } + } + + /** + * Set up a copied mode. + * + * @param name + * @param commandFluff True if should display command fluff messages + * @param m Mode to copy + */ + Mode(String name, boolean commandFluff, Mode m) { + this.name = name; + this.commandFluff = commandFluff; + cases = new EnumMap<>(FormatCase.class); + for (FormatCase fc : FormatCase.values()) { + EnumMap> ac = new EnumMap<>(FormatAction.class); + EnumMap> mc = m.cases.get(fc); + cases.put(fc, ac); + for (FormatAction fa : FormatAction.values()) { + EnumMap aw = new EnumMap<>(mc.get(fa)); + ac.put(fa, aw); + } + } + + actions = new EnumMap<>(FormatAction.class); + for (FormatAction fa : FormatAction.values()) { + EnumMap afw = new EnumMap<>(m.actions.get(fa)); + actions.put(fa, afw); + } + + resolves = new EnumMap<>(FormatResolve.class); + for (FormatResolve fr : FormatResolve.values()) { + EnumMap arw = new EnumMap<>(m.resolves.get(fr)); + resolves.put(fr, arw); + } + + whens = new EnumMap<>(m.whens); + + this.fname = m.fname; + this.ftype = m.ftype; + this.fresult = m.fresult; + this.pre = m.pre; + this.post = m.post; + this.errorPre = m.errorPre; + this.errorPost = m.errorPost; + this.prompt = m.prompt; + this.continuationPrompt = m.continuationPrompt; + } + + String getFormat(FormatCase fc, FormatWhen fw, FormatAction fa, FormatResolve fr, + boolean hasName, boolean hasType, boolean hasResult) { + Context context = new Context(fc, fw, fa, fr, + hasName, hasType, hasResult); + return context.format(); + } + + void setCases(String format, Collection cc, Collection ca, Collection cw) { + for (FormatCase fc : cc) { + EnumMap> ma = cases.get(fc); + for (FormatAction fa : ca) { + EnumMap mw = ma.get(fa); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + } + + void setActions(String format, Collection ca, Collection cw) { + for (FormatAction fa : ca) { + EnumMap mw = actions.get(fa); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + + void setResolves(String format, Collection cr, Collection cw) { + for (FormatResolve fr : cr) { + EnumMap mw = resolves.get(fr); + for (FormatWhen fw : cw) { + mw.put(fw, format); + } + } + } + + void setWhens(String format, Collection cw) { + for (FormatWhen fw : cw) { + whens.put(fw, format); + } + } + + void setName(String s) { + fname = s; + } + + void setType(String s) { + ftype = s; + } + + void setResult(String s) { + fresult = s; + } + + void setPre(String s) { + pre = s; + } + + void setPost(String s) { + post = s; + } + + void setErrorPre(String s) { + errorPre = s; + } + + void setErrorPost(String s) { + errorPost = s; + } + + String getPre() { + return pre; + } + + String getPost() { + return post; + } + + String getErrorPre() { + return errorPre; + } + + String getErrorPost() { + return errorPost; + } + + void setPrompts(String prompt, String continuationPrompt) { + this.prompt = prompt; + this.continuationPrompt = continuationPrompt; + } + + String getPrompt(String nextId) { + return String.format(prompt, nextId); + } + + String getContinuationPrompt(String nextId) { + return String.format(continuationPrompt, nextId); + } + } + + /** + * The brace delimited substitutions + */ + public enum FormatField { + WHEN, + ACTION, + RESOLVE("%1$s"), + NAME("%2$s"), + TYPE("%3$s"), + RESULT("%4$s"), + PRE, + POST, + ERRORPRE, + ERRORPOST; + String form; + + FormatField(String s) { + this.form = s; + } + + FormatField() { + this.form = null; + } + } + + /** + * The event cases + */ + public enum FormatCase { + IMPORT("import declaration: {action} {name}"), + CLASS("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + INTERFACE("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + ENUM("class, interface, enum, or annotation declaration: {action} {name} {resolve}"), + ANNOTATION("annotation interface declaration: {action} {name} {resolve}"), + METHOD("method declaration: {action} {name} {type}==parameter-types {resolve}"), + VARDECL("variable declaration: {action} {name} {type} {resolve}"), + VARDECLRECOVERABLE("recoverably failed variable declaration: {action} {name} {resolve}"), + VARINIT("variable declaration with init: {action} {name} {type} {resolve} {result}"), + VARRESET("variable reset on update: {action} {name}"), + EXPRESSION("expression: {action}=='Saved to scratch variable' {name} {type} {result}"), + VARVALUE("variable value expression: {action} {name} {type} {result}"), + ASSIGNMENT("assign variable: {action} {name} {type} {result}"), + STATEMENT("statement: {action}"); + String doc; + + private FormatCase(String doc) { + this.doc = doc; + } + } + + /** + * The event actions + */ + public enum FormatAction { + ADDED("snippet has been added"), + MODIFIED("an existing snippet has been modified"), + REPLACED("an existing snippet has been replaced with a new snippet"), + OVERWROTE("an existing snippet has been overwritten"), + DROPPED("snippet has been dropped"), + REJECTED("snippet has failed and been rejected"); + String doc; + + private FormatAction(String doc) { + this.doc = doc; + } + } + + /** + * When the event occurs: primary or update + */ + public enum FormatWhen { + PRIMARY("the entered snippet"), + UPDATE("an update to a dependent snippet"); + String doc; + + private FormatWhen(String doc) { + this.doc = doc; + } + } + + /** + * Resolution problems with event + */ + public enum FormatResolve { + OK("resolved correctly"), + DEFINED("defined despite recoverably unresolved references"), + NOTDEFINED("not defined because of recoverably unresolved references"); + String doc; + + private FormatResolve(String doc) { + this.doc = doc; + } + } + + // Class used to set custom eval output formats + // For both /set format and /set field -- Parse arguments, setting custom format, or printing error + private class FormatSetter { + + private final ArgTokenizer at; + private final JShellTool tool; + boolean valid = true; + + class Case, E2 extends Enum, E3 extends Enum> { + + Set e1; + Set e2; + Set e3; + + Case(Set e1, Set e2, Set e3) { + this.e1 = e1; + this.e2 = e2; + this.e3 = e3; + } + + Case(Set e1, Set e2) { + this.e1 = e1; + this.e2 = e2; + } + } + + FormatSetter(JShellTool tool, ArgTokenizer at) { + this.tool = tool; + this.at = at; + } + + void hard(String format, Object... args) { + tool.hard(format, args); + } + + > void hardEnums(EnumSet es, Function e2s) { + hardPairs(es.stream(), ev -> ev.name().toLowerCase(Locale.US), e2s); + } + + void hardPairs(Stream stream, Function a, Function b) { + tool.hardPairs(stream, a, b); + } + + void fluff(String format, Object... args) { + tool.fluff(format, args); + } + + void error(String format, Object... args) { + tool.error(format, args); + } + + void errorat(String format, Object... args) { + Object[] a2 = Arrays.copyOf(args, args.length + 1); + a2[args.length] = at.whole(); + tool.error(format + " -- /set %s", a2); + } + + void fluffRaw(String format, Object... args) { + tool.fluffRaw(format, args); + } + + // For /set prompt "" "" + boolean setPrompt() { + Mode m = nextMode(); + String prompt = nextFormat(); + String continuationPrompt = nextFormat(); + if (valid) { + m.setPrompts(prompt, continuationPrompt); + } else { + fluff("See '/help /set prompt' for help"); + } + return valid; + } + + // For /set newmode [command|quiet []] + boolean setNewMode() { + String umode = at.next(); + if (umode == null) { + errorat("Expected new feedback mode"); + valid = false; + } + if (modeMap.containsKey(umode)) { + errorat("Expected a new feedback mode name. %s is a known feedback mode", umode); + valid = false; + } + String[] fluffOpt = at.next("command", "quiet"); + boolean fluff = fluffOpt == null || fluffOpt.length != 1 || "command".equals(fluffOpt[0]); + if (fluffOpt != null && fluffOpt.length != 1) { + errorat("Specify either 'command' or 'quiet'"); + valid = false; + } + Mode om = null; + String omode = at.next(); + if (omode != null) { + om = toMode(omode); + } + if (valid) { + Mode nm = (om != null) + ? new Mode(umode, fluff, om) + : new Mode(umode, fluff); + modeMap.put(umode, nm); + fluff("Created new feedback mode: %s", nm.name); + } else { + fluff("See '/help /set newmode' for help"); + } + return valid; + } + + // For /set feedback + boolean setFeedback() { + Mode m = nextMode(); + if (valid && m != null) { + mode = m; + fluff("Feedback mode: %s", mode.name); + } else { + fluff("See '/help /set feedback' for help"); + } + return valid; + } + + // For /set format "" ... + boolean setFormat() { + Mode m = nextMode(); + String format = nextFormat(); + if (valid) { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatCase(d, 0), + parseFormatAction(d, 1), + parseFormatWhen(d, 2) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format in the specified cases + specs.stream() + .forEach(c -> m.setCases(format, c.e1, c.e2, c.e3)); + } + } + if (!valid) { + fluff("See '/help /set format' for help"); + } + return valid; + } + + // For /set field mode "" ... + boolean setField() { + Mode m = nextMode(); + String fieldName = at.next(); + FormatField field = parseFormatSelector(fieldName, EnumSet.allOf(FormatField.class), "field"); + String format = nextFormat(); + if (valid) { + switch (field) { + case ACTION: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatAction(d, 0), + parseFormatWhen(d, 1) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified actions + specs.stream() + .forEach(c -> m.setActions(format, c.e1, c.e2)); + } + break; + } + case RESOLVE: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatResolve(d, 0), + parseFormatWhen(d, 1) + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified resolves + specs.stream() + .forEach(c -> m.setResolves(format, c.e1, c.e2)); + } + break; + } + case WHEN: { + List> specs = new ArrayList<>(); + String s; + while ((s = at.next()) != null) { + String[] d = s.split("-"); + specs.add(new Case<>( + parseFormatWhen(d, 1), + null + )); + } + if (valid && specs.isEmpty()) { + errorat("At least one selector required"); + valid = false; + } + if (valid) { + // set the format of the specified whens + specs.stream() + .forEach(c -> m.setWhens(format, c.e1)); + } + break; + } + case NAME: { + m.setName(format); + break; + } + case TYPE: { + m.setType(format); + break; + } + case RESULT: { + m.setResult(format); + break; + } + case PRE: { + m.setPre(format); + break; + } + case POST: { + m.setPost(format); + break; + } + case ERRORPRE: { + m.setErrorPre(format); + break; + } + case ERRORPOST: { + m.setErrorPost(format); + break; + } + } + } + if (!valid) { + fluff("See '/help /set field' for help"); + } + return valid; + } + + Mode nextMode() { + String umode = at.next(); + return toMode(umode); + } + + Mode toMode(String umode) { + if (umode == null) { + errorat("Expected a feedback mode"); + valid = false; + return null; + } + Mode m = modeMap.get(umode); + if (m != null) { + return m; + } + // Failing an exact match, go searching + Mode[] matches = modeMap.entrySet().stream() + .filter(e -> e.getKey().startsWith(umode)) + .map(e -> e.getValue()) + .toArray(size -> new Mode[size]); + if (matches.length == 1) { + return matches[0]; + } else { + valid = false; + if (matches.length == 0) { + errorat("Does not match any current feedback mode: %s", umode); + } else { + errorat("Matchs more then one current feedback mode: %s", umode); + } + fluff("The feedback mode should be one of the following:"); + modeMap.keySet().stream() + .forEach(mk -> fluff(" %s", mk)); + fluff("You may also use just enough letters to make it unique."); + return null; + } + } + + // Test if the format string is correctly + final String nextFormat() { + String format = at.next(); + if (format == null) { + errorat("Expected format missing"); + valid = false; + return null; + } + if (!at.isQuoted()) { + errorat("Format '%s' must be quoted", format); + valid = false; + return null; + } + return format; + } + + final Set parseFormatCase(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatCase.class, EnumSet.allOf(FormatCase.class), "case"); + } + + final Set parseFormatAction(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatAction.class, + EnumSet.of(FormatAction.ADDED, FormatAction.MODIFIED, FormatAction.REPLACED), "action"); + } + + final Set parseFormatResolve(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatResolve.class, + EnumSet.of(FormatResolve.DEFINED, FormatResolve.NOTDEFINED), "resolve"); + } + + final Set parseFormatWhen(String[] s, int i) { + return parseFormatSelectorStar(s, i, FormatWhen.class, EnumSet.of(FormatWhen.PRIMARY), "when"); + } + + /** + * In a selector x-y-z , parse x, y, or z -- whether they are missing, + * or a comma separated list of identifiers and stars. + * + * @param The enum this selector should belong to + * @param sa The array of selector strings + * @param i The index of which selector string to use + * @param klass The class of the enum that should be used + * @param defaults The set of enum values to use if the selector is + * missing + * @return The set of enum values specified by this selector + */ + final > Set parseFormatSelectorStar(String[] sa, int i, Class klass, EnumSet defaults, String label) { + String s = sa.length > i + ? sa[i] + : null; + if (s == null || s.isEmpty()) { + return defaults; + } + Set set = EnumSet.noneOf(klass); + EnumSet values = EnumSet.allOf(klass); + for (String as : s.split(",")) { + if (as.equals("*")) { + set.addAll(values); + } else if (!as.isEmpty()) { + set.add(parseFormatSelector(as, values, label)); + } + } + return set; + } + + /** + * In a x-y-a,b selector, parse an x, y, a, or b -- that is an + * identifier + * + * @param The enum this selector should belong to + * @param s The string to parse: x, y, or z + * @param values The allowed of this enum + * @return The enum value + */ + final > E parseFormatSelector(String s, EnumSet values, String label) { + if (s == null) { + valid = false; + return null; + } + String u = s.toUpperCase(Locale.US); + for (E c : values) { + if (c.name().startsWith(u)) { + return c; + } + } + + errorat("Not a valid %s: %s, must be one of: %s", label, s, + values.stream().map(v -> v.name().toLowerCase(Locale.US)).collect(Collectors.joining(" "))); + valid = false; + return values.iterator().next(); + } + + final void printFormatHelp() { + hard("Set the format for reporting a snippet event."); + hard(""); + hard("/set format \"\" ..."); + hard(""); + hard("Where is the name of a previously defined feedback mode -- see '/help /set newmode'."); + hard("Where is a quoted string which will have these field substitutions:"); + hard(" {action} == The action, e.g.: Added, Modified, Assigned, ..."); + hard(" {name} == The name, e.g.: the variable name, ..."); + hard(" {type} == The type name"); + hard(" {resolve} == Unresolved info, e.g.: ', however, it cannot be invoked until'"); + hard(" {result} == The result value"); + hard(" {when} == The entered snippet or a resultant update"); + hard(" {pre} == The feedback prefix"); + hard(" {post} == The feedback postfix"); + hard(" {errorpre} == The error prefix"); + hard(" {errorpost} == The error postfix"); + hard("Use '/set field' to set the format of these substitutions."); + hard("Where is the context in which the format is applied."); + hard("The structure of selector is: [-[-]]"); + hard("Where each field component may be missing (indicating defaults),"); + hard("star (indicating all), or a comma separated list of field values."); + hard("For case, the field values are:"); + hardEnums(EnumSet.allOf(FormatCase.class), ev -> ev.doc); + hard("For action, the field values are:"); + hardEnums(EnumSet.allOf(FormatAction.class), ev -> ev.doc); + hard("For when, the field values are:"); + hardEnums(EnumSet.allOf(FormatWhen.class), ev -> ev.doc); + hard(""); + hard("Example:"); + hard(" /set format example '{pre}{action} variable {name}, reset to null{post}' varreset-*-update"); + } + + final void printFieldHelp() { + hard("Set the format of a field substitution as used in '/set format'."); + hard(""); + hard("/set field \"\" ..."); + hard(""); + hard("Where is the name of a previously defined feedback mode -- see '/set newmode'."); + hard("Where is context-specific format to set, each with its own selector structure:"); + hard(" action == The action. The selector: -."); + hard(" name == The name. '%%s' is the name. No selectors."); + hard(" type == The type name. '%%s' is the type. No selectors."); + hard(" resolve == Unresolved info. '%%s' is the unresolved list. The selector: -."); + hard(" result == The result value. '%%s' is the result value. No selectors."); + hard(" when == The entered snippet or a resultant update. The selector: "); + hard(" pre == The feedback prefix. No selectors."); + hard(" post == The feedback postfix. No selectors."); + hard(" errorpre == The error prefix. No selectors."); + hard(" errorpost == The error postfix. No selectors."); + hard("Where is a quoted string -- see the description specific to the field (above)."); + hard("Where is the context in which the format is applied (see above)."); + hard("For action, the field values are:"); + hardEnums(EnumSet.allOf(FormatAction.class), ev -> ev.doc); + hard("For when, the field values are:"); + hardEnums(EnumSet.allOf(FormatWhen.class), ev -> ev.doc); + hard("For resolve, the field values are:"); + hardEnums(EnumSet.allOf(FormatResolve.class), ev -> ev.doc); + hard(""); + hard("Example:"); + hard(" /set field example resolve ' which cannot be invoked until%%s is declared' defined-update"); + } + + final void printFeedbackHelp() { + hard("Set the feedback mode describing displayed feedback for entered snippets and commands."); + hard(""); + hard("/set feedback "); + hard(""); + hard("Where is the name of a previously defined feedback mode."); + hard("Currently defined feedback modes:"); + modeMap.keySet().stream() + .forEach(m -> hard(" %s", m)); + hard("User-defined modes can be added, see '/help /set newmode'"); + } + + final void printNewModeHelp() { + hard("Create a user-defined feedback mode, optionally copying from an existing mode."); + hard(""); + hard("/set newmode [command|quiet []]"); + hard(""); + hard("Where is the name of a mode you wish to create."); + hard("Where is the name of a previously defined feedback mode."); + hard("If is present, its settings are copied to the new mode."); + hard("'command' vs 'quiet' determines if informative/verifying command feedback is displayed."); + hard(""); + hard("Once the new mode is created, use '/set format', '/set field', and '/set prompt' to configure it."); + hard("Use '/set feedback' to use the new mode."); + } + + final void printPromptHelp() { + hard("Set the prompts. Both the normal prompt and the continuation-prompt must be set."); + hard(""); + hard("/set prompt \"\" \"\""); + hard(""); + hard("Where is the name of a previously defined feedback mode."); + hard("Where and are quoted strings printed as input promptds;"); + hard("Both may optionally contain '%%s' which will be substituted with the next snippet id --"); + hard("note that what is entered may not be assigned that id, for example it may be an error or command."); + hard("The continuation-prompt is used on the second and subsequent lines of a multi-line snippet."); + } + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index fe80db74ffe..55eb01bb908 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -1,6 +1,5 @@ - /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +34,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.PrintStream; import java.io.Reader; -import java.io.StreamTokenizer; import java.io.StringReader; import java.nio.charset.Charset; import java.nio.file.AccessDeniedException; @@ -66,24 +64,25 @@ import java.util.stream.StreamSupport; import jdk.internal.jshell.debug.InternalDebugControl; import jdk.internal.jshell.tool.IOContext.InputInterruptedException; +import jdk.jshell.DeclarationSnippet; import jdk.jshell.Diag; import jdk.jshell.EvalException; +import jdk.jshell.ExpressionSnippet; +import jdk.jshell.ImportSnippet; import jdk.jshell.JShell; -import jdk.jshell.Snippet; -import jdk.jshell.DeclarationSnippet; -import jdk.jshell.TypeDeclSnippet; +import jdk.jshell.JShell.Subscription; import jdk.jshell.MethodSnippet; import jdk.jshell.PersistentSnippet; -import jdk.jshell.VarSnippet; -import jdk.jshell.ExpressionSnippet; +import jdk.jshell.Snippet; import jdk.jshell.Snippet.Status; +import jdk.jshell.Snippet.SubKind; +import jdk.jshell.SnippetEvent; import jdk.jshell.SourceCodeAnalysis; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; import jdk.jshell.SourceCodeAnalysis.Suggestion; -import jdk.jshell.SnippetEvent; +import jdk.jshell.TypeDeclSnippet; import jdk.jshell.UnresolvedReferenceException; -import jdk.jshell.Snippet.SubKind; -import jdk.jshell.JShell.Subscription; +import jdk.jshell.VarSnippet; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; @@ -94,7 +93,13 @@ import java.util.ResourceBundle; import java.util.Spliterators; import java.util.function.Function; import java.util.function.Supplier; +import jdk.internal.jshell.tool.Feedback.FormatAction; +import jdk.internal.jshell.tool.Feedback.FormatCase; +import jdk.internal.jshell.tool.Feedback.FormatResolve; +import jdk.internal.jshell.tool.Feedback.FormatWhen; import static java.util.stream.Collectors.toList; +import static jdk.jshell.Snippet.Kind.METHOD; +import static java.util.stream.Collectors.toMap; import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; /** @@ -103,6 +108,7 @@ import static jdk.jshell.Snippet.SubKind.VAR_VALUE_SUBKIND; */ public class JShellTool { + private static final String LINE_SEP = System.getProperty("line.separator"); private static final Pattern LINEBREAK = Pattern.compile("\\R"); private static final Pattern HISTORY_ALL_START_FILENAME = Pattern.compile( "((?(all|history|start))(\\z|\\p{javaWhitespace}+))?(?.*)"); @@ -116,6 +122,8 @@ public class JShellTool { final PrintStream userout; final PrintStream usererr; + final Feedback feedback = new Feedback(); + /** * The constructor for the tool (used by tool launch via main and by test * harnesses to capture ins and outs. @@ -137,6 +145,70 @@ public class JShellTool { this.userin = userin; this.userout = userout; this.usererr = usererr; + initializeFeedbackModes(); + } + + /** + * Create the default set of feedback modes + */ + final void initializeFeedbackModes() { + // Initialize normal feedback mode + cmdSet("newmode normal command"); + cmdSet("prompt normal '\n-> ' '>> '"); + cmdSet("field normal pre '| '"); + cmdSet("field normal post '%n'"); + cmdSet("field normal errorpre '| '"); + cmdSet("field normal errorpost '%n'"); + cmdSet("field normal action 'Added' added-primary"); + cmdSet("field normal action 'Modified' modified-primary"); + cmdSet("field normal action 'Replaced' replaced-primary"); + cmdSet("field normal action 'Overwrote' overwrote-primary"); + cmdSet("field normal action 'Dropped' dropped-primary"); + cmdSet("field normal action 'Rejected' rejected-primary"); + cmdSet("field normal action ' Update added' added-update"); + cmdSet("field normal action ' Update modified' modified-update"); + cmdSet("field normal action ' Update replaced' replaced-update"); + cmdSet("field normal action ' Update overwrote' overwrote-update"); + cmdSet("field normal action ' Update dropped' dropped-update"); + cmdSet("field normal action ' Update rejected' rejected-update"); + cmdSet("field normal resolve '' ok-*"); + cmdSet("field normal resolve ', however, it cannot be invoked until%s is declared' defined-primary"); + cmdSet("field normal resolve ', however, it cannot be referenced until%s is declared' notdefined-primary"); + cmdSet("field normal resolve ' which cannot be invoked until%s is declared' defined-update"); + cmdSet("field normal resolve ' which cannot be referenced until%s is declared' notdefined-update"); + cmdSet("field normal name '%s'"); + cmdSet("field normal type '%s'"); + cmdSet("field normal result '%s'"); + + cmdSet("format normal '' *-*-*"); + + cmdSet("format normal '{pre}{action} class {name}{resolve}{post}' class"); + cmdSet("format normal '{pre}{action} interface {name}{resolve}{post}' interface"); + cmdSet("format normal '{pre}{action} enum {name}{resolve}{post}' enum"); + cmdSet("format normal '{pre}{action} annotation interface {name}{resolve}{post}' annotation"); + + cmdSet("format normal '{pre}{action} method {name}({type}){resolve}{post}' method"); + + cmdSet("format normal '{pre}{action} variable {name} of type {type}{resolve}{post}' vardecl"); + cmdSet("format normal '{pre}{action} variable {name} of type {type} with initial value {result}{resolve}{post}' varinit"); + cmdSet("format normal '{pre}{action} variable {name}{resolve}{post}' vardeclrecoverable"); + cmdSet("format normal '{pre}{action} variable {name}, reset to null{post}' varreset-*-update"); + + cmdSet("format normal '{pre}Expression value is: {result}{post}" + + "{pre} assigned to temporary variable {name} of type {type}{post}' expression"); + cmdSet("format normal '{pre}Variable {name} of type {type} has value {result}{post}' varvalue"); + cmdSet("format normal '{pre}Variable {name} has been assigned the value {result}{post}' assignment"); + + cmdSet("feedback normal"); + + // Initialize off feedback mode + cmdSet("newmode off quiet"); + cmdSet("prompt off '-> ' '>> '"); + cmdSet("field off pre '| '"); + cmdSet("field off post '%n'"); + cmdSet("field off errorpre '| '"); + cmdSet("field off errorpost '%n'"); + cmdSet("format off '' *-*-*"); } private IOContext input = null; @@ -150,7 +222,6 @@ public class JShellTool { private boolean debug = false; private boolean displayPrompt = true; public boolean testPrompt = false; - private Feedback feedback = Feedback.Default; private String cmdlineClasspath = null; private String cmdlineStartup = null; private String[] editor = null; @@ -185,6 +256,15 @@ public class JShellTool { Map mapSnippet; + /** + * Is the input/output currently interactive + * + * @return true if console + */ + boolean interactive() { + return input != null && input.interactiveOutput(); + } + void debug(String format, Object... args) { if (debug) { cmderr.printf(format + "\n", args); @@ -192,38 +272,98 @@ public class JShellTool { } /** - * For more verbose feedback modes - * @param format printf format - * @param args printf args + * Base output for command output -- no pre- or post-fix + * + * @param printf format + * @param printf args */ - void fluff(String format, Object... args) { - if (feedback() != Feedback.Off && feedback() != Feedback.Concise) { - hard(format, args); - } + void rawout(String format, Object... args) { + cmdout.printf(format, args); } /** - * For concise feedback mode only - * @param format printf format - * @param args printf args - */ - void concise(String format, Object... args) { - if (feedback() == Feedback.Concise) { - hard(format, args); - } - } - - /** - * For all feedback modes -- must show + * Must show command output + * * @param format printf format * @param args printf args */ void hard(String format, Object... args) { - cmdout.printf("| " + format + "\n", args); + rawout(feedback.getPre() + format + feedback.getPost(), args); + } + + /** + * Error command output + * + * @param format printf format + * @param args printf args + */ + void error(String format, Object... args) { + rawout(feedback.getErrorPre() + format + feedback.getErrorPost(), args); + } + + /** + * Optional output + * + * @param format printf format + * @param args printf args + */ + void fluff(String format, Object... args) { + if (feedback.shouldDisplayCommandFluff() && interactive()) { + hard(format, args); + } + } + + /** + * Optional output -- with embedded per- and post-fix + * + * @param format printf format + * @param args printf args + */ + void fluffRaw(String format, Object... args) { + if (feedback.shouldDisplayCommandFluff() && interactive()) { + rawout(format, args); + } + } + + void hardPairs(Stream stream, Function a, Function b) { + Map a2b = stream.collect(toMap(a, b, + (m1, m2) -> m1, + () -> new LinkedHashMap<>())); + int aLen = 0; + for (String av : a2b.keySet()) { + aLen = Math.max(aLen, av.length()); + } + String format = " %-" + aLen + "s -- %s"; + String indentedNewLine = LINE_SEP + feedback.getPre() + + String.format(" %-" + (aLen + 4) + "s", ""); + for (Entry e : a2b.entrySet()) { + hard(format, e.getKey(), e.getValue().replaceAll("\n", indentedNewLine)); + } + } + + /** + * User custom feedback mode only + * + * @param fcase Event to report + * @param update Is this an update (rather than primary) + * @param fa Action + * @param fr Resolution status + * @param name Name string + * @param type Type string or null + * @param result Result value or null + * @param unresolved The unresolved symbols + */ + void custom(FormatCase fcase, boolean update, FormatAction fa, FormatResolve fr, + String name, String type, String unresolved, String result) { + String format = feedback.getFormat(fcase, + (update ? FormatWhen.UPDATE : FormatWhen.PRIMARY), fa, fr, + name != null, type != null, result != null); + fluffRaw(format, unresolved, name, type, result); } /** * Trim whitespace off end of string + * * @param s * @return */ @@ -276,8 +416,8 @@ public class JShellTool { } if (regenerateOnDeath) { - fluff("Welcome to JShell -- Version %s", version()); - fluff("Type /help for help"); + hard("Welcome to JShell -- Version %s", version()); + hard("Type /help for help"); } try { @@ -369,14 +509,14 @@ public class JShellTool { } private void printUsage() { - cmdout.printf("Usage: jshell \n"); - cmdout.printf("where possible options include:\n"); - cmdout.printf(" -classpath Specify where to find user class files\n"); - cmdout.printf(" -cp Specify where to find user class files\n"); - cmdout.printf(" -startup One run replacement for the start-up definitions\n"); - cmdout.printf(" -nostartup Do not run the start-up definitions\n"); - cmdout.printf(" -help Print a synopsis of standard options\n"); - cmdout.printf(" -version Version information\n"); + rawout("Usage: jshell \n"); + rawout("where possible options include:\n"); + rawout(" -classpath Specify where to find user class files\n"); + rawout(" -cp Specify where to find user class files\n"); + rawout(" -startup One run replacement for the start-up definitions\n"); + rawout(" -nostartup Do not run the start-up definitions\n"); + rawout(" -help Print a synopsis of standard options\n"); + rawout(" -version Version information\n"); } private void resetState() { @@ -460,10 +600,8 @@ public class JShellTool { ? "\u0005" //ENQ : "\u0006" //ACK : incomplete.isEmpty() - ? feedback() == Feedback.Concise - ? "-> " - : "\n-> " - : ">> " + ? feedback.getPrompt(currentNameSpace.tidNext()) + : feedback.getContinuationPrompt(currentNameSpace.tidNext()) ; } else { prompt = ""; @@ -541,7 +679,7 @@ public class JShellTool { Command[] candidates = findCommand(cmd, c -> c.kind.isRealCommand); if (candidates.length == 0) { if (!rerunHistoryEntryById(cmd.substring(1))) { - hard("No such command or snippet id: %s", cmd); + error("No such command or snippet id: %s", cmd); fluff("Type /help for help."); } } else if (candidates.length == 1) { @@ -552,7 +690,7 @@ public class JShellTool { addToReplayHistory((command.command + " " + arg).trim()); } } else { - hard("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", "))); + error("Command: %s is ambiguous: %s", cmd, Arrays.stream(candidates).map(c -> c.command).collect(Collectors.joining(", "))); fluff("Type /help for help."); } } @@ -635,45 +773,6 @@ public class JShellTool { } } - class ArgTokenizer extends StreamTokenizer { - - ArgTokenizer(String arg) { - super(new StringReader(arg)); - resetSyntax(); - wordChars(0x00, 0xFF); - quoteChar('"'); - quoteChar('\''); - - whitespaceChars(0x09, 0x0D); - whitespaceChars(0x1C, 0x20); - whitespaceChars(0x85, 0x85); - whitespaceChars(0xA0, 0xA0); - whitespaceChars(0x1680, 0x1680); - whitespaceChars(0x180E, 0x180E); - whitespaceChars(0x2000, 0x200A); - whitespaceChars(0x202F, 0x202F); - whitespaceChars(0x205F, 0x205F); - whitespaceChars(0x3000, 0x3000); - } - - String next() { - try { - nextToken(); - } catch (Throwable t) { - return null; - } - return sval; - } - - String val() { - return sval; - } - - boolean isQuoted() { - return ttype == '\'' || ttype == '"'; - } - } - static final class FixedCompletionProvider implements CompletionProvider { private final String[] alternatives; @@ -801,16 +900,9 @@ public class JShellTool { " -- List the snippet with the specified snippet id\n", arg -> cmdList(arg), editKeywordCompletion())); - registerCommand(new Command("/seteditor", "", "set the external editor command to use", - "Specify the command to launch for the /edit command.\n" + - "The command is an operating system dependent string.\n" + - "The command may include space-separated arguments (such as flags).\n" + - "When /edit is used, temporary file to edit will be appended as the last argument.\n", - arg -> cmdSetEditor(arg), - EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/edit", "", "edit a source entry referenced by name or id", "Edit a snippet or snippets of source in an external editor.\n" + - "The editor to use is set with /seteditor.\n" + + "The editor to use is set with /set editor.\n" + "If no editor has been set, a simple editor will be launched.\n\n" + "/edit \n" + " -- Edit the snippet or snippets with the specified name (preference for active snippets)\n" + @@ -875,7 +967,7 @@ public class JShellTool { " * Start-up code is re-executed.\n" + " * The execution state is restarted.\n" + " * The classpath is cleared.\n" + - "Tool settings are maintained: /feedback, /prompt, and /seteditor\n" + + "Tool settings are maintained, as set with: /set ...\n" + "Save any work before using this command\n", arg -> cmdReset(), EMPTY_COMPLETION_PROVIDER)); @@ -895,25 +987,6 @@ public class JShellTool { " -- With the 'quiet' argument the replay is not shown. Errors will display.\n", arg -> cmdReload(arg), reloadCompletion())); - registerCommand(new Command("/feedback", "", "feedback information: off, concise, normal, verbose, default, or ?", - "Set the level of feedback describing the effect of commands and snippets.\n\n" + - "/feedback off\n" + - " -- Give no feedback\n" + - "/feedback concise\n" + - " -- Brief and generally symbolic feedback\n" + - "/feedback normal\n" + - " -- Give a natural language description of the actions\n" + - "/feedback verbose\n" + - " -- Like normal but with side-effects described\n" + - "/feedback default\n" + - " -- Same as normal for user input, off for input from a file\n", - arg -> cmdFeedback(arg), - new FixedCompletionProvider("off", "concise", "normal", "verbose", "default", "?"))); - registerCommand(new Command("/prompt", null, "toggle display of a prompt", - "Toggle between displaying an input prompt and not displaying a prompt.\n" + - "Particularly useful when pasting large amounts of text.\n", - arg -> cmdPrompt(), - EMPTY_COMPLETION_PROVIDER)); registerCommand(new Command("/classpath", "", "add a path to the classpath", "Append a additional path to the classpath.\n", arg -> cmdClasspath(arg), @@ -923,10 +996,6 @@ public class JShellTool { "Display the history of snippet and command input since this jshell was launched.\n", arg -> cmdHistory(), EMPTY_COMPLETION_PROVIDER)); - registerCommand(new Command("/setstart", "", "read file and set as the new start-up definitions", - "The contents of the specified file become the default start-up snippets and commands.\n", - arg -> cmdSetStart(arg), - FILE_COMPLETION_PROVIDER)); registerCommand(new Command("/debug", null, "toggle debugging of the jshell", "Display debugging information for the jshelll implementation.\n" + "0: Debugging off\n" + @@ -951,6 +1020,37 @@ public class JShellTool { " -- Display information about the specified help subject. Example: /help intro\n", arg -> cmdHelp(arg), EMPTY_COMPLETION_PROVIDER)); + registerCommand(new Command("/set", "editor|start|feedback|newmode|prompt|format|field ...", "set jshell configuration information", + "Set jshell configuration information, including:\n" + + "the external editor to use, the start-up definitions to use, a new feedback mode,\n" + + "the command prompt, the feedback mode to use, or the format of output.\n" + + "\n" + + "/set editor ...\n" + + " -- Specify the command to launch for the /edit command.\n" + + " The is an operating system dependent string.\n" + + "\n" + + "/set start \n" + + " -- The contents of the specified become the default start-up snippets and commands.\n" + + "\n" + + "/set feedback \n" + + " -- Set the feedback mode describing displayed feedback for entered snippets and commands.\n" + + "\n" + + "/set newmode [command|quiet []]\n" + + " -- Create a user-defined feedback mode, optionally copying from an existing mode.\n" + + "\n" + + "/set prompt \"\" \"\"\n" + + " -- Set the displayed prompts for a given feedback mode.\n" + + "\n" + + "/set format \"\" ...\n" + + " -- Configure a feedback mode by setting the format to use in a specified set of cases.\n" + + "\n" + + "/set field name|type|result|when|action|resolve|pre|post|errorpre|errorpost \"\" ...\n" + + " -- Set the format of a field within the of a \"/set format\" command\n" + + "\n" + + "To get more information about one of these forms, use /help with the form specified.\n" + + "For example: /help /set format\n", + arg -> cmdSet(arg), + new FixedCompletionProvider("format", "field", "feedback", "prompt", "newmode", "start", "editor"))); registerCommand(new Command("/?", "", "get information about jshell", "Display information about jshell (abbreviation for /help).\n" + "/?\n" + @@ -988,13 +1088,19 @@ public class JShellTool { CommandKind.HELP_SUBJECT)); registerCommand(new Command("shortcuts", "Describe shortcuts", "Supported shortcuts include:\n\n" + - " -- After entering the first few letters of a Java identifier,\n" + - " a jshell command, or, in some cases, a jshell command argument,\n" + - " press the key to complete the input.\n" + - " If there is more than one completion, show possible completions.\n" + - "Shift- -- After the name and open parenthesis of a method or constructor invocation,\n" + - " hold the key and press the to see a synopsis of all\n" + - " matching methods/constructors.\n", + " -- After entering the first few letters of a Java identifier,\n" + + " a jshell command, or, in some cases, a jshell command argument,\n" + + " press the key to complete the input.\n" + + " If there is more than one completion, show possible completions.\n" + + "Shift- -- After the name and open parenthesis of a method or constructor invocation,\n" + + " hold the key and press the to see a synopsis of all\n" + + " matching methods/constructors.\n" + + " v -- After a complete expression, press \" v\" to introduce a new variable\n" + + " whose type is based on the type of the expression.\n" + + " The \"\" is either Alt-F1 or Alt-Enter, depending on the platform.\n" + + " i -- After an unresolvable identifier, press \" i\" and jshell will propose\n" + + " possible fully qualified names based on the content of the specified classpath.\n" + + " The \"\" is either Alt-F1 or Alt-Enter, depending on the platform.\n", CommandKind.HELP_SUBJECT)); } @@ -1045,19 +1151,136 @@ public class JShellTool { // --- Command implementations --- - boolean cmdSetEditor(String arg) { - if (arg.isEmpty()) { - hard("/seteditor requires a path argument"); + private static final String[] setSub = new String[]{ + "format", "field", "feedback", "newmode", "prompt", "editor", "start"}; + + // The /set command. Currently /set format, /set field and /set feedback. + // Other commands will fold here, see: 8148317 + final boolean cmdSet(String arg) { + ArgTokenizer at = new ArgTokenizer(arg.trim()); + String which = setSubCommand(at); + if (which == null) { return false; - } else { - List ed = new ArrayList<>(); - ArgTokenizer at = new ArgTokenizer(arg); - String n; - while ((n = at.next()) != null) ed.add(n); - editor = ed.toArray(new String[ed.size()]); - fluff("Editor set to: %s", arg); - return true; } + switch (which) { + case "format": + return feedback.setFormat(this, at); + case "field": + return feedback.setField(this, at); + case "feedback": + return feedback.setFeedback(this, at); + case "newmode": + return feedback.setNewMode(this, at); + case "prompt": + return feedback.setPrompt(this, at); + case "editor": { + String prog = at.next(); + if (prog == null) { + hard("The '/set editor' command requires a path argument"); + return false; + } else { + List ed = new ArrayList<>(); + ed.add(prog); + String n; + while ((n = at.next()) != null) { + ed.add(n); + } + editor = ed.toArray(new String[ed.size()]); + fluff("Editor set to: %s", arg); + return true; + } + } + case "start": { + String filename = at.next(); + if (filename == null) { + hard("The '/set start' command requires a filename argument."); + } else { + try { + byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); + String init = new String(encoded); + PREFS.put(STARTUP_KEY, init); + } catch (AccessDeniedException e) { + hard("File '%s' for /set start is not accessible.", filename); + return false; + } catch (NoSuchFileException e) { + hard("File '%s' for /set start is not found.", filename); + return false; + } catch (Exception e) { + hard("Exception while reading start set file: %s", e); + return false; + } + } + return true; + } + default: + hard("Error: Invalid /set argument: %s", which); + return false; + } + } + + boolean printSetHelp(ArgTokenizer at) { + String which = setSubCommand(at); + if (which == null) { + return false; + } + switch (which) { + case "format": + feedback.printFormatHelp(this); + return true; + case "field": + feedback.printFieldHelp(this); + return true; + case "feedback": + feedback.printFeedbackHelp(this); + return true; + case "newmode": + feedback.printNewModeHelp(this); + return true; + case "prompt": + feedback.printPromptHelp(this); + return true; + case "editor": + hard("Specify the command to launch for the /edit command."); + hard(""); + hard("/set editor ..."); + hard(""); + hard("The is an operating system dependent string."); + hard("The may include space-separated arguments (such as flags) -- ...."); + hard("When /edit is used, the temporary file to edit will be appended as the last argument."); + return true; + case "start": + hard("Set the start-up configuration -- a sequence of snippets and commands read at start-up."); + hard(""); + hard("/set start "); + hard(""); + hard("The contents of the specified become the default start-up snippets and commands --"); + hard("which are run when the jshell tool is started or reset."); + return true; + default: + hard("Error: Invalid /set argument: %s", which); + return false; + } + } + + String setSubCommand(ArgTokenizer at) { + String[] matches = at.next(setSub); + if (matches == null) { + error("The /set command requires arguments. See: /help /set"); + return null; + } else if (matches.length == 0) { + error("Not a valid argument to /set: %s", at.val()); + fluff("/set is followed by one of: %s", Arrays.stream(setSub) + .collect(Collectors.joining(", ")) + ); + return null; + } else if (matches.length > 1) { + error("Ambiguous argument to /set: %s", at.val()); + fluff("Use one of: %s", Arrays.stream(matches) + .collect(Collectors.joining(", ")) + ); + return null; + } + return matches[0]; } boolean cmdClasspath(String arg) { @@ -1131,91 +1354,50 @@ public class JShellTool { return true; } - private boolean cmdFeedback(String arg) { - switch (arg) { - case "": - case "d": - case "default": - feedback = Feedback.Default; - break; - case "o": - case "off": - feedback = Feedback.Off; - break; - case "c": - case "concise": - feedback = Feedback.Concise; - break; - case "n": - case "normal": - feedback = Feedback.Normal; - break; - case "v": - case "verbose": - feedback = Feedback.Verbose; - break; - default: - hard("Follow /feedback with of the following:"); - hard(" off (errors and critical output only)"); - hard(" concise"); - hard(" normal"); - hard(" verbose"); - hard(" default"); - hard("You may also use just the first letter, for example: /f c"); - hard("In interactive mode 'default' is the same as 'normal', from a file it is the same as 'off'"); - return false; - } - fluff("Feedback mode: %s", feedback.name().toLowerCase()); - return true; - } - boolean cmdHelp(String arg) { - if (!arg.isEmpty()) { - StringBuilder sb = new StringBuilder(); - commands.values().stream() - .filter(c -> c.command.startsWith(arg)) - .forEach(c -> { - sb.append("\n"); - sb.append(c.command); - sb.append("\n\n"); - sb.append(c.help); - sb.append("\n"); - }); - if (sb.length() > 0) { - cmdout.print(sb); - return true; + ArgTokenizer at = new ArgTokenizer(arg); + String subject = at.next(); + if (subject != null) { + Command[] matches = commands.values().stream() + .filter(c -> c.command.startsWith(subject)) + .toArray(size -> new Command[size]); + at.mark(); + String sub = at.next(); + if (sub != null && matches.length == 1 && matches[0].command.equals("/set")) { + at.rewind(); + return printSetHelp(at); + } + if (matches.length > 0) { + for (Command c : matches) { + hard(""); + hard("%s", c.command); + hard(""); + hard("%s", c.help.replaceAll("\n", LINE_SEP + feedback.getPre())); + } + return true; + } else { + error("No commands or subjects start with the provided argument: %s\n\n", arg); } - cmdout.printf("No commands or subjects start with the provided argument: %s\n\n", arg); } - int synopsisLen = 0; - Map synopsis2Description = new LinkedHashMap<>(); - for (Command cmd : new LinkedHashSet<>(commands.values())) { - if (!cmd.kind.showInHelp) - continue; - StringBuilder synopsis = new StringBuilder(); - synopsis.append(cmd.command); - if (cmd.params != null) - synopsis.append(" ").append(cmd.params); - synopsis2Description.put(synopsis.toString(), cmd.description); - synopsisLen = Math.max(synopsisLen, synopsis.length()); - } - cmdout.println("Type a Java language expression, statement, or declaration."); - cmdout.println("Or type one of the following commands:\n"); - for (Entry e : synopsis2Description.entrySet()) { - cmdout.print(String.format("%-" + synopsisLen + "s", e.getKey())); - cmdout.print(" -- "); - String indentedNewLine = System.getProperty("line.separator") + - String.format("%-" + (synopsisLen + 4) + "s", ""); - cmdout.println(e.getValue().replace("\n", indentedNewLine)); - } - cmdout.println(); - cmdout.println("For more information type '/help' followed by the name of command or a subject."); - cmdout.println("For example '/help /list' or '/help intro'. Subjects:\n"); - commands.values().stream() - .filter(c -> c.kind == CommandKind.HELP_SUBJECT) - .forEach(c -> { - cmdout.printf("%-12s -- %s\n", c.command, c.description); - }); + hard("Type a Java language expression, statement, or declaration."); + hard("Or type one of the following commands:"); + hard(""); + hardPairs(commands.values().stream() + .filter(cmd -> cmd.kind.showInHelp), + cmd -> (cmd.params != null) + ? cmd.command + " " + cmd.params + : cmd.command, + cmd -> cmd.description + ); + hard(""); + hard("For more information type '/help' followed by the name of command or a subject."); + hard("For example '/help /list' or '/help intro'. Subjects:"); + hard(""); + hardPairs(commands.values().stream() + .filter(cmd -> cmd.kind == CommandKind.HELP_SUBJECT), + cmd -> cmd.command, + cmd -> cmd.description + ); return true; } @@ -1476,13 +1658,6 @@ public class JShellTool { return true; } - private boolean cmdPrompt() { - displayPrompt = !displayPrompt; - fluff("Prompt will %sdisplay. Use /prompt to toggle.", displayPrompt ? "" : "NOT "); - concise("Prompt: %s", displayPrompt ? "on" : "off"); - return true; - } - private boolean cmdReset() { live = false; fluff("Resetting state."); @@ -1571,28 +1746,6 @@ public class JShellTool { return true; } - private boolean cmdSetStart(String filename) { - if (filename.isEmpty()) { - hard("The /setstart command requires a filename argument."); - } else { - try { - byte[] encoded = Files.readAllBytes(toPathResolvingUserHome(filename)); - String init = new String(encoded); - PREFS.put(STARTUP_KEY, init); - } catch (AccessDeniedException e) { - hard("File '%s' for /setstart is not accessible.", filename); - return false; - } catch (NoSuchFileException e) { - hard("File '%s' for /setstart is not found.", filename); - return false; - } catch (Exception e) { - hard("Exception while reading start set file: %s", e); - return false; - } - } - return true; - } - private boolean cmdVars() { for (VarSnippet vk : state.variables()) { String val = state.status(vk) == Status.VALID @@ -1825,14 +1978,10 @@ public class JShellTool { printDiagnostics(source, diagnostics, true); } else { // Update - SubKind subkind = sn.subKind(); - if (sn instanceof DeclarationSnippet - && (feedback() == Feedback.Verbose - || ste.status() == Status.OVERWRITTEN - || subkind == SubKind.VAR_DECLARATION_SUBKIND - || subkind == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND)) { - // Under the conditions, display update information - displayDeclarationAndValue(ste, true, null); + if (sn instanceof DeclarationSnippet) { + // display update information + displayDeclarationAndValue(ste, true, ste.value()); + List other = errorsOnly(diagnostics); if (other.size() > 0) { printDiagnostics(source, other, true); @@ -1845,118 +1994,117 @@ public class JShellTool { @SuppressWarnings("fallthrough") private void displayDeclarationAndValue(SnippetEvent ste, boolean update, String value) { Snippet key = ste.snippet(); - String declared; + FormatAction action; Status status = ste.status(); switch (status) { case VALID: case RECOVERABLE_DEFINED: case RECOVERABLE_NOT_DEFINED: if (ste.previousStatus().isActive) { - declared = ste.isSignatureChange() - ? "Replaced" - : "Modified"; + action = ste.isSignatureChange() + ? FormatAction.REPLACED + : FormatAction.MODIFIED; } else { - declared = "Added"; + action = FormatAction.ADDED; } break; case OVERWRITTEN: - declared = "Overwrote"; + action = FormatAction.OVERWROTE; break; case DROPPED: - declared = "Dropped"; + action = FormatAction.DROPPED; break; case REJECTED: - declared = "Rejected"; + action = FormatAction.REJECTED; break; case NONEXISTENT: default: // Should not occur - declared = ste.previousStatus().toString() + "=>" + status.toString(); + error("Unexpected status: " + ste.previousStatus().toString() + "=>" + status.toString()); + return; } - if (update) { - declared = " Update " + declared.toLowerCase(); - } - String however; + FormatResolve resolution; + String unresolved; if (key instanceof DeclarationSnippet && (status == Status.RECOVERABLE_DEFINED || status == Status.RECOVERABLE_NOT_DEFINED)) { - String cannotUntil = (status == Status.RECOVERABLE_NOT_DEFINED) - ? " cannot be referenced until" - : " cannot be invoked until"; - however = (update? " which" : ", however, it") + cannotUntil + unresolved((DeclarationSnippet) key); + resolution = (status == Status.RECOVERABLE_NOT_DEFINED) + ? FormatResolve.NOTDEFINED + : FormatResolve.DEFINED; + unresolved = unresolved((DeclarationSnippet) key); } else { - however = ""; + resolution = FormatResolve.OK; + unresolved = ""; } switch (key.subKind()) { case CLASS_SUBKIND: - fluff("%s class %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.CLASS, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case INTERFACE_SUBKIND: - fluff("%s interface %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.INTERFACE, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case ENUM_SUBKIND: - fluff("%s enum %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.ENUM, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case ANNOTATION_TYPE_SUBKIND: - fluff("%s annotation interface %s%s", declared, ((TypeDeclSnippet) key).name(), however); + custom(FormatCase.ANNOTATION, update, action, resolution, + ((TypeDeclSnippet) key).name(), null, unresolved, null); break; case METHOD_SUBKIND: - fluff("%s method %s(%s)%s", declared, ((MethodSnippet) key).name(), - ((MethodSnippet) key).parameterTypes(), however); + custom(FormatCase.METHOD, update, action, resolution, + ((MethodSnippet) key).name(), ((MethodSnippet) key).parameterTypes(), unresolved, null); break; case VAR_DECLARATION_SUBKIND: - if (!update) { - VarSnippet vk = (VarSnippet) key; - if (status == Status.RECOVERABLE_NOT_DEFINED) { - fluff("%s variable %s%s", declared, vk.name(), however); - } else { - fluff("%s variable %s of type %s%s", declared, vk.name(), vk.typeName(), however); - } - break; - } - // Fall through case VAR_DECLARATION_WITH_INITIALIZER_SUBKIND: { VarSnippet vk = (VarSnippet) key; if (status == Status.RECOVERABLE_NOT_DEFINED) { - if (!update) { - fluff("%s variable %s%s", declared, vk.name(), however); - break; - } - } else if (update) { - if (ste.isSignatureChange()) { - hard("%s variable %s, reset to null", declared, vk.name()); - } + custom(FormatCase.VARDECLRECOVERABLE, update, action, resolution, + vk.name(), null, unresolved, null); + } else if (update && ste.isSignatureChange()) { + custom(FormatCase.VARRESET, update, action, resolution, + vk.name(), null, unresolved, value); + } else if (key.subKind() == SubKind.VAR_DECLARATION_WITH_INITIALIZER_SUBKIND) { + custom(FormatCase.VARINIT, update, action, resolution, + vk.name(), vk.typeName(), unresolved, value); } else { - fluff("%s variable %s of type %s with initial value %s", - declared, vk.name(), vk.typeName(), value); - concise("%s : %s", vk.name(), value); + custom(FormatCase.VARDECL, update, action, resolution, + vk.name(), vk.typeName(), unresolved, value); } break; } case TEMP_VAR_EXPRESSION_SUBKIND: { VarSnippet vk = (VarSnippet) key; - if (update) { - hard("%s temporary variable %s, reset to null", declared, vk.name()); - } else { - fluff("Expression value is: %s", (value)); - fluff(" assigned to temporary variable %s of type %s", vk.name(), vk.typeName()); - concise("%s : %s", vk.name(), value); - } + custom(FormatCase.EXPRESSION, update, action, resolution, + vk.name(), vk.typeName(), null, value); break; } case OTHER_EXPRESSION_SUBKIND: - fluff("Expression value is: %s", (value)); + error("Unexpected expression form -- value is: %s", (value)); break; case VAR_VALUE_SUBKIND: { ExpressionSnippet ek = (ExpressionSnippet) key; - fluff("Variable %s of type %s has value %s", ek.name(), ek.typeName(), (value)); - concise("%s : %s", ek.name(), value); + custom(FormatCase.VARVALUE, update, action, resolution, + ek.name(), ek.typeName(), null, value); break; } case ASSIGNMENT_SUBKIND: { ExpressionSnippet ek = (ExpressionSnippet) key; - fluff("Variable %s has been assigned the value %s", ek.name(), (value)); - concise("%s : %s", ek.name(), value); + custom(FormatCase.ASSIGNMENT, update, action, resolution, + ek.name(), ek.typeName(), null, value); break; } + case SINGLE_TYPE_IMPORT_SUBKIND: + case TYPE_IMPORT_ON_DEMAND_SUBKIND: + case SINGLE_STATIC_IMPORT_SUBKIND: + case STATIC_IMPORT_ON_DEMAND_SUBKIND: + custom(FormatCase.IMPORT, update, action, resolution, + ((ImportSnippet) key).name(), null, null, null); + break; + case STATEMENT_SUBKIND: + custom(FormatCase.STATEMENT, update, action, resolution, + null, null, null, null); + break; } } //where @@ -1992,7 +2140,7 @@ public class JShellTool { } //where void printUnresolved(UnresolvedReferenceException ex) { - MethodSnippet corralled = ex.getMethodSnippet(); + DeclarationSnippet corralled = ex.getSnippet(); List otherErrors = errorsOnly(state.diagnostics(corralled)); StringBuilder sb = new StringBuilder(); if (otherErrors.size() > 0) { @@ -2008,7 +2156,10 @@ public class JShellTool { sb.append("."); } - hard("Attempted to call %s which cannot be invoked until%s", corralled.name(), + String format = corralled.kind() == METHOD + ? "Attempted to call %s which cannot be invoked until%s" + : "Attempted to use %s which cannot be accessed until%s"; + hard(format, corralled.name(), unresolved(corralled), sb.toString()); if (otherErrors.size() > 0) { printDiagnostics(corralled.source(), otherErrors, true); @@ -2042,34 +2193,9 @@ public class JShellTool { sb.append(", "); } } - switch (unr.size()) { - case 0: - break; - case 1: - sb.append(" is declared"); - break; - default: - sb.append(" are declared"); - break; - } return sb.toString(); } - enum Feedback { - Default, - Off, - Concise, - Normal, - Verbose - } - - Feedback feedback() { - if (feedback == Feedback.Default) { - return input == null || input.interactiveOutput() ? Feedback.Normal : Feedback.Off; - } - return feedback; - } - /** The current version number as a string. */ static String version() { diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java index 462d61e87de..2ae696a026f 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/CompletenessAnalyzer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -231,7 +231,7 @@ class CompletenessAnalyzer { // Declarations and type parameters (thus expressions) EXTENDS(TokenKind.EXTENDS, XEXPR|XDECL), // extends - COMMA(TokenKind.COMMA, XEXPR|XDECL|XSTART), // , + COMMA(TokenKind.COMMA, XEXPR|XDECL), // , AMP(TokenKind.AMP, XEXPR|XDECL), // & GT(TokenKind.GT, XEXPR|XDECL), // > LT(TokenKind.LT, XEXPR|XDECL1), // < diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java new file mode 100644 index 00000000000..349e393caa0 --- /dev/null +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Corraller.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.jshell; + +import java.util.List; +import com.sun.source.tree.ArrayTypeTree; +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.ExpressionTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import jdk.jshell.Wrap.Range; +import static java.util.stream.Collectors.toList; + +/** + * Produce a corralled version of the Wrap for a snippet. + * + * @author Robert Field + */ +class Corraller { + + private final int index; + private final String compileSource; + private final TreeDissector dis; + + Corraller(int index, String compileSource, TreeDissector dis) { + this.index = index; + this.compileSource = compileSource; + this.dis = dis; + } + + Wrap corralTree(Tree tree, String enclosingType, int indent) { + switch (tree.getKind()) { + case VARIABLE: + return corralVariable((VariableTree) tree, indent); + case CLASS: + case ENUM: + case ANNOTATION_TYPE: + case INTERFACE: + return corralType((ClassTree) tree, indent); + case METHOD: + return corralMethod((MethodTree) tree, enclosingType, indent); + default: + return null; + } + } + + Wrap corralMethod(MethodTree mt) { + return corralMethod(mt, null, 1); + } + + Wrap corralMethod(MethodTree mt, String enclosingType, int indent) { + Range modRange = dis.treeToRange(mt.getModifiers()); + Range tpRange = dis.treeListToRange(mt.getTypeParameters()); + Range typeRange = dis.treeToRange(mt.getReturnType()); + String name = mt.getName().toString(); + if ("".equals(name)) { + name = enclosingType; + } + Range paramRange = dis.treeListToRange(mt.getParameters()); + Range throwsRange = dis.treeListToRange(mt.getThrows()); + return Wrap.corralledMethod(compileSource, + modRange, tpRange, typeRange, name, paramRange, throwsRange, index, indent); + } + + Wrap corralVariable(VariableTree vt, int indent) { + String name = vt.getName().toString(); + Range modRange = dis.treeToRange(vt.getModifiers()); + Tree baseType = vt.getType(); + StringBuilder sbBrackets = new StringBuilder(); + while (baseType instanceof ArrayTypeTree) { + //TODO handle annotations too + baseType = ((ArrayTypeTree) baseType).getType(); + sbBrackets.append("[]"); + } + Range rtype = dis.treeToRange(baseType); + Range runit = dis.treeToRange(vt); + runit = new Range(runit.begin, runit.end - 1); + ExpressionTree it = vt.getInitializer(); + int nameMax; + if (it != null) { + Range rinit = dis.treeToRange(it); + nameMax = rinit.begin - 1; + } else { + nameMax = runit.end - 1; + } + int nameStart = compileSource.lastIndexOf(name, nameMax); + if (nameStart < 0) { + throw new AssertionError("Name '" + name + "' not found"); + } + int nameEnd = nameStart + name.length(); + Range rname = new Range(nameStart, nameEnd); + return Wrap.corralledVar(compileSource, modRange, rtype, sbBrackets.toString(), rname, indent); + } + + Wrap corralType(ClassTree ct, int indent) { + boolean isClass; + switch (ct.getKind()) { + case CLASS: + isClass = true; + break; + case INTERFACE: + isClass = false; + break; + default: + return null; + } + Range modRange = dis.treeToRange(ct.getModifiers()); + String name = ct.getSimpleName().toString(); + Range tpRange = dis.treeListToRange(ct.getTypeParameters()); + Range extendsRange = dis.treeToRange(ct.getExtendsClause()); + List implementsRanges = ct.getImplementsClause().stream() + .map(ic -> dis.treeToRange(ic)) + .collect(toList()); + List members = ct.getMembers().stream() + .map(t -> corralTree(t, name, indent + 1)) + .filter(w -> w != null) + .collect(toList()); + boolean hasConstructor = ct.getMembers().stream() + .anyMatch(t -> t.getKind() == Tree.Kind.METHOD && ((MethodTree) t).getName().toString().equals("")); + Wrap wrap = Wrap.corralledType(compileSource, modRange, ct.getKind(), name, tpRange, + extendsRange, implementsRanges, members, isClass && !hasConstructor, index, indent); + return wrap; + } +} diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java index aede678b0b6..610840353ec 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Eval.java @@ -53,6 +53,7 @@ import java.util.Set; import jdk.jshell.ClassTracker.ClassInfo; import jdk.jshell.Key.ErroneousKey; import jdk.jshell.Key.MethodKey; +import jdk.jshell.Key.TypeDeclKey; import jdk.jshell.Snippet.SubKind; import jdk.jshell.TaskFactory.AnalyzeTask; import jdk.jshell.TaskFactory.BaseTask; @@ -300,7 +301,8 @@ class Eval { ClassTree klassTree = (ClassTree) unitTree; String name = klassTree.getSimpleName().toString(); Wrap guts = Wrap.classMemberWrap(compileSource); - Wrap corralled = null; //TODO + TypeDeclKey key = state.keyMap.keyForClass(name); + Wrap corralled = new Corraller(key.index(), compileSource, dis).corralType(klassTree, 1); Snippet snip = new TypeDeclSnippet(state.keyMap.keyForClass(name), userSource, guts, name, snippetKind, corralled, tds.declareReferences(), tds.bodyReferences()); @@ -362,12 +364,8 @@ class Eval { String unitName = mt.getName().toString(); Wrap guts = Wrap.classMemberWrap(compileSource); - Range modRange = dis.treeToRange(mt.getModifiers()); - Range tpRange = dis.treeListToRange(mt.getTypeParameters()); Range typeRange = dis.treeToRange(mt.getReturnType()); String name = mt.getName().toString(); - Range paramRange = dis.treeListToRange(mt.getParameters()); - Range throwsRange = dis.treeListToRange(mt.getThrows()); String parameterTypes = mt.getParameters() @@ -378,8 +376,7 @@ class Eval { MethodKey key = state.keyMap.keyForMethod(name, parameterTypes); // rewrap with correct Key index - Wrap corralled = Wrap.corralledMethod(compileSource, - modRange, tpRange, typeRange, name, paramRange, throwsRange, key.index()); + Wrap corralled = new Corraller(key.index(), compileSource, dis).corralMethod(mt); Snippet snip = new MethodSnippet(key, userSource, guts, unitName, signature, corralled, tds.declareReferences(), tds.bodyReferences()); @@ -420,7 +417,7 @@ class Eval { TaskFactory.AnalyzeTask at = trialCompile(guts); if (!at.hasErrors() && at.firstCuTree() != null) { return TreeDissector.createByFirstClass(at) - .typeOfReturnStatement(at.messages(), state.maps::fullClassNameAndPackageToClass); + .typeOfReturnStatement(at, state); } return null; } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java index ad115656661..8f629fd75c8 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/ExecutionControl.java @@ -225,7 +225,7 @@ class ExecutionControl { int id = in.readInt(); StackTraceElement[] elems = readStackTrace(); Snippet si = maps.getSnippet(id); - throw new UnresolvedReferenceException((MethodSnippet) si, elems); + throw new UnresolvedReferenceException((DeclarationSnippet) si, elems); } case RESULT_KILLED: { proc.out.println("Killed."); diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java index 858aee274dd..2c731f5ba0c 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/JShell.java @@ -346,10 +346,20 @@ public class JShell implements AutoCloseable { * @see JShell#onShutdown(java.util.function.Consumer) */ public List eval(String input) throws IllegalStateException { - checkIfAlive(); - List events = eval.eval(input); - events.forEach(this::notifyKeyStatusEvent); - return Collections.unmodifiableList(events); + SourceCodeAnalysisImpl a = sourceCodeAnalysis; + if (a != null) { + a.suspendIndexing(); + } + try { + checkIfAlive(); + List events = eval.eval(input); + events.forEach(this::notifyKeyStatusEvent); + return Collections.unmodifiableList(events); + } finally { + if (a != null) { + a.resumeIndexing(); + } + } } /** diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java index f9a31f1de76..3aee3204425 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysis.java @@ -69,6 +69,28 @@ public abstract class SourceCodeAnalysis { */ public abstract String documentation(String input, int cursor); + /** + * Infer the type of the given expression. The expression spans from the beginning of {@code code} + * to the given {@code cursor} position. Returns null if the type of the expression cannot + * be inferred. + * + * @param code the expression for which the type should be inferred + * @param cursor current cursor position in the given code + * @return the inferred type, or null if it cannot be inferred + */ + public abstract String analyzeType(String code, int cursor); + + /** + * List qualified names known for the simple name in the given code immediately + * to the left of the given cursor position. The qualified names are gathered by inspecting the + * classpath used by eval (see {@link JShell#addToClasspath(java.lang.String)}). + * + * @param code the expression for which the candidate qualified names should be computed + * @param cursor current cursor position in the given code + * @return the known qualified names + */ + public abstract QualifiedNames listQualifiedNames(String code, int cursor); + /** * Internal only constructor */ @@ -80,7 +102,7 @@ public abstract class SourceCodeAnalysis { */ public static class CompletionInfo { - public CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) { + CompletionInfo(Completeness completeness, int unitEndPos, String source, String remaining) { this.completeness = completeness; this.unitEndPos = unitEndPos; this.source = source; @@ -198,4 +220,65 @@ public abstract class SourceCodeAnalysis { */ public final boolean isSmart; } + + /** + * List of possible qualified names. + */ + public static final class QualifiedNames { + + private final List names; + private final int simpleNameLength; + private final boolean upToDate; + private final boolean resolvable; + + QualifiedNames(List names, int simpleNameLength, boolean upToDate, boolean resolvable) { + this.names = names; + this.simpleNameLength = simpleNameLength; + this.upToDate = upToDate; + this.resolvable = resolvable; + } + + /** + * Known qualified names for the given simple name in the original code. + * + * @return known qualified names + */ + public List getNames() { + return names; + } + + /** + * The length of the simple name in the original code for which the + * qualified names where gathered. + * + * @return the length of the simple name; -1 if there is no name immediately left to the cursor for + * which the candidates could be computed + */ + public int getSimpleNameLength() { + return simpleNameLength; + } + + /** + * Whether the result is based on up to date data. The + * {@link SourceCodeAnalysis#listQualifiedNames(java.lang.String, int) listQualifiedNames} + * method may return before the classpath is fully inspected, in which case this method will + * return {@code false}. If the result is based on a fully inspected classpath, this method + * will return {@code true}. + * + * @return true iff the results is based on up-to-date data + */ + public boolean isUpToDate() { + return upToDate; + } + + /** + * Whether the given simple name in the original code refers to a resolvable element. + * + * @return true iff the given simple name in the original code refers to a resolvable element + */ + public boolean isResolvable() { + return resolvable; + } + + } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java index bbd3c286322..2fbb46a2722 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/SourceCodeAnalysisImpl.java @@ -79,13 +79,23 @@ import java.net.URI; import java.nio.file.DirectoryStream; import java.nio.file.FileSystem; import java.nio.file.FileSystems; +import java.nio.file.FileVisitResult; +import java.nio.file.FileVisitor; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.nio.file.attribute.BasicFileAttributes; +import java.util.Arrays; +import java.util.Collection; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Set; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -99,6 +109,7 @@ import java.util.stream.Stream; import java.util.stream.StreamSupport; import javax.lang.model.SourceVersion; + import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.PackageElement; import javax.lang.model.element.QualifiedNameable; @@ -118,12 +129,30 @@ import static jdk.jshell.Util.REPL_DOESNOTMATTER_CLASS_NAME; * @author Robert Field */ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { + + private static final Map PATH_TO_INDEX = new HashMap<>(); + private static final ExecutorService INDEXER = Executors.newFixedThreadPool(1, r -> { + Thread t = new Thread(r); + t.setDaemon(true); + t.setUncaughtExceptionHandler((thread, ex) -> ex.printStackTrace()); + return t; + }); + private final JShell proc; private final CompletenessAnalyzer ca; + private final Map currentIndexes = new HashMap<>(); + private int indexVersion; + private int classpathVersion; + private final Object suspendLock = new Object(); + private int suspend; SourceCodeAnalysisImpl(JShell proc) { this.proc = proc; this.ca = new CompletenessAnalyzer(proc); + + int cpVersion = classpathVersion = 1; + + INDEXER.submit(() -> refreshIndexes(cpVersion)); } @Override @@ -203,6 +232,15 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { @Override public List completionSuggestions(String code, int cursor, int[] anchor) { + suspendIndexing(); + try { + return completionSuggestionsImpl(code, cursor, anchor); + } finally { + resumeIndexing(); + } + } + + private List completionSuggestionsImpl(String code, int cursor, int[] anchor) { code = code.substring(0, cursor); Matcher m = JAVA_IDENTIFIER.matcher(code); String identifier = ""; @@ -390,8 +428,11 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { long start = sp.getStartPosition(topLevel, tree); long end = sp.getEndPosition(topLevel, tree); + long prevEnd = deepest[0] != null ? sp.getEndPosition(topLevel, deepest[0].getLeaf()) : -1; - if (start <= pos && pos <= end) { + if (start <= pos && pos <= end && + (start != end || prevEnd != end || deepest[0] == null || + deepest[0].getParentPath().getLeaf() != getCurrentPath().getLeaf())) { deepest[0] = new TreePath(getCurrentPath(), tree); return super.scan(tree, p); } @@ -589,32 +630,28 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { .collect(toList()); } - private Set emptyContextPackages = null; - void classpathChanged() { - emptyContextPackages = null; + synchronized (currentIndexes) { + int cpVersion = ++classpathVersion; + + INDEXER.submit(() -> refreshIndexes(cpVersion)); + } } private Set listPackages(AnalyzeTask at, String enclosingPackage) { - Set packs; - - if (enclosingPackage.isEmpty() && emptyContextPackages != null) { - packs = emptyContextPackages; - } else { - packs = new HashSet<>(); - - listPackages(StandardLocation.PLATFORM_CLASS_PATH, enclosingPackage, packs); - listPackages(StandardLocation.CLASS_PATH, enclosingPackage, packs); - listPackages(StandardLocation.SOURCE_PATH, enclosingPackage, packs); - - if (enclosingPackage.isEmpty()) { - emptyContextPackages = packs; - } + synchronized (currentIndexes) { + return currentIndexes.values() + .stream() + .flatMap(idx -> idx.packages.stream()) + .filter(p -> enclosingPackage.isEmpty() || p.startsWith(enclosingPackage + ".")) + .map(p -> { + int dot = p.indexOf('.', enclosingPackage.length() + 1); + return dot == (-1) ? p : p.substring(0, dot); + }) + .distinct() + .map(p -> createPackageElement(at, p)) + .collect(Collectors.toSet()); } - - return packs.stream() - .map(pkg -> createPackageElement(at, pkg)) - .collect(Collectors.toSet()); } private PackageElement createPackageElement(AnalyzeTask at, String packageName) { @@ -625,79 +662,6 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { return existing; } - private void listPackages(Location loc, String enclosing, Set packs) { - Iterable paths = proc.taskFactory.fileManager().getLocationAsPaths(loc); - - if (paths == null) - return ; - - for (Path p : paths) { - listPackages(p, enclosing, packs); - } - } - - private void listPackages(Path path, String enclosing, Set packages) { - try { - if (path.equals(Paths.get("JRT_MARKER_FILE"))) { - FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); - Path modules = jrtfs.getPath("modules"); - try (DirectoryStream stream = Files.newDirectoryStream(modules)) { - for (Path c : stream) { - listDirectory(c, enclosing, packages); - } - } - } else if (!Files.isDirectory(path)) { - if (Files.exists(path)) { - ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader(); - - try (FileSystem zip = FileSystems.newFileSystem(path, cl)) { - listDirectory(zip.getRootDirectories().iterator().next(), enclosing, packages); - } - } - } else { - listDirectory(path, enclosing, packages); - } - } catch (IOException ex) { - proc.debug(ex, "SourceCodeAnalysisImpl.listPackages(" + path.toString() + ", " + enclosing + ", " + packages + ")"); - } - } - - private void listDirectory(Path path, String enclosing, Set packages) throws IOException { - String separator = path.getFileSystem().getSeparator(); - Path resolved = path.resolve(enclosing.replace(".", separator)); - - if (Files.isDirectory(resolved)) { - try (DirectoryStream ds = Files.newDirectoryStream(resolved)) { - for (Path entry : ds) { - String name = pathName(entry); - - if (SourceVersion.isIdentifier(name) && - Files.isDirectory(entry) && - validPackageCandidate(entry)) { - packages.add(enclosing + (enclosing.isEmpty() ? "" : ".") + name); - } - } - } - } - } - - private boolean validPackageCandidate(Path p) throws IOException { - try (Stream dir = Files.list(p)) { - return dir.anyMatch(e -> Files.isDirectory(e) && SourceVersion.isIdentifier(pathName(e)) || - e.getFileName().toString().endsWith(".class")); - } - } - - private String pathName(Path p) { - String separator = p.getFileSystem().getSeparator(); - String name = p.getFileName().toString(); - - if (name.endsWith(separator)) //jars have '/' appended - name = name.substring(0, name.length() - separator.length()); - - return name; - } - private Element createArrayLengthSymbol(AnalyzeTask at, TypeMirror site) { Name length = Names.instance(at.getContext()).length; Type intType = Symtab.instance(at.getContext()).intType; @@ -965,6 +929,15 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { @Override public String documentation(String code, int cursor) { + suspendIndexing(); + try { + return documentationImpl(code, cursor); + } finally { + resumeIndexing(); + } + } + + private String documentationImpl(String code, int cursor) { code = code.substring(0, cursor); if (code.trim().isEmpty()) { //TODO: comment handling code += ";"; @@ -1074,4 +1047,347 @@ class SourceCodeAnalysisImpl extends SourceCodeAnalysis { } return arrayType; } + + @Override + public String analyzeType(String code, int cursor) { + code = code.substring(0, cursor); + CompletionInfo completionInfo = analyzeCompletion(code); + if (!completionInfo.completeness.isComplete) + return null; + if (completionInfo.completeness == Completeness.COMPLETE_WITH_SEMI) { + code += ";"; + } + + OuterWrap codeWrap; + switch (guessKind(code)) { + case IMPORT: case METHOD: case CLASS: case ENUM: + case INTERFACE: case ANNOTATION_TYPE: case VARIABLE: + return null; + default: + codeWrap = wrapInClass(Wrap.methodWrap(code)); + break; + } + AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); + SourcePositions sp = at.trees().getSourcePositions(); + CompilationUnitTree topLevel = at.firstCuTree(); + int pos = codeWrap.snippetIndexToWrapIndex(code.length()); + TreePath tp = pathFor(topLevel, sp, pos); + while (ExpressionTree.class.isAssignableFrom(tp.getParentPath().getLeaf().getKind().asInterface()) && + tp.getParentPath().getLeaf().getKind() != Kind.ERRONEOUS && + tp.getParentPath().getParentPath() != null) + tp = tp.getParentPath(); + TypeMirror type = at.trees().getTypeMirror(tp); + + if (type == null) + return null; + + switch (type.getKind()) { + case ERROR: case NONE: case OTHER: + case PACKAGE: case VOID: + return null; //not usable + case NULL: + type = at.getElements().getTypeElement("java.lang.Object").asType(); + break; + } + + return TreeDissector.printType(at, proc, type); + } + + @Override + public QualifiedNames listQualifiedNames(String code, int cursor) { + code = code.substring(0, cursor); + if (code.trim().isEmpty()) { + return new QualifiedNames(Collections.emptyList(), -1, true, false); + } + OuterWrap codeWrap; + switch (guessKind(code)) { + case IMPORT: + return new QualifiedNames(Collections.emptyList(), -1, true, false); + case METHOD: + codeWrap = wrapInClass(Wrap.classMemberWrap(code)); + break; + default: + codeWrap = wrapInClass(Wrap.methodWrap(code)); + break; + } + AnalyzeTask at = proc.taskFactory.new AnalyzeTask(codeWrap); + SourcePositions sp = at.trees().getSourcePositions(); + CompilationUnitTree topLevel = at.firstCuTree(); + TreePath tp = pathFor(topLevel, sp, codeWrap.snippetIndexToWrapIndex(code.length())); + if (tp.getLeaf().getKind() != Kind.IDENTIFIER) { + return new QualifiedNames(Collections.emptyList(), -1, true, false); + } + Scope scope = at.trees().getScope(tp); + TypeMirror type = at.trees().getTypeMirror(tp); + Element el = at.trees().getElement(tp); + + boolean erroneous = (type.getKind() == TypeKind.ERROR && el.getKind() == ElementKind.CLASS) || + (el.getKind() == ElementKind.PACKAGE && el.getEnclosedElements().isEmpty()); + String simpleName = ((IdentifierTree) tp.getLeaf()).getName().toString(); + boolean upToDate; + List result; + + synchronized (currentIndexes) { + upToDate = classpathVersion == indexVersion; + result = currentIndexes.values() + .stream() + .flatMap(idx -> idx.classSimpleName2FQN.getOrDefault(simpleName, + Collections.emptyList()).stream()) + .distinct() + .filter(fqn -> isAccessible(at, scope, fqn)) + .sorted() + .collect(Collectors.toList()); + } + + return new QualifiedNames(result, simpleName.length(), upToDate, !erroneous); + } + + private boolean isAccessible(AnalyzeTask at, Scope scope, String fqn) { + TypeElement type = at.getElements().getTypeElement(fqn); + if (type == null) + return false; + return at.trees().isAccessible(scope, type); + } + + //-------------------- + // classpath indexing: + //-------------------- + + //the indexing can be suspended when a more important task is running: + private void waitIndexingNotSuspended() { + boolean suspendedNotified = false; + synchronized (suspendLock) { + while (suspend > 0) { + if (!suspendedNotified) { + suspendedNotified = true; + } + try { + suspendLock.wait(); + } catch (InterruptedException ex) { + } + } + } + } + + public void suspendIndexing() { + synchronized (suspendLock) { + suspend++; + } + } + + public void resumeIndexing() { + synchronized (suspendLock) { + if (--suspend == 0) { + suspendLock.notifyAll(); + } + } + } + + //update indexes, either initially or after a classpath change: + private void refreshIndexes(int version) { + try { + Collection paths = new ArrayList<>(); + MemoryFileManager fm = proc.taskFactory.fileManager(); + + appendPaths(fm, StandardLocation.PLATFORM_CLASS_PATH, paths); + appendPaths(fm, StandardLocation.CLASS_PATH, paths); + appendPaths(fm, StandardLocation.SOURCE_PATH, paths); + + Map newIndexes = new HashMap<>(); + + //setup existing/last known data: + for (Path p : paths) { + ClassIndex index = PATH_TO_INDEX.get(p); + if (index != null) { + newIndexes.put(p, index); + } + } + + synchronized (currentIndexes) { + //temporary setting old data: + currentIndexes.clear(); + currentIndexes.putAll(newIndexes); + } + + //update/compute the indexes if needed: + for (Path p : paths) { + waitIndexingNotSuspended(); + + ClassIndex index = indexForPath(p); + newIndexes.put(p, index); + } + + synchronized (currentIndexes) { + currentIndexes.clear(); + currentIndexes.putAll(newIndexes); + } + } catch (Exception ex) { + proc.debug(ex, "SourceCodeAnalysisImpl.refreshIndexes(" + version + ")"); + } finally { + synchronized (currentIndexes) { + indexVersion = version; + } + } + } + + private void appendPaths(MemoryFileManager fm, Location loc, Collection paths) { + Iterable locationPaths = fm.getLocationAsPaths(loc); + if (locationPaths == null) + return ; + for (Path path : locationPaths) { + if (".".equals(path.toString())) { + //skip CWD + continue; + } + + paths.add(path); + } + } + + //create/update index a given JavaFileManager entry (which may be a JDK installation, a jar/zip file or a directory): + //if an index exists for the given entry, the existing index is kept unless the timestamp is modified + private ClassIndex indexForPath(Path path) { + if (isJRTMarkerFile(path)) { + FileSystem jrtfs = FileSystems.getFileSystem(URI.create("jrt:/")); + Path modules = jrtfs.getPath("modules"); + return PATH_TO_INDEX.compute(path, (p, index) -> { + try { + long lastModified = Files.getLastModifiedTime(modules).toMillis(); + if (index == null || index.timestamp != lastModified) { + try (DirectoryStream stream = Files.newDirectoryStream(modules)) { + index = doIndex(lastModified, path, stream); + } + } + return index; + } catch (IOException ex) { + proc.debug(ex, "SourceCodeAnalysisImpl.indexesForPath(" + path.toString() + ")"); + return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap()); + } + }); + } else if (!Files.isDirectory(path)) { + if (Files.exists(path)) { + return PATH_TO_INDEX.compute(path, (p, index) -> { + try { + long lastModified = Files.getLastModifiedTime(p).toMillis(); + if (index == null || index.timestamp != lastModified) { + ClassLoader cl = SourceCodeAnalysisImpl.class.getClassLoader(); + + try (FileSystem zip = FileSystems.newFileSystem(path, cl)) { + index = doIndex(lastModified, path, zip.getRootDirectories()); + } + } + return index; + } catch (IOException ex) { + proc.debug(ex, "SourceCodeAnalysisImpl.indexesForPath(" + path.toString() + ")"); + return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap()); + } + }); + } else { + return new ClassIndex(-1, path, Collections.emptySet(), Collections.emptyMap()); + } + } else { + return PATH_TO_INDEX.compute(path, (p, index) -> { + //no persistence for directories, as we cannot check timestamps: + if (index == null) { + index = doIndex(-1, path, Arrays.asList(p)); + } + return index; + }); + } + } + + static boolean isJRTMarkerFile(Path path) { + return path.equals(Paths.get("JRT_MARKER_FILE")); + } + + //create an index based on the content of the given dirs; the original JavaFileManager entry is originalPath. + private ClassIndex doIndex(long timestamp, Path originalPath, Iterable dirs) { + Set packages = new HashSet<>(); + Map> classSimpleName2FQN = new HashMap<>(); + + for (Path d : dirs) { + try { + Files.walkFileTree(d, new FileVisitor() { + int depth; + @Override + public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { + waitIndexingNotSuspended(); + if (depth++ == 0) + return FileVisitResult.CONTINUE; + String dirName = dir.getFileName().toString(); + String sep = dir.getFileSystem().getSeparator(); + dirName = dirName.endsWith(sep) ? dirName.substring(0, dirName.length() - sep.length()) + : dirName; + if (SourceVersion.isIdentifier(dirName)) + return FileVisitResult.CONTINUE; + return FileVisitResult.SKIP_SUBTREE; + } + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { + waitIndexingNotSuspended(); + if (file.getFileName().toString().endsWith(".class")) { + String relativePath = d.relativize(file).toString(); + String binaryName = relativePath.substring(0, relativePath.length() - 6).replace('/', '.'); + int packageDot = binaryName.lastIndexOf('.'); + if (packageDot > (-1)) { + packages.add(binaryName.substring(0, packageDot)); + } + String typeName = binaryName.replace('$', '.'); + addClassName2Map(classSimpleName2FQN, typeName); + } + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException { + depth--; + return FileVisitResult.CONTINUE; + } + }); + } catch (IOException ex) { + proc.debug(ex, "doIndex(" + d.toString() + ")"); + } + } + + return new ClassIndex(timestamp, originalPath, packages, classSimpleName2FQN); + } + + private static void addClassName2Map(Map> classSimpleName2FQN, String typeName) { + int simpleNameDot = typeName.lastIndexOf('.'); + classSimpleName2FQN.computeIfAbsent(typeName.substring(simpleNameDot + 1), n -> new LinkedHashSet<>()) + .add(typeName); + } + + //holder for indexed data about a given path + public static final class ClassIndex { + public final long timestamp; + public final Path forPath; + public final Set packages; + public final Map> classSimpleName2FQN; + + public ClassIndex(long timestamp, Path forPath, Set packages, Map> classSimpleName2FQN) { + this.timestamp = timestamp; + this.forPath = forPath; + this.packages = packages; + this.classSimpleName2FQN = classSimpleName2FQN; + } + + } + + //for tests, to be able to wait until the indexing finishes: + public void waitBackgroundTaskFinished() throws Exception { + boolean upToDate; + synchronized (currentIndexes) { + upToDate = classpathVersion == indexVersion; + } + while (!upToDate) { + INDEXER.submit(() -> {}).get(); + synchronized (currentIndexes) { + upToDate = classpathVersion == indexVersion; + } + } + } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java index 0582fd66cae..f27b0c770be 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TaskFactory.java @@ -61,6 +61,7 @@ import javax.lang.model.util.Elements; import javax.tools.FileObject; import jdk.jshell.MemoryFileManager.SourceMemoryJavaFileObject; import jdk.jshell.ClassTracker.ClassInfo; +import jdk.Version; /** * The primary interface to the compiler API. Parsing, analysis, and @@ -73,6 +74,7 @@ class TaskFactory { private final MemoryFileManager fileManager; private final JShell state; private String classpath = System.getProperty("java.class.path"); + private final static Version INITIAL_SUPPORTED_VER = Version.parse("9"); TaskFactory(JShell state) { this.state = state; @@ -80,7 +82,8 @@ class TaskFactory { if (compiler == null) { throw new UnsupportedOperationException("Compiler not available, must be run with full JDK 9."); } - if (!System.getProperty("java.specification.version").equals("9")) { + Version current = Version.parse(System.getProperty("java.specification.version")); + if (INITIAL_SUPPORTED_VER.compareToIgnoreOpt(current) > 0) { throw new UnsupportedOperationException("Wrong compiler, must be run with full JDK 9."); } this.fileManager = new MemoryFileManager( diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java index aad59b54a42..f59d10b0d3a 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/TreeDissector.java @@ -41,13 +41,14 @@ import com.sun.tools.javac.code.Type; import com.sun.tools.javac.code.Type.MethodType; import com.sun.tools.javac.code.Types; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; -import com.sun.tools.javac.util.JavacMessages; import com.sun.tools.javac.util.Name; import static jdk.jshell.Util.isDoIt; +import jdk.jshell.TaskFactory.AnalyzeTask; import jdk.jshell.Wrap.Range; + import java.util.List; import java.util.Locale; -import java.util.function.BinaryOperator; + import java.util.function.Predicate; import java.util.stream.Stream; import javax.lang.model.type.TypeMirror; @@ -209,7 +210,7 @@ class TreeDissector { } - ExpressionInfo typeOfReturnStatement(JavacMessages messages, BinaryOperator fullClassNameAndPackageToClass) { + ExpressionInfo typeOfReturnStatement(AnalyzeTask at, JShell state) { ExpressionInfo ei = new ExpressionInfo(); Tree unitTree = firstStatement(); if (unitTree instanceof ReturnTree) { @@ -219,9 +220,7 @@ class TreeDissector { if (viPath != null) { TypeMirror tm = trees().getTypeMirror(viPath); if (tm != null) { - Type type = (Type)tm; - TypePrinter tp = new TypePrinter(messages, fullClassNameAndPackageToClass, type); - ei.typeName = tp.visit(type, Locale.getDefault()); + ei.typeName = printType(at, state, tm); switch (tm.getKind()) { case VOID: case NONE: @@ -263,6 +262,12 @@ class TreeDissector { return sg.toString(); } + public static String printType(AnalyzeTask at, JShell state, TypeMirror type) { + Type typeImpl = (Type) type; + TypePrinter tp = new TypePrinter(at.messages(), state.maps::fullClassNameAndPackageToClass, typeImpl); + return tp.visit(typeImpl, Locale.getDefault()); + } + /** * Signature Generation */ diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java index eaf240d47b2..3e3de8fd943 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/UnresolvedReferenceException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,33 +28,33 @@ package jdk.jshell; /** * Exception reported on attempting to execute a * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * method. + * snippet. *

    * The stack can be queried by methods on Exception. * Note that in stack trace frames representing JShell Snippets, * StackTraceElement.getFileName() will return "#" followed by * the Snippet id and for snippets without a method name (for example an - * expression) StackTraceElement.getMethodName() will be the + * expression) StackTraceElement.getName() will be the * empty string. */ @SuppressWarnings("serial") // serialVersionUID intentionally omitted public class UnresolvedReferenceException extends Exception { - final MethodSnippet methodSnippet; + final DeclarationSnippet snippet; - UnresolvedReferenceException(MethodSnippet methodSnippet, StackTraceElement[] stackElements) { - super("Attempt to invoke method with unresolved references"); - this.methodSnippet = methodSnippet; + UnresolvedReferenceException(DeclarationSnippet snippet, StackTraceElement[] stackElements) { + super("Attempt to use definition snippet with unresolved references"); + this.snippet = snippet; this.setStackTrace(stackElements); } /** - * Return the method Snippet which has the unresolved reference(s). - * @return the MethodSnippet of the + * Return the Snippet which has the unresolved reference(s). + * @return the Snippet of the * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED} - * method. + * definition snippet. */ - public MethodSnippet getMethodSnippet() { - return methodSnippet; + public DeclarationSnippet getSnippet() { + return snippet; } } diff --git a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java index 1b380444936..62759319a9b 100644 --- a/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java +++ b/langtools/src/jdk.jshell/share/classes/jdk/jshell/Wrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ package jdk.jshell; import java.util.ArrayList; import java.util.List; +import com.sun.source.tree.Tree; import static jdk.internal.jshell.remote.RemoteCodes.DOIT_METHOD_NAME; /** @@ -58,9 +59,18 @@ abstract class Wrap implements GeneralWrap { return methodWrap("", source, ""); } - public static Wrap corralledMethod(String source, Range modRange, Range tpRange, Range typeRange, String name, Range paramRange, Range throwsRange, int id) { + private static String indent(int n) { + return " ".substring(0, n * 4); + } + + private static String nlindent(int n) { + return "\n" + indent(n); + } + + public static Wrap corralledMethod(String source, Range modRange, Range tpRange, + Range typeRange, String name, Range paramRange, Range throwsRange, int id, int indent) { List l = new ArrayList<>(); - l.add(" public static\n "); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); if (!modRange.isEmpty()) { l.add(new RangeWrap(source, modRange)); l.add(" "); @@ -70,17 +80,81 @@ abstract class Wrap implements GeneralWrap { l.add(new RangeWrap(source, tpRange)); l.add("> "); } - l.add(new RangeWrap(source, typeRange)); - l.add(" " + name + "(\n "); - if (paramRange != null) { + if (!typeRange.isEmpty()) { + l.add(new RangeWrap(source, typeRange)); + l.add(" "); + } + l.add(name + "("); + if (paramRange != null && !paramRange.isEmpty()) { + l.add(nlindent(indent + 1)); l.add(new RangeWrap(source, paramRange)); } - l.add(") "); + l.add(")"); if (throwsRange != null) { - l.add("throws "); + l.add(" throws "); l.add(new RangeWrap(source, throwsRange)); } - l.add(" {\n throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");\n}\n"); + l.add(" {" + + nlindent(indent+1) + + "throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");" + + nlindent(indent) + + "}\n"); + return new CompoundWrap(l.toArray()); + } + + public static Wrap corralledType(String source, Range modRange, Tree.Kind kind, String name, Range tpRange, + Range extendsRange, List implementsRanges, List members, + boolean defaultConstructor, int id, int indent) { + boolean isInterface = kind == Tree.Kind.INTERFACE; + List l = new ArrayList<>(); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); + if (!modRange.isEmpty()) { + l.add(new RangeWrap(source, modRange)); + l.add(" "); + } + l.add((isInterface ? "interface " : "class ") + name); + if (tpRange != null) { + l.add("<"); + l.add(new RangeWrap(source, tpRange)); + l.add("> "); + } + if (extendsRange != null && !extendsRange.isEmpty()) { + l.add(" extends "); + l.add(new RangeWrap(source, extendsRange)); + } + for (int i = 0; i < implementsRanges.size(); ++i) { + Range ir = implementsRanges.get(i); + l.add(i == 0 ? " implements " : ", "); + l.add(new RangeWrap(source, ir)); + } + if (defaultConstructor) { + l.add(" {" + + nlindent(indent+1) + + ((indent == 1)? "public " : "") + name + "() {" + + nlindent(indent+2) + + "throw new jdk.internal.jshell.remote.RemoteResolutionException(" + id + ");" + + nlindent(indent+1) + + "}\n"); + } else { + l.add(" {\n"); + } + l.addAll(members); + l.add(indent(indent) + "}\n"); + return new CompoundWrap(l.toArray()); + } + + public static Wrap corralledVar(String source, Range modRange, Range typeRange, String brackets, Range nameRange, int indent) { + RangeWrap wname = new RangeWrap(source, nameRange); + List l = new ArrayList<>(); + l.add(indent(indent) + ((indent == 1) ? "public static" + nlindent(indent) : "")); + if (!modRange.isEmpty()) { + l.add(new RangeWrap(source, modRange)); + l.add(" "); + } + l.add(new RangeWrap(source, typeRange)); + l.add(" "); + l.add(wname); + l.add(semi(wname)); return new CompoundWrap(l.toArray()); } diff --git a/langtools/test/TEST.groups b/langtools/test/TEST.groups index 0065d8ec397..8a77c0804f1 100644 --- a/langtools/test/TEST.groups +++ b/langtools/test/TEST.groups @@ -22,15 +22,17 @@ # Tiered testing definitions -# All langtools tests are tier 1. +# (Nearly) all langtools tests are tier 1. tier1 = \ com \ jdk \ lib \ - tools + tools \ + -jdk/jshell/ToolReloadTest.java -# No langtools tests are tier 2. -tier2 = +# (Almost) no langtools tests are tier 2. +tier2 = \ + jdk/jshell/ToolReloadTest.java # No langtools tests are tier 3 either. tier3 = diff --git a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java index 617677363b9..9d1f63cd927 100644 --- a/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java +++ b/langtools/test/com/sun/javadoc/testHtmlVersion/TestHtmlVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8072945 8081854 8141492 + * @bug 8072945 8081854 8141492 8148985 * @summary Test the version of HTML generated by the javadoc tool. * @author bpatel * @library ../lib @@ -688,7 +688,7 @@ public class TestHtmlVersion extends JavadocTester { checkOutput("index.html", true, "", "", - "\n" + "\n" + "
    \n" + "
    \n" + "
    \n" @@ -1599,7 +1599,7 @@ public class TestHtmlVersion extends JavadocTester { checkOutput("index.html", true, "", "", - "\n" + "\n" + "
    \n" + "
    \n" + "
    \n" diff --git a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java index 866e238fbef..652ef6690fe 100644 --- a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java +++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -100,8 +100,15 @@ public class TestJavascript extends JavadocTester { + " }\n" + " return true;\n" + " }\n" + + " function loadFrames() {\n" + + " if (targetPage != \"\" && targetPage != \"undefined\")\n" + + " top.classFrame.location = top.targetPage;\n" + + " }\n" + ""); + checkOutput("index.html", true, + "", "", - "\n" + "\n" + "
    \n" + "
    \n" + "
    \n" @@ -1391,7 +1391,7 @@ public class TestHtmlVersion extends JavadocTester { checkOutput("index.html", true, "", "", - "\n" + "\n" + "
    \n" + "
    \n" + "
    \n" diff --git a/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java index 2abe9f05a29..3b16b9085d3 100644 --- a/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java +++ b/langtools/test/jdk/javadoc/doclet/testIncluded/TestIncluded.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8149468 + * @bug 8149842 * @summary Verify that non included classes are not inspected. * @library ../lib * @modules jdk.javadoc/jdk.javadoc.internal.tool diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java index ca03dcff89f..9e17061778c 100644 --- a/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java +++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/TestJavaFX.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 7112427 8012295 8025633 8026567 8061305 8081854 + * @bug 7112427 8012295 8025633 8026567 8061305 8081854 8150130 * @summary Test of the JavaFX doclet features. * @author jvalenta * @library ../lib @@ -137,6 +137,7 @@ public class TestJavaFX extends JavadocTester { + "\n" + ""); } + /* * Test without -javafx option, to ensure property getters and setters * are treated just like any other java method. @@ -181,4 +182,22 @@ public class TestJavaFX extends JavadocTester { + "() " ); } + + /* + * Force the doclet to emit a warning when processing a synthesized, + * DocComment, and ensure that the run succeeds. + */ + @Test + void test4() { + javadoc("-d", "out4", + "-javafx", + "-Xdoclint:none", + "-sourcepath", testSrc, + "-package", + "pkg4"); + checkExit(Exit.OK); + + // make sure the doclet indeed emits the warning + checkOutput(Output.OUT, true, "C.java:0: warning - invalid usage of tag >"); + } } diff --git a/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java b/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java new file mode 100644 index 00000000000..43f4a961876 --- /dev/null +++ b/langtools/test/jdk/javadoc/doclet/testJavaFX/pkg4/C.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg4; + +public class C { + + /** + * Defines the number of cycles in this animation. The {@code cycleCount} + * may be {@code INDEFINITE} for animations that repeat indefinitely. + * Now we add a > to deliberately cause an Html error. + * @defaultValue 11 + * @since JavaFX 8.0 + */ + public DoubleProperty rate; + + public final void setRate(double value) {} + + public final double getRate() {return 2.0d;} + + public final DoubleProperty rateProperty() {return new DoubleProperty();} + + class DoubleProperty {} + +} diff --git a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java index 866e238fbef..21eb3ab69b9 100644 --- a/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java +++ b/langtools/test/jdk/javadoc/doclet/testJavascript/TestJavascript.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 + * @bug 4665566 4855876 7025314 8012375 8015997 8016328 8024756 8148985 * @summary Verify that the output has the right javascript. * @author jamieh * @library ../lib @@ -100,8 +100,15 @@ public class TestJavascript extends JavadocTester { + " }\n" + " return true;\n" + " }\n" + + " function loadFrames() {\n" + + " if (targetPage != \"\" && targetPage != \"undefined\")\n" + + " top.classFrame.location = top.targetPage;\n" + + " }\n" + ""); + checkOutput("index.html", true, + "This is the description of package pkg.
    "); checkOutput("pkg/C.html", true, - "
    pkg
    "); + "
    " + + "Package pkg
    "); checkOutput("pkg/package-summary.html", false, "

    \n" + diff --git a/langtools/test/jdk/jshell/ClassesTest.java b/langtools/test/jdk/jshell/ClassesTest.java index 394d88b3c0e..058714fe438 100644 --- a/langtools/test/jdk/jshell/ClassesTest.java +++ b/langtools/test/jdk/jshell/ClassesTest.java @@ -43,12 +43,13 @@ import org.testng.annotations.Test; import jdk.jshell.Diag; import static jdk.jshell.Snippet.Status.VALID; import static jdk.jshell.Snippet.Status.RECOVERABLE_NOT_DEFINED; +import static jdk.jshell.Snippet.Status.RECOVERABLE_DEFINED; import static jdk.jshell.Snippet.Status.DROPPED; import static jdk.jshell.Snippet.Status.REJECTED; +import static jdk.jshell.Snippet.Status.OVERWRITTEN; import static jdk.jshell.Snippet.SubKind.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; -import static jdk.jshell.Snippet.Status.OVERWRITTEN; @Test public class ClassesTest extends KullaTesting { @@ -82,10 +83,10 @@ public class ClassesTest extends KullaTesting { TypeDeclSnippet c1 = (TypeDeclSnippet) assertDeclareFail("class A { void f() { return g(); } }", "compiler.err.prob.found.req"); assertTypeDeclSnippet(c1, "A", REJECTED, CLASS_SUBKIND, 0, 2); TypeDeclSnippet c2 = classKey(assertEval("class A { int f() { return g(); } }", - ste(c1, REJECTED, RECOVERABLE_NOT_DEFINED, false, null))); - assertTypeDeclSnippet(c2, "A", RECOVERABLE_NOT_DEFINED, CLASS_SUBKIND, 1, 0); + ste(c1, REJECTED, RECOVERABLE_DEFINED, true, null))); + assertTypeDeclSnippet(c2, "A", RECOVERABLE_DEFINED, CLASS_SUBKIND, 1, 0); assertDrop(c2, - ste(c2, RECOVERABLE_NOT_DEFINED, DROPPED, false, null)); + ste(c2, RECOVERABLE_DEFINED, DROPPED, true, null)); } public void classDeclaration() { diff --git a/langtools/test/jdk/jshell/CommandCompletionTest.java b/langtools/test/jdk/jshell/CommandCompletionTest.java index 1ca831f0c13..07f7fc3e397 100644 --- a/langtools/test/jdk/jshell/CommandCompletionTest.java +++ b/langtools/test/jdk/jshell/CommandCompletionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,13 +50,9 @@ import org.testng.annotations.Test; public class CommandCompletionTest extends ReplToolTesting { public void testCommand() { - assertCompletion("/f|", false, "/feedback "); assertCompletion("/deb|", false); - assertCompletion("/feedback v|", false, "verbose"); assertCompletion("/c|", false, "/classes ", "/classpath "); assertCompletion("/h|", false, "/help ", "/history "); - assertCompletion("/feedback |", false, - "?", "concise", "default", "normal", "off", "verbose"); } public void testList() { @@ -108,7 +104,7 @@ public class CommandCompletionTest extends ReplToolTesting { public void testSave() throws IOException { Compiler compiler = new Compiler(); - assertCompletion("/s|", false, "/save ", "/seteditor ", "/setstart "); + assertCompletion("/s|", false, "/save ", "/set "); List p1 = listFiles(Paths.get("")); Collections.addAll(p1, "all ", "history ", "start "); FileSystems.getDefault().getRootDirectories().forEach(s -> p1.add(s.toString())); diff --git a/langtools/test/jdk/jshell/CompletenessTest.java b/langtools/test/jdk/jshell/CompletenessTest.java index 893baeee6ed..bbf10d2b28b 100644 --- a/langtools/test/jdk/jshell/CompletenessTest.java +++ b/langtools/test/jdk/jshell/CompletenessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 8149524 * @summary Test SourceCodeAnalysis * @build KullaTesting TestingInputStream * @run testng CompletenessTest @@ -60,6 +61,7 @@ public class CompletenessTest extends KullaTesting { "try { } finally { }", "try (java.util.zip.ZipFile zf = new java.util.zip.ZipFile(zipFileName)) { }", "foo: while (true) { printf(\"Innn\"); break foo; }", + "class Case, E2 extends Enum, E3 extends Enum> {}", ";", }; diff --git a/langtools/test/jdk/jshell/ComputeFQNsTest.java b/langtools/test/jdk/jshell/ComputeFQNsTest.java new file mode 100644 index 00000000000..0f87fc7b950 --- /dev/null +++ b/langtools/test/jdk/jshell/ComputeFQNsTest.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8131027 + * @summary Test Get FQNs + * @library /tools/lib + * @build KullaTesting TestingInputStream ToolBox Compiler + * @run testng ComputeFQNsTest + */ + +import java.io.Writer; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + +import jdk.jshell.SourceCodeAnalysis.QualifiedNames; +import static org.testng.Assert.*; +import org.testng.annotations.Test; + +@Test +public class ComputeFQNsTest extends KullaTesting { + + private final Compiler compiler = new Compiler(); + private final Path outDir = Paths.get("ComputeFQNsTest"); + + public void testAddImport() throws Exception { + compiler.compile(outDir, "package test1; public class TestClass { }", "package test2; public class TestClass { }"); + String jarName = "test.jar"; + compiler.jar(outDir, jarName, "test1/TestClass.class", "test2/TestClass.class"); + addToClasspath(compiler.getPath(outDir).resolve(jarName)); + + assertInferredFQNs("LinkedList", "java.util.LinkedList"); + assertInferredFQNs("ArrayList", "java.util.ArrayList"); + assertInferredFQNs("TestClass", "test1.TestClass", "test2.TestClass"); + assertInferredFQNs("CharSequence", "CharSequence".length(), true, "java.lang.CharSequence"); + assertInferredFQNs("unresolvable"); + assertInferredFQNs("void test(ArrayList", "ArrayList".length(), false, "java.util.ArrayList"); + assertInferredFQNs("void test(ArrayList l) throws InvocationTargetException", "InvocationTargetException".length(), false, "java.lang.reflect.InvocationTargetException"); + assertInferredFQNs("void test(ArrayList l) { ArrayList", "ArrayList".length(), false, "java.util.ArrayList"); + assertInferredFQNs(" assertCommandCheckOutput(a, "/seteditor " + executionScript, + t[0] = a -> assertCommandCheckOutput(a, "/set editor " + executionScript, assertStartsWith("| Editor set to: " + executionScript)); System.arraycopy(tests, 0, t, 1, tests.length); super.testEditor(defaultStartup, args, t); @@ -193,8 +193,8 @@ public class ExternalEditorTest extends EditorTestBase { @Test public void setUnknownEditor() { test( - a -> assertCommand(a, "/seteditor", "| /seteditor requires a path argument\n"), - a -> assertCommand(a, "/seteditor UNKNOWN", "| Editor set to: UNKNOWN\n"), + a -> assertCommand(a, "/set editor", "| /set editor requires a path argument\n"), + a -> assertCommand(a, "/set editor UNKNOWN", "| Editor set to: UNKNOWN\n"), a -> assertCommand(a, "int a;", null), a -> assertCommand(a, "/e 1", "| Edit Error: process IO failure: Cannot run program \"UNKNOWN\": error=2, No such file or directory\n") @@ -204,7 +204,7 @@ public class ExternalEditorTest extends EditorTestBase { @Test(enabled = false) public void testRemoveTempFile() { test(new String[]{"-nostartup"}, - a -> assertCommandCheckOutput(a, "/seteditor " + executionScript, + a -> assertCommandCheckOutput(a, "/set editor " + executionScript, assertStartsWith("| Editor set to: " + executionScript)), a -> assertVariable(a, "int", "a", "0", "0"), a -> assertEditOutput(a, "/e 1", assertStartsWith("| Edit Error: Failure read edit file:"), () -> { diff --git a/langtools/test/jdk/jshell/InferTypeTest.java b/langtools/test/jdk/jshell/InferTypeTest.java new file mode 100644 index 00000000000..ce1f729be27 --- /dev/null +++ b/langtools/test/jdk/jshell/InferTypeTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8131027 + * @summary Test Type Inference + * @library /tools/lib + * @build KullaTesting TestingInputStream ToolBox Compiler + * @run testng InferTypeTest + */ + +import org.testng.annotations.Test; + +@Test +public class InferTypeTest extends KullaTesting { + + public void testTypeInference() { + assertInferredType("1", "int"); + assertEval("import java.util.*;"); + assertInferredType("new ArrayList()", "ArrayList"); + assertInferredType("null", "Object"); + assertInferredType("1 + ", null); //incomplete + assertInferredType("undef", null); //unresolvable + assertEval("List l1;"); + assertEval("List l2;"); + assertEval("List l3;"); + assertInferredType("l1", "List"); + assertInferredType("l2", "List"); + assertInferredType("l3", "List"); + assertInferredType("l1.get(0)", "String"); + assertInferredType("l2.get(0)", "String"); + assertInferredType("l3.get(0)", "Object"); + assertInferredType("\"\" + 1", "String"); + assertEval("int i = 0;"); + assertInferredType("i++", "int"); + assertInferredType("++i", "int"); + assertInferredType("i == 0 ? l1.get(0) : l2.get(0)", "String"); + assertInferredType("", null); + assertInferredType("void test() { }", null); + assertInferredType("class Test { }", null); + assertInferredType("enum Test { A; }", null); + assertInferredType("interface Test { }", null); + assertInferredType("@interface Test { }", null); + assertInferredType("Object o;", null); + } + +} diff --git a/langtools/test/jdk/jshell/KullaTesting.java b/langtools/test/jdk/jshell/KullaTesting.java index c74ee862b75..0ea4a622499 100644 --- a/langtools/test/jdk/jshell/KullaTesting.java +++ b/langtools/test/jdk/jshell/KullaTesting.java @@ -24,6 +24,7 @@ import java.io.ByteArrayOutputStream; import java.io.PrintStream; import java.io.StringWriter; +import java.lang.reflect.Method; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -61,6 +62,7 @@ import jdk.jshell.SnippetEvent; import jdk.jshell.SourceCodeAnalysis; import jdk.jshell.SourceCodeAnalysis.CompletionInfo; import jdk.jshell.SourceCodeAnalysis.Completeness; +import jdk.jshell.SourceCodeAnalysis.QualifiedNames; import jdk.jshell.SourceCodeAnalysis.Suggestion; import jdk.jshell.UnresolvedReferenceException; import org.testng.annotations.AfterMethod; @@ -189,14 +191,14 @@ public class KullaTesting { return key; } - public MethodSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { + public DeclarationSnippet assertEvalUnresolvedException(String input, String name, int unresolvedSize, int diagnosticsSize) { List events = assertEval(input, null, UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); SnippetEvent ste = events.get(0); - MethodSnippet methodKey = ((UnresolvedReferenceException) ste.exception()).getMethodSnippet(); - assertEquals(methodKey.name(), name, "Given input: " + input + ", checking name"); - assertEquals(getState().unresolvedDependencies(methodKey).size(), unresolvedSize, "Given input: " + input + ", checking unresolved"); - assertEquals(getState().diagnostics(methodKey).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics"); - return methodKey; + DeclarationSnippet sn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); + assertEquals(sn.name(), name, "Given input: " + input + ", checking name"); + assertEquals(getState().unresolvedDependencies(sn).size(), unresolvedSize, "Given input: " + input + ", checking unresolved"); + assertEquals(getState().diagnostics(sn).size(), diagnosticsSize, "Given input: " + input + ", checking diagnostics"); + return sn; } public Snippet assertKeyMatch(String input, boolean isExecutable, SubKind expectedSubKind, STEInfo mainInfo, STEInfo... updates) { @@ -862,6 +864,8 @@ public class KullaTesting { } private List computeCompletions(String code, Boolean isSmart) { + waitIndexingFinished(); + int cursor = code.indexOf('|'); code = code.replace("|", ""); assertTrue(cursor > -1, "'|' expected, but not found in: " + code); @@ -874,6 +878,37 @@ public class KullaTesting { .collect(Collectors.toList()); } + public void assertInferredType(String code, String expectedType) { + String inferredType = getAnalysis().analyzeType(code, code.length()); + + assertEquals(inferredType, expectedType, "Input: " + code + ", " + inferredType); + } + + public void assertInferredFQNs(String code, String... fqns) { + assertInferredFQNs(code, code.length(), false, fqns); + } + + public void assertInferredFQNs(String code, int simpleNameLen, boolean resolvable, String... fqns) { + waitIndexingFinished(); + + QualifiedNames candidates = getAnalysis().listQualifiedNames(code, code.length()); + + assertEquals(candidates.getNames(), Arrays.asList(fqns), "Input: " + code + ", candidates=" + candidates.getNames()); + assertEquals(candidates.getSimpleNameLength(), simpleNameLen, "Input: " + code + ", simpleNameLen=" + candidates.getSimpleNameLength()); + assertEquals(candidates.isResolvable(), resolvable, "Input: " + code + ", resolvable=" + candidates.isResolvable()); + } + + protected void waitIndexingFinished() { + try { + Method waitBackgroundTaskFinished = getAnalysis().getClass().getDeclaredMethod("waitBackgroundTaskFinished"); + + waitBackgroundTaskFinished.setAccessible(true); + waitBackgroundTaskFinished.invoke(getAnalysis()); + } catch (Exception ex) { + throw new AssertionError("Cannot wait for indexing end.", ex); + } + } + public void assertDocumentation(String code, String... expected) { int cursor = code.indexOf('|'); code = code.replace("|", ""); diff --git a/langtools/test/jdk/jshell/ReplToolTesting.java b/langtools/test/jdk/jshell/ReplToolTesting.java index 05dd5389e0b..d4f697d3613 100644 --- a/langtools/test/jdk/jshell/ReplToolTesting.java +++ b/langtools/test/jdk/jshell/ReplToolTesting.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -397,6 +397,15 @@ public class ReplToolTesting { assertCommand(after, cmd, out, "", null, "", ""); } + public void assertCommandOutputContains(boolean after, String cmd, String has) { + assertCommandCheckOutput(after, cmd, (s) -> + assertTrue(s.contains(has), "Output: \'" + s + "' does not contain: " + has)); + } + + public void assertCommandOutputStartsWith(boolean after, String cmd, String starts) { + assertCommandCheckOutput(after, cmd, assertStartsWith(starts)); + } + public void assertCommandCheckOutput(boolean after, String cmd, Consumer check) { if (!after) { assertCommand(false, cmd, null); @@ -437,13 +446,13 @@ public class ReplToolTesting { } private List computeCompletions(String code, boolean isSmart) { - JShellTool repl = this.repl != null ? this.repl + JShellTool js = this.repl != null ? this.repl : new JShellTool(null, null, null, null, null, null, null); int cursor = code.indexOf('|'); code = code.replace("|", ""); assertTrue(cursor > -1, "'|' not found: " + code); List completions = - repl.commandCompletionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now + js.commandCompletionSuggestions(code, cursor, new int[1]); //XXX: ignoring anchor for now return completions.stream() .filter(s -> isSmart == s.isSmart) .map(s -> s.continuation) @@ -481,6 +490,15 @@ public class ReplToolTesting { return name.hashCode(); } + @Override + public boolean equals(Object o) { + if (o instanceof MemberInfo) { + MemberInfo mi = (MemberInfo) o; + return name.equals(mi.name); + } + return false; + } + public abstract Consumer checkOutput(); public String getSource() { @@ -536,6 +554,11 @@ public class ReplToolTesting { "Output: " + output + " does not fit pattern: " + finalPattern); } + @Override + public int hashCode() { + return name.hashCode(); + } + @Override public boolean equals(Object o) { if (o instanceof VariableInfo) { @@ -585,6 +608,10 @@ public class ReplToolTesting { return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s); } + @Override + public int hashCode() { + return (name.hashCode() << 2) ^ type.hashCode() ; + } @Override public boolean equals(Object o) { @@ -615,6 +642,11 @@ public class ReplToolTesting { return s -> assertTrue(checkOutput.test(s), "Expected: '" + expectedOutput + "', actual: " + s); } + @Override + public int hashCode() { + return name.hashCode() ; + } + @Override public boolean equals(Object o) { if (o instanceof ClassInfo) { @@ -640,6 +672,11 @@ public class ReplToolTesting { return s -> assertTrue("".equals(s), "Expected: '', actual: " + s); } + @Override + public int hashCode() { + return (name.hashCode() << 2) ^ type.hashCode() ; + } + @Override public boolean equals(Object o) { if (o instanceof ImportInfo) { diff --git a/langtools/test/jdk/jshell/ReplaceTest.java b/langtools/test/jdk/jshell/ReplaceTest.java index a26545da577..36b1c505cd4 100644 --- a/langtools/test/jdk/jshell/ReplaceTest.java +++ b/langtools/test/jdk/jshell/ReplaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,7 +22,7 @@ */ /* - * @test + * @test 8080069 * @summary Test of Snippet redefinition and replacement. * @build KullaTesting TestingInputStream * @run testng ReplaceTest @@ -30,6 +30,7 @@ import java.util.Collection; +import java.util.List; import jdk.jshell.Snippet; import jdk.jshell.MethodSnippet; import jdk.jshell.PersistentSnippet; @@ -38,9 +39,11 @@ import jdk.jshell.VarSnippet; import jdk.jshell.DeclarationSnippet; import org.testng.annotations.Test; +import jdk.jshell.SnippetEvent; +import jdk.jshell.UnresolvedReferenceException; +import static org.testng.Assert.assertEquals; import static jdk.jshell.Snippet.Status.*; import static jdk.jshell.Snippet.SubKind.*; -import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertTrue; @Test @@ -259,7 +262,7 @@ public class ReplaceTest extends KullaTesting { ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), ste(f, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); - MethodSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1); + DeclarationSnippet exsn = assertEvalUnresolvedException("t();", "f", 0, 1); assertTrue(exsn == f, "Identity must not change"); assertActiveKeys(); } @@ -289,13 +292,95 @@ public class ReplaceTest extends KullaTesting { } public void testForwardVarToClass() { - DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_NOT_DEFINED))); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable g"); + DeclarationSnippet a = classKey(assertEval("class A { int f() { return g; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g"); Snippet g = varKey(assertEval("int g = 10;", "10", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + ste(a, RECOVERABLE_DEFINED, VALID, false, null))); assertEval("new A().f();", "10"); assertEval("double g = 10;", "10.0", null, + DiagCheck.DIAG_OK, + DiagCheck.DIAG_ERROR, + ste(MAIN_SNIPPET, VALID, VALID, true, null), + ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); + assertUnresolvedDependencies(a, 0); + assertActiveKeys(); + } + + public void testForwardVarToClassGeneric() { + DeclarationSnippet a = classKey(assertEval("class A { final T x; A(T v) { this.x = v; } ; T get() { return x; } int core() { return g; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "variable g"); + + List events = assertEval("A as = new A<>(\"hi\");", null, + UnresolvedReferenceException.class, DiagCheck.DIAG_OK, DiagCheck.DIAG_OK, null); + SnippetEvent ste = events.get(0); + Snippet assn = ste.snippet(); + DeclarationSnippet unsn = ((UnresolvedReferenceException) ste.exception()).getSnippet(); + assertEquals(unsn.name(), "A", "Wrong with unresolved"); + assertEquals(getState().unresolvedDependencies(unsn).size(), 1, "Wrong size unresolved"); + assertEquals(getState().diagnostics(unsn).size(), 0, "Expected no diagnostics"); + + Snippet g = varKey(assertEval("int g = 10;", "10", + added(VALID), + ste(a, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); + assertEval("A as = new A<>(\"low\");", + ste(MAIN_SNIPPET, VALID, VALID, false, null), + ste(assn, VALID, OVERWRITTEN, false, MAIN_SNIPPET)); + assertEval("as.get();", "\"low\""); + assertUnresolvedDependencies(a, 0); + assertActiveKeys(); + } + + public void testForwardVarToClassExtendsImplements() { + DeclarationSnippet ik = classKey(assertEval("interface I { default int ii() { return 1; } }", added(VALID))); + DeclarationSnippet jk = classKey(assertEval("interface J { default int jj() { return 2; } }", added(VALID))); + DeclarationSnippet ck = classKey(assertEval("class C { int cc() { return 3; } }", added(VALID))); + DeclarationSnippet dk = classKey(assertEval("class D extends C implements I,J { int dd() { return g; } }", added(RECOVERABLE_DEFINED))); + DeclarationSnippet ek = classKey(assertEval("class E extends D { int ee() { return 5; } }", added(VALID))); + assertUnresolvedDependencies1(dk, RECOVERABLE_DEFINED, "variable g"); + assertEvalUnresolvedException("new D();", "D", 1, 0); + assertEvalUnresolvedException("new E();", "D", 1, 0); + VarSnippet g = varKey(assertEval("int g = 10;", "10", + added(VALID), + ste(dk, RECOVERABLE_DEFINED, VALID, false, MAIN_SNIPPET))); + assertEval("E e = new E();"); + assertDrop(g, + ste(g, VALID, DROPPED, true, null), + ste(dk, VALID, RECOVERABLE_DEFINED, false, g)); + assertEvalUnresolvedException("new D();", "D", 1, 0); + assertEvalUnresolvedException("new E();", "D", 1, 0); + assertEval("e.ee();", "5"); + assertEvalUnresolvedException("e.dd();", "D", 1, 0); + assertEval("e.cc();", "3"); + assertEval("e.jj();", "2"); + assertEval("e.ii();", "1"); + assertActiveKeys(); + } + + public void testForwardVarToInterface() { + DeclarationSnippet i = classKey(assertEval("interface I { default int f() { return x; } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(i, RECOVERABLE_DEFINED, "variable x"); + DeclarationSnippet c = classKey(assertEval("class C implements I { int z() { return 2; } }", added(VALID))); + assertEval("C c = new C();"); + assertEval("c.z();", "2"); + assertEvalUnresolvedException("c.f()", "I", 1, 0); + Snippet g = varKey(assertEval("int x = 55;", "55", + added(VALID), + ste(i, RECOVERABLE_DEFINED, VALID, false, null))); + assertEval("c.f();", "55"); + assertUnresolvedDependencies(i, 0); + assertActiveKeys(); + } + + public void testForwardVarToEnum() { + DeclarationSnippet a = classKey(assertEval("enum E { Q, W, E; float ff() { return fff; } }", added(RECOVERABLE_NOT_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "variable fff"); + Snippet g = varKey(assertEval("float fff = 4.5f;", "4.5", + added(VALID), + ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + assertEval("E.Q.ff();", "4.5"); + assertEval("double fff = 3.3;", "3.3", null, DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), @@ -305,20 +390,21 @@ public class ReplaceTest extends KullaTesting { assertActiveKeys(); } - public void testForwardMethodToClass() { - DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_NOT_DEFINED))); - assertUnresolvedDependencies1(a, RECOVERABLE_NOT_DEFINED, "method g()"); + DeclarationSnippet a = classKey(assertEval("class A { int f() { return g(); } }", added(RECOVERABLE_DEFINED))); + assertUnresolvedDependencies1(a, RECOVERABLE_DEFINED, "method g()"); + assertEval("A foo() { return null; }"); + assertEvalUnresolvedException("new A();", "A", 1, 0); Snippet g = methodKey(assertEval("int g() { return 10; }", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null))); + ste(a, RECOVERABLE_DEFINED, VALID, false, null))); assertEval("new A().f();", "10"); assertEval("double g() { return 10; }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(g, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET)); assertUnresolvedDependencies(a, 0); assertActiveKeys(); } @@ -336,8 +422,8 @@ public class ReplaceTest extends KullaTesting { DiagCheck.DIAG_ERROR, ste(MAIN_SNIPPET, VALID, VALID, true, null), ste(b, VALID, OVERWRITTEN, false, MAIN_SNIPPET), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET)); - assertDeclareFail("new A().b;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, MAIN_SNIPPET)); + assertEvalUnresolvedException("new A().b;", "A", 0, 1); assertActiveKeys(); } @@ -503,42 +589,42 @@ public class ReplaceTest extends KullaTesting { public void testForwardSingleImportMethodToClass1() { PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.format;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s;", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, MAIN_SNIPPET))); - assertDeclareFail("new A().s;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, MAIN_SNIPPET))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardSingleImportMethodToClass2() { PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.format;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s();", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardSingleImportClassToClass1() { @@ -589,42 +675,44 @@ public class ReplaceTest extends KullaTesting { public void testForwardImportOnDemandMethodToClass1() { PersistentSnippet a = classKey(assertEval("class A { String s = format(\"%d\", 10); }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); - assertEval("new A().s;", "\"10\""); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); + assertEval("A x = new A();"); + assertEval("x.s;", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s;", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); + assertEval("x.s;", "\"10\""); } public void testForwardImportOnDemandMethodToClass2() { PersistentSnippet a = classKey(assertEval("class A { String s() { return format(\"%d\", 10); } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.String.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("new A().s();", "\"10\""); PersistentSnippet format = methodKey(assertEval("void format(String s, int d) { }", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A().s();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(format, ste(format, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, format)); + ste(a, RECOVERABLE_DEFINED, VALID, false, format)); } public void testForwardImportOnDemandClassToClass1() { @@ -673,86 +761,87 @@ public class ReplaceTest extends KullaTesting { public void testForwardSingleImportFieldToClass1() { PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.PI;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, false, list)); } public void testForwardSingleImportFieldToClass2() { PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.PI;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, true, null)); assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, true, list)); } public void testForwardImportOnDemandFieldToClass1() { PersistentSnippet a = classKey(assertEval("class A { static double pi() { return PI; } }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, false, null)); assertEval("Math.abs(A.pi() - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, false, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, false, list)); } public void testForwardImportOnDemandFieldToClass2() { PersistentSnippet a = classKey(assertEval("class A { static double pi = PI; }", - added(RECOVERABLE_NOT_DEFINED))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + added(RECOVERABLE_DEFINED))); + assertEvalUnresolvedException("new A();", "A", 1, 0); assertEval("import static java.lang.Math.*;", added(VALID), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, null)); + ste(a, RECOVERABLE_DEFINED, VALID, true, null)); assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); PersistentSnippet list = varKey(assertEval("String PI;", DiagCheck.DIAG_OK, DiagCheck.DIAG_ERROR, added(VALID), - ste(a, VALID, RECOVERABLE_NOT_DEFINED, true, null))); - assertDeclareFail("new A();", "compiler.err.cant.resolve.location"); + ste(a, VALID, RECOVERABLE_DEFINED, true, null))); + assertEvalUnresolvedException("new A();", "A", 0, 1); assertActiveKeys(); assertDrop(list, ste(list, VALID, DROPPED, true, null), - ste(a, RECOVERABLE_NOT_DEFINED, VALID, true, list)); + ste(a, RECOVERABLE_DEFINED, VALID, true, list)); + assertEval("Math.abs(A.pi - 3.1415) < 0.001;", "true"); } public void testReplaceCausesMethodReferenceError() { diff --git a/langtools/test/jdk/jshell/ToolBasicTest.java b/langtools/test/jdk/jshell/ToolBasicTest.java index f4501c84d32..e38ff644e77 100644 --- a/langtools/test/jdk/jshell/ToolBasicTest.java +++ b/langtools/test/jdk/jshell/ToolBasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 + * @bug 8143037 8142447 8144095 8140265 8144906 8146138 8147887 8147886 8148316 8148317 * @requires os.family != "solaris" * @summary Tests for Basic tests for REPL tool * @library /tools/lib @@ -90,8 +90,7 @@ public class ToolBasicTest extends ReplToolTesting { public void elideStartUpFromList() { test( - (a) -> assertCommandCheckOutput(a, "123", (s) -> - assertTrue(s.contains("type int"), s)), + (a) -> assertCommandOutputContains(a, "123", "type int"), (a) -> assertCommandCheckOutput(a, "/list", (s) -> { int cnt; try (Scanner scanner = new Scanner(s)) { @@ -112,8 +111,7 @@ public class ToolBasicTest extends ReplToolTesting { Compiler compiler = new Compiler(); Path path = compiler.getPath("myfile"); test( - (a) -> assertCommandCheckOutput(a, "123", - (s) -> assertTrue(s.contains("type int"), s)), + (a) -> assertCommandOutputContains(a, "123", "type int"), (a) -> assertCommand(a, "/save " + path.toString(), "") ); try (Stream lines = Files.lines(path)) { @@ -594,12 +592,12 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertMethod(a, "void f() {}", "()V", "f"), (a) -> assertImport(a, "import java.util.stream.*;", "", "java.util.stream.*"), (a) -> assertCommand(a, "/save " + startUpFile.toString(), null), - (a) -> assertCommand(a, "/setstart " + startUpFile.toString(), null) + (a) -> assertCommand(a, "/set start " + startUpFile.toString(), null) ); Path unknown = compiler.getPath("UNKNOWN"); test( - (a) -> assertCommand(a, "/setstart " + unknown.toString(), - "| File '" + unknown + "' for /setstart is not found.\n") + (a) -> assertCommand(a, "/set start " + unknown.toString(), + "| File '" + unknown + "' for /set start is not found.\n") ); test(false, new String[0], (a) -> { @@ -619,7 +617,7 @@ public class ToolBasicTest extends ReplToolTesting { } private void removeStartup() { - Preferences preferences = Preferences.userRoot().node("tool/REPL"); + Preferences preferences = Preferences.userRoot().node("tool/JShell"); if (preferences != null) { preferences.remove("STARTUP"); } @@ -636,7 +634,7 @@ public class ToolBasicTest extends ReplToolTesting { } public void testNoArgument() { - String[] commands = {"/save", "/open", "/setstart"}; + String[] commands = {"/save", "/open", "/set start"}; test(Stream.of(commands) .map(cmd -> { String c = cmd; @@ -670,8 +668,7 @@ public class ToolBasicTest extends ReplToolTesting { test( a -> assertVariable(a, "int", "x"), a -> assertCommandCheckOutput(a, "/vars", assertVariables()), - a -> assertCommandCheckOutput(a, "System.exit(5);", s -> - assertTrue(s.contains("terminated"), s)), + a -> assertCommandOutputContains(a, "System.exit(5);", "terminated"), a -> assertCommandCheckOutput(a, "/vars", s -> assertTrue(s.trim().isEmpty(), s)), a -> assertMethod(a, "void f() { }", "()void", "f"), @@ -699,8 +696,7 @@ public class ToolBasicTest extends ReplToolTesting { s -> assertEquals(s, "| No definition or id named " + arg + " found. There are no active definitions.\n")), a -> assertVariable(a, "int", "aardvark"), - a -> assertCommandCheckOutput(a, "/list aardvark", - s -> assertTrue(s.contains("aardvark"))), + a -> assertCommandOutputContains(a, "/list aardvark", "aardvark"), a -> assertCommandCheckOutput(a, "/list start", s -> checkLineToList(s, START_UP)), a -> assertCommandCheckOutput(a, "/list all", @@ -714,14 +710,14 @@ public class ToolBasicTest extends ReplToolTesting { } public void testFeedbackNegative() { - test(a -> assertCommandCheckOutput(a, "/feedback aaaa", - assertStartsWith("| Follow /feedback with of the following"))); + test(a -> assertCommandCheckOutput(a, "/set feedback aaaa", + assertStartsWith("| Does not match any current feedback mode"))); } public void testFeedbackOff() { for (String off : new String[]{"o", "off"}) { test( - a -> assertCommand(a, "/feedback " + off, ""), + a -> assertCommand(a, "/set feedback " + off, ""), a -> assertCommand(a, "int a", ""), a -> assertCommand(a, "void f() {}", ""), a -> assertCommandCheckOutput(a, "aaaa", assertStartsWith("| Error:")), @@ -730,23 +726,6 @@ public class ToolBasicTest extends ReplToolTesting { } } - public void testFeedbackConcise() { - Compiler compiler = new Compiler(); - Path testConciseFile = compiler.getPath("testConciseFeedback"); - String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; - compiler.writeToFile(testConciseFile, sources); - for (String concise : new String[]{"c", "concise"}) { - test( - a -> assertCommand(a, "/feedback " + concise, ""), - a -> assertCommand(a, sources[0], ""), - a -> assertCommand(a, sources[1], ""), - a -> assertCommand(a, sources[2], ""), - a -> assertCommand(a, sources[3], "| a : 10\n"), - a -> assertCommand(a, "/o " + testConciseFile.toString(), "| a : 10\n") - ); - } - } - public void testFeedbackNormal() { Compiler compiler = new Compiler(); Path testNormalFile = compiler.getPath("testConciseNormal"); @@ -759,58 +738,20 @@ public class ToolBasicTest extends ReplToolTesting { "| Variable a has been assigned the value 10\n" }; compiler.writeToFile(testNormalFile, sources2); - for (String feedback : new String[]{"/f", "/feedback"}) { - for (String feedbackState : new String[]{"n", "normal", "v", "verbose"}) { - String f = null; - if (feedbackState.startsWith("n")) { - f = "normal"; - } else if (feedbackState.startsWith("v")) { - f = "verbose"; - } - final String finalF = f; + for (String feedback : new String[]{"/set f", "/set feedback"}) { + for (String feedbackState : new String[]{"n", "normal", "o", "off"}) { test( - a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: " + finalF +"\n"), + a -> assertCommand(a, feedback + " " + feedbackState, "| Feedback mode: normal\n"), a -> assertCommand(a, sources[0], output[0]), a -> assertCommand(a, sources[1], output[1]), a -> assertCommand(a, sources[2], output[2]), a -> assertCommand(a, sources[3], output[3]), - a -> assertCommand(a, "/o " + testNormalFile.toString(), - "| Modified variable a of type int\n" + - "| Modified method f()\n" + - "| Update overwrote method f()\n" + - "| Modified class A\n" + - "| Update overwrote class A\n" + - "| Variable a has been assigned the value 10\n") + a -> assertCommand(a, "/o " + testNormalFile.toString(), "") ); } } } - public void testFeedbackDefault() { - Compiler compiler = new Compiler(); - Path testDefaultFile = compiler.getPath("testDefaultFeedback"); - String[] sources = new String[] {"int a", "void f() {}", "class A {}", "a = 10"}; - String[] output = new String[] { - "| Added variable a of type int\n", - "| Added method f()\n", - "| Added class A\n", - "| Variable a has been assigned the value 10\n" - }; - compiler.writeToFile(testDefaultFile, sources); - for (String defaultFeedback : new String[]{"", "d", "default"}) { - test( - a -> assertCommand(a, "/feedback o", ""), - a -> assertCommand(a, "int x", ""), - a -> assertCommand(a, "/feedback " + defaultFeedback, "| Feedback mode: default\n"), - a -> assertCommand(a, sources[0], output[0]), - a -> assertCommand(a, sources[1], output[1]), - a -> assertCommand(a, sources[2], output[2]), - a -> assertCommand(a, sources[3], output[3]), - a -> assertCommand(a, "/o " + testDefaultFile.toString(), "") - ); - } - } - public void testDrop() { test(false, new String[]{"-nostartup"}, a -> assertVariable(a, "int", "a"), @@ -906,7 +847,7 @@ public class ToolBasicTest extends ReplToolTesting { public void testCommandPrefix() { test(a -> assertCommandCheckOutput(a, "/s", - assertStartsWith("| Command: /s is ambiguous: /seteditor, /save, /setstart")), + assertStartsWith("| Command: /s is ambiguous: /save, /set")), a -> assertCommand(a, "int var", "| Added variable var of type int\n"), a -> assertCommandCheckOutput(a, "/va", assertStartsWith("| int var = 0")), diff --git a/langtools/test/jdk/jshell/ToolFormatTest.java b/langtools/test/jdk/jshell/ToolFormatTest.java new file mode 100644 index 00000000000..cc3aa0273af --- /dev/null +++ b/langtools/test/jdk/jshell/ToolFormatTest.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8148316 8148317 + * @summary Tests for output customization + * @library /tools/lib + * @build KullaTesting TestingInputStream ToolBox Compiler + * @run testng ToolFormatTest + */ +import org.testng.annotations.Test; + +@Test +public class ToolFormatTest extends ReplToolTesting { + + public void testSetFormat() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode test command", "| Created new feedback mode: test"), + (a) -> assertCommand(a, "/set field test pre '$ '", ""), + (a) -> assertCommand(a, "/set field test post ''", ""), + (a) -> assertCommand(a, "/set field test action 'ADD ' added-primary", ""), + (a) -> assertCommand(a, "/set field test action 'MOD ' modified-primary", ""), + (a) -> assertCommand(a, "/set field test action 'REP ' replaced-primary", ""), + (a) -> assertCommand(a, "/set field test action 'UP-ADD ' added-update", ""), + (a) -> assertCommand(a, "/set field test action 'UP-MOD ' modified-update", ""), + (a) -> assertCommand(a, "/set field test action 'UP-REP ' replaced-update", ""), + (a) -> assertCommand(a, "/set field test resolve 'OK' ok-*", ""), + (a) -> assertCommand(a, "/set field test resolve 'DEF' defined-*", ""), + (a) -> assertCommand(a, "/set field test resolve 'NODEF' notdefined-*", ""), + (a) -> assertCommand(a, "/set field test name ':%s ' ", ""), + (a) -> assertCommand(a, "/set field test type '[%s]' ", ""), + (a) -> assertCommand(a, "/set field test result '=%s ' ", ""), + (a) -> assertCommand(a, "/set format test '{pre}{action}{type}{name}{result}{resolve}' *-*-*", ""), + (a) -> assertCommand(a, "/set format test '{pre}HI this is enum' enum", ""), + (a) -> assertCommand(a, "/set feedback test", "$ Feedback mode: test"), + (a) -> assertCommand(a, "class D {}", "$ ADD :D OK"), + (a) -> assertCommand(a, "void m() {}", "$ ADD []:m OK"), + (a) -> assertCommand(a, "interface EX extends EEX {}", "$ ADD :EX NODEF"), + (a) -> assertCommand(a, "56", "$ ADD [int]:$4 =56 OK"), + (a) -> assertCommand(a, "class D { int hh; }", "$ REP :D OK$ OVERWROTE-UPDATE:D OK"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback normal", "| Feedback mode: normal") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testNewModeQuiet() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode nmq quiet normal", "| Created new feedback mode: nmq"), + (a) -> assertCommand(a, "/set feedback nmq", ""), + (a) -> assertCommand(a, "/se ne nmq2 q nor", ""), + (a) -> assertCommand(a, "/se fee nmq2", ""), + (a) -> assertCommand(a, "/set newmode nmc command normal", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback nmc", "| Feedback mode: nmc"), + (a) -> assertCommandOutputStartsWith(a, "/set newmode nm", "| Created new feedback mode: nm"), + (a) -> assertCommandOutputStartsWith(a, "/set feedback nm", "| Feedback mode: nm") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetError() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"), + (a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback te", ""), + (a) -> assertCommandCheckOutput(a, "/set ", assertStartsWith("ERROR: The /set command requires arguments")), + (a) -> assertCommandCheckOutput(a, "/set xyz", assertStartsWith("ERROR: Not a valid argument to /set")), + (a) -> assertCommandCheckOutput(a, "/set f", assertStartsWith("ERROR: Ambiguous argument to /set")), + (a) -> assertCommandCheckOutput(a, "/set feedback", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set feedback xyz", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format xyz", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set format te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set format te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa'", assertStartsWith("ERROR: At least one selector required")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa' frog", assertStartsWith("ERROR: Not a valid case")), + (a) -> assertCommandCheckOutput(a, "/set format te 'aaa' import-frog", assertStartsWith("ERROR: Not a valid action")), + (a) -> assertCommandCheckOutput(a, "/set newmode", assertStartsWith("ERROR: Expected new feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set newmode te", assertStartsWith("ERROR: Expected a new feedback mode name")), + (a) -> assertCommandCheckOutput(a, "/set newmode x xyz", assertStartsWith("ERROR: Specify either 'command' or 'quiet'")), + (a) -> assertCommandCheckOutput(a, "/set newmode x quiet y", assertStartsWith("ERROR: Does not match any current feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set prompt te aaa xyz", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa' xyz", assertStartsWith("ERROR: Format 'xyz' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set prompt te", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set prompt te aaa", assertStartsWith("ERROR: Format 'aaa' must be quoted")), + (a) -> assertCommandCheckOutput(a, "/set prompt te 'aaa'", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set field", assertStartsWith("ERROR: Expected a feedback mode")), + (a) -> assertCommandCheckOutput(a, "/set field xyz", assertStartsWith("ERROR: Does not match any current feedback mode: xyz")), + (a) -> assertCommandCheckOutput(a, "/set field te xyz", assertStartsWith("ERROR: Not a valid field: xyz, must be one of: when")), + (a) -> assertCommandCheckOutput(a, "/set field te action", assertStartsWith("ERROR: Expected format missing")), + (a) -> assertCommandCheckOutput(a, "/set field te action 'act'", assertStartsWith("ERROR: At least one selector required")) + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetHelp() { + try { + test( + (a) -> assertCommandOutputContains(a, "/help /set", "command to launch"), + (a) -> assertCommandOutputContains(a, "/help /set format", "vardecl"), + (a) -> assertCommandOutputContains(a, "/hel /se for", "vardecl"), + (a) -> assertCommandOutputContains(a, "/help /set editor", "temporary file") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } + + public void testSetHelpError() { + try { + test( + (a) -> assertCommandOutputStartsWith(a, "/set newmode te command normal", "| Created new feedback mode: te"), + (a) -> assertCommand(a, "/set field te errorpre 'ERROR: '", ""), + (a) -> assertCommandOutputStartsWith(a, "/set feedback te", "| Feedback mode: te"), + (a) -> assertCommandOutputContains(a, "/help /set xyz", "ERROR: Not a valid argument to /set: xyz"), + (a) -> assertCommandOutputContains(a, "/help /set f", "ERROR: Ambiguous argument to /set: f") + ); + } finally { + assertCommandCheckOutput(false, "/set feedback normal", s -> { + }); + } + } +} diff --git a/langtools/test/jdk/jshell/ToolReloadTest.java b/langtools/test/jdk/jshell/ToolReloadTest.java index 44578dec261..4871fccd946 100644 --- a/langtools/test/jdk/jshell/ToolReloadTest.java +++ b/langtools/test/jdk/jshell/ToolReloadTest.java @@ -23,6 +23,7 @@ /* * @test + * @key intermittent * @bug 8081845 8147898 * @summary Tests for /reload in JShell tool * @modules jdk.compiler/com.sun.tools.javac.api diff --git a/langtools/test/tools/javac/6257443/T6257443.java b/langtools/test/tools/javac/6257443/T6257443.java index 5d81ed5d12f..91d3120908f 100644 --- a/langtools/test/tools/javac/6257443/T6257443.java +++ b/langtools/test/tools/javac/6257443/T6257443.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,13 +31,7 @@ * * @clean foo.package-info * - * @compile -XD-printflat package-info.java - * @run main/othervm T6257443 -no foo/package-info.class - * - * @compile -XD-stubs package-info.java - * @run main/othervm T6257443 -no foo/package-info.class - * - * @compile -XD-printsource package-info.java + * @compile -printsource package-info.java * @run main/othervm T6257443 -no foo/package-info.class */ diff --git a/langtools/test/tools/javac/6521805/T6521805a.java b/langtools/test/tools/javac/6521805/T6521805a.java deleted file mode 100644 index d81fab6ddc5..00000000000 --- a/langtools/test/tools/javac/6521805/T6521805a.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * @test /nodynamiccopyright/ - * @bug 6521805 - * @summary Regression: JDK5/JDK6 javac allows write access to outer class reference - * @author mcimadamore - * - * @compile/fail/ref=T6521805a_1.out T6521805a.java -XDrawDiagnostics - * @compile/ref=T6521805a_2.out T6521805a.java -XDwarnOnSyntheticConflicts -XDrawDiagnostics - */ - -class T6521805a { - - static class Outer { - T6521805a this$0 = null; - } - - public class Inner extends Outer { - public void foo() { - this$0 = new T6521805a(); - } - } -} diff --git a/langtools/test/tools/javac/6521805/T6521805a_1.out b/langtools/test/tools/javac/6521805/T6521805a_1.out deleted file mode 100644 index 3c069c0a793..00000000000 --- a/langtools/test/tools/javac/6521805/T6521805a_1.out +++ /dev/null @@ -1,2 +0,0 @@ -T6521805a.java:17:12: compiler.err.synthetic.name.conflict: this$0, T6521805a.Outer -1 error diff --git a/langtools/test/tools/javac/6521805/T6521805a_2.out b/langtools/test/tools/javac/6521805/T6521805a_2.out deleted file mode 100644 index 98d97813f36..00000000000 --- a/langtools/test/tools/javac/6521805/T6521805a_2.out +++ /dev/null @@ -1,2 +0,0 @@ -T6521805a.java:17:12: compiler.warn.synthetic.name.conflict: this$0, T6521805a.Outer -1 warning diff --git a/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java b/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java new file mode 100644 index 00000000000..4c8917bbbf9 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/TestIndyStringConcat.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.BootstrapMethods_attribute.BootstrapMethodSpecifier; +import com.sun.tools.classfile.ConstantPool.CONSTANT_InvokeDynamic_info; +import com.sun.tools.classfile.ConstantPool.CONSTANT_MethodHandle_info; + +import java.io.File; + +/* + * @test + * @bug 8148483 8151516 8151223 + * @summary Test that StringConcat is working for JDK >= 9 + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean TestIndyStringConcat* + * @compile -source 6 -target 6 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -source 7 -target 7 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -source 8 -target 8 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat false + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat true + * + * @clean TestIndyStringConcat* + * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java + * @run main TestIndyStringConcat true + */ +public class TestIndyStringConcat { + + static String other; + + public static String test() { + return "Foo" + other; + } + + public static void main(String[] args) throws Exception { + boolean expected = Boolean.valueOf(args[0]); + boolean actual = hasStringConcatFactoryCall("test"); + if (expected != actual) { + throw new AssertionError("expected = " + expected + ", actual = " + actual); + } + } + + public static boolean hasStringConcatFactoryCall(String methodName) throws Exception { + ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."), + TestIndyStringConcat.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + BootstrapMethods_attribute bsm_attr = + (BootstrapMethods_attribute)classFile + .getAttribute(Attribute.BootstrapMethods); + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals(methodName)) { + Code_attribute code = (Code_attribute) method.attributes + .get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = + (CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1)); + + BootstrapMethodSpecifier bsmSpec = + bsm_attr.bootstrap_method_specifiers[indyInfo.bootstrap_method_attr_index]; + + CONSTANT_MethodHandle_info bsmInfo = + (CONSTANT_MethodHandle_info) constantPool.get(bsmSpec.bootstrap_method_ref); + + if (bsmInfo.getCPRefInfo().getClassName().equals("java/lang/invoke/StringConcatFactory")) { + return true; + } + } + } + } + } + return false; + } + +} diff --git a/langtools/test/tools/javac/StringConcat/access/Holder.java b/langtools/test/tools/javac/StringConcat/access/Holder.java new file mode 100644 index 00000000000..6b4cb37e688 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Holder.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Holder { + public Private_PublicClass c1 = new Private_PublicClass(); + public Private_PublicInterface c2 = new Private_PublicInterface(); + public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); + public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); + + public Public_PublicClass c5 = new Public_PublicClass(); + public Public_PublicInterface c6 = new Public_PublicInterface(); + public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); + public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); + + public Private_PublicClass[] ac1 = new Private_PublicClass[0]; + public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; + public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; + public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; + + public Public_PublicClass[] ac5 = new Public_PublicClass[0]; + public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; + public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; + public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; + + public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; + public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; + public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; + public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; + + public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; + public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; + public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; + public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; + + public PublicInterface i1 = new Private_PublicInterface(); + public PrivateInterface1 i2 = new Private_PrivateInterface1(); + public PrivateInterface2 i3 = new Private_PrivateInterface2(); + + public PublicInterface[] ai1 = new Private_PublicInterface[0]; + public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; + public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; + + public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; + public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; + public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; +} + +interface PrivateInterface1 { +} + +interface PrivateInterface2 extends PublicInterface { +} + +class Private_PublicClass extends PublicClass { + public String toString() { + return "passed"; + } +} + +class Private_PublicInterface implements PublicInterface { + public String toString() { + return "passed"; + } +} + +class Private_PrivateInterface1 implements PrivateInterface1 { + public String toString() { + return "passed"; + } +} + +class Private_PrivateInterface2 implements PrivateInterface2 { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/PublicClass.java b/langtools/test/tools/javac/StringConcat/access/PublicClass.java new file mode 100644 index 00000000000..d4ae6bfc36e --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/PublicClass.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class PublicClass { +} diff --git a/langtools/test/tools/javac/StringConcat/access/PublicInterface.java b/langtools/test/tools/javac/StringConcat/access/PublicInterface.java new file mode 100644 index 00000000000..ba26be94955 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/PublicInterface.java @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public interface PublicInterface { +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java new file mode 100644 index 00000000000..301f90ec798 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface1.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PrivateInterface1 implements PrivateInterface1 { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java new file mode 100644 index 00000000000..dcfcea14ad4 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PrivateInterface2.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PrivateInterface2 implements PrivateInterface2 { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java b/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java new file mode 100644 index 00000000000..20d28acf0d3 --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Public_PublicClass.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package p1; + +public class Public_PublicClass { + public String toString() { + return "passed"; + } +} diff --git a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java b/langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java similarity index 76% rename from langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java rename to langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java index 508cfb4ceca..1c8ae4b60bd 100644 --- a/langtools/test/tools/javac/diags/examples/WarnSyntheticNameConflict.java +++ b/langtools/test/tools/javac/StringConcat/access/Public_PublicInterface.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,14 +21,10 @@ * questions. */ -// key: compiler.warn.synthetic.name.conflict -// options: -XDwarnOnSyntheticConflicts +package p1; -class WarnSyntheticNameConflict { - - static class Outer { - WarnSyntheticNameConflict this$0 = null; +public class Public_PublicInterface implements PublicInterface { + public String toString() { + return "passed"; } - - public class Inner extends Outer { } } diff --git a/langtools/test/tools/javac/StringConcat/access/Test.java b/langtools/test/tools/javac/StringConcat/access/Test.java new file mode 100644 index 00000000000..72237e8b4ef --- /dev/null +++ b/langtools/test/tools/javac/StringConcat/access/Test.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.classfile.*; +import com.sun.tools.classfile.ConstantPool.*; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/* + * @test + * @bug 8151223 + * @summary String concatenation fails with implicit toString() on package-private class + * @modules jdk.jdeps/com.sun.tools.classfile + * + * @clean * + * @compile -XDstringConcat=indy Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + * + * @clean * + * @compile -XDstringConcat=indyWithConstants Holder.java PublicClass.java PublicInterface.java Public_PublicClass.java Public_PublicInterface.java Public_PrivateInterface1.java Public_PrivateInterface2.java Test.java + * @run main Test + */ + +public class Test { + static List actualTypes; + + public static void main(String[] argv) throws Exception { + readIndyTypes(); + + p1.Holder holder = new p1.Holder(); + + int idx = 0; + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass c1 = new Private_PublicClass(); + test("" + holder.c1, idx++, "(Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface c2 = new Private_PublicInterface(); + test("" + holder.c2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1 c3 = new Private_PrivateInterface1(); + test("" + holder.c3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2 c4 = new Private_PrivateInterface2(); + test("" + holder.c4, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass c5 = new Public_PublicClass(); + test("" + holder.c5, idx++, "(Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface c6 = new Public_PublicInterface(); + test("" + holder.c6, idx++, "(Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1 c7 = new Public_PrivateInterface1(); + test("" + holder.c7, idx++, "(Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2 c8 = new Public_PrivateInterface2(); + test("" + holder.c8, idx++, "(Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass[] ac1 = new Private_PublicClass[0]; + test("" + holder.ac1, idx++, "([Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface[] ac2 = new Private_PublicInterface[0]; + test("" + holder.ac2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1[] ac3 = new Private_PrivateInterface1[0]; + test("" + holder.ac3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[] ac4 = new Private_PrivateInterface2[0]; + test("" + holder.ac4, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass[] ac5 = new Public_PublicClass[0]; + test("" + holder.ac5, idx++, "([Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface[] ac6 = new Public_PublicInterface[0]; + test("" + holder.ac6, idx++, "([Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[] ac7 = new Public_PrivateInterface1[0]; + test("" + holder.ac7, idx++, "([Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[] ac8 = new Public_PrivateInterface2[0]; + test("" + holder.ac8, idx++, "([Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public Private_PublicClass[][] aac1 = new Private_PublicClass[0][]; + test("" + holder.aac1, idx++, "([[Lp1/PublicClass;)Ljava/lang/String;"); + + // public Private_PublicInterface[][] aac2 = new Private_PublicInterface[0][]; + test("" + holder.aac2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface1[][] aac3 = new Private_PrivateInterface1[0][]; + test("" + holder.aac3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Private_PrivateInterface2[][] aac4 = new Private_PrivateInterface2[0][]; + test("" + holder.aac4, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public Public_PublicClass[][] aac5 = new Public_PublicClass[0][]; + test("" + holder.aac5, idx++, "([[Lp1/Public_PublicClass;)Ljava/lang/String;"); + + // public Public_PublicInterface[][] aac6 = new Public_PublicInterface[0][]; + test("" + holder.aac6, idx++, "([[Lp1/Public_PublicInterface;)Ljava/lang/String;"); + + // public Public_PrivateInterface1[][] aac7 = new Public_PrivateInterface1[0][]; + test("" + holder.aac7, idx++, "([[Lp1/Public_PrivateInterface1;)Ljava/lang/String;"); + + // public Public_PrivateInterface2[][] aac8 = new Public_PrivateInterface2[0][]; + test("" + holder.aac8, idx++, "([[Lp1/Public_PrivateInterface2;)Ljava/lang/String;"); + + // ---------------------------------------------------------------------------- + + // public PublicInterface i1 = new Private_PublicInterface(); + test("" + holder.i1, idx++, "(Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1 i2 = new Private_PrivateInterface1(); + test("" + holder.i2, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2 i3 = new Private_PrivateInterface2(); + test("" + holder.i3, idx++, "(Ljava/lang/Object;)Ljava/lang/String;"); + + // public PublicInterface[] ai1 = new Private_PublicInterface[0]; + test("" + holder.ai1, idx++, "([Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1[] ai2 = new Private_PrivateInterface1[0]; + test("" + holder.ai2, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2[] ai3 = new Private_PrivateInterface2[0]; + test("" + holder.ai3, idx++, "([Ljava/lang/Object;)Ljava/lang/String;"); + + // public PublicInterface[][] aai1 = new Private_PublicInterface[0][]; + test("" + holder.aai1, idx++, "([[Lp1/PublicInterface;)Ljava/lang/String;"); + + // public PrivateInterface1[][] aai2 = new Private_PrivateInterface1[0][]; + test("" + holder.aai2, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + // public PrivateInterface2[][] aai3 = new Private_PrivateInterface2[0][]; + test("" + holder.aai3, idx++, "([[Ljava/lang/Object;)Ljava/lang/String;"); + + } + + public static void test(String actual, int index, String expectedType) { + if (!"passed".equals(actual) && !actual.startsWith("[")) { + throw new IllegalStateException("Unexpected result: " + actual); + } + String actualType = actualTypes.get(index); + if (!actualType.equals(expectedType)) { + throw new IllegalStateException("Unexpected type: expected = " + expectedType + ", actual = " + actualType); + } + } + + public static void readIndyTypes() throws Exception { + actualTypes = new ArrayList(); + + ClassFile classFile = ClassFile.read(new File(System.getProperty("test.classes", "."), + Test.class.getName() + ".class")); + ConstantPool constantPool = classFile.constant_pool; + + for (Method method : classFile.methods) { + if (method.getName(constantPool).equals("main")) { + Code_attribute code = (Code_attribute) method.attributes + .get(Attribute.Code); + for (Instruction i : code.getInstructions()) { + if (i.getOpcode() == Opcode.INVOKEDYNAMIC) { + CONSTANT_InvokeDynamic_info indyInfo = (CONSTANT_InvokeDynamic_info) constantPool.get(i.getUnsignedShort(1)); + CONSTANT_NameAndType_info natInfo = indyInfo.getNameAndTypeInfo(); + actualTypes.add(natInfo.getType()); + } + } + } + } + } +} diff --git a/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java b/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java new file mode 100644 index 00000000000..5e0c19cddb3 --- /dev/null +++ b/langtools/test/tools/javac/T8139474/DashRelease7DashVerboseTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * bug 8139474 + * @summary -release 7 -verbose causes Javac exception + * @compile -release 7 -verbose DashRelease7DashVerboseTest.java +*/ + +public class DashRelease7DashVerboseTest {} diff --git a/langtools/test/tools/javac/TestIndyStringConcat.java b/langtools/test/tools/javac/TestIndyStringConcat.java deleted file mode 100644 index b799f70015b..00000000000 --- a/langtools/test/tools/javac/TestIndyStringConcat.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test - * @summary Test that StringConcat is working for JDK >= 9 - * @compile -source 6 -target 6 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -source 7 -target 7 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -source 8 -target 8 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=inline -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat false - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=indy -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat true - * @clean TestIndyStringConcat* - * @compile -XDstringConcat=indyWithConstants -source 9 -target 9 TestIndyStringConcat.java - * @run main TestIndyStringConcat true - */ -public class TestIndyStringConcat { - - private static class MyObject { - public String toString() { - throw new RuntimeException("Boyyaa"); - } - } - - class Inner { } - - public static void main(String[] args) { - boolean useIndyConcat = Boolean.valueOf(args[0]); - try { - String s = "Foo" + new MyObject(); - } catch (RuntimeException ex) { - boolean indifiedStringConcat = false; - ex.printStackTrace(); - for (StackTraceElement e : ex.getStackTrace()) { - if (e.getClassName().contains("$$StringConcat") && - e.getMethodName().equals("concat")) { - indifiedStringConcat = true; - break; - } - } - if (indifiedStringConcat != useIndyConcat) { - throw new AssertionError(); - } - } - } -} diff --git a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java index b9be7190088..62b92bcc15a 100644 --- a/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java +++ b/langtools/test/tools/javac/api/taskListeners/EventsBalancedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -61,8 +61,6 @@ public class EventsBalancedTest { test(null, Arrays.asList(a, b)); test(null, Arrays.asList(b, a)); - test(Arrays.asList("-XD-relax"), Arrays.asList(a, b)); - test(Arrays.asList("-XD-relax"), Arrays.asList(b, a)); for (CompileState stop : CompileState.values()) { test(Arrays.asList("-XDshouldStopPolicyIfNoError=" + stop, diff --git a/langtools/test/tools/javac/diags/CheckResourceKeys.java b/langtools/test/tools/javac/diags/CheckResourceKeys.java index 1c29a7240e0..9c1c0380fad 100644 --- a/langtools/test/tools/javac/diags/CheckResourceKeys.java +++ b/langtools/test/tools/javac/diags/CheckResourceKeys.java @@ -231,22 +231,15 @@ public class CheckResourceKeys { "compiler.err.type.var.more.than.once.in.result", // UNUSED "compiler.misc.non.denotable.type", // UNUSED "compiler.misc.unnamed.package", // should be required, CR 6964147 - "compiler.misc.verbose.retro", // UNUSED - "compiler.misc.verbose.retro.with", // UNUSED - "compiler.misc.verbose.retro.with.list", // UNUSED "compiler.warn.proc.type.already.exists", // TODO in JavacFiler "javac.err.invalid.arg", // UNUSED ?? "javac.opt.arg.class", // UNUSED ?? "javac.opt.arg.pathname", // UNUSED ?? "javac.opt.moreinfo", // option commented out "javac.opt.nogj", // UNUSED - "javac.opt.printflat", // option commented out "javac.opt.printsearch", // option commented out "javac.opt.prompt", // option commented out - "javac.opt.retrofit", // UNUSED - "javac.opt.s", // option commented out - "javac.opt.scramble", // option commented out - "javac.opt.scrambleall" // option commented out + "javac.opt.s" // option commented out )); /** diff --git a/langtools/test/tools/javac/diags/examples.not-yet.txt b/langtools/test/tools/javac/diags/examples.not-yet.txt index bd79b7940d0..806d471ea99 100644 --- a/langtools/test/tools/javac/diags/examples.not-yet.txt +++ b/langtools/test/tools/javac/diags/examples.not-yet.txt @@ -86,9 +86,6 @@ compiler.misc.unable.to.access.file # ClassFile compiler.misc.undecl.type.var # ClassReader compiler.misc.unicode.str.not.supported # ClassReader compiler.misc.malformed.vararg.method # ClassReader -compiler.misc.verbose.retro # UNUSED -compiler.misc.verbose.retro.with # UNUSED -compiler.misc.verbose.retro.with.list # UNUSED compiler.misc.version.not.available # JavaCompiler; implies build error compiler.misc.where.description.captured compiler.misc.where.typevar.1 diff --git a/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java b/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java new file mode 100644 index 00000000000..6f84ae482d2 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/DiamondMethodDoesNotOverride.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.anonymous.diamond.method.does.not.override.superclass +// key: compiler.misc.diamond.anonymous.methods.implicitly.override + +class X { + interface Foo { + void g(T t); + } + void m() { + Foo fs = new Foo<>() { + public void g(String s) { } + void someMethod() { } + }; + } +} diff --git a/langtools/test/tools/javac/file/T8150475.java b/langtools/test/tools/javac/file/T8150475.java new file mode 100644 index 00000000000..790b944cbf8 --- /dev/null +++ b/langtools/test/tools/javac/file/T8150475.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @compile -sourcepath / T8150475.java + */ + +class T8150475 { } + diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg15.java b/langtools/test/tools/javac/generics/diamond/neg/Neg15.java index 2c0d28607fa..573a5a1be3c 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg15.java +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg15.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8062373 + * @bug 8062373 8151018 * * @summary Test that javac complains when a <> inferred class contains a public method that does override a supertype method. * @author sadayapalam diff --git a/langtools/test/tools/javac/generics/diamond/neg/Neg15.out b/langtools/test/tools/javac/generics/diamond/neg/Neg15.out index 1e6f1efa8ac..9d2d1b3a378 100644 --- a/langtools/test/tools/javac/generics/diamond/neg/Neg15.out +++ b/langtools/test/tools/javac/generics/diamond/neg/Neg15.out @@ -1,4 +1,4 @@ -Neg15.java:48:28: compiler.err.method.does.not.override.superclass -Neg15.java:52:21: compiler.err.method.does.not.override.superclass -Neg15.java:56:31: compiler.err.method.does.not.override.superclass +Neg15.java:48:28: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override) +Neg15.java:52:21: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override) +Neg15.java:56:31: compiler.err.anonymous.diamond.method.does.not.override.superclass: (compiler.misc.diamond.anonymous.methods.implicitly.override) 3 errors diff --git a/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java b/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java new file mode 100644 index 00000000000..4e37114d27e --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/CheckNoTimeoutException.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8148930 + * @summary Verify that there is no spurious unreported exception error. + * @modules java.sql + * @compile CheckNoTimeoutException.java + */ + +import java.util.Collection; +import java.util.List; +import java.util.ArrayList; +import java.util.concurrent.TimeoutException; +import java.io.*; +import java.sql.SQLException; +import java.sql.SQLTransientException; + +class CheckNoTimeoutException { + + interface V {List foo(List arg) throws EOFException, SQLException, TimeoutException;} + interface U {Collection foo(List arg) throws IOException, SQLTransientException;} + + //SAM type ([List], List/List, {EOFException, SQLTransientException}) + interface UV extends U, V {} + + + private static List strs = new ArrayList(); + void methodUV(UV uv) { + System.out.println("methodUV(): SAM type interface UV object instantiated: " + uv); + try{ + System.out.println("result returned: " + uv.foo(strs)); + }catch(EOFException e){ + System.out.println(e.getMessage()); + }catch(SQLTransientException ex){ + System.out.println(ex.getMessage()); + } + } +} \ No newline at end of file diff --git a/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java new file mode 100644 index 00000000000..4a37c4ef4d9 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.java @@ -0,0 +1,28 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8148930 + * @summary Incorrect erasure of exceptions in override-equivalent dual interface impl + * @compile/fail/ref=IntersectThrownTypesTest.out -XDrawDiagnostics IntersectThrownTypesTest.java + */ + +public class IntersectThrownTypesTest { + + interface S1 { + void run(Class clazz) throws K; + } + + interface S2 { + void run(Class clazz) throws K; + } + + interface S extends S1, S2 {} + + public void foo(S1 s) { + s.run(java.io.IOException.class); + } + + public void foo(S s) { + s.run(java.io.IOException.class); + } + +} diff --git a/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out new file mode 100644 index 00000000000..c42a1c9d6b5 --- /dev/null +++ b/langtools/test/tools/javac/generics/inference/IntersectThrownTypesTest.out @@ -0,0 +1,3 @@ +IntersectThrownTypesTest.java:21:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException +IntersectThrownTypesTest.java:25:14: compiler.err.unreported.exception.need.to.catch.or.throw: java.io.IOException +2 errors diff --git a/langtools/test/tools/sjavac/IdleShutdown.java b/langtools/test/tools/sjavac/IdleShutdown.java index 567677e529a..7178d6c89e5 100644 --- a/langtools/test/tools/sjavac/IdleShutdown.java +++ b/langtools/test/tools/sjavac/IdleShutdown.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,11 +65,11 @@ public class IdleShutdown { // Use Sjavac object and wait less than TIMEOUT_MS in between calls Thread.sleep(TIMEOUT_MS - 1000); log("Compiling"); - service.compile(new String[0], null, null); + service.compile(new String[0]); Thread.sleep(TIMEOUT_MS - 1000); log("Compiling"); - service.compile(new String[0], null, null); + service.compile(new String[0]); if (timeoutTimestamp.get() != -1) throw new AssertionError("Premature timeout detected."); @@ -103,7 +103,7 @@ public class IdleShutdown { public void shutdown() { } @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { // Attempt to trigger idle timeout during a call by sleeping try { Thread.sleep(TIMEOUT_MS + 1000); diff --git a/langtools/test/tools/sjavac/OverlappingSrcDst.java b/langtools/test/tools/sjavac/OverlappingSrcDst.java new file mode 100644 index 00000000000..516fb118dd1 --- /dev/null +++ b/langtools/test/tools/sjavac/OverlappingSrcDst.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary Make sure sjavac doesn't allow overlapping source and destination + * directories. + * @bug 8061320 + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.file + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.sjavac + * @build Wrapper ToolBox + * @run main Wrapper OverlappingSrcDst + */ + +import java.io.File; +import java.nio.file.Paths; + +public class OverlappingSrcDst extends SJavacTester { + public static void main(String... args) { + new OverlappingSrcDst().run(); + } + + public void run() { + String abs = ToolBox.currDir.toAbsolutePath().toString(); + + // Relative vs relative + test("dir", "dir", false); + test("dir", "dir/dst", false); + test("dir/src", "dir", false); + test("src", "dst", true); + + // Absolute vs absolute + test(abs + "/dir", abs + "/dir", false); + test(abs + "/dir", abs + "/dir/dst", false); + test(abs + "/dir/src", abs + "/dir", false); + test(abs + "/src", abs + "/dst", true); + + // Absolute vs relative + test(abs + "/dir", "dir", false); + test(abs + "/dir", "dir/dst", false); + test(abs + "/dir/src", "dir", false); + test(abs + "/src", "dst", true); + + // Relative vs absolute + test("dir", abs + "/dir", false); + test("dir", abs + "/dir/dst", false); + test("dir/src", abs + "/dir", false); + test("src", abs + "/dst", true); + } + + private void test(String srcDir, String dstDir, boolean shouldSucceed) { + boolean succeeded = testCompilation(srcDir, dstDir); + if (shouldSucceed != succeeded) { + throw new AssertionError( + String.format("Test failed for " + + "srcDir=\"%s\", " + + "dstDir=\"%s\". " + + "Compilation was expected to %s but %s.", + srcDir, + dstDir, + shouldSucceed ? "succeed" : "fail", + succeeded ? "succeeded" : "failed")); + } + } + + private boolean testCompilation(String srcDir, String dstDir) { + try { + srcDir = srcDir.replace('/', File.separatorChar); + dstDir = dstDir.replace('/', File.separatorChar); + tb.writeFile(Paths.get(srcDir, "pkg", "A.java"), "package pkg; class A {}"); + compile("--state-dir=state", "-src", srcDir, "-d", dstDir); + return true; + } catch (Exception e) { + return false; + } + } +} diff --git a/langtools/test/tools/sjavac/PooledExecution.java b/langtools/test/tools/sjavac/PooledExecution.java index 28c0105bf5a..ccd4265fee2 100644 --- a/langtools/test/tools/sjavac/PooledExecution.java +++ b/langtools/test/tools/sjavac/PooledExecution.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,12 @@ * @build Wrapper * @run main Wrapper PooledExecution */ +import java.io.PrintWriter; import java.io.Writer; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; +import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.server.Sjavac; @@ -67,7 +69,7 @@ public class PooledExecution { for (int i = 0; i < NUM_REQUESTS; i++) { tasks[i] = new Thread() { public void run() { - service.compile(new String[0], null, null); + service.compile(new String[0]); tasksFinished.incrementAndGet(); } }; @@ -109,7 +111,7 @@ public class PooledExecution { AtomicInteger activeRequests = new AtomicInteger(0); @Override - public int compile(String[] args, Writer out, Writer err) { + public int compile(String[] args) { leftToStart.countDown(); int numActiveRequests = activeRequests.incrementAndGet(); System.out.printf("Left to start: %2d / Currently active: %2d%n", diff --git a/make/CompileJavaModules.gmk b/make/CompileJavaModules.gmk index 8593b3c784f..e8928e2130d 100644 --- a/make/CompileJavaModules.gmk +++ b/make/CompileJavaModules.gmk @@ -368,21 +368,7 @@ jdk.compiler_CLEAN_FILES := $(wildcard \ ################################################################################ jdk.hotspot.agent_ADD_JAVAC_FLAGS := $(DISABLE_WARNINGS),-overrides -jdk.hotspot.agent_COPY := .png sa.js .properties - -ifeq ($(MODULE), jdk.hotspot.agent) - ### Copy gif files - # Special handling to copy gif files in images/toolbarButtonGraphics \ - # -> classes/toolbarButtonGraphics. - # These can't be handled by COPY to SetupJavaCompilation since they chop off - # one directory level. - $(eval $(call SetupCopyFiles, COPY_SA_IMAGES, \ - SRC := $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/images, \ - DEST := $(JDK_OUTPUTDIR)/modules/$(MODULE), \ - FILES := $(wildcard $(HOTSPOT_TOPDIR)/src/jdk.hotspot.agent/share/classes/images/*/*/*.gif), \ - )) - jdk.hotspot.agent: $(COPY_SA_IMAGES) -endif +jdk.hotspot.agent_COPY := .gif .png sa.js .properties ################################################################################ diff --git a/make/Images.gmk b/make/Images.gmk index ca6a4e2d8bf..7fc063773d6 100644 --- a/make/Images.gmk +++ b/make/Images.gmk @@ -42,7 +42,7 @@ MAIN_MODULES += java.se java.smartcardio jdk.httpserver jdk.sctp \ jdk.security.auth jdk.security.jgss jdk.pack200 jdk.xml.dom \ jdk.accessibility jdk.internal.le jdk.dynalink \ jdk.scripting.nashorn jdk.scripting.nashorn.shell \ - jdk.vm.ci jdk.management + jdk.vm.ci jdk.management jdk.jsobject # providers PROVIDER_MODULES += jdk.charsets jdk.crypto.ec jdk.crypto.pkcs11 jdk.jvmstat jdk.jvmstat.rmi \ @@ -62,10 +62,6 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) PROVIDER_MODULES += jdk.crypto.ucrypto endif -ifeq ($(OPENJDK_TARGET_OS), macosx) - MAIN_MODULES += jdk.deploy.osx -endif - JRE_MODULES := $(filter-out $(MODULES_FILTER), $(MAIN_MODULES) $(PROVIDER_MODULES)) JDK_MODULES := $(filter-out $(MODULES_FILTER), $(JRE_MODULES) $(TOOLS_MODULES)) diff --git a/make/Init.gmk b/make/Init.gmk index 4ed492c68fc..ee67aeaa65f 100644 --- a/make/Init.gmk +++ b/make/Init.gmk @@ -154,6 +154,9 @@ ifeq ($(HAS_SPEC),) # Do nothing endif + # Do not let make delete spec files even if aborted while doing a reconfigure + .PRECIOUS: $(SPECS) + # Unless reconfigure is explicitely called, let all main targets depend on # the spec files to be up to date. ifeq ($(findstring reconfigure, $(INIT_TARGETS)), ) diff --git a/make/Main.gmk b/make/Main.gmk index b354d9de9ab..66509ddfdcb 100644 --- a/make/Main.gmk +++ b/make/Main.gmk @@ -413,9 +413,6 @@ else # Declare dependencies from all other -lib to java.base-lib $(foreach t, $(filter-out java.base-libs, $(LIBS_TARGETS)), \ $(eval $t: java.base-libs)) - # Declare the special case dependency for jdk.deploy.osx where libosx - # links against libosxapp. - jdk.deploy.osx-libs: java.desktop-libs # jdk.accessibility depends on java.desktop jdk.accessibility-libs: java.desktop-libs diff --git a/make/common/CORE_PKGS.gmk b/make/common/CORE_PKGS.gmk index 6a3ba63a243..eb6ac3d769e 100644 --- a/make/common/CORE_PKGS.gmk +++ b/make/common/CORE_PKGS.gmk @@ -103,6 +103,7 @@ CORE_PKGS = \ java.lang.reflect \ java.math \ java.net \ + java.net.http \ java.net.spi \ java.nio \ java.nio.channels \ diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index e068be7dd23..6200851793c 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -282,7 +282,7 @@ define SetupLogging # Default shell seems to always be /bin/sh. Must override with bash to get this to work on Solaris. # Only use time if it's GNU time which supports format and output file. WRAPPER_SHELL := $$(BASH) $$(SRC_ROOT)/common/bin/shell-tracer.sh $$(if $$(findstring yes,$$(IS_GNU_TIME)),$$(TIME),-) $$(OUTPUT_ROOT)/build-trace-time.log $$(SHELL) - SHELL := $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL) + SHELL = $$(warning $$(if $$@,Building $$@,Running shell command) $$(if $$<, (from $$<))$$(if $$?, ($$(wordlist 1, 20, $$?) $$(if $$(wordlist 21, 22, $$?), ... [in total $$(words $$?) files]) newer)))$$(WRAPPER_SHELL) endif # The warn level can never be turned off LogWarn = $$(info $$(strip $$1)) diff --git a/make/common/NON_CORE_PKGS.gmk b/make/common/NON_CORE_PKGS.gmk index bf02064cf63..7e63750d28f 100644 --- a/make/common/NON_CORE_PKGS.gmk +++ b/make/common/NON_CORE_PKGS.gmk @@ -98,8 +98,7 @@ SMARTCARDIO_PKGS = javax.smartcardio SCTPAPI_PKGS = com.sun.nio.sctp ifeq ($(PLATFORM), macosx) - APPLE_EXT_PKGS = com.apple.concurrent \ - com.apple.eawt \ + APPLE_EXT_PKGS = com.apple.eawt \ com.apple.eawt.event \ com.apple.eio endif diff --git a/make/common/NativeCompilation.gmk b/make/common/NativeCompilation.gmk index 53637fcb953..f675790efc6 100644 --- a/make/common/NativeCompilation.gmk +++ b/make/common/NativeCompilation.gmk @@ -651,12 +651,15 @@ define SetupNativeCompilationBody $$($1_RES): $$($1_VERSIONINFO_RESOURCE) $$($1_RES_VARDEPS_FILE) $$(call LogInfo, Compiling resource $$(notdir $$($1_VERSIONINFO_RESOURCE)) (for $$(notdir $$($1_TARGET)))) + $$(call MakeDir, $$(@D) $$($1_OBJECT_DIR)) $$(call ExecuteWithLog, $$@, \ $$($1_RC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) $(CC_OUT_OPTION)$$@ \ $$($1_VERSIONINFO_RESOURCE)) # Windows RC compiler does not support -showIncludes, so we mis-use CL for this. - $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ - $(CC_OUT_OPTION)$$($1_RES_DEP).obj $$($1_VERSIONINFO_RESOURCE) > $$($1_RES_DEP).raw 2>&1 || true ; \ + $$(call ExecuteWithLog, $$($1_RES_DEP).obj, \ + $$($1_CC) $$($1_RC_FLAGS) $$($1_SYSROOT_CFLAGS) -showIncludes -nologo -TC \ + $(CC_OUT_OPTION)$$($1_RES_DEP).obj -P -Fi$$($1_RES_DEP).pp \ + $$($1_VERSIONINFO_RESOURCE)) > $$($1_RES_DEP).raw 2>&1 || true ; \ $(ECHO) $$($1_RES): \\ > $$($1_RES_DEP) ; \ $(SED) $(WINDOWS_SHOWINCLUDE_SED_PATTERN) $$($1_RES_DEP).raw >> $$($1_RES_DEP) ; \ $(SED) $(DEPENDENCY_TARGET_SED_PATTERN) $$($1_RES_DEP) > $$($1_RES_DEP_TARGETS) @@ -670,7 +673,7 @@ define SetupNativeCompilationBody $1_REAL_MAPFILE := $$($1_OBJECT_DIR)/mapfile $$($1_REAL_MAPFILE) : $$($1_MAPFILE) $$($1_REORDER) - $$(MKDIR) -p $$(@D) + $$(call MakeDir, $$(@D)) $$(CP) $$($1_MAPFILE) $$@.tmp $$(SED) -e 's=OUTPUTDIR=$$($1_OBJECT_DIR)=' $$($1_REORDER) >> $$@.tmp $$(MV) $$@.tmp $$@ @@ -768,7 +771,10 @@ define SetupNativeCompilationBody $1_EXTRA_LDFLAGS += "-implib:$$($1_OBJECT_DIR)/$$($1_LIBRARY).lib" endif - $1_EXTRA_LIBS += $(GLOBAL_LIBS) + # Create loadmap on AIX. Helps in diagnosing some problems. + ifneq ($(COMPILER_BINDCMD_FILE_FLAG),) + $1_EXTRA_LDFLAGS += $(COMPILER_BINDCMD_FILE_FLAG)$$($1_OBJECT_DIR)/$$($1_NOSUFFIX).loadmap + endif $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_CREATE_DEBUGINFO_CMDS) \ @@ -846,8 +852,6 @@ define SetupNativeCompilationBody ifneq (,$$($1_PROGRAM)) # A executable binary has been specified, setup the target for it. - $1_EXTRA_LIBS += $(GLOBAL_LIBS) - $1_VARDEPS := $$($1_LD) $$($1_SYSROOT_LDFLAGS) $$($1_LDFLAGS) $$($1_EXTRA_LDFLAGS) \ $$($1_LIBS) $$($1_EXTRA_LIBS) $$($1_MT) \ $$($1_CODESIGN) $$($1_CREATE_DEBUGINFO_CMDS) $$($1_MANIFEST_VERSION) \ diff --git a/make/devkit/createWindowsDevkit.sh b/make/devkit/createWindowsDevkit.sh index 187a4c7c154..fd007a01a9b 100644 --- a/make/devkit/createWindowsDevkit.sh +++ b/make/devkit/createWindowsDevkit.sh @@ -74,6 +74,10 @@ if [ ! -d $DEVKIT_ROOT/VC ]; then cp $DEVKIT_ROOT/VC/redist/x86/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/ cp $DEVKIT_ROOT/VC/redist/x64/$MSVCR_DLL $DEVKIT_ROOT/VC/bin/amd64/ cp $DEVKIT_ROOT/VC/redist/x64/$MSVCP_DLL $DEVKIT_ROOT/VC/bin/amd64/ + # The msvcdis dll is needed to run some of the tools in VC/bin but is not + # shipped in that directory. Copy it from the common dir. + cp "$VS_INSTALL_DIR/Common7/IDE/msvcdis${VS_VERSION_NUM_NODOT}.dll" \ + $DEVKIT_ROOT/VC/bin/ fi ################################################################################ diff --git a/modules.xml b/modules.xml index 458859b5327..7061f52301b 100644 --- a/modules.xml +++ b/modules.xml @@ -239,6 +239,7 @@ java.xml jdk.charsets jdk.management.resource + jdk.jfr jdk.net jdk.scripting.nashorn jdk.vm.ci @@ -249,6 +250,22 @@ java.management jdk.jvmstat + + jdk.internal.org.xml.sax + jdk.jfr + + + jdk.internal.org.xml.sax.helpers + jdk.jfr + + + jdk.internal.util.xml + jdk.jfr + + + jdk.internal.util.xml.impl + jdk.jfr + jdk.internal.org.objectweb.asm java.instrument @@ -300,7 +317,6 @@ java.xml jdk.charsets jdk.crypto.pkcs11 - jdk.deploy.osx jdk.httpserver jdk.jartool jdk.jconsole @@ -314,6 +330,11 @@ jdk.vm.ci jdk.zipfs java.instrument + jdk.jfr + + + sun.net + java.httpclient sun.net.dns @@ -417,7 +438,6 @@ sun.security.pkcs jdk.crypto.ec - jdk.deploy.osx jdk.jartool @@ -458,7 +478,6 @@ jdk.crypto.mscapi jdk.crypto.pkcs11 jdk.crypto.ucrypto - jdk.deploy.osx jdk.jartool jdk.policytool jdk.security.auth @@ -469,7 +488,6 @@ java.naming jdk.crypto.ec jdk.crypto.pkcs11 - jdk.deploy.osx jdk.jartool jdk.security.auth @@ -496,6 +514,7 @@ java.logging java.management java.prefs + java.httpclient sun.util.resources @@ -520,6 +539,7 @@ java.compact2 java.compiler java.instrument + java.httpclient java.management java.naming java.prefs @@ -837,6 +857,25 @@ jdk.jshell + + jdk.jsobject + java.base + java.desktop + + netscape.javascript + + + jdk.internal.netscape.javascript.spi + jdk.plugin + + + + java.httpclient + java.base + + java.net.http + + java.instrument java.base @@ -901,6 +940,7 @@ sun.management.spi jdk.management jdk.management.cmm + jdk.management.jfr @@ -1681,11 +1721,6 @@ jdk.crypto.ucrypto java.base - - jdk.deploy.osx - java.base - java.desktop - jdk.dev java.base @@ -1789,10 +1824,10 @@ com.sun.tools.javadoc - jdk.javadoc.doclet + jdk.javadoc.doclet - jdk.javadoc.doclet.taglet + jdk.javadoc.doclet.taglet diff --git a/nashorn/.hgignore b/nashorn/.hgignore index cba852416c5..92acdd9d019 100644 --- a/nashorn/.hgignore +++ b/nashorn/.hgignore @@ -28,3 +28,4 @@ test/script/external/* .project .externalToolBuilders/* .settings/* +NashornProfile.txt diff --git a/nashorn/.hgtags b/nashorn/.hgtags index a2b4cd909db..98a913b7fce 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -340,3 +340,6 @@ c9406f325a23e9093fa667ad3c594e2efe078f47 jdk-9+103 a618d3e89fdea5361895ef142a59074fe7ae3d98 jdk-9+104 4e9749cc32f15251d9b2d0eab4373529952902a3 jdk-9+105 cfb3167456932b14c16a6d4cffd5fe295fbe01ff jdk-9+106 +8042e81b530e480dfdad41fd53a7a26f69ebba26 jdk-9+107 +58409eff7e3e0c07f12f543341769964619c0acf jdk-9+108 +70f0c397021116d7dbd79b01c6711c5d2e68dab4 jdk-9+109 diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 5092b958692..dff7478f6f1 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -242,6 +242,7 @@ + @@ -261,6 +262,7 @@ + @@ -276,6 +278,7 @@ + @@ -289,6 +292,7 @@ + diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index 6b3551065bc..fbaca210b7e 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -34,6 +34,8 @@ build.compiler=modern javac.source=1.8 javac.target=1.8 +javadoc.option=-tag "implSpec:a:Implementation Requirements:" + # nashorn version information nashorn.version=0.1 nashorn.fullversion=0.1 diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java index ce2c18811ca..0d5bf7157ee 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/AbstractJSObject.java @@ -27,6 +27,7 @@ package jdk.nashorn.api.scripting; import java.util.Collection; import java.util.Collections; +import java.util.Objects; import java.util.Set; /** @@ -34,19 +35,19 @@ import java.util.Set; * * This class can also be subclassed by an arbitrary Java class. Nashorn will * treat objects of such classes just like nashorn script objects. Usual nashorn - * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued + * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be delegated * to appropriate method call of this class. * * @since 1.8u40 */ public abstract class AbstractJSObject implements JSObject { /** - * Call this object as a JavaScript function. This is equivalent to - * 'func.apply(thiz, args)' in JavaScript. - * - * @param thiz 'this' object to be passed to the function - * @param args arguments to method - * @return result of call + * The default constructor. + */ + public AbstractJSObject() {} + + /** + * @implSpec This implementation always throws UnsupportedOperationException */ @Override public Object call(final Object thiz, final Object... args) { @@ -54,11 +55,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Call this 'constructor' JavaScript function to create a new object. - * This is equivalent to 'new func(arg1, arg2...)' in JavaScript. - * - * @param args arguments to method - * @return result of constructor call + * @implSpec This implementation always throws UnsupportedOperationException */ @Override public Object newObject(final Object... args) { @@ -66,10 +63,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Evaluate a JavaScript expression. - * - * @param s JavaScript expression to evaluate - * @return evaluation result + * @implSpec This imlementation always throws UnsupportedOperationException */ @Override public Object eval(final String s) { @@ -77,21 +71,16 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Retrieves a named member of this JavaScript object. - * - * @param name of member - * @return member + * @implSpec This implementation always returns null */ @Override public Object getMember(final String name) { + Objects.requireNonNull(name); return null; } /** - * Retrieves an indexed member of this JavaScript object. - * - * @param index index slot to retrieve - * @return member + * @implSpec This implementation always returns null */ @Override public Object getSlot(final int index) { @@ -99,21 +88,16 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Does this object have a named member? - * - * @param name name of member - * @return true if this object has a member of the given name + * @implSpec This implementation always returns false */ @Override public boolean hasMember(final String name) { + Objects.requireNonNull(name); return false; } /** - * Does this object have a indexed property? - * - * @param slot index to check - * @return true if this object has a slot + * @implSpec This implementation always returns false */ @Override public boolean hasSlot(final int slot) { @@ -121,31 +105,25 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Remove a named member from this JavaScript object - * - * @param name name of the member + * @implSpec This implementation is a no-op */ @Override public void removeMember(final String name) { + Objects.requireNonNull(name); //empty } /** - * Set a named member in this JavaScript object - * - * @param name name of the member - * @param value value of the member + * @implSpec This implementation is a no-op */ @Override public void setMember(final String name, final Object value) { + Objects.requireNonNull(name); //empty } /** - * Set an indexed member in this JavaScript object - * - * @param index index of the member slot - * @param value value of the member + * @implSpec This implementation is a no-op */ @Override public void setSlot(final int index, final Object value) { @@ -155,9 +133,7 @@ public abstract class AbstractJSObject implements JSObject { // property and value iteration /** - * Returns the set of all property names of this object. - * - * @return set of property names + * @implSpec This implementation returns empty set */ @Override public Set keySet() { @@ -165,9 +141,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Returns the set of all property values of this object. - * - * @return set of property values. + * @implSpec This implementation returns empty set */ @Override public Collection values() { @@ -177,22 +151,13 @@ public abstract class AbstractJSObject implements JSObject { // JavaScript instanceof check /** - * Checking whether the given object is an instance of 'this' object. - * - * @param instance instance to check - * @return true if the given 'instance' is an instance of this 'function' object + * @implSpec This implementation always returns false */ @Override public boolean isInstance(final Object instance) { return false; } - /** - * Checking whether this object is an instance of the given 'clazz' object. - * - * @param clazz clazz to check - * @return true if this object is an instance of the given 'clazz' - */ @Override public boolean isInstanceOf(final Object clazz) { if (clazz instanceof JSObject) { @@ -202,20 +167,13 @@ public abstract class AbstractJSObject implements JSObject { return false; } - /** - * ECMA [[Class]] property - * - * @return ECMA [[Class]] property value of this object - */ @Override public String getClassName() { return getClass().getName(); } /** - * Is this a function object? - * - * @return if this mirror wraps a ECMAScript function instance + * @implSpec This implementation always returns false */ @Override public boolean isFunction() { @@ -223,9 +181,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Is this a 'use strict' function object? - * - * @return true if this mirror represents a ECMAScript 'use strict' function + * @implSpec This implementation always returns false */ @Override public boolean isStrictFunction() { @@ -233,9 +189,7 @@ public abstract class AbstractJSObject implements JSObject { } /** - * Is this an array object? - * - * @return if this mirror wraps a ECMAScript array object + * @implSpec This implementation always returns false */ @Override public boolean isArray() { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java index 8545bf79665..afbb0a21363 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/JSObject.java @@ -32,7 +32,7 @@ import jdk.nashorn.internal.runtime.JSType; /** * This interface can be implemented by an arbitrary Java class. Nashorn will * treat objects of such classes just like nashorn script objects. Usual nashorn - * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be glued + * operations like obj[i], obj.foo, obj.func(), delete obj.foo will be delegated * to appropriate method call of this interface. * * @since 1.8u40 @@ -42,7 +42,7 @@ public interface JSObject { * Call this object as a JavaScript function. This is equivalent to * 'func.apply(thiz, args)' in JavaScript. * - * @param thiz 'this' object to be passed to the function + * @param thiz 'this' object to be passed to the function. This may be null. * @param args arguments to method * @return result of call */ @@ -70,6 +70,7 @@ public interface JSObject { * * @param name of member * @return member + * @throws NullPointerException if name is null */ public Object getMember(final String name); @@ -101,6 +102,7 @@ public interface JSObject { * Remove a named member from this JavaScript object * * @param name name of the member + * @throws NullPointerException if name is null */ public void removeMember(final String name); @@ -109,6 +111,7 @@ public interface JSObject { * * @param name name of the member * @param value value of the member + * @throws NullPointerException if name is null */ public void setMember(final String name, final Object value); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java index 1f7631d332d..fc1a7464df0 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornException.java @@ -46,6 +46,8 @@ import jdk.nashorn.internal.runtime.ScriptObject; */ @SuppressWarnings("serial") public abstract class NashornException extends RuntimeException { + private static final long serialVersionUID = 1L; + // script file name private String fileName; // script line number @@ -58,7 +60,7 @@ public abstract class NashornException extends RuntimeException { private Object ecmaError; /** - * Constructor + * Constructor to initialize error message, file name, line and column numbers. * * @param msg exception message * @param fileName file name @@ -70,7 +72,7 @@ public abstract class NashornException extends RuntimeException { } /** - * Constructor + * Constructor to initialize error message, cause exception, file name, line and column numbers. * * @param msg exception message * @param cause exception cause @@ -86,7 +88,7 @@ public abstract class NashornException extends RuntimeException { } /** - * Constructor + * Constructor to initialize error message and cause exception. * * @param msg exception message * @param cause exception cause diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java index f05b7070471..2012bf12600 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/NashornScriptEngineFactory.java @@ -154,7 +154,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given class loader. + * Create a new Script engine initialized with the given class loader. * * @param appLoader class loader to be used as script "app" class loader. * @return newly created script engine. @@ -167,7 +167,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given class filter. + * Create a new Script engine initialized with the given class filter. * * @param classFilter class filter to use. * @return newly created script engine. @@ -181,7 +181,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given arguments. + * Create a new Script engine initialized with the given arguments. * * @param args arguments array passed to script engine. * @return newly created script engine. @@ -195,7 +195,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given arguments. + * Create a new Script engine initialized with the given arguments and the given class loader. * * @param args arguments array passed to script engine. * @param appLoader class loader to be used as script "app" class loader. @@ -210,7 +210,7 @@ public final class NashornScriptEngineFactory implements ScriptEngineFactory { } /** - * Create a new Script engine initialized by given arguments. + * Create a new Script engine initialized with the given arguments, class loader and class filter. * * @param args arguments array passed to script engine. * @param appLoader class loader to be used as script "app" class loader. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java index ea2f51f1e7c..8d7fe11bea6 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptObjectMirror.java @@ -287,22 +287,21 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin }); } - @Override - public boolean isInstance(final Object obj) { - if (! (obj instanceof ScriptObjectMirror)) { + public boolean isInstance(final Object instance) { + if (! (instance instanceof ScriptObjectMirror)) { return false; } - final ScriptObjectMirror instance = (ScriptObjectMirror)obj; + final ScriptObjectMirror mirror = (ScriptObjectMirror)instance; // if not belongs to my global scope, return false - if (global != instance.global) { + if (global != mirror.global) { return false; } return inGlobal(new Callable() { @Override public Boolean call() { - return sobj.isInstance(instance.sobj); + return sobj.isInstance(mirror.sobj); } }); } @@ -653,10 +652,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin } /** - * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. + * Make a script object mirror on given object if needed. * * @param obj object to be wrapped/converted - * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param homeGlobal global to which this object belongs. * @return wrapped/converted object */ public static Object wrap(final Object obj, final Object homeGlobal) { @@ -664,13 +663,13 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin } /** - * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. The - * created wrapper will implement the Java {@code List} interface if {@code obj} is a JavaScript - * {@code Array} object; this is compatible with Java JSON libraries expectations. Arrays retrieved through its + * Make a script object mirror on given object if needed. The created wrapper will implement + * the Java {@code List} interface if {@code obj} is a JavaScript {@code Array} object; + * this is compatible with Java JSON libraries expectations. Arrays retrieved through its * properties (transitively) will also implement the list interface. * * @param obj object to be wrapped/converted - * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param homeGlobal global to which this object belongs. * @return wrapped/converted object */ public static Object wrapAsJSONCompatible(final Object obj, final Object homeGlobal) { @@ -678,10 +677,10 @@ public final class ScriptObjectMirror extends AbstractJSObject implements Bindin } /** - * Make a script object mirror on given object if needed. Also converts ConsString instances to Strings. + * Make a script object mirror on given object if needed. * * @param obj object to be wrapped/converted - * @param homeGlobal global to which this object belongs. Not used for ConsStrings. + * @param homeGlobal global to which this object belongs. * @param jsonCompatible if true, the created wrapper will implement the Java {@code List} interface if * {@code obj} is a JavaScript {@code Array} object. Arrays retrieved through its properties (transitively) * will also implement the list interface. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java index 367efa56591..e824cceb1c5 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/api/scripting/ScriptUtils.java @@ -74,9 +74,15 @@ public final class ScriptUtils { * @param func the function to wrap * @param sync the object to synchronize on * @return a synchronizing wrapper function + * @throws IllegalArgumentException if func does not represent a script function */ - public static Object makeSynchronizedFunction(final ScriptFunction func, final Object sync) { - return func.createSynchronized(unwrap(sync)); + public static Object makeSynchronizedFunction(final Object func, final Object sync) { + final Object unwrapped = unwrap(func); + if (unwrapped instanceof ScriptFunction) { + return ((ScriptFunction)unwrapped).createSynchronized(unwrap(sync)); + } + + throw new IllegalArgumentException(); } /** @@ -84,9 +90,19 @@ public final class ScriptUtils { * * @param obj object to be wrapped * @return wrapped object + * @throws IllegalArgumentException if obj cannot be wrapped */ - public static ScriptObjectMirror wrap(final ScriptObject obj) { - return (ScriptObjectMirror) ScriptObjectMirror.wrap(obj, Context.getGlobal()); + public static ScriptObjectMirror wrap(final Object obj) { + if (obj instanceof ScriptObjectMirror) { + return (ScriptObjectMirror)obj; + } + + if (obj instanceof ScriptObject) { + final ScriptObject sobj = (ScriptObject)obj; + return (ScriptObjectMirror) ScriptObjectMirror.wrap(sobj, Context.getGlobal()); + } + + throw new IllegalArgumentException(); } /** @@ -135,7 +151,8 @@ public final class ScriptUtils { * Convert the given object to the given type. * * @param obj object to be converted - * @param type destination type to convert to + * @param type destination type to convert to. type is either a Class + * or nashorn representation of a Java type returned by Java.type() call in script. * @return converted object */ public static Object convert(final Object obj, final Object type) { diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java index db042890cd7..adfb15ba20a 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/objects/Global.java @@ -2724,12 +2724,9 @@ public final class Global extends Scope { // Retrieve current state of ENV variables. env.putAll(System.getenv(), scriptEnv._strict); - // Some platforms, e.g., Windows, do not define the PWD environment - // variable, so that the $ENV.PWD property needs to be explicitly - // set. - if (!env.containsKey(ScriptingFunctions.PWD_NAME)) { - env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); - } + // Set the PWD variable to a value that is guaranteed to be understood + // by the underlying platform. + env.put(ScriptingFunctions.PWD_NAME, System.getProperty("user.dir"), scriptEnv._strict); } addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java index b7194c649a3..a0abdbd7d7b 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CodeStore.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,13 +34,10 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.security.AccessControlException; import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import java.util.Iterator; import java.util.Map; -import java.util.ServiceLoader; import jdk.nashorn.internal.codegen.OptimisticTypesPersistence; import jdk.nashorn.internal.codegen.types.Type; import jdk.nashorn.internal.runtime.logging.DebugLogger; @@ -54,11 +51,6 @@ import jdk.nashorn.internal.runtime.options.Options; @Logger(name="codestore") public abstract class CodeStore implements Loggable { - /** - * Permission needed to provide a CodeStore instance via ServiceLoader. - */ - public final static String NASHORN_PROVIDE_CODE_STORE = "nashorn.provideCodeStore"; - private DebugLogger log; /** @@ -85,23 +77,6 @@ public abstract class CodeStore implements Loggable { * @return The instance, or null if code store could not be created */ public static CodeStore newCodeStore(final Context context) { - final Class baseClass = CodeStore.class; - try { - // security check first - final SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(new RuntimePermission(NASHORN_PROVIDE_CODE_STORE)); - } - final ServiceLoader services = ServiceLoader.load(baseClass); - final Iterator iterator = services.iterator(); - if (iterator.hasNext()) { - final CodeStore store = iterator.next(); - store.initLogger(context).info("using code store provider ", store.getClass().getCanonicalName()); - return store; - } - } catch (final AccessControlException e) { - context.getLogger(CodeStore.class).warning("failed to load code store provider ", e); - } try { final CodeStore store = new DirectoryCodeStore(context); store.initLogger(context); diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java index d8115bc4324..dcebbbb3db8 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/CommandExecutor.java @@ -64,6 +64,9 @@ class CommandExecutor { return System.getProperty("os.name").contains("Windows"); }); + // Cygwin drive alias prefix. + private static final String CYGDRIVE = "/cygdrive/"; + // User's home directory private static final String HOME_DIRECTORY = AccessController.doPrivileged((PrivilegedAction)() -> { @@ -246,18 +249,22 @@ class CommandExecutor { // Stream to copy to. private final OutputStream output; + private final Thread thread; + Piper(final InputStream input, final OutputStream output) { this.input = input; this.output = output; + this.thread = new Thread(this, "$EXEC Piper"); } /** * start - start the Piper in a new daemon thread + * @return this Piper */ - void start() { - Thread thread = new Thread(this, "$EXEC Piper"); + Piper start() { thread.setDaemon(true); thread.start(); + return this; } /** @@ -292,6 +299,10 @@ class CommandExecutor { } } + public void join() throws InterruptedException { + thread.join(); + } + // Exit thread. } @@ -388,7 +399,7 @@ class CommandExecutor { * @return resolved Path to file */ private static Path resolvePath(final String cwd, final String fileName) { - return Paths.get(cwd).resolve(fileName).normalize(); + return Paths.get(sanitizePath(cwd)).resolve(fileName).normalize(); } /** @@ -402,7 +413,8 @@ class CommandExecutor { switch (cmd.get(0)) { // Set current working directory. case "cd": - // If zero args then use home dirrectory as cwd else use first arg. + final boolean cygpath = IS_WINDOWS && cwd.startsWith(CYGDRIVE); + // If zero args then use home directory as cwd else use first arg. final String newCWD = cmd.size() < 2 ? HOME_DIRECTORY : cmd.get(1); // Normalize the cwd final Path cwdPath = resolvePath(cwd, newCWD); @@ -418,7 +430,13 @@ class CommandExecutor { } // Set PWD environment variable to be picked up as cwd. - environment.put("PWD", cwdPath.toString()); + // Make sure Cygwin paths look like Unix paths. + String scwd = cwdPath.toString(); + if (cygpath && scwd.length() >= 2 && + Character.isLetter(scwd.charAt(0)) && scwd.charAt(1) == ':') { + scwd = CYGDRIVE + Character.toLowerCase(scwd.charAt(0)) + "/" + scwd.substring(2); + } + environment.put("PWD", scwd); return true; // Set an environment variable. @@ -445,7 +463,8 @@ class CommandExecutor { } /** - * preprocessCommand - scan the command for redirects + * preprocessCommand - scan the command for redirects, and sanitize the + * executable path * @param tokens command tokens * @param cwd current working directory * @param redirectInfo redirection information @@ -471,9 +490,38 @@ class CommandExecutor { command.add(stripQuotes(token)); } + if (command.size() > 0) { + command.set(0, sanitizePath(command.get(0))); + } + return command; } + /** + * Sanitize a path in case the underlying platform is Cygwin. In that case, + * convert from the {@code /cygdrive/x} drive specification to the usual + * Windows {@code X:} format. + * + * @param d a String representing a path + * @return a String representing the same path in a form that can be + * processed by the underlying platform + */ + private static String sanitizePath(final String d) { + if (!IS_WINDOWS || (IS_WINDOWS && !d.startsWith(CYGDRIVE))) { + return d; + } + final String pd = d.substring(CYGDRIVE.length()); + if (pd.length() >= 2 && pd.charAt(1) == '/') { + // drive letter plus / -> convert /cygdrive/x/... to X:/... + return pd.charAt(0) + ":" + pd.substring(1); + } else if (pd.length() == 1) { + // just drive letter -> convert /cygdrive/x to X: + return pd.charAt(0) + ":"; + } + // remaining case: /cygdrive/ -> can't convert + return d; + } + /** * createProcessBuilder - create a ProcessBuilder for the command. * @param command command tokens @@ -485,7 +533,7 @@ class CommandExecutor { // Create new ProcessBuilder. final ProcessBuilder pb = new ProcessBuilder(command); // Set current working directory. - pb.directory(new File(cwd)); + pb.directory(new File(sanitizePath(cwd))); // Map environment variables. final Map processEnvironment = pb.environment(); @@ -523,7 +571,7 @@ class CommandExecutor { // Create ProcessBuilder with cwd and redirects set. createProcessBuilder(command, cwd, redirectInfo); - // If piped the wait for the next command. + // If piped, wait for the next command. if (isPiped) { return; } @@ -581,15 +629,17 @@ class CommandExecutor { ByteArrayOutputStream byteOutputStream = null; ByteArrayOutputStream byteErrorStream = null; + final List piperThreads = new ArrayList<>(); + // If input is not redirected. if (inputIsPipe) { // If inputStream other than System.in is provided. if (inputStream != null) { // Pipe inputStream to first process output stream. - new Piper(inputStream, firstProcess.getOutputStream()).start(); + piperThreads.add(new Piper(inputStream, firstProcess.getOutputStream()).start()); } else { // Otherwise assume an input string has been provided. - new Piper(new ByteArrayInputStream(inputString.getBytes()), firstProcess.getOutputStream()).start(); + piperThreads.add(new Piper(new ByteArrayInputStream(inputString.getBytes()), firstProcess.getOutputStream()).start()); } } @@ -598,11 +648,11 @@ class CommandExecutor { // If outputStream other than System.out is provided. if (outputStream != null ) { // Pipe outputStream from last process input stream. - new Piper(lastProcess.getInputStream(), outputStream).start(); + piperThreads.add(new Piper(lastProcess.getInputStream(), outputStream).start()); } else { // Otherwise assume an output string needs to be prepared. byteOutputStream = new ByteArrayOutputStream(BUFFER_SIZE); - new Piper(lastProcess.getInputStream(), byteOutputStream).start(); + piperThreads.add(new Piper(lastProcess.getInputStream(), byteOutputStream).start()); } } @@ -610,11 +660,11 @@ class CommandExecutor { if (errorIsPipe) { // If errorStream other than System.err is provided. if (errorStream != null) { - new Piper(lastProcess.getErrorStream(), errorStream).start(); + piperThreads.add(new Piper(lastProcess.getErrorStream(), errorStream).start()); } else { // Otherwise assume an error string needs to be prepared. byteErrorStream = new ByteArrayOutputStream(BUFFER_SIZE); - new Piper(lastProcess.getErrorStream(), byteErrorStream).start(); + piperThreads.add(new Piper(lastProcess.getErrorStream(), byteErrorStream).start()); } } @@ -622,13 +672,13 @@ class CommandExecutor { for (int i = 0, n = processes.size() - 1; i < n; i++) { final Process prev = processes.get(i); final Process next = processes.get(i + 1); - new Piper(prev.getInputStream(), next.getOutputStream()).start(); + piperThreads.add(new Piper(prev.getInputStream(), next.getOutputStream()).start()); } // Wind up processes. try { // Get the user specified timeout. - long timeout = envVarLongValue("JJS_TIMEOUT"); + final long timeout = envVarLongValue("JJS_TIMEOUT"); // If user specified timeout (milliseconds.) if (timeout != 0) { @@ -643,6 +693,10 @@ class CommandExecutor { // Wait for last process and get exit code. exitCode = lastProcess.waitFor(); } + // Wait for all piper threads to terminate + for (final Piper piper : piperThreads) { + piper.join(); + } // Accumulate the output and error streams. outputString += byteOutputStream != null ? byteOutputStream.toString() : ""; @@ -765,7 +819,7 @@ class CommandExecutor { /** * process - process a command array of strings - * @param script command script to be processed + * @param tokens command script to be processed */ void process(final List tokens) { // Prepare to accumulate command tokens. diff --git a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java index 5c312cc6040..42f17522656 100644 --- a/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java +++ b/nashorn/src/jdk.scripting.nashorn/share/classes/jdk/nashorn/internal/runtime/ScriptingFunctions.java @@ -72,7 +72,7 @@ public final class ScriptingFunctions { public static final String EXIT_NAME = "$EXIT"; /** Names of special properties used by $ENV API. */ - public static final String ENV_NAME = "$ENV"; + public static final String ENV_NAME = "$ENV"; /** Name of the environment variable for the current working directory. */ public static final String PWD_NAME = "PWD"; diff --git a/nashorn/test/script/basic/JDK-8026367.js b/nashorn/test/script/basic/JDK-8026367.js index 0b14ecfe481..6d498c1fe7c 100644 --- a/nashorn/test/script/basic/JDK-8026367.js +++ b/nashorn/test/script/basic/JDK-8026367.js @@ -37,10 +37,12 @@ var obj = { // Sync called with one argument will synchronize on this-object of invocation inc: sync(function(d) { this.count += d; + Assert.assertTrue(java.lang.Thread.holdsLock(this)); }), // Pass explicit object to synchronize on as second argument dec: sync(function(d) { this.count -= d; + Assert.assertTrue(java.lang.Thread.holdsLock(obj)); }, obj) }; diff --git a/nashorn/test/script/nosecurity/JDK-8151291.js b/nashorn/test/script/nosecurity/JDK-8151291.js new file mode 100644 index 00000000000..15ae427913c --- /dev/null +++ b/nashorn/test/script/nosecurity/JDK-8151291.js @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Test $EXEC and $ENV.PWD handling across platforms. + * There must be a java executable in the PATH. + * + * @test + * @option -scripting + * @run + */ + +$EXEC(["java", "-version"]) +if ($EXIT != 0) { + throw 'java executable problem: ' + $ERR +} + +function eq(p, q, e) { + if (p != q) { + throw e + } +} + +function neq(p, q, e) { + if (p == q) { + throw e + } +} + +var File = Java.type("java.io.File"), + System = Java.type("java.lang.System"), + win = System.getProperty("os.name").startsWith("Windows"), + sep = File.separator, + startwd = $ENV.PWD, + upwd = startwd.substring(0, startwd.lastIndexOf(sep)) + +$EXEC("ls") +var ls_startwd = $OUT +$EXEC("cd ..; ls") +var ls_cdupwd = $OUT +eq($ENV.PWD, startwd, 'PWD changed during $EXEC cd') +neq(ls_startwd, ls_cdupwd, 'same ls result for startwd and upwd with $EXEC cd') + +$ENV.PWD = upwd +eq($ENV.PWD, upwd, '$ENV.PWD change had no effect') +$EXEC("ls") +var ls_epupwd = $OUT +neq(ls_startwd, ls_epupwd, 'same ls result for startwd and upwd with $ENV.PWD cd') diff --git a/nashorn/test/script/trusted/JDK-8087292.js b/nashorn/test/script/trusted/JDK-8087292.js index 41869ed68dc..fec9efb37c4 100644 --- a/nashorn/test/script/trusted/JDK-8087292.js +++ b/nashorn/test/script/trusted/JDK-8087292.js @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,26 +29,58 @@ * @run */ +load(__DIR__ + "JDK-util.js") + +var jHomePath = System.getenv("JAVA_HOME") +var jLauncher = "${jHomePath}/bin/java" +var altjLauncher = which('java') + +if (windows) { + if(winCyg) { + jLauncher = "${jHomePath}" + "/bin/java.exe" + jLauncher = cygpath(jLauncher,outPath.windows) + } + else { + jLauncher = "${jHomePath}" + "\\bin\\java.exe" + altjLauncher = which('java.exe') + altjLauncher = cygpath(altjLauncher,outPath.windows) + } +} + +function exists(f) { + return Files.exists(Paths.get(f)) +} + +var javaLauncher = exists(jLauncher) ? jLauncher : altjLauncher + + +if (!exists(javaLauncher)) { + throw "no java launcher found; tried ${jLauncher} and ${altjLauncher}" +} + function tryExec() { try { - `java` + $EXEC("${javaLauncher}") } catch (e) { - print(e); + print(e) } // make sure we got non-zero ("failure") exit code! if ($EXIT == 0) { - print("Error: expected $EXIT code to be non-zero"); + print("Error: expected $EXIT code to be non-zero") } } +//convert windows paths to cygwin +if (windows) + javaLauncher = (winCyg) ? cygpath(javaLauncher,outPath.mixed).trim() : cygpath(javaLauncher,outPath.windows).trim() // no exception now! -tryExec(); +tryExec() // turn on error with non-zero exit code -$ENV.JJS_THROW_ON_EXIT = "1"; -tryExec(); +$ENV.JJS_THROW_ON_EXIT = "1" +tryExec() // no exception after this -$ENV.JJS_THROW_ON_EXIT = "0"; -tryExec(); +$ENV.JJS_THROW_ON_EXIT = "0" +tryExec() diff --git a/nashorn/test/script/trusted/JDK-util.js b/nashorn/test/script/trusted/JDK-util.js new file mode 100644 index 00000000000..f2a118315ce --- /dev/null +++ b/nashorn/test/script/trusted/JDK-util.js @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This file contains utility functions used by other tests. + * @subtest + */ + +var Files = Java.type('java.nio.file.Files'), + Paths = Java.type('java.nio.file.Paths'), + System = Java.type('java.lang.System') + +var File = java.io.File +var windows = System.getProperty("os.name").startsWith("Windows") +var winCyg = false + +var outPath = { + windows:0, //C:\dir + mixed:1 //C:/dir +} + +if (windows) { + //Is there any better way to diffrentiate between cygwin/command prompt on windows + var term = System.getenv("TERM") + winCyg = term ? true:false +} + +/** + * Returns which command is selected from PATH + * @param cmd name of the command searched from PATH + */ +function which(cmd) { + var path = System.getenv("PATH") + var st = new java.util.StringTokenizer(path, File.pathSeparator) + while (st.hasMoreTokens()) { + var file = new File(st.nextToken(), cmd) + if (file.exists()) { + return (file.getAbsolutePath()) + } + } +} + +/** + * Unix cygpath implementation + * Supports only two outputs,windows(C:\dir\) and mixed(C:/dir/) + */ +function cygpath(path,mode) { + + var newpath = path + if(path.startsWith("/cygdrive/")){ + var str = path.substring(10) + var index = str.indexOf('/',0) + var drv = str.substring(0,index) + var rstr = drv.toUpperCase() + ":" + newpath = str.replaceFirst(drv,rstr) + } + if (mode == outPath.windows) + return Paths.get(newpath).toString() + else { + newpath = newpath.replaceAll('\\\\','/') + return newpath + } + +} + diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java index fcf3df7251b..43b9c4b2b23 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/test/JDK_8148140_Test.java @@ -22,7 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.nashorn.internal.runtime.test; +package jdk.nashorn.api.scripting.test; import java.util.Arrays; import javax.script.ScriptEngine; @@ -70,4 +70,4 @@ public class JDK_8148140_Test { assertEquals(RESULT, engine.eval("Function.prototype.apply.call(f, null, [1,2,3])")); } -} \ No newline at end of file +} diff --git a/test/lib/sun/hotspot/WhiteBox.java b/test/lib/sun/hotspot/WhiteBox.java index 6b7863ad938..668d2f00c1a 100644 --- a/test/lib/sun/hotspot/WhiteBox.java +++ b/test/lib/sun/hotspot/WhiteBox.java @@ -119,6 +119,28 @@ public class WhiteBox { return getConstantPool0(aClass); } + private native int getConstantPoolCacheIndexTag0(); + public int getConstantPoolCacheIndexTag() { + return getConstantPoolCacheIndexTag0(); + } + + private native int getConstantPoolCacheLength0(Class aClass); + public int getConstantPoolCacheLength(Class aClass) { + Objects.requireNonNull(aClass); + return getConstantPoolCacheLength0(aClass); + } + + private native int remapInstructionOperandFromCPCache0(Class aClass, int index); + public int remapInstructionOperandFromCPCache(Class aClass, int index) { + Objects.requireNonNull(aClass); + return remapInstructionOperandFromCPCache0(aClass, index); + } + + private native int encodeConstantPoolIndyIndex0(int index); + public int encodeConstantPoolIndyIndex(int index) { + return encodeConstantPoolIndyIndex0(index); + } + // JVMTI private native void addToBootstrapClassLoaderSearch0(String segment); public void addToBootstrapClassLoaderSearch(String segment){ @@ -185,7 +207,7 @@ public class WhiteBox { // Compiler public native int matchesMethod(Executable method, String pattern); public native int matchesInline(Executable method, String pattern); - public native boolean shouldPrintAssembly(Executable method); + public native boolean shouldPrintAssembly(Executable method, int comp_level); public native int deoptimizeFrames(boolean makeNotEntrant); public native void deoptimizeAll();