diff --git a/.hgtags b/.hgtags index f59b4028db2..f5f0bdfd1da 100644 --- a/.hgtags +++ b/.hgtags @@ -228,3 +228,6 @@ bbe43d712fe08e650808d774861b256ccb34e500 jdk8-b102 b5ed503c26ad38869c247c5e32debec217fd056b jdk8-b104 589f4fdc584e373a47cde0162e9eceec9165c381 jdk8-b105 514b0b69fb9683ef52062fd962a3e0644431f64d jdk8-b106 +892889f445755790ae90e61775bfb59ddc6182b5 jdk8-b107 +74049f7a28b48c14910106a75d9f2504169c352e jdk8-b108 +af9a674e12a16da1a4bd53e4990ddb1121a21ef1 jdk8-b109 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index ca1497b3968..8ee790af31a 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -228,3 +228,6 @@ b7e64be81c8a7690703df5711f4fc2375da8a9cb jdk8-b103 96c1b9b7524b52c3fcefc90ffad4c767396727c8 jdk8-b104 5166118c59178b5d31001bc4058e92486ee07d9b jdk8-b105 8e7b4d9fb00fdf1334376aeac050c9bca6d1b383 jdk8-b106 +0874bb4707b723d5bb108d379c557cf41529d1a7 jdk8-b107 +9286a6e61291246d88af713f1ef79adeea30fe2e jdk8-b108 +91f47e8da5c60de58ed195e9b57f3bf192a18f83 jdk8-b109 diff --git a/Makefile b/Makefile index f7b9d1b35e3..2ef4bb99853 100644 --- a/Makefile +++ b/Makefile @@ -404,7 +404,6 @@ COMPILER_PATH.desc = Compiler install directory CACERTS_FILE.desc = Location of certificates file DEVTOOLS_PATH.desc = Directory containing zip and gnumake CUPS_HEADERS_PATH.desc = Include directory location for CUPS header files -DXSDK_PATH.desc = Root directory of DirectX SDK # Make variables to print out (description and value) VARIABLE_PRINTVAL_LIST += \ @@ -429,17 +428,6 @@ VARIABLE_CHECKDIR_LIST += \ VARIABLE_CHECKFIL_LIST += \ CACERTS_FILE -# Some are windows specific -ifeq ($(PLATFORM), windows) - -VARIABLE_PRINTVAL_LIST += \ - DXSDK_PATH - -VARIABLE_CHECKDIR_LIST += \ - DXSDK_PATH - -endif - # For pattern rules below, so all are treated the same DO_PRINTVAL_LIST=$(VARIABLE_PRINTVAL_LIST:%=%.printval) DO_CHECKDIR_LIST=$(VARIABLE_CHECKDIR_LIST:%=%.checkdir) diff --git a/README-builds.html b/README-builds.html index 71c05c0fbf4..14796a27e87 100644 --- a/README-builds.html +++ b/README-builds.html @@ -444,10 +444,6 @@ Install Visual Studio 2010 -
  • - Install the - Microsoft DirectX SDK -
  • @@ -971,25 +967,6 @@ developer install location - - --with-dxsdk=path - - select location of the Windows Direct X SDK install -
    - The Microsoft DirectX 9.0 SDK - header files and libraries - from the Summer 2004 edition - are required for building OpenJDK. - This SDK can be downloaded from - - Microsoft DirectX 9.0 SDK (Summer 2004). - If the link above becomes obsolete, the SDK can be found from - the Microsoft Download Site - (search with "DirectX 9.0 SDK Update Summer 2004"). - Installation usually will set the environment variable - DXSDK_DIR to it's install location. - - --with-freetype=path diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 126993b5cd7..f3911ff9bd9 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -203,6 +203,15 @@ AC_DEFUN([BASIC_REMOVE_SYMBOLIC_LINKS], fi ]) +# Register a --with argument but mark it as deprecated +# $1: The name of the with argument to deprecate, not including --with- +AC_DEFUN([BASIC_DEPRECATED_ARG_WITH], +[ + AC_ARG_WITH($1, [AS_HELP_STRING([--with-$1], + [Deprecated. Option is kept for backwards compatibility and is ignored])], + [AC_MSG_WARN([Option --with-$1 is deprecated and will be ignored.])]) +]) + AC_DEFUN_ONCE([BASIC_INIT], [ # Save the original command line. This is passed to us by the wrapper configure script. diff --git a/common/autoconf/basics_windows.m4 b/common/autoconf/basics_windows.m4 index 9ddb9e8c5c0..0a26d830239 100644 --- a/common/autoconf/basics_windows.m4 +++ b/common/autoconf/basics_windows.m4 @@ -211,7 +211,7 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_CYGWIN], # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then diff --git a/common/autoconf/build-aux/autoconf-config.guess b/common/autoconf/build-aux/autoconf-config.guess index 3aa7f690629..15ee4389269 100644 --- a/common/autoconf/build-aux/autoconf-config.guess +++ b/common/autoconf/build-aux/autoconf-config.guess @@ -26,10 +26,10 @@ # Attempt to guess a canonical system name. # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, -# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 -# Free Software Foundation, Inc. +# 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, +# 2011, 2012 Free Software Foundation, Inc. -timestamp='2008-01-23' +timestamp='2012-02-10' # This file is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by @@ -42,9 +42,7 @@ timestamp='2008-01-23' # General Public License for more details. # # You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA -# 02110-1301, USA. +# along with this program; if not, see . # # As a special exception to the GNU General Public License, if you # distribute this file as part of a program that contains a @@ -52,16 +50,16 @@ timestamp='2008-01-23' # the same distribution terms that you use for the rest of that program. -# Originally written by Per Bothner . -# Please send patches to . Submit a context -# diff and a properly formatted ChangeLog entry. +# Originally written by Per Bothner. Please send patches (context +# diff format) to and include a ChangeLog +# entry. # # This script attempts to guess a canonical system name similar to # config.sub. If it succeeds, it prints the system name on stdout, and # exits with 0. Otherwise, it exits with 1. # -# The plan is that this can be called by configure scripts if you -# don't specify an explicit build system type. +# You can get the latest version of this script from: +# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess;hb=HEAD me=`echo "$0" | sed -e 's,.*/,,'` @@ -81,8 +79,9 @@ version="\ GNU config.guess ($timestamp) Originally written by Per Bothner. -Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, -2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, +2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 +Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." @@ -169,7 +168,7 @@ UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in *:NetBSD:*:*) # NetBSD (nbsd) targets should (where applicable) match one or - # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*, # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently # switched to ELF, *-*-netbsd* would select the old # object file format. This provides both forward @@ -195,7 +194,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in arm*|i386|m68k|ns32k|sh3*|sparc|vax) eval $set_cc_for_build if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep __ELF__ >/dev/null + | grep -q __ELF__ then # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). # Return netbsd for either. FIX? @@ -205,7 +204,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in fi ;; *) - os=netbsd + os=netbsd ;; esac # The OS release @@ -248,7 +247,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` ;; *5.*) - UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'` ;; esac # According to Compaq, /usr/sbin/psrinfo has been available on @@ -294,7 +293,10 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # A Xn.n version is an unreleased experimental baselevel. # 1.2 uses "1.2" for uname -r. echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - exit ;; + # Reset EXIT trap before exiting to avoid spurious non-zero exit code. + exitcode=$? + trap '' 0 + exit $exitcode ;; Alpha\ *:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # Should we change UNAME_MACHINE based on the output of uname instead @@ -320,7 +322,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in echo s390-ibm-zvmoe exit ;; *:OS400:*:*) - echo powerpc-ibm-os400 + echo powerpc-ibm-os400 exit ;; arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) echo arm-acorn-riscix${UNAME_RELEASE} @@ -349,14 +351,33 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in case `/usr/bin/uname -p` in sparc) echo sparc-icl-nx7; exit ;; esac ;; + s390x:SunOS:*:*) + echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit ;; sun4H:SunOS:5.*:*) echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; + i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*) + echo i386-pc-auroraux${UNAME_RELEASE} + exit ;; i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*) - echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + eval $set_cc_for_build + SUN_ARCH="i386" + # If there is a compiler, see if it is configured for 64-bit objects. + # Note that the Sun cc does not turn __LP64__ into 1 like gcc does. + # This test works for both compilers. + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + SUN_ARCH="x86_64" + fi + fi + echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` exit ;; sun4*:SunOS:6*:*) # According to config.sub, this is the proper way to canonicalize @@ -400,23 +421,23 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in # MiNT. But MiNT is downward compatible to TOS, so this should # be no problem. atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) echo m68k-atari-mint${UNAME_RELEASE} - exit ;; + exit ;; *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) - echo m68k-atari-mint${UNAME_RELEASE} + echo m68k-atari-mint${UNAME_RELEASE} exit ;; milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) - echo m68k-milan-mint${UNAME_RELEASE} - exit ;; + echo m68k-milan-mint${UNAME_RELEASE} + exit ;; hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) - echo m68k-hades-mint${UNAME_RELEASE} - exit ;; + echo m68k-hades-mint${UNAME_RELEASE} + exit ;; *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) - echo m68k-unknown-mint${UNAME_RELEASE} - exit ;; + echo m68k-unknown-mint${UNAME_RELEASE} + exit ;; m68k:machten:*:*) echo m68k-apple-machten${UNAME_RELEASE} exit ;; @@ -486,8 +507,8 @@ EOF echo m88k-motorola-sysv3 exit ;; AViiON:dgux:*:*) - # DG/UX returns AViiON for all architectures - UNAME_PROCESSOR=`/usr/bin/uname -p` + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] then if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ @@ -500,7 +521,7 @@ EOF else echo i586-dg-dgux${UNAME_RELEASE} fi - exit ;; + exit ;; M88*:DolphinOS:*:*) # DolphinOS (SVR3) echo m88k-dolphin-sysv3 exit ;; @@ -557,7 +578,7 @@ EOF echo rs6000-ibm-aix3.2 fi exit ;; - *:AIX:*:[456]) + *:AIX:*:[4567]) IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then IBM_ARCH=rs6000 @@ -600,52 +621,52 @@ EOF 9000/[678][0-9][0-9]) if [ -x /usr/bin/getconf ]; then sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` - sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` - case "${sc_cpu_version}" in - 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 - 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 - 532) # CPU_PA_RISC2_0 - case "${sc_kernel_bits}" in - 32) HP_ARCH="hppa2.0n" ;; - 64) HP_ARCH="hppa2.0w" ;; + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 - esac ;; - esac + esac ;; + esac fi if [ "${HP_ARCH}" = "" ]; then eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c + sed 's/^ //' << EOF >$dummy.c - #define _HPUX_SOURCE - #include - #include + #define _HPUX_SOURCE + #include + #include - int main () - { - #if defined(_SC_KERNEL_BITS) - long bits = sysconf(_SC_KERNEL_BITS); - #endif - long cpu = sysconf (_SC_CPU_VERSION); + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); - switch (cpu) - { - case CPU_PA_RISC1_0: puts ("hppa1.0"); break; - case CPU_PA_RISC1_1: puts ("hppa1.1"); break; - case CPU_PA_RISC2_0: - #if defined(_SC_KERNEL_BITS) - switch (bits) - { - case 64: puts ("hppa2.0w"); break; - case 32: puts ("hppa2.0n"); break; - default: puts ("hppa2.0"); break; - } break; - #else /* !defined(_SC_KERNEL_BITS) */ - puts ("hppa2.0"); break; - #endif - default: puts ("hppa1.0"); break; - } - exit (0); - } + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } EOF (CCOPTS= $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy` test -z "$HP_ARCH" && HP_ARCH=hppa @@ -665,7 +686,7 @@ EOF # => hppa64-hp-hpux11.23 if echo __LP64__ | (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | - grep __LP64__ >/dev/null + grep -q __LP64__ then HP_ARCH="hppa2.0w" else @@ -736,22 +757,22 @@ EOF exit ;; C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) echo c1-convex-bsd - exit ;; + exit ;; C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) if getsysinfo -f scalar_acc then echo c32-convex-bsd else echo c2-convex-bsd fi - exit ;; + exit ;; C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) echo c34-convex-bsd - exit ;; + exit ;; C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) echo c38-convex-bsd - exit ;; + exit ;; C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) echo c4-convex-bsd - exit ;; + exit ;; CRAY*Y-MP:*:*:*) echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' exit ;; @@ -775,14 +796,14 @@ EOF exit ;; F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` - echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" - exit ;; + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit ;; 5000:UNIX_System_V:4.*:*) - FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` - FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` - echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/ /_/'` + echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" exit ;; i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} @@ -794,13 +815,12 @@ EOF echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} exit ;; *:FreeBSD:*:*) - case ${UNAME_MACHINE} in - pc98) - echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + UNAME_PROCESSOR=`/usr/bin/uname -p` + case ${UNAME_PROCESSOR} in amd64) echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; *) - echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; + echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;; esac exit ;; i*:CYGWIN*:*) @@ -809,19 +829,22 @@ EOF *:MINGW*:*) echo ${UNAME_MACHINE}-pc-mingw32 exit ;; + i*:MSYS*:*) + echo ${UNAME_MACHINE}-pc-msys + exit ;; i*:windows32*:*) - # uname -m includes "-pc" on this system. - echo ${UNAME_MACHINE}-mingw32 + # uname -m includes "-pc" on this system. + echo ${UNAME_MACHINE}-mingw32 exit ;; i*:PW*:*) echo ${UNAME_MACHINE}-pc-pw32 exit ;; - *:Interix*:[3456]*) - case ${UNAME_MACHINE} in + *:Interix*:*) + case ${UNAME_MACHINE} in x86) echo i586-pc-interix${UNAME_RELEASE} exit ;; - EM64T | authenticamd) + authenticamd | genuineintel | EM64T) echo x86_64-unknown-interix${UNAME_RELEASE} exit ;; IA64) @@ -831,6 +854,9 @@ EOF [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*) echo i${UNAME_MACHINE}-pc-mks exit ;; + 8664:Windows_NT:*) + echo x86_64-pc-mks + exit ;; i*:Windows_NT*:* | Pentium*:Windows_NT*:*) # How do we know it's Interix rather than the generic POSIX subsystem? # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we @@ -860,92 +886,13 @@ EOF i*86:Minix:*:*) echo ${UNAME_MACHINE}-pc-minix exit ;; - arm*:Linux:*:*) - eval $set_cc_for_build - if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ - | grep -q __ARM_EABI__ - then - echo ${UNAME_MACHINE}-unknown-linux-gnu - else - echo ${UNAME_MACHINE}-unknown-linux-gnueabi - fi - exit ;; - avr32*:Linux:*:*) + aarch64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - cris:Linux:*:*) - echo cris-axis-linux-gnu - exit ;; - crisv32:Linux:*:*) - echo crisv32-axis-linux-gnu - exit ;; - frv:Linux:*:*) - echo frv-unknown-linux-gnu - exit ;; - ia64:Linux:*:*) + aarch64_be:Linux:*:*) + UNAME_MACHINE=aarch64_be echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - m32r*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - m68*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu - exit ;; - mips:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips - #undef mipsel - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mipsel - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - mips64:Linux:*:*) - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #undef CPU - #undef mips64 - #undef mips64el - #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) - CPU=mips64el - #else - #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) - CPU=mips64 - #else - CPU= - #endif - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^CPU/{ - s: ::g - p - }'`" - test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } - ;; - or32:Linux:*:*) - echo or32-unknown-linux-gnu - exit ;; - ppc:Linux:*:*) - echo powerpc-unknown-linux-gnu - exit ;; - ppc64:Linux:*:*) - echo powerpc64-unknown-linux-gnu - exit ;; alpha:Linux:*:*) case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in EV5) UNAME_MACHINE=alphaev5 ;; @@ -955,11 +902,90 @@ EOF EV6) UNAME_MACHINE=alphaev6 ;; EV67) UNAME_MACHINE=alphaev67 ;; EV68*) UNAME_MACHINE=alphaev68 ;; - esac - objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + esac + objdump --private-headers /bin/sh | grep -q ld.so.1 if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} exit ;; + arm*:Linux:*:*) + eval $set_cc_for_build + if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_EABI__ + then + echo ${UNAME_MACHINE}-unknown-linux-gnu + else + if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep -q __ARM_PCS_VFP + then + echo ${UNAME_MACHINE}-unknown-linux-gnueabi + else + echo ${UNAME_MACHINE}-unknown-linux-gnueabihf + fi + fi + exit ;; + avr32*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + cris:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + crisv32:Linux:*:*) + echo ${UNAME_MACHINE}-axis-linux-gnu + exit ;; + frv:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + hexagon:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + i*86:Linux:*:*) + LIBC=gnu + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #ifdef __dietlibc__ + LIBC=dietlibc + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC'` + echo "${UNAME_MACHINE}-pc-linux-${LIBC}" + exit ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m32r*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + mips:Linux:*:* | mips64:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef ${UNAME_MACHINE} + #undef ${UNAME_MACHINE}el + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=${UNAME_MACHINE}el + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=${UNAME_MACHINE} + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'` + test x"${CPU}" != x && { echo "${CPU}-unknown-linux-gnu"; exit; } + ;; + or32:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; + padre:Linux:*:*) + echo sparc-unknown-linux-gnu + exit ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit ;; parisc:Linux:*:* | hppa:Linux:*:*) # Look for CPU level case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in @@ -968,14 +994,17 @@ EOF *) echo hppa-unknown-linux-gnu ;; esac exit ;; - parisc64:Linux:*:* | hppa64:Linux:*:*) - echo hppa64-unknown-linux-gnu + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu exit ;; s390:Linux:*:* | s390x:Linux:*:*) echo ${UNAME_MACHINE}-ibm-linux exit ;; sh64*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; sh*:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu @@ -983,78 +1012,18 @@ EOF sparc:Linux:*:* | sparc64:Linux:*:*) echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; + tile*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit ;; vax:Linux:*:*) echo ${UNAME_MACHINE}-dec-linux-gnu exit ;; x86_64:Linux:*:*) - echo x86_64-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; xtensa*:Linux:*:*) - echo ${UNAME_MACHINE}-unknown-linux-gnu + echo ${UNAME_MACHINE}-unknown-linux-gnu exit ;; - i*86:Linux:*:*) - # The BFD linker knows what the default object file format is, so - # first see if it will tell us. cd to the root directory to prevent - # problems with other programs or directories called `ld' in the path. - # Set LC_ALL=C to ensure ld outputs messages in English. - ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ - | sed -ne '/supported targets:/!d - s/[ ][ ]*/ /g - s/.*supported targets: *// - s/ .*// - p'` - case "$ld_supported_targets" in - elf32-i386) - TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" - ;; - a.out-i386-linux) - echo "${UNAME_MACHINE}-pc-linux-gnuaout" - exit ;; - coff-i386) - echo "${UNAME_MACHINE}-pc-linux-gnucoff" - exit ;; - "") - # Either a pre-BFD a.out linker (linux-gnuoldld) or - # one that does not give us useful --help. - echo "${UNAME_MACHINE}-pc-linux-gnuoldld" - exit ;; - esac - # Determine whether the default compiler is a.out or elf - eval $set_cc_for_build - sed 's/^ //' << EOF >$dummy.c - #include - #ifdef __ELF__ - # ifdef __GLIBC__ - # if __GLIBC__ >= 2 - LIBC=gnu - # else - LIBC=gnulibc1 - # endif - # else - LIBC=gnulibc1 - # endif - #else - #if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) - LIBC=gnu - #else - LIBC=gnuaout - #endif - #endif - #ifdef __dietlibc__ - LIBC=dietlibc - #endif -EOF - eval "`$CC_FOR_BUILD -E $dummy.c 2>/dev/null | sed -n ' - /^LIBC/{ - s: ::g - p - }'`" - test x"${LIBC}" != x && { - echo "${UNAME_MACHINE}-pc-linux-${LIBC}" - exit - } - test x"${TENTATIVE}" != x && { echo "${TENTATIVE}"; exit; } - ;; i*86:DYNIX/ptx:4*:*) # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. # earlier versions are messed up and put the nodename in both @@ -1062,11 +1031,11 @@ EOF echo i386-sequent-sysv4 exit ;; i*86:UNIX_SV:4.2MP:2.*) - # Unixware is an offshoot of SVR4, but it has its own version - # number series starting with 2... - # I am not positive that other SVR4 systems won't match this, + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, # I just have to hope. -- rms. - # Use sysv4.2uw... so that sysv4* matches it. + # Use sysv4.2uw... so that sysv4* matches it. echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} exit ;; i*86:OS/2:*:*) @@ -1083,7 +1052,7 @@ EOF i*86:syllable:*:*) echo ${UNAME_MACHINE}-pc-syllable exit ;; - i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*) echo i386-unknown-lynxos${UNAME_RELEASE} exit ;; i*86:*DOS:*:*) @@ -1098,7 +1067,7 @@ EOF fi exit ;; i*86:*:5:[678]*) - # UnixWare 7.x, OpenUNIX and OpenServer 6. + # UnixWare 7.x, OpenUNIX and OpenServer 6. case `/bin/uname -X | grep "^Machine"` in *486*) UNAME_MACHINE=i486 ;; *Pentium) UNAME_MACHINE=i586 ;; @@ -1126,10 +1095,13 @@ EOF exit ;; pc:*:*:*) # Left here for compatibility: - # uname -m prints for DJGPP always 'pc', but it prints nothing about - # the processor, so we play safe by assuming i386. - echo i386-pc-msdosdjgpp - exit ;; + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i586. + # Note: whatever this is, it MUST be the same as what config.sub + # prints for the "djgpp" host, or else GDB configury will decide that + # this is a cross-build. + echo i586-pc-msdosdjgpp + exit ;; Intel:Mach:3*:*) echo i386-pc-mach3 exit ;; @@ -1164,8 +1136,18 @@ EOF /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) - /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ - && { echo i486-ncr-sysv4; exit; } ;; + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4; exit; } ;; + NCR*:*:4.2:* | MPRAS*:*:4.2:*) + OS_REL='.3' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && { echo i486-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } + /bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \ + && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;; m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) echo m68k-unknown-lynxos${UNAME_RELEASE} exit ;; @@ -1178,7 +1160,7 @@ EOF rs6000:LynxOS:2.*:*) echo rs6000-unknown-lynxos${UNAME_RELEASE} exit ;; - PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*) echo powerpc-unknown-lynxos${UNAME_RELEASE} exit ;; SM[BE]S:UNIX_SV:*:*) @@ -1198,10 +1180,10 @@ EOF echo ns32k-sni-sysv fi exit ;; - PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort - # says - echo i586-unisys-sysv4 - exit ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says + echo i586-unisys-sysv4 + exit ;; *:UNIX_System_V:4*:FTX*) # From Gerald Hewes . # How about differentiating between stratus architectures? -djm @@ -1227,11 +1209,11 @@ EOF exit ;; R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) if [ -d /usr/nec ]; then - echo mips-nec-sysv${UNAME_RELEASE} + echo mips-nec-sysv${UNAME_RELEASE} else - echo mips-unknown-sysv${UNAME_RELEASE} + echo mips-unknown-sysv${UNAME_RELEASE} fi - exit ;; + exit ;; BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. echo powerpc-be-beos exit ;; @@ -1241,6 +1223,9 @@ EOF BePC:BeOS:*:*) # BeOS running on Intel PC compatible. echo i586-pc-beos exit ;; + BePC:Haiku:*:*) # Haiku running on Intel PC compatible. + echo i586-pc-haiku + exit ;; SX-4:SUPER-UX:*:*) echo sx4-nec-superux${UNAME_RELEASE} exit ;; @@ -1267,12 +1252,17 @@ EOF exit ;; *:Darwin:*:*) UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown - eval $set_cc_for_build - echo "int main(){}" > $dummy.c - if test "`$CC_FOR_BUILD -o $dummy $dummy.c; file $dummy | grep -c x86_64`" = 1 ; then - UNAME_PROCESSOR=x86_64 - fi case $UNAME_PROCESSOR in + i386) + eval $set_cc_for_build + if [ "$CC_FOR_BUILD" != 'no_compiler_found' ]; then + if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \ + (CCOPTS= $CC_FOR_BUILD -E - 2>/dev/null) | \ + grep IS_64BIT_ARCH >/dev/null + then + UNAME_PROCESSOR="x86_64" + fi + fi ;; unknown) UNAME_PROCESSOR=powerpc ;; esac echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE} @@ -1288,6 +1278,9 @@ EOF *:QNX:*:4*) echo i386-pc-qnx exit ;; + NEO-?:NONSTOP_KERNEL:*:*) + echo neo-tandem-nsk${UNAME_RELEASE} + exit ;; NSE-?:NONSTOP_KERNEL:*:*) echo nse-tandem-nsk${UNAME_RELEASE} exit ;; @@ -1333,13 +1326,13 @@ EOF echo pdp10-unknown-its exit ;; SEI:*:*:SEIUX) - echo mips-sei-seiux${UNAME_RELEASE} + echo mips-sei-seiux${UNAME_RELEASE} exit ;; *:DragonFly:*:*) echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` exit ;; *:*VMS:*:*) - UNAME_MACHINE=`(uname -p) 2>/dev/null` + UNAME_MACHINE=`(uname -p) 2>/dev/null` case "${UNAME_MACHINE}" in A*) echo alpha-dec-vms ; exit ;; I*) echo ia64-dec-vms ; exit ;; @@ -1354,6 +1347,12 @@ EOF i*86:rdos:*:*) echo ${UNAME_MACHINE}-pc-rdos exit ;; + i*86:AROS:*:*) + echo ${UNAME_MACHINE}-pc-aros + exit ;; + x86_64:VMkernel:*:*) + echo ${UNAME_MACHINE}-unknown-esx + exit ;; esac #echo '(No uname command or uname output not recognized.)' 1>&2 @@ -1376,11 +1375,11 @@ main () #include printf ("m68k-sony-newsos%s\n", #ifdef NEWSOS4 - "4" + "4" #else - "" + "" #endif - ); exit (0); + ); exit (0); #endif #endif diff --git a/common/autoconf/configure b/common/autoconf/configure index 8e4560df114..7378efe379d 100644 --- a/common/autoconf/configure +++ b/common/autoconf/configure @@ -219,9 +219,4 @@ else echo configure exiting with result code $conf_result_code fi -# Move the log file to the output root, if this was successfully created -if test -d "$OUTPUT_ROOT"; then - mv -f config.log "$OUTPUT_ROOT" 2> /dev/null -fi - exit $conf_result_code diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index 274f278fb3d..ad8bd97cea3 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -232,9 +232,15 @@ CUSTOM_LATE_HOOK # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$OUTPUT_ROOT/config.status" + # Create the actual output files. Now the main work of configure is done. AC_OUTPUT +# Try to move the config.log file to the output directory. +if test -e ./config.log; then + $MV -f ./config.log "$OUTPUT_ROOT/config.log" 2> /dev/null +fi + # Make the compare script executable $CHMOD +x $OUTPUT_ROOT/compare.sh diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 7679cc5c4df..7a65a92ecc4 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -709,7 +709,6 @@ STATIC_LIBRARY SHARED_LIBRARY OBJ_SUFFIX COMPILER_NAME -TARGET_BITS_FLAG JT_HOME JTREGEXE LIPO @@ -766,8 +765,6 @@ BUILD_LD BUILD_CXX BUILD_CC MSVCR_DLL -DXSDK_INCLUDE_PATH -DXSDK_LIB_PATH VS_PATH VS_LIB VS_INCLUDE @@ -1031,6 +1028,7 @@ with_override_corba with_override_jaxp with_override_jaxws with_override_hotspot +with_override_nashorn with_override_jdk with_import_hotspot with_msvcr_dll @@ -1784,17 +1782,19 @@ Optional Packages: --with-override-jaxp use this jaxp dir for the build --with-override-jaxws use this jaxws dir for the build --with-override-hotspot use this hotspot dir for the build + --with-override-nashorn use this nashorn dir for the build --with-override-jdk use this jdk dir for the build --with-import-hotspot import hotspot binaries from this jdk image or hotspot build dist dir instead of building from source --with-msvcr-dll copy this msvcr100.dll into the built JDK (Windows only) [probed] - --with-dxsdk the DirectX SDK (Windows only) [probed] - --with-dxsdk-lib the DirectX SDK lib directory (Windows only) - [probed] - --with-dxsdk-include the DirectX SDK include directory (Windows only) - [probed] + --with-dxsdk Deprecated. Option is kept for backwards + compatibility and is ignored + --with-dxsdk-lib Deprecated. Option is kept for backwards + compatibility and is ignored + --with-dxsdk-include Deprecated. Option is kept for backwards + compatibility and is ignored --with-jtreg Regression Test Harness [probed] --with-extra-cflags extra flags to be used when compiling jdk c-files --with-extra-cxxflags extra flags to be used when compiling jdk c++-files @@ -3144,6 +3144,10 @@ ac_configure="$SHELL $ac_aux_dir/configure" # Please don't use this var. +# Register a --with argument but mark it as deprecated +# $1: The name of the with argument to deprecate, not including --with- + + # Test that variable $1 denoting a program is not empty. If empty, exit with an error. @@ -3805,10 +3809,6 @@ fi -# Setup the DXSDK paths - - - @@ -3818,7 +3818,7 @@ fi #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1378914658 +DATE_WHEN_GENERATED=1379504921 ############################################################################### # @@ -8352,7 +8352,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -8709,7 +8709,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -9063,7 +9063,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -9422,7 +9422,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -9775,7 +9775,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -11075,7 +11075,7 @@ elif test "x$with_user_release_suffix" != x; then else BUILD_DATE=`date '+%Y_%m_%d_%H_%M'` # Avoid [:alnum:] since it depends on the locale. - CLEAN_USERNAME=`echo "$USER" | $TR -d -c 'abcdefghijklmnopqrstuvqxyz0123456789'` + CLEAN_USERNAME=`echo "$USER" | $TR -d -c 'abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'` USER_RELEASE_SUFFIX=`echo "${CLEAN_USERNAME}_${BUILD_DATE}" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` fi @@ -16102,6 +16102,10 @@ if test "x$with_add_source_root" != x; then test -f $with_add_source_root/hotspot/make/Makefile; then as_fn_error $? "Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources." "$LINENO" 5 fi + if test -f $with_add_source_root/nashorn/makefiles/Makefile || \ + test -f $with_add_source_root/nashorn/make/Makefile; then + as_fn_error $? "Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources." "$LINENO" 5 + fi if test -f $with_add_source_root/jdk/makefiles/Makefile || \ test -f $with_add_source_root/jdk/make/Makefile; then as_fn_error $? "Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources." "$LINENO" 5 @@ -16137,6 +16141,10 @@ if test "x$with_override_source_root" != x; then test -f $with_override_source_root/hotspot/make/Makefile; then as_fn_error $? "Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override." "$LINENO" 5 fi + if test -f $with_override_source_root/nashorn/makefiles/Makefile || \ + test -f $with_override_source_root/nashorn/make/Makefile; then + as_fn_error $? "Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override." "$LINENO" 5 + fi if test -f $with_override_source_root/jdk/makefiles/Makefile || \ test -f $with_override_source_root/jdk/make/Makefile; then as_fn_error $? "Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override." "$LINENO" 5 @@ -16199,6 +16207,13 @@ fi +# Check whether --with-override-nashorn was given. +if test "${with_override_nashorn+set}" = set; then : + withval=$with_override_nashorn; +fi + + + # Check whether --with-override-jdk was given. if test "${with_override_jdk+set}" = set; then : withval=$with_override_jdk; @@ -16276,7 +16291,7 @@ if test "x$with_override_nashorn" != x; then cd "$with_override_nashorn" NASHORN_TOPDIR="`pwd`" cd "$CURDIR" - if ! test -f $NASHORN_TOPDIR/makefiles/BuildNashorn.gmk; then + if ! test -f $NASHORN_TOPDIR/makefiles/Makefile; then as_fn_error $? "You have to override nashorn with a full nashorn repo!" "$LINENO" 5 fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking if nashorn should be overridden" >&5 @@ -17086,7 +17101,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -17586,437 +17601,29 @@ $as_echo "$as_me: The path of MSVCR_DLL, which resolves as \"$path\", is invalid # Check whether --with-dxsdk was given. if test "${with_dxsdk+set}" = set; then : - withval=$with_dxsdk; + withval=$with_dxsdk; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-dxsdk is deprecated and will be ignored." >&2;} fi + + # Check whether --with-dxsdk-lib was given. if test "${with_dxsdk_lib+set}" = set; then : - withval=$with_dxsdk_lib; + withval=$with_dxsdk_lib; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk-lib is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-dxsdk-lib is deprecated and will be ignored." >&2;} fi + + # Check whether --with-dxsdk-include was given. if test "${with_dxsdk_include+set}" = set; then : - withval=$with_dxsdk_include; + withval=$with_dxsdk_include; { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Option --with-dxsdk-include is deprecated and will be ignored." >&5 +$as_echo "$as_me: WARNING: Option --with-dxsdk-include is deprecated and will be ignored." >&2;} fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectX SDK" >&5 -$as_echo_n "checking for DirectX SDK... " >&6; } - - if test "x$with_dxsdk" != x; then - dxsdk_path="$with_dxsdk" - elif test "x$DXSDK_DIR" != x; then - dxsdk_path="$DXSDK_DIR" - elif test -d "C:/DXSDK"; then - dxsdk_path="C:/DXSDK" - else - as_fn_error $? "Could not find the DirectX SDK" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $dxsdk_path" >&5 -$as_echo "$dxsdk_path" >&6; } - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # Input might be given as Windows format, start by converting to - # unix format. - path="$dxsdk_path" - new_path=`$CYGPATH -u "$path"` - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file precense. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of dxsdk_path" "$LINENO" 5 - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - - if test "x$path" != "x$new_path"; then - dxsdk_path="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting dxsdk_path to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting dxsdk_path to \"$new_path\"" >&6;} - fi - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - path="$dxsdk_path" - has_colon=`$ECHO $path | $GREP ^.:` - new_path="$path" - if test "x$has_colon" = x; then - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $path` - fi - - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - if test "x$path" != "x$new_path"; then - dxsdk_path="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting dxsdk_path to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting dxsdk_path to \"$new_path\"" >&6;} - fi - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - - else - # We're on a posix platform. Hooray! :) - path="$dxsdk_path" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of dxsdk_path, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 - fi - - # Use eval to expand a potential ~ - eval path="$path" - if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of dxsdk_path, which resolves as \"$path\", is not found." "$LINENO" 5 - fi - - dxsdk_path="`cd "$path"; $THEPWDCMD -L`" - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectX SDK lib dir" >&5 -$as_echo_n "checking for DirectX SDK lib dir... " >&6; } - if test "x$with_dxsdk_lib" != x; then - DXSDK_LIB_PATH="$with_dxsdk_lib" - elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then - DXSDK_LIB_PATH="$dxsdk_path/Lib/x64" - else - DXSDK_LIB_PATH="$dxsdk_path/Lib" - fi - # dsound.lib is linked to in jsoundds - if test ! -f "$DXSDK_LIB_PATH/dsound.lib"; then - as_fn_error $? "Invalid DirectX SDK lib dir" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DXSDK_LIB_PATH" >&5 -$as_echo "$DXSDK_LIB_PATH" >&6; } - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # Input might be given as Windows format, start by converting to - # unix format. - path="$DXSDK_LIB_PATH" - new_path=`$CYGPATH -u "$path"` - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file precense. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of DXSDK_LIB_PATH" "$LINENO" 5 - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - - if test "x$path" != "x$new_path"; then - DXSDK_LIB_PATH="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&6;} - fi - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - path="$DXSDK_LIB_PATH" - has_colon=`$ECHO $path | $GREP ^.:` - new_path="$path" - if test "x$has_colon" = x; then - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $path` - fi - - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - if test "x$path" != "x$new_path"; then - DXSDK_LIB_PATH="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting DXSDK_LIB_PATH to \"$new_path\"" >&6;} - fi - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - - else - # We're on a posix platform. Hooray! :) - path="$DXSDK_LIB_PATH" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of DXSDK_LIB_PATH, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 - fi - - # Use eval to expand a potential ~ - eval path="$path" - if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of DXSDK_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 - fi - - DXSDK_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for DirectX SDK include dir" >&5 -$as_echo_n "checking for DirectX SDK include dir... " >&6; } - if test "x$with_dxsdk_include" != x; then - DXSDK_INCLUDE_PATH="$with_dxsdk_include" - else - DXSDK_INCLUDE_PATH="$dxsdk_path/Include" - fi - # dsound.h is included in jsoundds - if test ! -f "$DXSDK_INCLUDE_PATH/dsound.h"; then - as_fn_error $? "Invalid DirectX SDK lib dir" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DXSDK_INCLUDE_PATH" >&5 -$as_echo "$DXSDK_INCLUDE_PATH" >&6; } - - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - - # Input might be given as Windows format, start by converting to - # unix format. - path="$DXSDK_INCLUDE_PATH" - new_path=`$CYGPATH -u "$path"` - - # Cygwin tries to hide some aspects of the Windows file system, such that binaries are - # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered - # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then - # "foo.exe" is OK but "foo" is an error. - # - # This test is therefore slightly more accurate than "test -f" to check for file precense. - # It is also a way to make sure we got the proper file name for the real test later on. - test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` - if test "x$test_shortpath" = x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Cannot locate the the path of DXSDK_INCLUDE_PATH" "$LINENO" 5 - fi - - # Call helper function which possibly converts this using DOS-style short mode. - # If so, the updated path is stored in $new_path. - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - shortmode_path=`$CYGPATH -s -m -a "$input_path"` - path_after_shortmode=`$CYGPATH -u "$shortmode_path"` - if test "x$path_after_shortmode" != "x$input_to_shortpath"; then - # Going to short mode and back again did indeed matter. Since short mode is - # case insensitive, let's make it lowercase to improve readability. - shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - # Now convert it back to Unix-stile (cygpath) - input_path=`$CYGPATH -u "$shortmode_path"` - new_path="$input_path" - fi - fi - - test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` - if test "x$test_cygdrive_prefix" = x; then - # As a simple fix, exclude /usr/bin since it's not a real path. - if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then - # The path is in a Cygwin special directory (e.g. /home). We need this converted to - # a path prefixed by /cygdrive for fixpath to work. - new_path="$CYGWIN_ROOT_PATH$input_path" - fi - fi - - - if test "x$path" != "x$new_path"; then - DXSDK_INCLUDE_PATH="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&6;} - fi - - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - - path="$DXSDK_INCLUDE_PATH" - has_colon=`$ECHO $path | $GREP ^.:` - new_path="$path" - if test "x$has_colon" = x; then - # Not in mixed or Windows style, start by that. - new_path=`cmd //c echo $path` - fi - - - input_path="$new_path" - # Check if we need to convert this using DOS-style short mode. If the path - # contains just simple characters, use it. Otherwise (spaces, weird characters), - # take no chances and rewrite it. - # Note: m4 eats our [], so we need to use [ and ] instead. - has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` - if test "x$has_forbidden_chars" != x; then - # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) - new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` - fi - - - windows_path="$new_path" - if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then - unix_path=`$CYGPATH -u "$windows_path"` - new_path="$unix_path" - elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then - unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` - new_path="$unix_path" - fi - - if test "x$path" != "x$new_path"; then - DXSDK_INCLUDE_PATH="$new_path" - { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&5 -$as_echo "$as_me: Rewriting DXSDK_INCLUDE_PATH to \"$new_path\"" >&6;} - fi - - # Save the first 10 bytes of this path to the storage, so fixpath can work. - all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") - - else - # We're on a posix platform. Hooray! :) - path="$DXSDK_INCLUDE_PATH" - has_space=`$ECHO "$path" | $GREP " "` - if test "x$has_space" != x; then - { $as_echo "$as_me:${as_lineno-$LINENO}: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5 -$as_echo "$as_me: The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;} - as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 - fi - - # Use eval to expand a potential ~ - eval path="$path" - if test ! -f "$path" && test ! -d "$path"; then - as_fn_error $? "The path of DXSDK_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 - fi - - DXSDK_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" - fi - - - - - LDFLAGS_JDK="$LDFLAGS_JDK -libpath:$DXSDK_LIB_PATH" - fi @@ -18140,7 +17747,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -18451,7 +18058,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -18757,7 +18364,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -19350,7 +18957,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -19786,7 +19393,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -20922,7 +20529,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -21358,7 +20965,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -22259,7 +21866,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -22640,7 +22247,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -22987,7 +22594,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -23324,7 +22931,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -23645,7 +23252,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -24020,7 +23627,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -24326,7 +23933,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -24737,7 +24344,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -25137,7 +24744,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -25466,7 +25073,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -25778,7 +25385,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -26084,7 +25691,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -26390,7 +25997,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -26696,7 +26303,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -27055,7 +26662,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -27415,7 +27022,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -27788,7 +27395,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -28159,7 +27766,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -28468,7 +28075,7 @@ $as_echo "$as_me: You might be mixing spaces in the path and extra arguments, wh # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then # "foo.exe" is OK but "foo" is an error. # - # This test is therefore slightly more accurate than "test -f" to check for file precense. + # This test is therefore slightly more accurate than "test -f" to check for file presence. # It is also a way to make sure we got the proper file name for the real test later on. test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` if test "x$test_shortpath" = x; then @@ -28830,35 +28437,41 @@ done if test "x$OPENJDK_TARGET_OS" = xsolaris; then # Always specify -m flags on Solaris - # keep track of c/cxx flags that we added outselves... - # to prevent emitting warning... - TARGET_BITS_FLAG="-m${OPENJDK_TARGET_CPU_BITS}" + # When we add flags to the "official" CFLAGS etc, we need to + # keep track of these additions in ADDED_CFLAGS etc. These + # will later be checked to make sure only controlled additions + # have been made to CFLAGS etc. + ADDED_CFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + ADDED_CXXFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + ADDED_LDFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + CFLAGS="${CFLAGS}${ADDED_CFLAGS}" + CXXFLAGS="${CXXFLAGS}${ADDED_CXXFLAGS}" + LDFLAGS="${LDFLAGS}${ADDED_LDFLAGS}" - CFLAGS="${CFLAGS} ${TARGET_BITS_FLAG}" - CXXFLAGS="${CXXFLAGS} ${TARGET_BITS_FLAG}" - LDFLAGS="${LDFLAGS} ${TARGET_BITS_FLAG}" - - CFLAGS_JDK="${CFLAGS_JDK} ${TARGET_BITS_FLAG}" - CXXFLAGS_JDK="${CXXFLAGS_JDK} ${TARGET_BITS_FLAG}" - LDFLAGS_JDK="${LDFLAGS_JDK} ${TARGET_BITS_FLAG}" + CFLAGS_JDK="${CFLAGS_JDK}${ADDED_CFLAGS}" + CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" + LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" elif test "x$COMPILE_TYPE" = xreduced; then if test "x$OPENJDK_TARGET_OS" != xwindows; then # Specify -m if running reduced on other Posix platforms - # keep track of c/cxx flags that we added outselves... - # to prevent emitting warning... - TARGET_BITS_FLAG="-m${OPENJDK_TARGET_CPU_BITS}" + # When we add flags to the "official" CFLAGS etc, we need to + # keep track of these additions in ADDED_CFLAGS etc. These + # will later be checked to make sure only controlled additions + # have been made to CFLAGS etc. + ADDED_CFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + ADDED_CXXFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + ADDED_LDFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + CFLAGS="${CFLAGS}${ADDED_CFLAGS}" + CXXFLAGS="${CXXFLAGS}${ADDED_CXXFLAGS}" + LDFLAGS="${LDFLAGS}${ADDED_LDFLAGS}" - CFLAGS="${CFLAGS} ${TARGET_BITS_FLAG}" - CXXFLAGS="${CXXFLAGS} ${TARGET_BITS_FLAG}" - LDFLAGS="${LDFLAGS} ${TARGET_BITS_FLAG}" - - CFLAGS_JDK="${CFLAGS_JDK} ${TARGET_BITS_FLAG}" - CXXFLAGS_JDK="${CXXFLAGS_JDK} ${TARGET_BITS_FLAG}" - LDFLAGS_JDK="${LDFLAGS_JDK} ${TARGET_BITS_FLAG}" + CFLAGS_JDK="${CFLAGS_JDK}${ADDED_CFLAGS}" + CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" + LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" fi fi @@ -33618,6 +33231,7 @@ fi # We're messing a bit with internal autoconf variables to put the config.status # in the output directory instead of the current directory. CONFIG_STATUS="$OUTPUT_ROOT/config.status" + # Create the actual output files. Now the main work of configure is done. cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -34899,6 +34513,11 @@ $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;} fi +# Try to move the config.log file to the output directory. +if test -e ./config.log; then + $MV -f ./config.log "$OUTPUT_ROOT/config.log" 2> /dev/null +fi + # Make the compare script executable $CHMOD +x $OUTPUT_ROOT/compare.sh diff --git a/common/autoconf/jdk-options.m4 b/common/autoconf/jdk-options.m4 index ba14373e593..b1c99bbe7dc 100644 --- a/common/autoconf/jdk-options.m4 +++ b/common/autoconf/jdk-options.m4 @@ -446,7 +446,7 @@ elif test "x$with_user_release_suffix" != x; then else BUILD_DATE=`date '+%Y_%m_%d_%H_%M'` # Avoid [:alnum:] since it depends on the locale. - CLEAN_USERNAME=`echo "$USER" | $TR -d -c 'abcdefghijklmnopqrstuvqxyz0123456789'` + CLEAN_USERNAME=`echo "$USER" | $TR -d -c 'abcdefghijklmnopqrstuvqxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'` USER_RELEASE_SUFFIX=`echo "${CLEAN_USERNAME}_${BUILD_DATE}" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` fi AC_SUBST(USER_RELEASE_SUFFIX) diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index 71ae2ceab7b..96c710d8a18 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -422,18 +422,21 @@ AC_SUBST(OS_VERSION_MICRO) # Add -mX to various FLAGS variables. AC_DEFUN([PLATFORM_SET_COMPILER_TARGET_BITS_FLAGS], [ - # keep track of c/cxx flags that we added outselves... - # to prevent emitting warning... - TARGET_BITS_FLAG="-m${OPENJDK_TARGET_CPU_BITS}" - AC_SUBST(TARGET_BITS_FLAG) + # When we add flags to the "official" CFLAGS etc, we need to + # keep track of these additions in ADDED_CFLAGS etc. These + # will later be checked to make sure only controlled additions + # have been made to CFLAGS etc. + ADDED_CFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + ADDED_CXXFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" + ADDED_LDFLAGS=" -m${OPENJDK_TARGET_CPU_BITS}" - CFLAGS="${CFLAGS} ${TARGET_BITS_FLAG}" - CXXFLAGS="${CXXFLAGS} ${TARGET_BITS_FLAG}" - LDFLAGS="${LDFLAGS} ${TARGET_BITS_FLAG}" + CFLAGS="${CFLAGS}${ADDED_CFLAGS}" + CXXFLAGS="${CXXFLAGS}${ADDED_CXXFLAGS}" + LDFLAGS="${LDFLAGS}${ADDED_LDFLAGS}" - CFLAGS_JDK="${CFLAGS_JDK} ${TARGET_BITS_FLAG}" - CXXFLAGS_JDK="${CXXFLAGS_JDK} ${TARGET_BITS_FLAG}" - LDFLAGS_JDK="${LDFLAGS_JDK} ${TARGET_BITS_FLAG}" + CFLAGS_JDK="${CFLAGS_JDK}${ADDED_CFLAGS}" + CXXFLAGS_JDK="${CXXFLAGS_JDK}${ADDED_CXXFLAGS}" + LDFLAGS_JDK="${LDFLAGS_JDK}${ADDED_LDFLAGS}" ]) AC_DEFUN_ONCE([PLATFORM_SETUP_OPENJDK_TARGET_BITS], diff --git a/common/autoconf/source-dirs.m4 b/common/autoconf/source-dirs.m4 index bb0aba1b826..e040cc82f69 100644 --- a/common/autoconf/source-dirs.m4 +++ b/common/autoconf/source-dirs.m4 @@ -101,6 +101,10 @@ if test "x$with_add_source_root" != x; then test -f $with_add_source_root/hotspot/make/Makefile; then AC_MSG_ERROR([Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources.]) fi + if test -f $with_add_source_root/nashorn/makefiles/Makefile || \ + test -f $with_add_source_root/nashorn/make/Makefile; then + AC_MSG_ERROR([Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources.]) + fi if test -f $with_add_source_root/jdk/makefiles/Makefile || \ test -f $with_add_source_root/jdk/make/Makefile; then AC_MSG_ERROR([Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources.]) @@ -136,6 +140,10 @@ if test "x$with_override_source_root" != x; then test -f $with_override_source_root/hotspot/make/Makefile; then AC_MSG_ERROR([Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override.]) fi + if test -f $with_override_source_root/nashorn/makefiles/Makefile || \ + test -f $with_override_source_root/nashorn/make/Makefile; then + AC_MSG_ERROR([Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override.]) + fi if test -f $with_override_source_root/jdk/makefiles/Makefile || \ test -f $with_override_source_root/jdk/make/Makefile; then AC_MSG_ERROR([Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override.]) @@ -177,6 +185,9 @@ AC_ARG_WITH(override-jaxws, [AS_HELP_STRING([--with-override-jaxws], AC_ARG_WITH(override-hotspot, [AS_HELP_STRING([--with-override-hotspot], [use this hotspot dir for the build])]) +AC_ARG_WITH(override-nashorn, [AS_HELP_STRING([--with-override-nashorn], + [use this nashorn dir for the build])]) + AC_ARG_WITH(override-jdk, [AS_HELP_STRING([--with-override-jdk], [use this jdk dir for the build])]) @@ -241,7 +252,7 @@ if test "x$with_override_nashorn" != x; then cd "$with_override_nashorn" NASHORN_TOPDIR="`pwd`" cd "$CURDIR" - if ! test -f $NASHORN_TOPDIR/makefiles/BuildNashorn.gmk; then + if ! test -f $NASHORN_TOPDIR/makefiles/Makefile; then AC_MSG_ERROR([You have to override nashorn with a full nashorn repo!]) fi AC_MSG_CHECKING([if nashorn should be overridden]) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index d2ffb614bcc..7e186693700 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -291,10 +291,6 @@ X_CFLAGS:=@X_CFLAGS@ X_LIBS:=@X_LIBS@ OPENWIN_HOME:=@OPENWIN_HOME@ -# DirectX SDK -DXSDK_LIB_PATH=@DXSDK_LIB_PATH@ -DXSDK_INCLUDE_PATH=@DXSDK_INCLUDE_PATH@ - # The lowest required version of macosx to enforce compatiblity for MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ @@ -304,7 +300,6 @@ MACOSX_VERSION_MIN=@MACOSX_VERSION_MIN@ COMPILER_TYPE:=@COMPILER_TYPE@ COMPILER_NAME:=@COMPILER_NAME@ -TARGET_BITS_FLAG=@TARGET_BITS_FLAG@ COMPILER_SUPPORTS_TARGET_BITS_FLAG=@COMPILER_SUPPORTS_TARGET_BITS_FLAG@ CC_OUT_OPTION:=@CC_OUT_OPTION@ diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index efaecc18960..21733003023 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -176,7 +176,9 @@ AC_DEFUN([TOOLCHAIN_SETUP_PATHS], [ if test "x$OPENJDK_TARGET_OS" = "xwindows"; then TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV - TOOLCHAIN_SETUP_DXSDK + BASIC_DEPRECATED_ARG_WITH([dxsdk]) + BASIC_DEPRECATED_ARG_WITH([dxsdk-lib]) + BASIC_DEPRECATED_ARG_WITH([dxsdk-include]) fi AC_SUBST(MSVCR_DLL) diff --git a/common/autoconf/toolchain_windows.m4 b/common/autoconf/toolchain_windows.m4 index e5d4fff38f9..f97713f952f 100644 --- a/common/autoconf/toolchain_windows.m4 +++ b/common/autoconf/toolchain_windows.m4 @@ -277,61 +277,3 @@ AC_DEFUN([TOOLCHAIN_SETUP_VISUAL_STUDIO_ENV], AC_MSG_RESULT([$MSVCR_DLL]) BASIC_FIXUP_PATH(MSVCR_DLL) ]) - - -# Setup the DXSDK paths -AC_DEFUN([TOOLCHAIN_SETUP_DXSDK], -[ - AC_ARG_WITH(dxsdk, [AS_HELP_STRING([--with-dxsdk], - [the DirectX SDK (Windows only) @<:@probed@:>@])]) - AC_ARG_WITH(dxsdk-lib, [AS_HELP_STRING([--with-dxsdk-lib], - [the DirectX SDK lib directory (Windows only) @<:@probed@:>@])]) - AC_ARG_WITH(dxsdk-include, [AS_HELP_STRING([--with-dxsdk-include], - [the DirectX SDK include directory (Windows only) @<:@probed@:>@])]) - - AC_MSG_CHECKING([for DirectX SDK]) - - if test "x$with_dxsdk" != x; then - dxsdk_path="$with_dxsdk" - elif test "x$DXSDK_DIR" != x; then - dxsdk_path="$DXSDK_DIR" - elif test -d "C:/DXSDK"; then - dxsdk_path="C:/DXSDK" - else - AC_MSG_ERROR([Could not find the DirectX SDK]) - fi - AC_MSG_RESULT([$dxsdk_path]) - BASIC_FIXUP_PATH(dxsdk_path) - - AC_MSG_CHECKING([for DirectX SDK lib dir]) - if test "x$with_dxsdk_lib" != x; then - DXSDK_LIB_PATH="$with_dxsdk_lib" - elif test "x$OPENJDK_TARGET_CPU" = "xx86_64"; then - DXSDK_LIB_PATH="$dxsdk_path/Lib/x64" - else - DXSDK_LIB_PATH="$dxsdk_path/Lib" - fi - # dsound.lib is linked to in jsoundds - if test ! -f "$DXSDK_LIB_PATH/dsound.lib"; then - AC_MSG_ERROR([Invalid DirectX SDK lib dir]) - fi - AC_MSG_RESULT([$DXSDK_LIB_PATH]) - BASIC_FIXUP_PATH(DXSDK_LIB_PATH) - - AC_MSG_CHECKING([for DirectX SDK include dir]) - if test "x$with_dxsdk_include" != x; then - DXSDK_INCLUDE_PATH="$with_dxsdk_include" - else - DXSDK_INCLUDE_PATH="$dxsdk_path/Include" - fi - # dsound.h is included in jsoundds - if test ! -f "$DXSDK_INCLUDE_PATH/dsound.h"; then - AC_MSG_ERROR([Invalid DirectX SDK lib dir]) - fi - AC_MSG_RESULT([$DXSDK_INCLUDE_PATH]) - BASIC_FIXUP_PATH(DXSDK_INCLUDE_PATH) - - AC_SUBST(DXSDK_LIB_PATH) - AC_SUBST(DXSDK_INCLUDE_PATH) - LDFLAGS_JDK="$LDFLAGS_JDK -libpath:$DXSDK_LIB_PATH" -]) diff --git a/common/bin/compare.sh b/common/bin/compare.sh index aacdc718b6f..732c6757fc7 100644 --- a/common/bin/compare.sh +++ b/common/bin/compare.sh @@ -76,13 +76,13 @@ diff_text() { TMP=1 if [[ "$THIS_FILE" = *"META-INF/MANIFEST.MF" ]]; then - TMP=$(LANG=C $DIFF $OTHER_FILE $THIS_FILE | \ + TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \ $GREP '^[<>]' | \ $SED -e '/[<>] Ant-Version: Apache Ant .*/d' \ -e '/[<>] Created-By: .* (Oracle Corporation).*/d') fi if test "x$SUFFIX" = "xjava"; then - TMP=$(LANG=C $DIFF $OTHER_FILE $THIS_FILE | \ + TMP=$(LC_ALL=C $DIFF $OTHER_FILE $THIS_FILE | \ $GREP '^[<>]' | \ $SED -e '/[<>] \* from.*\.idl/d' \ -e '/[<>] \*.*[0-9]\{4\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}_[0-9]\{2\}-b[0-9]\{2\}.*/d' \ @@ -121,8 +121,8 @@ diff_text() { # | $SED -e '/^#/d' -e '/^$/d' \ # -e :a -e '/\\$/N; s/\\\n//; ta' \ # -e 's/^[ \t]*//;s/[ \t]*$//' \ -# -e 's/\\=/=/' | LANG=C $SORT > $OTHER_FILE.cleaned - TMP=$(LANG=C $DIFF $OTHER_FILE.cleaned $THIS_FILE) +# -e 's/\\=/=/' | LC_ALL=C $SORT > $OTHER_FILE.cleaned + TMP=$(LC_ALL=C $DIFF $OTHER_FILE.cleaned $THIS_FILE) fi if test -n "$TMP"; then echo Files $OTHER_FILE and $THIS_FILE differ @@ -410,11 +410,11 @@ compare_zip_file() { CONTENTS_DIFF_FILE=$WORK_DIR/$ZIP_FILE.diff # On solaris, there is no -q option. if [ "$OPENJDK_TARGET_OS" = "solaris" ]; then - LANG=C $DIFF -r $OTHER_UNZIPDIR $THIS_UNZIPDIR \ + LC_ALL=C $DIFF -r $OTHER_UNZIPDIR $THIS_UNZIPDIR \ | $GREP -v -e "^<" -e "^>" -e "^Common subdirectories:" \ > $CONTENTS_DIFF_FILE else - LANG=C $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE + LC_ALL=C $DIFF -rq $OTHER_UNZIPDIR $THIS_UNZIPDIR > $CONTENTS_DIFF_FILE fi ONLY_OTHER=$($GREP "^Only in $OTHER_UNZIPDIR" $CONTENTS_DIFF_FILE) @@ -459,11 +459,11 @@ compare_zip_file() { if [ -n "$SHOW_DIFFS" ]; then for i in $(cat $WORK_DIR/$ZIP_FILE.difflist) ; do if [ -f "${OTHER_UNZIPDIR}/$i.javap" ]; then - LANG=C $DIFF ${OTHER_UNZIPDIR}/$i.javap ${THIS_UNZIPDIR}/$i.javap + LC_ALL=C $DIFF ${OTHER_UNZIPDIR}/$i.javap ${THIS_UNZIPDIR}/$i.javap elif [ -f "${OTHER_UNZIPDIR}/$i.cleaned" ]; then - LANG=C $DIFF ${OTHER_UNZIPDIR}/$i.cleaned ${THIS_UNZIPDIR}/$i + LC_ALL=C $DIFF ${OTHER_UNZIPDIR}/$i.cleaned ${THIS_UNZIPDIR}/$i else - LANG=C $DIFF ${OTHER_UNZIPDIR}/$i ${THIS_UNZIPDIR}/$i + LC_ALL=C $DIFF ${OTHER_UNZIPDIR}/$i ${THIS_UNZIPDIR}/$i fi done fi @@ -703,7 +703,7 @@ compare_bin_file() { $NM -a $ORIG_THIS_FILE 2> /dev/null | $GREP -v $NAME | $AWK '{print $2, $3, $4, $5}' | $SYM_SORT_CMD > $WORK_FILE_BASE.symbols.this fi - LANG=C $DIFF $WORK_FILE_BASE.symbols.other $WORK_FILE_BASE.symbols.this > $WORK_FILE_BASE.symbols.diff + LC_ALL=C $DIFF $WORK_FILE_BASE.symbols.other $WORK_FILE_BASE.symbols.this > $WORK_FILE_BASE.symbols.diff if [ -s $WORK_FILE_BASE.symbols.diff ]; then SYM_MSG=" diff " if [[ "$ACCEPTED_SYM_DIFF" != *"$BIN_FILE"* ]]; then @@ -732,8 +732,8 @@ compare_bin_file() { (cd $FILE_WORK_DIR && $CP $THIS_FILE . && $LDD_CMD $NAME 2 $WORK_FILE_BASE.deps.this.uniq) (cd $FILE_WORK_DIR && $RM -f $NAME) - LANG=C $DIFF $WORK_FILE_BASE.deps.other $WORK_FILE_BASE.deps.this > $WORK_FILE_BASE.deps.diff - LANG=C $DIFF $WORK_FILE_BASE.deps.other.uniq $WORK_FILE_BASE.deps.this.uniq > $WORK_FILE_BASE.deps.diff.uniq + LC_ALL=C $DIFF $WORK_FILE_BASE.deps.other $WORK_FILE_BASE.deps.this > $WORK_FILE_BASE.deps.diff + LC_ALL=C $DIFF $WORK_FILE_BASE.deps.other.uniq $WORK_FILE_BASE.deps.this.uniq > $WORK_FILE_BASE.deps.diff.uniq if [ -s $WORK_FILE_BASE.deps.diff ]; then if [ -s $WORK_FILE_BASE.deps.diff.uniq ]; then @@ -768,7 +768,7 @@ compare_bin_file() { if [ -n "$FULLDUMP_CMD" ] && [ -z "$SKIP_FULLDUMP_DIFF" ]; then $FULLDUMP_CMD $OTHER_FILE > $WORK_FILE_BASE.fulldump.other 2>&1 $FULLDUMP_CMD $THIS_FILE > $WORK_FILE_BASE.fulldump.this 2>&1 - LANG=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this > $WORK_FILE_BASE.fulldump.diff + LC_ALL=C $DIFF $WORK_FILE_BASE.fulldump.other $WORK_FILE_BASE.fulldump.this > $WORK_FILE_BASE.fulldump.diff if [ -s $WORK_FILE_BASE.fulldump.diff ]; then ELF_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.fulldump.diff | awk '{print $5}') @@ -802,7 +802,7 @@ compare_bin_file() { $DIS_CMD $OTHER_FILE | $GREP -v $NAME | $DIS_DIFF_FILTER > $WORK_FILE_BASE.dis.other 2>&1 $DIS_CMD $THIS_FILE | $GREP -v $NAME | $DIS_DIFF_FILTER > $WORK_FILE_BASE.dis.this 2>&1 - LANG=C $DIFF $WORK_FILE_BASE.dis.other $WORK_FILE_BASE.dis.this > $WORK_FILE_BASE.dis.diff + LC_ALL=C $DIFF $WORK_FILE_BASE.dis.other $WORK_FILE_BASE.dis.this > $WORK_FILE_BASE.dis.diff if [ -s $WORK_FILE_BASE.dis.diff ]; then DIS_DIFF_SIZE=$(ls -n $WORK_FILE_BASE.dis.diff | awk '{print $5}') diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh index 12cf0234b17..1dc50390b42 100644 --- a/common/bin/hgforest.sh +++ b/common/bin/hgforest.sh @@ -47,7 +47,7 @@ python="" bpython="" if [ "#!" = "$has_hash_bang" ] ; then - python="`head -n 1 ${whichhg} | cut -b 3-`" + python="`head -n 1 ${whichhg} | cut -b 3- | sed -e 's/^[ \t]*//;s/[ \t]*$//'`" bpython="`basename "$python"`" fi diff --git a/common/makefiles/Jprt.gmk b/common/makefiles/Jprt.gmk index 4b19dc45e38..cf05583a869 100644 --- a/common/makefiles/Jprt.gmk +++ b/common/makefiles/Jprt.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -200,13 +200,8 @@ $(JPRT_ARCHIVE_BUNDLE): bundles $(RM) $@ $(CP) $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip $@ -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) - SRC_JDK_IMAGE_DIR := $(JDK_OVERLAY_IMAGE_DIR) - SRC_JRE_IMAGE_DIR := $(JRE_OVERLAY_IMAGE_DIR) -else - SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) - SRC_JRE_IMAGE_DIR := $(JRE_IMAGE_DIR) -endif +SRC_JDK_IMAGE_DIR := $(JDK_IMAGE_DIR) +SRC_JRE_IMAGE_DIR := $(JRE_IMAGE_DIR) SRC_JDK_BUNDLE_DIR := $(JDK_BUNDLE_DIR) SRC_JRE_BUNDLE_DIR := $(JRE_BUNDLE_DIR) @@ -215,10 +210,10 @@ bundles: all bundles-only bundles-only: start-make @$(call TargetEnter) $(MKDIR) -p $(BUILD_OUTPUT)/bundles - $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip . - $(CD) $(SRC_JRE_IMAGE_DIR) && $(ZIP) -q -r $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip . + $(CD) $(SRC_JDK_IMAGE_DIR) && $(ZIP) -y -q -r $(BUILD_OUTPUT)/bundles/$(JDK_IMAGE_SUBDIR).zip . + $(CD) $(SRC_JRE_IMAGE_DIR) && $(ZIP) -y -q -r $(BUILD_OUTPUT)/bundles/$(JRE_IMAGE_SUBDIR).zip . if [ -d $(BUILD_OUTPUT)/install/bundles ] ; then \ - $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -q -r $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \ + $(CD) $(BUILD_OUTPUT)/install/bundles && $(ZIP) -y -q -r $(JPRT_ARCHIVE_INSTALL_BUNDLE) . ; \ fi @$(call TargetExit) diff --git a/common/makefiles/Main.gmk b/common/makefiles/Main.gmk index f5f01fce1ba..47b17e2631a 100644 --- a/common/makefiles/Main.gmk +++ b/common/makefiles/Main.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -68,10 +68,6 @@ default: jdk all: images docs @$(call CheckIfMakeAtEnd) -ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) - all: overlay-images -endif - # Setup a rule for SPEC file that fails if executed. This check makes sure the configuration # is up to date after changes to configure $(SPEC): $(wildcard $(SRC_ROOT)/common/autoconf/*) diff --git a/corba/.hgtags b/corba/.hgtags index f96b90eb232..fac06acf758 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -228,3 +228,6 @@ a013024b07475782f1fa8e196e950b34b4077663 jdk8-b101 d411c60a8c2fe8fdc572af907775e90f7eefd513 jdk8-b104 4e38de7c767e34104fa147b5b346d9fe6b731279 jdk8-b105 2e3a056c84a71eba78945c18b05397858ffd7ad0 jdk8-b106 +23fc34133152692b725db4bd617b4c8dfd6ccb05 jdk8-b107 +a4bb3b4500164748a9c33b2283cfda76d89f25ab jdk8-b108 +428428cf5e06163322144cfb5367e1faa86acf20 jdk8-b109 diff --git a/corba/make/jprt.properties b/corba/make/jprt.properties index 360b6b22dba..b03c53ca656 100644 --- a/corba/make/jprt.properties +++ b/corba/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,8 @@ jprt.build.targets= \ solaris_x64_5.10-{product|fastdebug}, \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # Directories to be excluded from the source bundles jprt.bundle.exclude.src.dirs=build dist webrev diff --git a/corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java b/corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java index fc1ffc70197..63578b9c3d1 100644 --- a/corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java +++ b/corba/src/share/classes/com/sun/corba/se/impl/transport/DefaultSocketFactoryImpl.java @@ -32,6 +32,7 @@ import java.net.SocketException; import java.net.ServerSocket; import java.nio.channels.SocketChannel; import java.nio.channels.ServerSocketChannel; +import java.security.PrivilegedAction; import com.sun.corba.se.pept.transport.Acceptor; @@ -44,6 +45,22 @@ public class DefaultSocketFactoryImpl implements ORBSocketFactory { private ORB orb; + private static final boolean keepAlive; + + static { + keepAlive = java.security.AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public Boolean run () { + String value = + System.getProperty("com.sun.CORBA.transport.enableTcpKeepAlive"); + if (value != null) + return new Boolean(!"false".equalsIgnoreCase(value)); + + return Boolean.FALSE; + } + }); + } public void setORB(ORB orb) { @@ -85,6 +102,9 @@ public class DefaultSocketFactoryImpl // Disable Nagle's algorithm (i.e., always send immediately). socket.setTcpNoDelay(true); + if (keepAlive) + socket.setKeepAlive(true); + return socket; } @@ -95,6 +115,8 @@ public class DefaultSocketFactoryImpl { // Disable Nagle's algorithm (i.e., always send immediately). socket.setTcpNoDelay(true); + if (keepAlive) + socket.setKeepAlive(true); } } diff --git a/hotspot/.hgtags b/hotspot/.hgtags index bc3aba45318..3432d8a4113 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -375,3 +375,9 @@ acac3bde66b2c22791c257a8d99611d6d08c6713 jdk8-b105 18b4798adbc42c6fa16f5ecb7d5cd3ca130754bf hs25-b48 aed585cafc0d9655726af6d1e1081d1c94cb3b5c jdk8-b106 50794d8ac11c9579b41dec4de23b808fef9f34a1 hs25-b49 +5b7f90aab3ad25a25b75b7b2bb18d5ae23d8231c jdk8-b107 +a09fe9d1e016c285307507a5793bc4fa6215e9c9 hs25-b50 +85072013aad46050a362d10ab78e963121c8014c jdk8-b108 +566db1b0e6efca31f181456e54c8911d0192410d hs25-b51 +c81dd5393a5e333df7cb1f6621f5897ada6522b5 jdk8-b109 +58043478c26d4e8bf48700acea5f97aba8b417d4 hs25-b52 diff --git a/hotspot/agent/src/os/linux/ps_core.c b/hotspot/agent/src/os/linux/ps_core.c index 85abab802e0..c1620407894 100644 --- a/hotspot/agent/src/os/linux/ps_core.c +++ b/hotspot/agent/src/os/linux/ps_core.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -698,29 +698,58 @@ err: // read segments of a shared object static bool read_lib_segments(struct ps_prochandle* ph, int lib_fd, ELF_EHDR* lib_ehdr, uintptr_t lib_base) { - int i = 0; - ELF_PHDR* phbuf; - ELF_PHDR* lib_php = NULL; + int i = 0; + ELF_PHDR* phbuf; + ELF_PHDR* lib_php = NULL; - if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) - return false; + int page_size=sysconf(_SC_PAGE_SIZE); - // we want to process only PT_LOAD segments that are not writable. - // i.e., text segments. The read/write/exec (data) segments would - // have been already added from core file segments. - for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { - if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { - if (add_map_info(ph, lib_fd, lib_php->p_offset, lib_php->p_vaddr + lib_base, lib_php->p_filesz) == NULL) - goto err; + if ((phbuf = read_program_header_table(lib_fd, lib_ehdr)) == NULL) { + return false; + } + + // we want to process only PT_LOAD segments that are not writable. + // i.e., text segments. The read/write/exec (data) segments would + // have been already added from core file segments. + for (lib_php = phbuf, i = 0; i < lib_ehdr->e_phnum; i++) { + if ((lib_php->p_type == PT_LOAD) && !(lib_php->p_flags & PF_W) && (lib_php->p_filesz != 0)) { + + uintptr_t target_vaddr = lib_php->p_vaddr + lib_base; + map_info *existing_map = core_lookup(ph, target_vaddr); + + if (existing_map == NULL){ + if (add_map_info(ph, lib_fd, lib_php->p_offset, + target_vaddr, lib_php->p_filesz) == NULL) { + goto err; + } + } else { + if ((existing_map->memsz != page_size) && + (existing_map->fd != lib_fd) && + (existing_map->memsz != lib_php->p_filesz)){ + + print_debug("address conflict @ 0x%lx (size = %ld, flags = %d\n)", + target_vaddr, lib_php->p_filesz, lib_php->p_flags); + goto err; + } + + /* replace PT_LOAD segment with library segment */ + print_debug("overwrote with new address mapping (memsz %ld -> %ld)\n", + existing_map->memsz, lib_php->p_filesz); + + existing_map->fd = lib_fd; + existing_map->offset = lib_php->p_offset; + existing_map->memsz = lib_php->p_filesz; } - lib_php++; - } + } - free(phbuf); - return true; + lib_php++; + } + + free(phbuf); + return true; err: - free(phbuf); - return false; + free(phbuf); + return false; } // process segments from interpreter (ld.so or ld-linux.so) diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java index 1840caf9313..354f0b906b3 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/CommandProcessor.java @@ -1213,6 +1213,7 @@ public class CommandProcessor { } HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); if (t.countTokens() == 1) { + String name = t.nextToken(); out.println("intConstant " + name + " " + db.lookupIntConstant(name)); } else if (t.countTokens() == 0) { Iterator i = db.getIntConstants(); @@ -1235,6 +1236,7 @@ public class CommandProcessor { } HotSpotTypeDataBase db = (HotSpotTypeDataBase)agent.getTypeDataBase(); if (t.countTokens() == 1) { + String name = t.nextToken(); out.println("longConstant " + name + " " + db.lookupLongConstant(name)); } else if (t.countTokens() == 0) { Iterator i = db.getLongConstants(); diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java index d1b56881f13..f25d50ff23c 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/debugger/bsd/BsdAddress.java @@ -81,7 +81,7 @@ class BsdAddress implements Address { public Address getCompKlassAddressAt(long offset) throws UnalignedAddressException, UnmappedAddressException { - return debugger.readCompOopAddress(addr + offset); + return debugger.readCompKlassAddress(addr + offset); } // diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java index f84da894ac2..319d2430af2 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/runtime/VM.java @@ -792,7 +792,7 @@ public class VM { public boolean isCompressedKlassPointersEnabled() { if (compressedKlassPointersEnabled == null) { - Flag flag = getCommandLineFlag("UseCompressedKlassPointers"); + Flag flag = getCommandLineFlag("UseCompressedClassPointers"); compressedKlassPointersEnabled = (flag == null) ? Boolean.FALSE: (flag.getBool()? Boolean.TRUE: Boolean.FALSE); } diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java index a0123dd4c99..daab682aaef 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/tools/HeapSummary.java @@ -66,18 +66,18 @@ public class HeapSummary extends Tool { printGCAlgorithm(flagMap); System.out.println(); System.out.println("Heap Configuration:"); - printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap)); - printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap)); - printValMB("MaxHeapSize = ", getFlagValue("MaxHeapSize", flagMap)); - printValMB("NewSize = ", getFlagValue("NewSize", flagMap)); - printValMB("MaxNewSize = ", getFlagValue("MaxNewSize", flagMap)); - printValMB("OldSize = ", getFlagValue("OldSize", flagMap)); - printValue("NewRatio = ", getFlagValue("NewRatio", flagMap)); - printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap)); - printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap)); - printValMB("ClassMetaspaceSize = ", getFlagValue("ClassMetaspaceSize", flagMap)); - printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap)); - printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); + printValue("MinHeapFreeRatio = ", getFlagValue("MinHeapFreeRatio", flagMap)); + printValue("MaxHeapFreeRatio = ", getFlagValue("MaxHeapFreeRatio", flagMap)); + printValMB("MaxHeapSize = ", getFlagValue("MaxHeapSize", flagMap)); + printValMB("NewSize = ", getFlagValue("NewSize", flagMap)); + printValMB("MaxNewSize = ", getFlagValue("MaxNewSize", flagMap)); + printValMB("OldSize = ", getFlagValue("OldSize", flagMap)); + printValue("NewRatio = ", getFlagValue("NewRatio", flagMap)); + printValue("SurvivorRatio = ", getFlagValue("SurvivorRatio", flagMap)); + printValMB("MetaspaceSize = ", getFlagValue("MetaspaceSize", flagMap)); + printValMB("CompressedClassSpaceSize = ", getFlagValue("CompressedClassSpaceSize", flagMap)); + printValMB("MaxMetaspaceSize = ", getFlagValue("MaxMetaspaceSize", flagMap)); + printValMB("G1HeapRegionSize = ", HeapRegion.grainBytes()); System.out.println(); System.out.println("Heap Usage:"); diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index b98485f901d..0277bb66aa3 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -80,7 +80,7 @@ ifeq ($(SPEC),) HOSTCC = $(CC) endif - AS = $(CC) -c -x assembler-with-cpp + AS = $(CC) -c endif @@ -347,6 +347,13 @@ ifeq ($(OS_VENDOR), Darwin) LDFLAGS += -mmacosx-version-min=$(MACOSX_VERSION_MIN) endif + +#------------------------------------------------------------------------ +# Assembler flags + +# Enforce prerpocessing of .s files +ASFLAGS += -x assembler-with-cpp + #------------------------------------------------------------------------ # Linker flags diff --git a/hotspot/make/excludeSrc.make b/hotspot/make/excludeSrc.make index 7cc879a3d7b..a95dc1b114c 100644 --- a/hotspot/make/excludeSrc.make +++ b/hotspot/make/excludeSrc.make @@ -88,7 +88,7 @@ ifeq ($(INCLUDE_ALL_GCS), false) g1ErgoVerbose.cpp g1GCPhaseTimes.cpp g1HRPrinter.cpp g1HotCardCache.cpp g1Log.cpp \ g1MMUTracker.cpp g1MarkSweep.cpp g1MemoryPool.cpp g1MonitoringSupport.cpp \ g1RemSet.cpp g1RemSetSummary.cpp g1SATBCardTableModRefBS.cpp g1_globals.cpp heapRegion.cpp \ - heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \ + g1BiasedArray.cpp heapRegionRemSet.cpp heapRegionSeq.cpp heapRegionSet.cpp heapRegionSets.cpp \ ptrQueue.cpp satbQueue.cpp sparsePRT.cpp survRateGroup.cpp vm_operations_g1.cpp \ adjoiningGenerations.cpp adjoiningVirtualSpaces.cpp asPSOldGen.cpp asPSYoungGen.cpp \ cardTableExtension.cpp gcTaskManager.cpp gcTaskThread.cpp objectStartArray.cpp \ @@ -99,7 +99,7 @@ ifeq ($(INCLUDE_ALL_GCS), false) psTasks.cpp psVirtualspace.cpp psYoungGen.cpp vmPSOperations.cpp asParNewGeneration.cpp \ parCardTableModRefBS.cpp parGCAllocBuffer.cpp parNewGeneration.cpp mutableSpace.cpp \ gSpaceCounters.cpp allocationStats.cpp spaceCounters.cpp gcAdaptivePolicyCounters.cpp \ - mutableNUMASpace.cpp immutableSpace.cpp yieldingWorkGroup.cpp + mutableNUMASpace.cpp immutableSpace.cpp yieldingWorkGroup.cpp hSpaceCounters.cpp endif ifeq ($(INCLUDE_NMT), false) diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index 15223e843df..dc0872c1db3 100644 --- a/hotspot/make/hotspot_version +++ b/hotspot/make/hotspot_version @@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2013 HS_MAJOR_VER=25 HS_MINOR_VER=0 -HS_BUILD_NUMBER=49 +HS_BUILD_NUMBER=52 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/hotspot/make/jprt.properties b/hotspot/make/jprt.properties index 5971546c6d9..f322e7024ae 100644 --- a/hotspot/make/jprt.properties +++ b/hotspot/make/jprt.properties @@ -120,13 +120,13 @@ jprt.my.macosx.x64.jdk7=macosx_x64_10.7 jprt.my.macosx.x64.jdk7u8=${jprt.my.macosx.x64.jdk7} jprt.my.macosx.x64=${jprt.my.macosx.x64.${jprt.tools.default.release}} -jprt.my.windows.i586.jdk8=windows_i586_5.1 -jprt.my.windows.i586.jdk7=windows_i586_5.1 +jprt.my.windows.i586.jdk8=windows_i586_6.1 +jprt.my.windows.i586.jdk7=windows_i586_6.1 jprt.my.windows.i586.jdk7u8=${jprt.my.windows.i586.jdk7} jprt.my.windows.i586=${jprt.my.windows.i586.${jprt.tools.default.release}} -jprt.my.windows.x64.jdk8=windows_x64_5.2 -jprt.my.windows.x64.jdk7=windows_x64_5.2 +jprt.my.windows.x64.jdk8=windows_x64_6.1 +jprt.my.windows.x64.jdk7=windows_x64_6.1 jprt.my.windows.x64.jdk7u8=${jprt.my.windows.x64.jdk7} jprt.my.windows.x64=${jprt.my.windows.x64.${jprt.tools.default.release}} diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 12d51571ccb..cb4c04a388b 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -105,7 +105,7 @@ bool LIR_Assembler::is_single_instruction(LIR_Op* op) { if (src->is_address() && !src->is_stack() && (src->type() == T_OBJECT || src->type() == T_ARRAY)) return false; } - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { if (src->is_address() && !src->is_stack() && src->type() == T_ADDRESS && src->as_address_ptr()->disp() == oopDesc::klass_offset_in_bytes()) return false; } @@ -963,7 +963,7 @@ int LIR_Assembler::load(Register base, int offset, LIR_Opr to_reg, BasicType typ case T_METADATA: __ ld_ptr(base, offset, to_reg->as_register()); break; case T_ADDRESS: #ifdef _LP64 - if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedKlassPointers) { + if (offset == oopDesc::klass_offset_in_bytes() && UseCompressedClassPointers) { __ lduw(base, offset, to_reg->as_register()); __ decode_klass_not_null(to_reg->as_register()); } else @@ -2208,7 +2208,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // We don't know the array types are compatible if (basic_type != T_OBJECT) { // Simple test for basic type arrays - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { // We don't need decode because we just need to compare __ lduw(src, oopDesc::klass_offset_in_bytes(), tmp); __ lduw(dst, oopDesc::klass_offset_in_bytes(), tmp2); @@ -2342,7 +2342,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // but not necessarily exactly of type default_type. Label known_ok, halt; metadata2reg(op->expected_type()->constant_encoding(), tmp); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { // tmp holds the default type. It currently comes uncompressed after the // load of a constant, so encode it. __ encode_klass_not_null(tmp); diff --git a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp index bf4074b30fd..6d10ab81aaf 100644 --- a/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_MacroAssembler_sparc.cpp @@ -186,7 +186,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register set((intx)markOopDesc::prototype(), t1); } st_ptr(t1, obj, oopDesc::mark_offset_in_bytes()); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { // Save klass mov(klass, t1); encode_klass_not_null(t1); @@ -196,7 +196,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register } if (len->is_valid()) { st(len, obj, arrayOopDesc::length_offset_in_bytes()); - } else if (UseCompressedKlassPointers) { + } else if (UseCompressedClassPointers) { // otherwise length is in the class gap store_klass_gap(G0, obj); } diff --git a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp index 093be806072..e4fe6bb00a4 100644 --- a/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/c2_globals_sparc.hpp @@ -57,6 +57,7 @@ define_pd_global(intx, RegisterCostAreaRatio, 12000); define_pd_global(bool, UseTLAB, true); define_pd_global(bool, ResizeTLAB, true); define_pd_global(intx, LoopUnrollLimit, 60); // Design center runs on 1.3.1 +define_pd_global(intx, MinJumpTableSize, 5); // Peephole and CISC spilling both break the graph, and so makes the // scheduler sick. diff --git a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp index d2c4e3b0261..9f1f2e53371 100644 --- a/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/macroAssembler_sparc.cpp @@ -3911,7 +3911,7 @@ void MacroAssembler::load_klass(Register src_oop, Register klass) { // The number of bytes in this code is used by // MachCallDynamicJavaNode::ret_addr_offset() // if this changes, change that. - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { lduw(src_oop, oopDesc::klass_offset_in_bytes(), klass); decode_klass_not_null(klass); } else { @@ -3920,7 +3920,7 @@ void MacroAssembler::load_klass(Register src_oop, Register klass) { } void MacroAssembler::store_klass(Register klass, Register dst_oop) { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { assert(dst_oop != klass, "not enough registers"); encode_klass_not_null(klass); st(klass, dst_oop, oopDesc::klass_offset_in_bytes()); @@ -3930,7 +3930,7 @@ void MacroAssembler::store_klass(Register klass, Register dst_oop) { } void MacroAssembler::store_klass_gap(Register s, Register d) { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { assert(s != d, "not enough registers"); st(s, d, oopDesc::klass_gap_offset_in_bytes()); } @@ -4089,7 +4089,7 @@ void MacroAssembler::decode_heap_oop_not_null(Register src, Register dst) { } void MacroAssembler::encode_klass_not_null(Register r) { - assert (UseCompressedKlassPointers, "must be compressed"); + assert (UseCompressedClassPointers, "must be compressed"); assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); assert(r != G6_heapbase, "bad register choice"); set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); @@ -4105,7 +4105,7 @@ void MacroAssembler::encode_klass_not_null(Register src, Register dst) { if (src == dst) { encode_klass_not_null(src); } else { - assert (UseCompressedKlassPointers, "must be compressed"); + assert (UseCompressedClassPointers, "must be compressed"); assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); set((intptr_t)Universe::narrow_klass_base(), dst); sub(src, dst, dst); @@ -4119,7 +4119,7 @@ void MacroAssembler::encode_klass_not_null(Register src, Register dst) { // generated by decode_klass_not_null() and reinit_heapbase(). Hence, if // the instructions they generate change, then this method needs to be updated. int MacroAssembler::instr_size_for_decode_klass_not_null() { - assert (UseCompressedKlassPointers, "only for compressed klass ptrs"); + assert (UseCompressedClassPointers, "only for compressed klass ptrs"); // set + add + set int num_instrs = insts_for_internal_set((intptr_t)Universe::narrow_klass_base()) + 1 + insts_for_internal_set((intptr_t)Universe::narrow_ptrs_base()); @@ -4135,7 +4135,7 @@ int MacroAssembler::instr_size_for_decode_klass_not_null() { void MacroAssembler::decode_klass_not_null(Register r) { // Do not add assert code to this unless you change vtableStubs_sparc.cpp // pd_code_size_limit. - assert (UseCompressedKlassPointers, "must be compressed"); + assert (UseCompressedClassPointers, "must be compressed"); assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); assert(r != G6_heapbase, "bad register choice"); set((intptr_t)Universe::narrow_klass_base(), G6_heapbase); @@ -4151,7 +4151,7 @@ void MacroAssembler::decode_klass_not_null(Register src, Register dst) { } else { // Do not add assert code to this unless you change vtableStubs_sparc.cpp // pd_code_size_limit. - assert (UseCompressedKlassPointers, "must be compressed"); + assert (UseCompressedClassPointers, "must be compressed"); assert(Universe::narrow_klass_base() != NULL, "narrow_klass_base should be initialized"); if (Universe::narrow_klass_shift() != 0) { assert((src != G6_heapbase) && (dst != G6_heapbase), "bad register choice"); @@ -4167,7 +4167,7 @@ void MacroAssembler::decode_klass_not_null(Register src, Register dst) { } void MacroAssembler::reinit_heapbase() { - if (UseCompressedOops || UseCompressedKlassPointers) { + if (UseCompressedOops || UseCompressedClassPointers) { if (Universe::heap() != NULL) { set((intptr_t)Universe::narrow_ptrs_base(), G6_heapbase); } else { diff --git a/hotspot/src/cpu/sparc/vm/sparc.ad b/hotspot/src/cpu/sparc/vm/sparc.ad index a72bffdadeb..58c113a0c1a 100644 --- a/hotspot/src/cpu/sparc/vm/sparc.ad +++ b/hotspot/src/cpu/sparc/vm/sparc.ad @@ -557,7 +557,7 @@ int MachCallDynamicJavaNode::ret_addr_offset() { int entry_offset = InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size(); int v_off = entry_offset*wordSize + vtableEntry::method_offset_in_bytes(); int klass_load_size; - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { assert(Universe::heap() != NULL, "java heap should be initialized"); klass_load_size = MacroAssembler::instr_size_for_decode_klass_not_null() + 1*BytesPerInstWord; } else { @@ -1657,7 +1657,7 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const { void MachUEPNode::format( PhaseRegAlloc *ra_, outputStream *st ) const { st->print_cr("\nUEP:"); #ifdef _LP64 - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { assert(Universe::heap() != NULL, "java heap should be initialized"); st->print_cr("\tLDUW [R_O0 + oopDesc::klass_offset_in_bytes],R_G5\t! Inline cache check - compressed klass"); st->print_cr("\tSET Universe::narrow_klass_base,R_G6_heap_base"); @@ -1897,7 +1897,7 @@ bool Matcher::narrow_oop_use_complex_address() { bool Matcher::narrow_klass_use_complex_address() { NOT_LP64(ShouldNotCallThis()); - assert(UseCompressedKlassPointers, "only for compressed klass code"); + assert(UseCompressedClassPointers, "only for compressed klass code"); return false; } @@ -2561,7 +2561,7 @@ encode %{ int off = __ offset(); __ load_klass(O0, G3_scratch); int klass_load_size; - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { assert(Universe::heap() != NULL, "java heap should be initialized"); klass_load_size = MacroAssembler::instr_size_for_decode_klass_not_null() + 1*BytesPerInstWord; } else { diff --git a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp index 214940cdbfb..612ae118ee4 100644 --- a/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/stubGenerator_sparc.cpp @@ -2945,7 +2945,7 @@ class StubGenerator: public StubCodeGenerator { BLOCK_COMMENT("arraycopy argument klass checks"); // get src->klass() - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ delayed()->nop(); // ??? not good __ load_klass(src, G3_src_klass); } else { @@ -2980,7 +2980,7 @@ class StubGenerator: public StubCodeGenerator { // Load 32-bits signed value. Use br() instruction with it to check icc. __ lduw(G3_src_klass, lh_offset, G5_lh); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ load_klass(dst, G4_dst_klass); } // Handle objArrays completely differently... @@ -2988,7 +2988,7 @@ class StubGenerator: public StubCodeGenerator { __ set(objArray_lh, O5_temp); __ cmp(G5_lh, O5_temp); __ br(Assembler::equal, false, Assembler::pt, L_objArray); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ delayed()->nop(); } else { __ delayed()->ld_ptr(dst, oopDesc::klass_offset_in_bytes(), G4_dst_klass); diff --git a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp index 39663758035..cdbb57fbecd 100644 --- a/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vtableStubs_sparc.cpp @@ -52,6 +52,11 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, oopDesc* receiver, VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { const int sparc_code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new(sparc_code_length) VtableStub(true, vtable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), sparc_code_length); MacroAssembler* masm = new MacroAssembler(&cb); @@ -125,6 +130,11 @@ VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { VtableStub* VtableStubs::create_itable_stub(int itable_index) { const int sparc_code_length = VtableStub::pd_code_size_limit(false); VtableStub* s = new(sparc_code_length) VtableStub(false, itable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), sparc_code_length); MacroAssembler* masm = new MacroAssembler(&cb); @@ -218,13 +228,13 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { // ld;ld;ld,jmp,nop const int basic = 5*BytesPerInstWord + // shift;add for load_klass (only shift with zero heap based) - (UseCompressedKlassPointers ? + (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); return basic + slop; } else { const int basic = (28 LP64_ONLY(+ 6)) * BytesPerInstWord + // shift;add for load_klass (only shift with zero heap based) - (UseCompressedKlassPointers ? + (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); return (basic + slop); } diff --git a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp index ea5d6d39da6..2d1b5f1f3c7 100644 --- a/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c1_FrameMap_x86.hpp @@ -148,7 +148,7 @@ static int adjust_reg_range(int range) { // Reduce the number of available regs (to free r12) in case of compressed oops - if (UseCompressedOops || UseCompressedKlassPointers) return range - 1; + if (UseCompressedOops || UseCompressedClassPointers) return range - 1; return range; } diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index 334d0cc92db..94c2c39d26f 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -341,7 +341,7 @@ int LIR_Assembler::check_icache() { Register receiver = FrameMap::receiver_opr->as_register(); Register ic_klass = IC_Klass; const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); - const bool do_post_padding = VerifyOops || UseCompressedKlassPointers; + const bool do_post_padding = VerifyOops || UseCompressedClassPointers; if (!do_post_padding) { // insert some nops so that the verified entry point is aligned on CodeEntryAlignment while ((__ offset() + ic_cmp_size) % CodeEntryAlignment != 0) { @@ -1263,7 +1263,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch break; case T_ADDRESS: - if (UseCompressedKlassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { + if (UseCompressedClassPointers && addr->disp() == oopDesc::klass_offset_in_bytes()) { __ movl(dest->as_register(), from_addr); } else { __ movptr(dest->as_register(), from_addr); @@ -1371,7 +1371,7 @@ void LIR_Assembler::mem2reg(LIR_Opr src, LIR_Opr dest, BasicType type, LIR_Patch __ verify_oop(dest->as_register()); } else if (type == T_ADDRESS && addr->disp() == oopDesc::klass_offset_in_bytes()) { #ifdef _LP64 - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ decode_klass_not_null(dest->as_register()); } #endif @@ -1716,7 +1716,7 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } else if (obj == klass_RInfo) { klass_RInfo = dst; } - if (k->is_loaded() && !UseCompressedKlassPointers) { + if (k->is_loaded() && !UseCompressedClassPointers) { select_different_registers(obj, dst, k_RInfo, klass_RInfo); } else { Rtmp1 = op->tmp3()->as_register(); @@ -1724,14 +1724,6 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } assert_different_registers(obj, k_RInfo, klass_RInfo); - if (!k->is_loaded()) { - klass2reg_with_patching(k_RInfo, op->info_for_patch()); - } else { -#ifdef _LP64 - __ mov_metadata(k_RInfo, k->constant_encoding()); -#endif // _LP64 - } - assert(obj != k_RInfo, "must be different"); __ cmpptr(obj, (int32_t)NULL_WORD); if (op->should_profile()) { @@ -1748,13 +1740,21 @@ void LIR_Assembler::emit_typecheck_helper(LIR_OpTypeCheck *op, Label* success, L } else { __ jcc(Assembler::equal, *obj_is_null); } + + if (!k->is_loaded()) { + klass2reg_with_patching(k_RInfo, op->info_for_patch()); + } else { +#ifdef _LP64 + __ mov_metadata(k_RInfo, k->constant_encoding()); +#endif // _LP64 + } __ verify_oop(obj); if (op->fast_check()) { // get object class // not a safepoint as obj null check happens earlier #ifdef _LP64 - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ load_klass(Rtmp1, obj); __ cmpptr(k_RInfo, Rtmp1); } else { @@ -3294,7 +3294,7 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { // We don't know the array types are compatible if (basic_type != T_OBJECT) { // Simple test for basic type arrays - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ movl(tmp, src_klass_addr); __ cmpl(tmp, dst_klass_addr); } else { @@ -3456,21 +3456,21 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) { Label known_ok, halt; __ mov_metadata(tmp, default_type->constant_encoding()); #ifdef _LP64 - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { __ encode_klass_not_null(tmp); } #endif if (basic_type != T_OBJECT) { - if (UseCompressedKlassPointers) __ cmpl(tmp, dst_klass_addr); + if (UseCompressedClassPointers) __ cmpl(tmp, dst_klass_addr); else __ cmpptr(tmp, dst_klass_addr); __ jcc(Assembler::notEqual, halt); - if (UseCompressedKlassPointers) __ cmpl(tmp, src_klass_addr); + if (UseCompressedClassPointers) __ cmpl(tmp, src_klass_addr); else __ cmpptr(tmp, src_klass_addr); __ jcc(Assembler::equal, known_ok); } else { - if (UseCompressedKlassPointers) __ cmpl(tmp, dst_klass_addr); + if (UseCompressedClassPointers) __ cmpl(tmp, dst_klass_addr); else __ cmpptr(tmp, dst_klass_addr); __ jcc(Assembler::equal, known_ok); __ cmpptr(src, dst); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp index e6638581bcf..308befddc77 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRGenerator_x86.cpp @@ -1239,7 +1239,7 @@ void LIRGenerator::do_CheckCast(CheckCast* x) { } LIR_Opr reg = rlock_result(x); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedKlassPointers) { + if (!x->klass()->is_loaded() || UseCompressedClassPointers) { tmp3 = new_register(objectType); } __ checkcast(reg, obj.result(), x->klass(), @@ -1261,7 +1261,7 @@ void LIRGenerator::do_InstanceOf(InstanceOf* x) { } obj.load_item(); LIR_Opr tmp3 = LIR_OprFact::illegalOpr; - if (!x->klass()->is_loaded() || UseCompressedKlassPointers) { + if (!x->klass()->is_loaded() || UseCompressedClassPointers) { tmp3 = new_register(objectType); } __ instanceof(reg, obj.result(), x->klass(), diff --git a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp index d9ae6ce5de5..805fe5a48ca 100644 --- a/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_MacroAssembler_x86.cpp @@ -157,7 +157,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register movptr(Address(obj, oopDesc::mark_offset_in_bytes ()), (int32_t)(intptr_t)markOopDesc::prototype()); } #ifdef _LP64 - if (UseCompressedKlassPointers) { // Take care not to kill klass + if (UseCompressedClassPointers) { // Take care not to kill klass movptr(t1, klass); encode_klass_not_null(t1); movl(Address(obj, oopDesc::klass_offset_in_bytes()), t1); @@ -171,7 +171,7 @@ void C1_MacroAssembler::initialize_header(Register obj, Register klass, Register movl(Address(obj, arrayOopDesc::length_offset_in_bytes()), len); } #ifdef _LP64 - else if (UseCompressedKlassPointers) { + else if (UseCompressedClassPointers) { xorptr(t1, t1); store_klass_gap(obj, t1); } @@ -334,7 +334,7 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { assert(!MacroAssembler::needs_explicit_null_check(oopDesc::klass_offset_in_bytes()), "must add explicit null check"); int start_offset = offset(); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { load_klass(rscratch1, receiver); cmpptr(rscratch1, iCache); } else { @@ -345,7 +345,7 @@ void C1_MacroAssembler::inline_cache_check(Register receiver, Register iCache) { jump_cc(Assembler::notEqual, RuntimeAddress(SharedRuntime::get_ic_miss_stub())); const int ic_cmp_size = LP64_ONLY(10) NOT_LP64(9); - assert(UseCompressedKlassPointers || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry"); + assert(UseCompressedClassPointers || offset() - start_offset == ic_cmp_size, "check alignment in emit_method_entry"); } diff --git a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp index d49bec21fe7..a45bd9624e5 100644 --- a/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp +++ b/hotspot/src/cpu/x86/vm/c2_globals_x86.hpp @@ -30,7 +30,6 @@ // Sets the default values for platform dependent flags used by the server compiler. // (see c2_globals.hpp). Alpha-sorted. - define_pd_global(bool, BackgroundCompilation, true); define_pd_global(bool, UseTLAB, true); define_pd_global(bool, ResizeTLAB, true); @@ -52,6 +51,7 @@ define_pd_global(intx, OnStackReplacePercentage, 140); define_pd_global(intx, ConditionalMoveLimit, 3); define_pd_global(intx, FLOATPRESSURE, 6); define_pd_global(intx, FreqInlineSize, 325); +define_pd_global(intx, MinJumpTableSize, 10); #ifdef AMD64 define_pd_global(intx, INTPRESSURE, 13); define_pd_global(intx, InteriorEntryAlignment, 16); diff --git a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp index b331f694959..fed50ef4286 100644 --- a/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/macroAssembler_x86.cpp @@ -1635,7 +1635,7 @@ void MacroAssembler::call_VM_base(Register oop_result, #ifdef ASSERT // TraceBytecodes does not use r12 but saves it over the call, so don't verify // r12 is the heapbase. - LP64_ONLY(if ((UseCompressedOops || UseCompressedKlassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");) + LP64_ONLY(if ((UseCompressedOops || UseCompressedClassPointers) && !TraceBytecodes) verify_heapbase("call_VM_base: heap base corrupted?");) #endif // ASSERT assert(java_thread != oop_result , "cannot use the same register for java_thread & oop_result"); @@ -4802,7 +4802,7 @@ void MacroAssembler::restore_cpu_control_state_after_jni() { void MacroAssembler::load_klass(Register dst, Register src) { #ifdef _LP64 - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { movl(dst, Address(src, oopDesc::klass_offset_in_bytes())); decode_klass_not_null(dst); } else @@ -4817,7 +4817,7 @@ void MacroAssembler::load_prototype_header(Register dst, Register src) { void MacroAssembler::store_klass(Register dst, Register src) { #ifdef _LP64 - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { encode_klass_not_null(src); movl(Address(dst, oopDesc::klass_offset_in_bytes()), src); } else @@ -4892,7 +4892,7 @@ void MacroAssembler::store_heap_oop_null(Address dst) { #ifdef _LP64 void MacroAssembler::store_klass_gap(Register dst, Register src) { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { // Store to klass gap in destination movl(Address(dst, oopDesc::klass_gap_offset_in_bytes()), src); } @@ -5075,7 +5075,7 @@ void MacroAssembler::encode_klass_not_null(Register dst, Register src) { // when (Universe::heap() != NULL). Hence, if the instructions they // generate change, then this method needs to be updated. int MacroAssembler::instr_size_for_decode_klass_not_null() { - assert (UseCompressedKlassPointers, "only for compressed klass ptrs"); + assert (UseCompressedClassPointers, "only for compressed klass ptrs"); // mov64 + addq + shlq? + mov64 (for reinit_heapbase()). return (Universe::narrow_klass_shift() == 0 ? 20 : 24); } @@ -5085,7 +5085,7 @@ int MacroAssembler::instr_size_for_decode_klass_not_null() { void MacroAssembler::decode_klass_not_null(Register r) { // Note: it will change flags assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert(r != r12_heapbase, "Decoding a klass in r12"); // Cannot assert, unverified entry point counts instructions (see .ad file) // vtableStubs also counts instructions in pd_code_size_limit. @@ -5103,7 +5103,7 @@ void MacroAssembler::decode_klass_not_null(Register r) { void MacroAssembler::decode_klass_not_null(Register dst, Register src) { // Note: it will change flags assert(Universe::narrow_klass_base() != NULL, "Base should be initialized"); - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (UseCompressedClassPointers, "should only be used for compressed headers"); if (dst == src) { decode_klass_not_null(dst); } else { @@ -5141,7 +5141,7 @@ void MacroAssembler::set_narrow_oop(Address dst, jobject obj) { } void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5149,7 +5149,7 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { } void MacroAssembler::set_narrow_klass(Address dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5175,7 +5175,7 @@ void MacroAssembler::cmp_narrow_oop(Address dst, jobject obj) { } void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5183,7 +5183,7 @@ void MacroAssembler::cmp_narrow_klass(Register dst, Klass* k) { } void MacroAssembler::cmp_narrow_klass(Address dst, Klass* k) { - assert (UseCompressedKlassPointers, "should only be used for compressed headers"); + assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != NULL, "this assembler needs an OopRecorder"); int klass_index = oop_recorder()->find_index(k); RelocationHolder rspec = metadata_Relocation::spec(klass_index); @@ -5191,7 +5191,7 @@ void MacroAssembler::cmp_narrow_klass(Address dst, Klass* k) { } void MacroAssembler::reinit_heapbase() { - if (UseCompressedOops || UseCompressedKlassPointers) { + if (UseCompressedOops || UseCompressedClassPointers) { if (Universe::heap() != NULL) { if (Universe::narrow_oop_base() == NULL) { MacroAssembler::xorptr(r12_heapbase, r12_heapbase); diff --git a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp index c828c90fba1..a632fbab313 100644 --- a/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp +++ b/hotspot/src/cpu/x86/vm/templateInterpreter_x86.hpp @@ -34,9 +34,9 @@ // Run with +PrintInterpreter to get the VM to print out the size. // Max size with JVMTI #ifdef AMD64 - const static int InterpreterCodeSize = 200 * 1024; + const static int InterpreterCodeSize = 208 * 1024; #else - const static int InterpreterCodeSize = 168 * 1024; + const static int InterpreterCodeSize = 176 * 1024; #endif // AMD64 #endif // CPU_X86_VM_TEMPLATEINTERPRETER_X86_HPP diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp index c470004ebc8..7c49d737fa5 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_32.cpp @@ -58,6 +58,11 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, oop receiver, int VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { const int i486_code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new(i486_code_length) VtableStub(true, vtable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), i486_code_length); MacroAssembler* masm = new MacroAssembler(&cb); @@ -132,6 +137,11 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { // add code here, bump the code stub size returned by pd_code_size_limit! const int i486_code_length = VtableStub::pd_code_size_limit(false); VtableStub* s = new(i486_code_length) VtableStub(false, itable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), i486_code_length); MacroAssembler* masm = new MacroAssembler(&cb); diff --git a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp index 518da23eb60..911341736d8 100644 --- a/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp +++ b/hotspot/src/cpu/x86/vm/vtableStubs_x86_64.cpp @@ -49,6 +49,11 @@ extern "C" void bad_compiled_vtable_index(JavaThread* thread, VtableStub* VtableStubs::create_vtable_stub(int vtable_index) { const int amd64_code_length = VtableStub::pd_code_size_limit(true); VtableStub* s = new(amd64_code_length) VtableStub(true, vtable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), amd64_code_length); MacroAssembler* masm = new MacroAssembler(&cb); @@ -126,6 +131,11 @@ VtableStub* VtableStubs::create_itable_stub(int itable_index) { // returned by pd_code_size_limit! const int amd64_code_length = VtableStub::pd_code_size_limit(false); VtableStub* s = new(amd64_code_length) VtableStub(false, itable_index); + // Can be NULL if there is no free space in the code cache. + if (s == NULL) { + return NULL; + } + ResourceMark rm; CodeBuffer cb(s->entry_point(), amd64_code_length); MacroAssembler* masm = new MacroAssembler(&cb); @@ -211,11 +221,11 @@ int VtableStub::pd_code_size_limit(bool is_vtable_stub) { if (is_vtable_stub) { // Vtable stub size return (DebugVtables ? 512 : 24) + (CountCompiledCalls ? 13 : 0) + - (UseCompressedKlassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); + (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); } else { // Itable stub size return (DebugVtables ? 512 : 74) + (CountCompiledCalls ? 13 : 0) + - (UseCompressedKlassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); + (UseCompressedClassPointers ? MacroAssembler::instr_size_for_decode_klass_not_null() : 0); } // In order to tune these parameters, run the JVM with VM options // +PrintMiscellaneous and +WizardMode to see information about diff --git a/hotspot/src/cpu/x86/vm/x86_64.ad b/hotspot/src/cpu/x86/vm/x86_64.ad index f550208e94d..ed13b3da1d1 100644 --- a/hotspot/src/cpu/x86/vm/x86_64.ad +++ b/hotspot/src/cpu/x86/vm/x86_64.ad @@ -1391,7 +1391,7 @@ uint BoxLockNode::size(PhaseRegAlloc *ra_) const #ifndef PRODUCT void MachUEPNode::format(PhaseRegAlloc* ra_, outputStream* st) const { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { st->print_cr("movl rscratch1, [j_rarg0 + oopDesc::klass_offset_in_bytes()]\t# compressed klass"); st->print_cr("\tdecode_klass_not_null rscratch1, rscratch1"); st->print_cr("\tcmpq rax, rscratch1\t # Inline cache check"); @@ -1408,7 +1408,7 @@ void MachUEPNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const { MacroAssembler masm(&cbuf); uint insts_size = cbuf.insts_size(); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { masm.load_klass(rscratch1, j_rarg0); masm.cmpptr(rax, rscratch1); } else { @@ -1557,7 +1557,7 @@ bool Matcher::narrow_oop_use_complex_address() { } bool Matcher::narrow_klass_use_complex_address() { - assert(UseCompressedKlassPointers, "only for compressed klass code"); + assert(UseCompressedClassPointers, "only for compressed klass code"); return (LogKlassAlignmentInBytes <= 3); } diff --git a/hotspot/src/os/bsd/vm/os_bsd.cpp b/hotspot/src/os/bsd/vm/os_bsd.cpp index 6b636d379de..58c961b43eb 100644 --- a/hotspot/src/os/bsd/vm/os_bsd.cpp +++ b/hotspot/src/os/bsd/vm/os_bsd.cpp @@ -3589,8 +3589,6 @@ jint os::init_2(void) #endif } - os::large_page_init(); - // initialize suspend/resume support - must do this before signal_sets_init() if (SR_initialize() != 0) { perror("SR_initialize failed"); diff --git a/hotspot/src/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 70837a850d8..6c794793cfe 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -131,6 +131,7 @@ bool os::Linux::_is_NPTL = false; bool os::Linux::_supports_fast_thread_cpu_time = false; const char * os::Linux::_glibc_version = NULL; const char * os::Linux::_libpthread_version = NULL; +pthread_condattr_t os::Linux::_condattr[1]; static jlong initial_time_count=0; @@ -1399,12 +1400,15 @@ void os::Linux::clock_init() { clock_gettime_func(CLOCK_MONOTONIC, &tp) == 0) { // yes, monotonic clock is supported _clock_gettime = clock_gettime_func; + return; } else { // close librt if there is no monotonic clock dlclose(handle); } } } + warning("No monotonic clock was available - timed services may " \ + "be adversely affected if the time-of-day clock changes"); } #ifndef SYS_clock_getres @@ -2165,23 +2169,49 @@ void os::print_os_info(outputStream* st) { } // Try to identify popular distros. -// Most Linux distributions have /etc/XXX-release file, which contains -// the OS version string. Some have more than one /etc/XXX-release file -// (e.g. Mandrake has both /etc/mandrake-release and /etc/redhat-release.), -// so the order is important. +// Most Linux distributions have a /etc/XXX-release file, which contains +// the OS version string. Newer Linux distributions have a /etc/lsb-release +// file that also contains the OS version string. Some have more than one +// /etc/XXX-release file (e.g. Mandrake has both /etc/mandrake-release and +// /etc/redhat-release.), so the order is important. +// Any Linux that is based on Redhat (i.e. Oracle, Mandrake, Sun JDS...) have +// their own specific XXX-release file as well as a redhat-release file. +// Because of this the XXX-release file needs to be searched for before the +// redhat-release file. +// Since Red Hat has a lsb-release file that is not very descriptive the +// search for redhat-release needs to be before lsb-release. +// Since the lsb-release file is the new standard it needs to be searched +// before the older style release files. +// Searching system-release (Red Hat) and os-release (other Linuxes) are a +// next to last resort. The os-release file is a new standard that contains +// distribution information and the system-release file seems to be an old +// standard that has been replaced by the lsb-release and os-release files. +// Searching for the debian_version file is the last resort. It contains +// an informative string like "6.0.6" or "wheezy/sid". Because of this +// "Debian " is printed before the contents of the debian_version file. void os::Linux::print_distro_info(outputStream* st) { - if (!_print_ascii_file("/etc/mandrake-release", st) && - !_print_ascii_file("/etc/sun-release", st) && - !_print_ascii_file("/etc/redhat-release", st) && - !_print_ascii_file("/etc/SuSE-release", st) && - !_print_ascii_file("/etc/turbolinux-release", st) && - !_print_ascii_file("/etc/gentoo-release", st) && - !_print_ascii_file("/etc/debian_version", st) && - !_print_ascii_file("/etc/ltib-release", st) && - !_print_ascii_file("/etc/angstrom-version", st)) { - st->print("Linux"); - } - st->cr(); + if (!_print_ascii_file("/etc/oracle-release", st) && + !_print_ascii_file("/etc/mandriva-release", st) && + !_print_ascii_file("/etc/mandrake-release", st) && + !_print_ascii_file("/etc/sun-release", st) && + !_print_ascii_file("/etc/redhat-release", st) && + !_print_ascii_file("/etc/lsb-release", st) && + !_print_ascii_file("/etc/SuSE-release", st) && + !_print_ascii_file("/etc/turbolinux-release", st) && + !_print_ascii_file("/etc/gentoo-release", st) && + !_print_ascii_file("/etc/ltib-release", st) && + !_print_ascii_file("/etc/angstrom-version", st) && + !_print_ascii_file("/etc/system-release", st) && + !_print_ascii_file("/etc/os-release", st)) { + + if (file_exists("/etc/debian_version")) { + st->print("Debian "); + _print_ascii_file("/etc/debian_version", st); + } else { + st->print("Linux"); + } + } + st->cr(); } void os::Linux::print_libversion_info(outputStream* st) { @@ -4709,6 +4739,26 @@ void os::init(void) { Linux::clock_init(); initial_time_count = os::elapsed_counter(); + + // pthread_condattr initialization for monotonic clock + int status; + pthread_condattr_t* _condattr = os::Linux::condAttr(); + if ((status = pthread_condattr_init(_condattr)) != 0) { + fatal(err_msg("pthread_condattr_init: %s", strerror(status))); + } + // Only set the clock if CLOCK_MONOTONIC is available + if (Linux::supports_monotonic_clock()) { + if ((status = pthread_condattr_setclock(_condattr, CLOCK_MONOTONIC)) != 0) { + if (status == EINVAL) { + warning("Unable to use monotonic clock with relative timed-waits" \ + " - changes to the time-of-day clock may have adverse affects"); + } else { + fatal(err_msg("pthread_condattr_setclock: %s", strerror(status))); + } + } + } + // else it defaults to CLOCK_REALTIME + pthread_mutex_init(&dl_mutex, NULL); // If the pagesize of the VM is greater than 8K determine the appropriate @@ -4755,8 +4805,6 @@ jint os::init_2(void) #endif } - os::large_page_init(); - // initialize suspend/resume support - must do this before signal_sets_init() if (SR_initialize() != 0) { perror("SR_initialize failed"); @@ -5519,21 +5567,36 @@ void os::pause() { static struct timespec* compute_abstime(timespec* abstime, jlong millis) { if (millis < 0) millis = 0; - struct timeval now; - int status = gettimeofday(&now, NULL); - assert(status == 0, "gettimeofday"); + jlong seconds = millis / 1000; millis %= 1000; if (seconds > 50000000) { // see man cond_timedwait(3T) seconds = 50000000; } - abstime->tv_sec = now.tv_sec + seconds; - long usec = now.tv_usec + millis * 1000; - if (usec >= 1000000) { - abstime->tv_sec += 1; - usec -= 1000000; + + if (os::Linux::supports_monotonic_clock()) { + struct timespec now; + int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); + assert_status(status == 0, status, "clock_gettime"); + abstime->tv_sec = now.tv_sec + seconds; + long nanos = now.tv_nsec + millis * NANOSECS_PER_MILLISEC; + if (nanos >= NANOSECS_PER_SEC) { + abstime->tv_sec += 1; + nanos -= NANOSECS_PER_SEC; + } + abstime->tv_nsec = nanos; + } else { + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); + abstime->tv_sec = now.tv_sec + seconds; + long usec = now.tv_usec + millis * 1000; + if (usec >= 1000000) { + abstime->tv_sec += 1; + usec -= 1000000; + } + abstime->tv_nsec = usec * 1000; } - abstime->tv_nsec = usec * 1000; return abstime; } @@ -5625,7 +5688,7 @@ int os::PlatformEvent::park(jlong millis) { status = os::Linux::safe_cond_timedwait(_cond, _mutex, &abst); if (status != 0 && WorkAroundNPTLTimedWaitHang) { pthread_cond_destroy (_cond); - pthread_cond_init (_cond, NULL) ; + pthread_cond_init (_cond, os::Linux::condAttr()) ; } assert_status(status == 0 || status == EINTR || status == ETIME || status == ETIMEDOUT, @@ -5726,32 +5789,50 @@ void os::PlatformEvent::unpark() { static void unpackTime(timespec* absTime, bool isAbsolute, jlong time) { assert (time > 0, "convertTime"); + time_t max_secs = 0; - struct timeval now; - int status = gettimeofday(&now, NULL); - assert(status == 0, "gettimeofday"); + if (!os::Linux::supports_monotonic_clock() || isAbsolute) { + struct timeval now; + int status = gettimeofday(&now, NULL); + assert(status == 0, "gettimeofday"); - time_t max_secs = now.tv_sec + MAX_SECS; + max_secs = now.tv_sec + MAX_SECS; - if (isAbsolute) { - jlong secs = time / 1000; - if (secs > max_secs) { - absTime->tv_sec = max_secs; + if (isAbsolute) { + jlong secs = time / 1000; + if (secs > max_secs) { + absTime->tv_sec = max_secs; + } else { + absTime->tv_sec = secs; + } + absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; + } else { + jlong secs = time / NANOSECS_PER_SEC; + if (secs >= MAX_SECS) { + absTime->tv_sec = max_secs; + absTime->tv_nsec = 0; + } else { + absTime->tv_sec = now.tv_sec + secs; + absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; + if (absTime->tv_nsec >= NANOSECS_PER_SEC) { + absTime->tv_nsec -= NANOSECS_PER_SEC; + ++absTime->tv_sec; // note: this must be <= max_secs + } + } } - else { - absTime->tv_sec = secs; - } - absTime->tv_nsec = (time % 1000) * NANOSECS_PER_MILLISEC; - } - else { + } else { + // must be relative using monotonic clock + struct timespec now; + int status = os::Linux::clock_gettime(CLOCK_MONOTONIC, &now); + assert_status(status == 0, status, "clock_gettime"); + max_secs = now.tv_sec + MAX_SECS; jlong secs = time / NANOSECS_PER_SEC; if (secs >= MAX_SECS) { absTime->tv_sec = max_secs; absTime->tv_nsec = 0; - } - else { + } else { absTime->tv_sec = now.tv_sec + secs; - absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_usec*1000; + absTime->tv_nsec = (time % NANOSECS_PER_SEC) + now.tv_nsec; if (absTime->tv_nsec >= NANOSECS_PER_SEC) { absTime->tv_nsec -= NANOSECS_PER_SEC; ++absTime->tv_sec; // note: this must be <= max_secs @@ -5831,15 +5912,19 @@ void Parker::park(bool isAbsolute, jlong time) { jt->set_suspend_equivalent(); // cleared by handle_special_suspend_equivalent_condition() or java_suspend_self() + assert(_cur_index == -1, "invariant"); if (time == 0) { - status = pthread_cond_wait (_cond, _mutex) ; + _cur_index = REL_INDEX; // arbitrary choice when not timed + status = pthread_cond_wait (&_cond[_cur_index], _mutex) ; } else { - status = os::Linux::safe_cond_timedwait (_cond, _mutex, &absTime) ; + _cur_index = isAbsolute ? ABS_INDEX : REL_INDEX; + status = os::Linux::safe_cond_timedwait (&_cond[_cur_index], _mutex, &absTime) ; if (status != 0 && WorkAroundNPTLTimedWaitHang) { - pthread_cond_destroy (_cond) ; - pthread_cond_init (_cond, NULL); + pthread_cond_destroy (&_cond[_cur_index]) ; + pthread_cond_init (&_cond[_cur_index], isAbsolute ? NULL : os::Linux::condAttr()); } } + _cur_index = -1; assert_status(status == 0 || status == EINTR || status == ETIME || status == ETIMEDOUT, status, "cond_timedwait"); @@ -5868,17 +5953,24 @@ void Parker::unpark() { s = _counter; _counter = 1; if (s < 1) { - if (WorkAroundNPTLTimedWaitHang) { - status = pthread_cond_signal (_cond) ; - assert (status == 0, "invariant") ; + // thread might be parked + if (_cur_index != -1) { + // thread is definitely parked + if (WorkAroundNPTLTimedWaitHang) { + status = pthread_cond_signal (&_cond[_cur_index]); + assert (status == 0, "invariant"); status = pthread_mutex_unlock(_mutex); - assert (status == 0, "invariant") ; - } else { + assert (status == 0, "invariant"); + } else { status = pthread_mutex_unlock(_mutex); - assert (status == 0, "invariant") ; - status = pthread_cond_signal (_cond) ; - assert (status == 0, "invariant") ; - } + assert (status == 0, "invariant"); + status = pthread_cond_signal (&_cond[_cur_index]); + assert (status == 0, "invariant"); + } + } else { + pthread_mutex_unlock(_mutex); + assert (status == 0, "invariant") ; + } } else { pthread_mutex_unlock(_mutex); assert (status == 0, "invariant") ; diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index c824e8ad3fe..5eed54f8c1e 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -221,6 +221,13 @@ class Linux { static jlong fast_thread_cpu_time(clockid_t clockid); + // pthread_cond clock suppport + private: + static pthread_condattr_t _condattr[1]; + + public: + static pthread_condattr_t* condAttr() { return _condattr; } + // Stack repair handling // none present @@ -295,7 +302,7 @@ class PlatformEvent : public CHeapObj { public: PlatformEvent() { int status; - status = pthread_cond_init (_cond, NULL); + status = pthread_cond_init (_cond, os::Linux::condAttr()); assert_status(status == 0, status, "cond_init"); status = pthread_mutex_init (_mutex, NULL); assert_status(status == 0, status, "mutex_init"); @@ -310,14 +317,19 @@ class PlatformEvent : public CHeapObj { void park () ; void unpark () ; int TryPark () ; - int park (jlong millis) ; + int park (jlong millis) ; // relative timed-wait only void SetAssociation (Thread * a) { _Assoc = a ; } } ; class PlatformParker : public CHeapObj { protected: + enum { + REL_INDEX = 0, + ABS_INDEX = 1 + }; + int _cur_index; // which cond is in use: -1, 0, 1 pthread_mutex_t _mutex [1] ; - pthread_cond_t _cond [1] ; + pthread_cond_t _cond [2] ; // one for relative times and one for abs. public: // TODO-FIXME: make dtor private ~PlatformParker() { guarantee (0, "invariant") ; } @@ -325,10 +337,13 @@ class PlatformParker : public CHeapObj { public: PlatformParker() { int status; - status = pthread_cond_init (_cond, NULL); - assert_status(status == 0, status, "cond_init"); + status = pthread_cond_init (&_cond[REL_INDEX], os::Linux::condAttr()); + assert_status(status == 0, status, "cond_init rel"); + status = pthread_cond_init (&_cond[ABS_INDEX], NULL); + assert_status(status == 0, status, "cond_init abs"); status = pthread_mutex_init (_mutex, NULL); assert_status(status == 0, status, "mutex_init"); + _cur_index = -1; // mark as unused } }; diff --git a/hotspot/src/os/solaris/vm/os_solaris.cpp b/hotspot/src/os/solaris/vm/os_solaris.cpp index c3e6e879077..8e5984ffa3d 100644 --- a/hotspot/src/os/solaris/vm/os_solaris.cpp +++ b/hotspot/src/os/solaris/vm/os_solaris.cpp @@ -5178,9 +5178,7 @@ jint os::init_2(void) { if(Verbose && PrintMiscellaneous) tty->print("[Memory Serialize Page address: " INTPTR_FORMAT "]\n", (intptr_t)mem_serialize_page); #endif -} - - os::large_page_init(); + } // Check minimum allowable stack size for thread creation and to initialize // the java system classes, including StackOverflowError - depends on page diff --git a/hotspot/src/os/windows/vm/decoder_windows.cpp b/hotspot/src/os/windows/vm/decoder_windows.cpp index 326d3288020..b99adaa9f4f 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.cpp +++ b/hotspot/src/os/windows/vm/decoder_windows.cpp @@ -32,7 +32,11 @@ WindowsDecoder::WindowsDecoder() { _can_decode_in_vm = false; _pfnSymGetSymFromAddr64 = NULL; _pfnUndecorateSymbolName = NULL; - +#ifdef AMD64 + _pfnStackWalk64 = NULL; + _pfnSymFunctionTableAccess64 = NULL; + _pfnSymGetModuleBase64 = NULL; +#endif _decoder_status = no_error; initialize(); } @@ -53,14 +57,24 @@ void WindowsDecoder::initialize() { _pfnUndecorateSymbolName = (pfn_UndecorateSymbolName)::GetProcAddress(handle, "UnDecorateSymbolName"); if (_pfnSymSetOptions == NULL || _pfnSymInitialize == NULL || _pfnSymGetSymFromAddr64 == NULL) { - _pfnSymGetSymFromAddr64 = NULL; - _pfnUndecorateSymbolName = NULL; - ::FreeLibrary(handle); - _dbghelp_handle = NULL; + uninitialize(); _decoder_status = helper_func_error; return; } +#ifdef AMD64 + _pfnStackWalk64 = (pfn_StackWalk64)::GetProcAddress(handle, "StackWalk64"); + _pfnSymFunctionTableAccess64 = (pfn_SymFunctionTableAccess64)::GetProcAddress(handle, "SymFunctionTableAccess64"); + _pfnSymGetModuleBase64 = (pfn_SymGetModuleBase64)::GetProcAddress(handle, "SymGetModuleBase64"); + if (_pfnStackWalk64 == NULL || _pfnSymFunctionTableAccess64 == NULL || _pfnSymGetModuleBase64 == NULL) { + // We can't call StackWalk64 to walk the stack, but we are still + // able to decode the symbols. Let's limp on. + _pfnStackWalk64 = NULL; + _pfnSymFunctionTableAccess64 = NULL; + _pfnSymGetModuleBase64 = NULL; + } +#endif + HANDLE hProcess = ::GetCurrentProcess(); _pfnSymSetOptions(SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS | SYMOPT_EXACT_SYMBOLS); if (!_pfnSymInitialize(hProcess, NULL, TRUE)) { @@ -156,6 +170,11 @@ void WindowsDecoder::initialize() { void WindowsDecoder::uninitialize() { _pfnSymGetSymFromAddr64 = NULL; _pfnUndecorateSymbolName = NULL; +#ifdef AMD64 + _pfnStackWalk64 = NULL; + _pfnSymFunctionTableAccess64 = NULL; + _pfnSymGetModuleBase64 = NULL; +#endif if (_dbghelp_handle != NULL) { ::FreeLibrary(_dbghelp_handle); } @@ -195,3 +214,65 @@ bool WindowsDecoder::demangle(const char* symbol, char *buf, int buflen) { _pfnUndecorateSymbolName(symbol, buf, buflen, UNDNAME_COMPLETE); } +#ifdef AMD64 +BOOL WindowsDbgHelp::StackWalk64(DWORD MachineType, + HANDLE hProcess, + HANDLE hThread, + LPSTACKFRAME64 StackFrame, + PVOID ContextRecord, + PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress) { + DecoderLocker locker; + WindowsDecoder* wd = (WindowsDecoder*)locker.decoder(); + + if (!wd->has_error() && wd->_pfnStackWalk64) { + return wd->_pfnStackWalk64(MachineType, + hProcess, + hThread, + StackFrame, + ContextRecord, + ReadMemoryRoutine, + FunctionTableAccessRoutine, + GetModuleBaseRoutine, + TranslateAddress); + } else { + return false; + } +} + +PVOID WindowsDbgHelp::SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase) { + DecoderLocker locker; + WindowsDecoder* wd = (WindowsDecoder*)locker.decoder(); + + if (!wd->has_error() && wd->_pfnSymFunctionTableAccess64) { + return wd->_pfnSymFunctionTableAccess64(hProcess, AddrBase); + } else { + return NULL; + } +} + +pfn_SymFunctionTableAccess64 WindowsDbgHelp::pfnSymFunctionTableAccess64() { + DecoderLocker locker; + WindowsDecoder* wd = (WindowsDecoder*)locker.decoder(); + + if (!wd->has_error()) { + return wd->_pfnSymFunctionTableAccess64; + } else { + return NULL; + } +} + +pfn_SymGetModuleBase64 WindowsDbgHelp::pfnSymGetModuleBase64() { + DecoderLocker locker; + WindowsDecoder* wd = (WindowsDecoder*)locker.decoder(); + + if (!wd->has_error()) { + return wd->_pfnSymGetModuleBase64; + } else { + return NULL; + } +} + +#endif // AMD64 diff --git a/hotspot/src/os/windows/vm/decoder_windows.hpp b/hotspot/src/os/windows/vm/decoder_windows.hpp index 3008ee79136..2555e8c9b79 100644 --- a/hotspot/src/os/windows/vm/decoder_windows.hpp +++ b/hotspot/src/os/windows/vm/decoder_windows.hpp @@ -38,6 +38,20 @@ typedef DWORD (WINAPI *pfn_UndecorateSymbolName)(const char*, char*, DWORD, DWOR typedef BOOL (WINAPI *pfn_SymSetSearchPath)(HANDLE, PCTSTR); typedef BOOL (WINAPI *pfn_SymGetSearchPath)(HANDLE, PTSTR, int); +#ifdef AMD64 +typedef BOOL (WINAPI *pfn_StackWalk64)(DWORD MachineType, + HANDLE hProcess, + HANDLE hThread, + LPSTACKFRAME64 StackFrame, + PVOID ContextRecord, + PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); +typedef PVOID (WINAPI *pfn_SymFunctionTableAccess64)(HANDLE hProcess, DWORD64 AddrBase); +typedef DWORD64 (WINAPI *pfn_SymGetModuleBase64)(HANDLE hProcess, DWORD64 dwAddr); +#endif + class WindowsDecoder : public AbstractDecoder { public: @@ -61,7 +75,34 @@ private: bool _can_decode_in_vm; pfn_SymGetSymFromAddr64 _pfnSymGetSymFromAddr64; pfn_UndecorateSymbolName _pfnUndecorateSymbolName; +#ifdef AMD64 + pfn_StackWalk64 _pfnStackWalk64; + pfn_SymFunctionTableAccess64 _pfnSymFunctionTableAccess64; + pfn_SymGetModuleBase64 _pfnSymGetModuleBase64; + + friend class WindowsDbgHelp; +#endif }; +#ifdef AMD64 +// TODO: refactor and move the handling of dbghelp.dll outside of Decoder +class WindowsDbgHelp : public Decoder { +public: + static BOOL StackWalk64(DWORD MachineType, + HANDLE hProcess, + HANDLE hThread, + LPSTACKFRAME64 StackFrame, + PVOID ContextRecord, + PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress); + static PVOID SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase); + + static pfn_SymFunctionTableAccess64 pfnSymFunctionTableAccess64(); + static pfn_SymGetModuleBase64 pfnSymGetModuleBase64(); +}; +#endif + #endif // OS_WINDOWS_VM_DECODER_WINDOWS_HPP diff --git a/hotspot/src/os/windows/vm/os_windows.cpp b/hotspot/src/os/windows/vm/os_windows.cpp index 015f94d6662..7daee35632e 100644 --- a/hotspot/src/os/windows/vm/os_windows.cpp +++ b/hotspot/src/os/windows/vm/os_windows.cpp @@ -3189,9 +3189,12 @@ char* os::reserve_memory_special(size_t bytes, size_t alignment, char* addr, boo return p_buf; } else { + if (TracePageSizes && Verbose) { + tty->print_cr("Reserving large pages in a single large chunk."); + } // normal policy just allocate it all at once DWORD flag = MEM_RESERVE | MEM_COMMIT | MEM_LARGE_PAGES; - char * res = (char *)VirtualAlloc(NULL, bytes, flag, prot); + char * res = (char *)VirtualAlloc(addr, bytes, flag, prot); if (res != NULL) { address pc = CALLER_PC; MemTracker::record_virtual_memory_reserve_and_commit((address)res, bytes, mtNone, pc); @@ -3917,8 +3920,6 @@ jint os::init_2(void) { #endif } - os::large_page_init(); - // Setup Windows Exceptions // for debugging float code generation bugs @@ -5429,7 +5430,7 @@ char* os::build_agent_function_name(const char *sym_name, const char *lib_name, if ((start = strrchr(lib_name, *os::file_separator())) != NULL) { lib_name = ++start; } else { - // Need to check for C: + // Need to check for drive prefix if ((start = strchr(lib_name, ':')) != NULL) { lib_name = ++start; } @@ -5714,7 +5715,66 @@ BOOL os::Advapi32Dll::AdvapiAvailable() { #endif #ifndef PRODUCT + +// test the code path in reserve_memory_special() that tries to allocate memory in a single +// contiguous memory block at a particular address. +// The test first tries to find a good approximate address to allocate at by using the same +// method to allocate some memory at any address. The test then tries to allocate memory in +// the vicinity (not directly after it to avoid possible by-chance use of that location) +// This is of course only some dodgy assumption, there is no guarantee that the vicinity of +// the previously allocated memory is available for allocation. The only actual failure +// that is reported is when the test tries to allocate at a particular location but gets a +// different valid one. A NULL return value at this point is not considered an error but may +// be legitimate. +// If -XX:+VerboseInternalVMTests is enabled, print some explanatory messages. void TestReserveMemorySpecial_test() { - // No tests available for this platform + if (!UseLargePages) { + if (VerboseInternalVMTests) { + gclog_or_tty->print("Skipping test because large pages are disabled"); + } + return; + } + // save current value of globals + bool old_use_large_pages_individual_allocation = UseLargePagesIndividualAllocation; + bool old_use_numa_interleaving = UseNUMAInterleaving; + + // set globals to make sure we hit the correct code path + UseLargePagesIndividualAllocation = UseNUMAInterleaving = false; + + // do an allocation at an address selected by the OS to get a good one. + const size_t large_allocation_size = os::large_page_size() * 4; + char* result = os::reserve_memory_special(large_allocation_size, os::large_page_size(), NULL, false); + if (result == NULL) { + if (VerboseInternalVMTests) { + gclog_or_tty->print("Failed to allocate control block with size "SIZE_FORMAT". Skipping remainder of test.", + large_allocation_size); + } + } else { + os::release_memory_special(result, large_allocation_size); + + // allocate another page within the recently allocated memory area which seems to be a good location. At least + // we managed to get it once. + const size_t expected_allocation_size = os::large_page_size(); + char* expected_location = result + os::large_page_size(); + char* actual_location = os::reserve_memory_special(expected_allocation_size, os::large_page_size(), expected_location, false); + if (actual_location == NULL) { + if (VerboseInternalVMTests) { + gclog_or_tty->print("Failed to allocate any memory at "PTR_FORMAT" size "SIZE_FORMAT". Skipping remainder of test.", + expected_location, large_allocation_size); + } + } else { + // release memory + os::release_memory_special(actual_location, expected_allocation_size); + // only now check, after releasing any memory to avoid any leaks. + assert(actual_location == expected_location, + err_msg("Failed to allocate memory at requested location "PTR_FORMAT" of size "SIZE_FORMAT", is "PTR_FORMAT" instead", + expected_location, expected_allocation_size, actual_location)); + } + } + + // restore globals + UseLargePagesIndividualAllocation = old_use_large_pages_individual_allocation; + UseNUMAInterleaving = old_use_numa_interleaving; } -#endif +#endif // PRODUCT + diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp b/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp index 595cd781447..e0ed6961e3a 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/globals_solaris_sparc.hpp @@ -35,7 +35,9 @@ define_pd_global(intx, CompilerThreadStackSize, 0); // Used on 64 bit platforms for UseCompressedOops base address #ifdef _LP64 -define_pd_global(uintx, HeapBaseMinAddress, CONST64(4)*G); +// use 6G as default base address because by default the OS maps the application +// to 4G on Solaris-Sparc. This leaves at least 2G for the native heap. +define_pd_global(uintx, HeapBaseMinAddress, CONST64(6)*G); #else define_pd_global(uintx, HeapBaseMinAddress, 2*G); #endif diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index a0f2a7680be..09735dae0c6 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -29,6 +29,7 @@ #include "classfile/vmSymbols.hpp" #include "code/icBuffer.hpp" #include "code/vtableStubs.hpp" +#include "decoder_windows.hpp" #include "interpreter/interpreter.hpp" #include "jvm_windows.h" #include "memory/allocation.inline.hpp" @@ -327,6 +328,94 @@ add_ptr_func_t* os::atomic_add_ptr_func = os::atomic_add_ptr_bootstrap cmpxchg_long_func_t* os::atomic_cmpxchg_long_func = os::atomic_cmpxchg_long_bootstrap; +#ifdef AMD64 +/* + * Windows/x64 does not use stack frames the way expected by Java: + * [1] in most cases, there is no frame pointer. All locals are addressed via RSP + * [2] in rare cases, when alloca() is used, a frame pointer is used, but this may + * not be RBP. + * See http://msdn.microsoft.com/en-us/library/ew5tede7.aspx + * + * So it's not possible to print the native stack using the + * while (...) {... fr = os::get_sender_for_C_frame(&fr); } + * loop in vmError.cpp. We need to roll our own loop. + */ +bool os::platform_print_native_stack(outputStream* st, void* context, + char *buf, int buf_size) +{ + CONTEXT ctx; + if (context != NULL) { + memcpy(&ctx, context, sizeof(ctx)); + } else { + RtlCaptureContext(&ctx); + } + + st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); + + STACKFRAME stk; + memset(&stk, 0, sizeof(stk)); + stk.AddrStack.Offset = ctx.Rsp; + stk.AddrStack.Mode = AddrModeFlat; + stk.AddrFrame.Offset = ctx.Rbp; + stk.AddrFrame.Mode = AddrModeFlat; + stk.AddrPC.Offset = ctx.Rip; + stk.AddrPC.Mode = AddrModeFlat; + + int count = 0; + address lastpc = 0; + while (count++ < StackPrintLimit) { + intptr_t* sp = (intptr_t*)stk.AddrStack.Offset; + intptr_t* fp = (intptr_t*)stk.AddrFrame.Offset; // NOT necessarily the same as ctx.Rbp! + address pc = (address)stk.AddrPC.Offset; + + if (pc != NULL && sp != NULL && fp != NULL) { + if (count == 2 && lastpc == pc) { + // Skip it -- StackWalk64() may return the same PC + // (but different SP) on the first try. + } else { + // Don't try to create a frame(sp, fp, pc) -- on WinX64, stk.AddrFrame + // may not contain what Java expects, and may cause the frame() constructor + // to crash. Let's just print out the symbolic address. + frame::print_C_frame(st, buf, buf_size, pc); + st->cr(); + } + lastpc = pc; + } else { + break; + } + + PVOID p = WindowsDbgHelp::SymFunctionTableAccess64(GetCurrentProcess(), stk.AddrPC.Offset); + if (!p) { + // StackWalk64() can't handle this PC. Calling StackWalk64 again may cause crash. + break; + } + + BOOL result = WindowsDbgHelp::StackWalk64( + IMAGE_FILE_MACHINE_AMD64, // __in DWORD MachineType, + GetCurrentProcess(), // __in HANDLE hProcess, + GetCurrentThread(), // __in HANDLE hThread, + &stk, // __inout LP STACKFRAME64 StackFrame, + &ctx, // __inout PVOID ContextRecord, + NULL, // __in_opt PREAD_PROCESS_MEMORY_ROUTINE64 ReadMemoryRoutine, + WindowsDbgHelp::pfnSymFunctionTableAccess64(), + // __in_opt PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine, + WindowsDbgHelp::pfnSymGetModuleBase64(), + // __in_opt PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine, + NULL); // __in_opt PTRANSLATE_ADDRESS_ROUTINE64 TranslateAddress + + if (!result) { + break; + } + } + if (count > StackPrintLimit) { + st->print_cr("......"); + } + st->cr(); + + return true; +} +#endif // AMD64 + ExtendedPC os::fetch_frame_from_context(void* ucVoid, intptr_t** ret_sp, intptr_t** ret_fp) { @@ -401,6 +490,9 @@ frame os::current_frame() { StubRoutines::x86::get_previous_fp_entry()); if (func == NULL) return frame(); intptr_t* fp = (*func)(); + if (fp == NULL) { + return frame(); + } #else intptr_t* fp = _get_previous_fp(); #endif // AMD64 diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp index 41814b6c61b..22ffeb5dc34 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.hpp @@ -62,4 +62,10 @@ static bool register_code_area(char *low, char *high); +#ifdef AMD64 +#define PLATFORM_PRINT_NATIVE_STACK 1 +static bool platform_print_native_stack(outputStream* st, void* context, + char *buf, int buf_size); +#endif + #endif // OS_CPU_WINDOWS_X86_VM_OS_WINDOWS_X86_HPP diff --git a/hotspot/src/share/tools/LogCompilation/README b/hotspot/src/share/tools/LogCompilation/README index 90dc3b893bb..aa18fe891f6 100644 --- a/hotspot/src/share/tools/LogCompilation/README +++ b/hotspot/src/share/tools/LogCompilation/README @@ -4,14 +4,14 @@ It's main purpose is to recreate output similar to requires a 1.5 JDK to build and simply typing make should build it. It produces a jar file, logc.jar, that can be run on the -hotspot.log from LogCompilation output like this: +HotSpot log (by default, hotspot_pid{pid}.log) from LogCompilation output like this: - java -jar logc.jar hotspot.log + java -jar logc.jar hotspot_pid1234.log This will produce something like the normal PrintCompilation output. Adding the -i option with also report inlining like PrintInlining. -More information about the LogCompilation output can be found at +More information about the LogCompilation output can be found at https://wikis.oracle.com/display/HotSpotInternals/LogCompilation+overview https://wikis.oracle.com/display/HotSpotInternals/PrintCompilation diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index b7ea6eebb26..03d0d75fa30 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -4219,7 +4219,9 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes } } - if (!PrintInlining) return; + if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) { + return; + } CompileTask::print_inlining(callee, scope()->level(), bci(), msg); if (success && CIPrintMethodCodes) { callee->print_codes(); diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 037bc31f658..080eaf67088 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -709,10 +709,10 @@ static Klass* resolve_field_return_klass(methodHandle caller, int bci, TRAPS) { Bytecodes::Code code = field_access.code(); // We must load class, initialize class and resolvethe field - FieldAccessInfo result; // initialize class if needed + fieldDescriptor result; // initialize class if needed constantPoolHandle constants(THREAD, caller->constants()); - LinkResolver::resolve_field(result, constants, field_access.index(), Bytecodes::java_code(code), false, CHECK_NULL); - return result.klass()(); + LinkResolver::resolve_field_access(result, constants, field_access.index(), Bytecodes::java_code(code), CHECK_NULL); + return result.field_holder(); } @@ -826,11 +826,11 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i if (stub_id == Runtime1::access_field_patching_id) { Bytecode_field field_access(caller_method, bci); - FieldAccessInfo result; // initialize class if needed + fieldDescriptor result; // initialize class if needed Bytecodes::Code code = field_access.code(); constantPoolHandle constants(THREAD, caller_method->constants()); - LinkResolver::resolve_field(result, constants, field_access.index(), Bytecodes::java_code(code), false, CHECK); - patch_field_offset = result.field_offset(); + LinkResolver::resolve_field_access(result, constants, field_access.index(), Bytecodes::java_code(code), CHECK); + patch_field_offset = result.offset(); // If we're patching a field which is volatile then at compile it // must not have been know to be volatile, so the generated code diff --git a/hotspot/src/share/vm/ci/ciArray.cpp b/hotspot/src/share/vm/ci/ciArray.cpp index 584b1aeb50f..fdcc63a0dec 100644 --- a/hotspot/src/share/vm/ci/ciArray.cpp +++ b/hotspot/src/share/vm/ci/ciArray.cpp @@ -24,13 +24,92 @@ #include "precompiled.hpp" #include "ci/ciArray.hpp" +#include "ci/ciArrayKlass.hpp" +#include "ci/ciConstant.hpp" #include "ci/ciKlass.hpp" #include "ci/ciUtilities.hpp" +#include "oops/objArrayOop.hpp" +#include "oops/typeArrayOop.hpp" // ciArray // // This class represents an arrayOop in the HotSpot virtual // machine. +static BasicType fixup_element_type(BasicType bt) { + if (bt == T_ARRAY) return T_OBJECT; + if (bt == T_BOOLEAN) return T_BYTE; + return bt; +} + +ciConstant ciArray::element_value_impl(BasicType elembt, + arrayOop ary, + int index) { + if (ary == NULL) + return ciConstant(); + assert(ary->is_array(), ""); + if (index < 0 || index >= ary->length()) + return ciConstant(); + ArrayKlass* ak = (ArrayKlass*) ary->klass(); + BasicType abt = ak->element_type(); + if (fixup_element_type(elembt) != + fixup_element_type(abt)) + return ciConstant(); + switch (elembt) { + case T_ARRAY: + case T_OBJECT: + { + assert(ary->is_objArray(), ""); + objArrayOop objary = (objArrayOop) ary; + oop elem = objary->obj_at(index); + ciEnv* env = CURRENT_ENV; + ciObject* box = env->get_object(elem); + return ciConstant(T_OBJECT, box); + } + } + assert(ary->is_typeArray(), ""); + typeArrayOop tary = (typeArrayOop) ary; + jint value = 0; + switch (elembt) { + case T_LONG: return ciConstant(tary->long_at(index)); + case T_FLOAT: return ciConstant(tary->float_at(index)); + case T_DOUBLE: return ciConstant(tary->double_at(index)); + default: return ciConstant(); + case T_BYTE: value = tary->byte_at(index); break; + case T_BOOLEAN: value = tary->byte_at(index) & 1; break; + case T_SHORT: value = tary->short_at(index); break; + case T_CHAR: value = tary->char_at(index); break; + case T_INT: value = tary->int_at(index); break; + } + return ciConstant(elembt, value); +} + +// ------------------------------------------------------------------ +// ciArray::element_value +// +// Current value of an element. +// Returns T_ILLEGAL if there is no element at the given index. +ciConstant ciArray::element_value(int index) { + BasicType elembt = element_basic_type(); + GUARDED_VM_ENTRY( + return element_value_impl(elembt, get_arrayOop(), index); + ) +} + +// ------------------------------------------------------------------ +// ciArray::element_value_by_offset +// +// Current value of an element at the specified offset. +// Returns T_ILLEGAL if there is no element at the given offset. +ciConstant ciArray::element_value_by_offset(intptr_t element_offset) { + BasicType elembt = element_basic_type(); + intptr_t shift = exact_log2(type2aelembytes(elembt)); + 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) + return ciConstant(); + return element_value((jint) index); +} // ------------------------------------------------------------------ // ciArray::print_impl diff --git a/hotspot/src/share/vm/ci/ciArray.hpp b/hotspot/src/share/vm/ci/ciArray.hpp index 440e407a510..c5c86265d61 100644 --- a/hotspot/src/share/vm/ci/ciArray.hpp +++ b/hotspot/src/share/vm/ci/ciArray.hpp @@ -25,6 +25,8 @@ #ifndef SHARE_VM_CI_CIARRAY_HPP #define SHARE_VM_CI_CIARRAY_HPP +#include "ci/ciArrayKlass.hpp" +#include "ci/ciConstant.hpp" #include "ci/ciObject.hpp" #include "oops/arrayOop.hpp" #include "oops/objArrayOop.hpp" @@ -45,15 +47,30 @@ protected: ciArray(ciKlass* klass, int len) : ciObject(klass), _length(len) {} - arrayOop get_arrayOop() { return (arrayOop)get_oop(); } + arrayOop get_arrayOop() const { return (arrayOop)get_oop(); } const char* type_string() { return "ciArray"; } void print_impl(outputStream* st); + ciConstant element_value_impl(BasicType elembt, arrayOop ary, int index); + public: int length() { return _length; } + // Convenience routines. + ciArrayKlass* array_type() { return klass()->as_array_klass(); } + ciType* element_type() { return array_type()->element_type(); } + BasicType element_basic_type() { return element_type()->basic_type(); } + + // Current value of an element. + // Returns T_ILLEGAL if there is no element at the given index. + ciConstant element_value(int index); + + // Current value of an element at the specified offset. + // Returns T_ILLEGAL if there is no element at the given offset. + ciConstant element_value_by_offset(intptr_t element_offset); + // What kind of ciObject is this? bool is_array() { return true; } bool is_java_object() { return true; } diff --git a/hotspot/src/share/vm/ci/ciConstant.hpp b/hotspot/src/share/vm/ci/ciConstant.hpp index 8cdc893fd2b..7a72a7de1e5 100644 --- a/hotspot/src/share/vm/ci/ciConstant.hpp +++ b/hotspot/src/share/vm/ci/ciConstant.hpp @@ -41,7 +41,6 @@ private: union { jint _int; jlong _long; - jint _long_half[2]; jfloat _float; jdouble _double; ciObject* _object; @@ -111,6 +110,20 @@ public: return _value._object; } + bool is_null_or_zero() const { + if (!is_java_primitive(basic_type())) { + return as_object()->is_null_object(); + } else if (type2size[basic_type()] == 1) { + // treat float bits as int, to avoid comparison with -0 and NaN + return (_value._int == 0); + } else if (type2size[basic_type()] == 2) { + // treat double bits as long, to avoid comparison with -0 and NaN + return (_value._long == 0); + } else { + return false; + } + } + // Debugging output void print(); }; diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp index fe967554c3a..b08ec3616fa 100644 --- a/hotspot/src/share/vm/ci/ciField.cpp +++ b/hotspot/src/share/vm/ci/ciField.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,7 +75,6 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with_put(NUL assert(klass->get_instanceKlass()->is_linked(), "must be linked before using its constan-pool"); - _cp_index = index; constantPoolHandle cpool(thread, klass->get_instanceKlass()->constants()); // Get the field's name, signature, and type. @@ -116,7 +115,7 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with_put(NUL // The declared holder of this field may not have been loaded. // Bail out with partial field information. if (!holder_is_accessible) { - // _cp_index and _type have already been set. + // _type has already been set. // The default values for _flags and _constant_value will suffice. // We need values for _holder, _offset, and _is_constant, _holder = declared_holder; @@ -146,8 +145,6 @@ ciField::ciField(ciInstanceKlass* klass, int index): _known_to_link_with_put(NUL ciField::ciField(fieldDescriptor *fd): _known_to_link_with_put(NULL), _known_to_link_with_get(NULL) { ASSERT_IN_VM; - _cp_index = -1; - // Get the field's name, signature, and type. ciEnv* env = CURRENT_ENV; _name = env->get_symbol(fd->name()); @@ -189,12 +186,14 @@ void ciField::initialize_from(fieldDescriptor* fd) { _holder = CURRENT_ENV->get_instance_klass(fd->field_holder()); // Check to see if the field is constant. - if (_holder->is_initialized() && this->is_final()) { + bool is_final = this->is_final(); + bool is_stable = FoldStableValues && this->is_stable(); + if (_holder->is_initialized() && (is_final || is_stable)) { if (!this->is_static()) { // A field can be constant if it's a final static field or if // it's a final non-static field of a trusted class (classes in // java.lang.invoke and sun.invoke packages and subpackages). - if (trust_final_non_static_fields(_holder)) { + if (is_stable || trust_final_non_static_fields(_holder)) { _is_constant = true; return; } @@ -227,7 +226,6 @@ void ciField::initialize_from(fieldDescriptor* fd) { Handle mirror = k->java_mirror(); - _is_constant = true; switch(type()->basic_type()) { case T_BYTE: _constant_value = ciConstant(type()->basic_type(), mirror->byte_field(_offset)); @@ -273,6 +271,12 @@ void ciField::initialize_from(fieldDescriptor* fd) { } } } + if (is_stable && _constant_value.is_null_or_zero()) { + // It is not a constant after all; treat it as uninitialized. + _is_constant = false; + } else { + _is_constant = true; + } } else { _is_constant = false; } @@ -344,12 +348,11 @@ bool ciField::will_link(ciInstanceKlass* accessing_klass, } } - FieldAccessInfo result; - constantPoolHandle c_pool(THREAD, - accessing_klass->get_instanceKlass()->constants()); - LinkResolver::resolve_field(result, c_pool, _cp_index, - Bytecodes::java_code(bc), - true, false, KILL_COMPILE_ON_FATAL_(false)); + fieldDescriptor result; + LinkResolver::resolve_field(result, _holder->get_instanceKlass(), + _name->get_symbol(), _signature->get_symbol(), + accessing_klass->get_Klass(), bc, true, false, + KILL_COMPILE_ON_FATAL_(false)); // update the hit-cache, unless there is a problem with memory scoping: if (accessing_klass->is_shared() || !is_shared()) { @@ -373,8 +376,11 @@ void ciField::print() { tty->print(" signature="); _signature->print_symbol(); tty->print(" offset=%d type=", _offset); - if (_type != NULL) _type->print_name(); - else tty->print("(reference)"); + if (_type != NULL) + _type->print_name(); + else + tty->print("(reference)"); + tty->print(" flags=%04x", flags().as_int()); tty->print(" is_constant=%s", bool_to_str(_is_constant)); if (_is_constant && is_static()) { tty->print(" constant_value="); diff --git a/hotspot/src/share/vm/ci/ciField.hpp b/hotspot/src/share/vm/ci/ciField.hpp index ff96c99313c..75263e3f217 100644 --- a/hotspot/src/share/vm/ci/ciField.hpp +++ b/hotspot/src/share/vm/ci/ciField.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,9 +53,6 @@ private: ciInstanceKlass* _known_to_link_with_get; ciConstant _constant_value; - // Used for will_link - int _cp_index; - ciType* compute_type(); ciType* compute_type_impl(); @@ -139,7 +136,10 @@ public: // non-constant fields. These are java.lang.System.in // and java.lang.System.out. Abomination. // - // Note: the check for case 4 is not yet implemented. + // A field is also considered constant if it is marked @Stable + // and is non-null (or non-zero, if a primitive). + // For non-static fields, the null/zero check must be + // arranged by the user, as constant_value().is_null_or_zero(). bool is_constant() { return _is_constant; } // Get the constant value of this field. @@ -173,6 +173,7 @@ public: bool is_protected () { return flags().is_protected(); } bool is_static () { return flags().is_static(); } bool is_final () { return flags().is_final(); } + bool is_stable () { return flags().is_stable(); } bool is_volatile () { return flags().is_volatile(); } bool is_transient () { return flags().is_transient(); } diff --git a/hotspot/src/share/vm/ci/ciFlags.hpp b/hotspot/src/share/vm/ci/ciFlags.hpp index 6dc50d25a60..87e19466f27 100644 --- a/hotspot/src/share/vm/ci/ciFlags.hpp +++ b/hotspot/src/share/vm/ci/ciFlags.hpp @@ -59,6 +59,7 @@ public: bool is_interface () const { return (_flags & JVM_ACC_INTERFACE ) != 0; } bool is_abstract () const { return (_flags & JVM_ACC_ABSTRACT ) != 0; } bool is_strict () const { return (_flags & JVM_ACC_STRICT ) != 0; } + bool is_stable () const { return (_flags & JVM_ACC_FIELD_STABLE) != 0; } // Conversion jint as_int() { return _flags; } diff --git a/hotspot/src/share/vm/ci/ciInstance.cpp b/hotspot/src/share/vm/ci/ciInstance.cpp index a74eb04f4a7..8b48b1b3706 100644 --- a/hotspot/src/share/vm/ci/ciInstance.cpp +++ b/hotspot/src/share/vm/ci/ciInstance.cpp @@ -127,6 +127,8 @@ ciConstant ciInstance::field_value(ciField* field) { ciConstant ciInstance::field_value_by_offset(int field_offset) { ciInstanceKlass* ik = klass()->as_instance_klass(); ciField* field = ik->get_field_by_offset(field_offset, false); + if (field == NULL) + return ciConstant(); // T_ILLEGAL return field_value(field); } diff --git a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp index d74e484c66e..c689efa46d6 100644 --- a/hotspot/src/share/vm/ci/ciInstanceKlass.cpp +++ b/hotspot/src/share/vm/ci/ciInstanceKlass.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -522,8 +522,7 @@ ciInstanceKlass::compute_nonstatic_fields_impl(GrowableArray* for (JavaFieldStream fs(k); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) continue; - fieldDescriptor fd; - fd.initialize(k, fs.index()); + fieldDescriptor& fd = fs.field_descriptor(); ciField* field = new (arena) ciField(&fd); fields->append(field); } diff --git a/hotspot/src/share/vm/ci/ciMethod.cpp b/hotspot/src/share/vm/ci/ciMethod.cpp index d0363250ee6..486d8c499b6 100644 --- a/hotspot/src/share/vm/ci/ciMethod.cpp +++ b/hotspot/src/share/vm/ci/ciMethod.cpp @@ -286,7 +286,10 @@ int ciMethod::itable_index() { check_is_loaded(); assert(holder()->is_linked(), "must be linked"); VM_ENTRY_MARK; - return klassItable::compute_itable_index(get_Method()); + Method* m = get_Method(); + if (!m->has_itable_index()) + return Method::nonvirtual_vtable_index; + return m->itable_index(); } #endif // SHARK @@ -1137,6 +1140,10 @@ bool ciMethod::is_klass_loaded(int refinfo_index, bool must_be_resolved) const { // ------------------------------------------------------------------ // ciMethod::check_call bool ciMethod::check_call(int refinfo_index, bool is_static) const { + // This method is used only in C2 from InlineTree::ok_to_inline, + // and is only used under -Xcomp or -XX:CompileTheWorld. + // It appears to fail when applied to an invokeinterface call site. + // FIXME: Remove this method and resolve_method_statically; refactor to use the other LinkResolver entry points. VM_ENTRY_MARK; { EXCEPTION_MARK; diff --git a/hotspot/src/share/vm/ci/ciSymbol.hpp b/hotspot/src/share/vm/ci/ciSymbol.hpp index d54b54009be..3c974cf272e 100644 --- a/hotspot/src/share/vm/ci/ciSymbol.hpp +++ b/hotspot/src/share/vm/ci/ciSymbol.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ class ciSymbol : public ciBaseObject { friend class ciInstanceKlass; friend class ciSignature; friend class ciMethod; + friend class ciField; friend class ciObjArrayKlass; private: diff --git a/hotspot/src/share/vm/ci/ciTypeArray.cpp b/hotspot/src/share/vm/ci/ciTypeArray.cpp index d4a6eff6f41..2d013e21c0e 100644 --- a/hotspot/src/share/vm/ci/ciTypeArray.cpp +++ b/hotspot/src/share/vm/ci/ciTypeArray.cpp @@ -39,5 +39,10 @@ jchar ciTypeArray::char_at(int index) { VM_ENTRY_MARK; assert(index >= 0 && index < length(), "out of range"); - return get_typeArrayOop()->char_at(index); + jchar c = get_typeArrayOop()->char_at(index); +#ifdef ASSERT + jchar d = element_value(index).as_char(); + assert(c == d, ""); +#endif //ASSERT + return c; } diff --git a/hotspot/src/share/vm/classfile/classFileParser.cpp b/hotspot/src/share/vm/classfile/classFileParser.cpp index 0705c5f14d6..70662d3e8b8 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -888,6 +888,7 @@ void ClassFileParser::parse_field_attributes(u2 attributes_count, int runtime_visible_type_annotations_length = 0; u1* runtime_invisible_type_annotations = NULL; int runtime_invisible_type_annotations_length = 0; + bool runtime_invisible_type_annotations_exists = false; while (attributes_count--) { cfs->guarantee_more(6, CHECK); // attribute_name_index, attribute_length u2 attribute_name_index = cfs->get_u2_fast(); @@ -946,15 +947,27 @@ void ClassFileParser::parse_field_attributes(u2 attributes_count, assert(runtime_invisible_annotations != NULL, "null invisible annotations"); cfs->skip_u1(runtime_invisible_annotations_length, CHECK); } else if (attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + if (runtime_visible_type_annotations != NULL) { + classfile_parse_error( + "Multiple RuntimeVisibleTypeAnnotations attributes for field in class file %s", CHECK); + } runtime_visible_type_annotations_length = attribute_length; runtime_visible_type_annotations = cfs->get_u1_buffer(); assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); cfs->skip_u1(runtime_visible_type_annotations_length, CHECK); - } else if (PreserveAllAnnotations && attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { - runtime_invisible_type_annotations_length = attribute_length; - runtime_invisible_type_annotations = cfs->get_u1_buffer(); - assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); - cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK); + } else if (attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + if (runtime_invisible_type_annotations_exists) { + classfile_parse_error( + "Multiple RuntimeInvisibleTypeAnnotations attributes for field in class file %s", CHECK); + } else { + runtime_invisible_type_annotations_exists = true; + } + if (PreserveAllAnnotations) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + } + cfs->skip_u1(attribute_length, CHECK); } else { cfs->skip_u1(attribute_length, CHECK); // Skip unknown attributes } @@ -1774,6 +1787,10 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d if (_location != _in_method) break; // only allow for methods if (!privileged) break; // only allow in privileged code return _method_LambdaForm_Hidden; + case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_invoke_Stable_signature): + if (_location != _in_field) break; // only allow for fields + if (!privileged) break; // only allow in privileged code + return _field_Stable; case vmSymbols::VM_SYMBOL_ENUM_NAME(sun_misc_Contended_signature): if (_location != _in_field && _location != _in_class) break; // only allow for fields and classes if (!EnableContended || (RestrictContended && !privileged)) break; // honor privileges @@ -1786,6 +1803,8 @@ ClassFileParser::AnnotationCollector::annotation_index(ClassLoaderData* loader_d void ClassFileParser::FieldAnnotationCollector::apply_to(FieldInfo* f) { if (is_contended()) f->set_contended_group(contended_group()); + if (is_stable()) + f->set_stable(true); } ClassFileParser::FieldAnnotationCollector::~FieldAnnotationCollector() { @@ -2060,6 +2079,7 @@ methodHandle ClassFileParser::parse_method(bool is_interface, int runtime_visible_type_annotations_length = 0; u1* runtime_invisible_type_annotations = NULL; int runtime_invisible_type_annotations_length = 0; + bool runtime_invisible_type_annotations_exists = false; u1* annotation_default = NULL; int annotation_default_length = 0; @@ -2316,16 +2336,30 @@ methodHandle ClassFileParser::parse_method(bool is_interface, assert(annotation_default != NULL, "null annotation default"); cfs->skip_u1(annotation_default_length, CHECK_(nullHandle)); } else if (method_attribute_name == vmSymbols::tag_runtime_visible_type_annotations()) { + if (runtime_visible_type_annotations != NULL) { + classfile_parse_error( + "Multiple RuntimeVisibleTypeAnnotations attributes for method in class file %s", + CHECK_(nullHandle)); + } runtime_visible_type_annotations_length = method_attribute_length; runtime_visible_type_annotations = cfs->get_u1_buffer(); assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); // No need for the VM to parse Type annotations cfs->skip_u1(runtime_visible_type_annotations_length, CHECK_(nullHandle)); - } else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { - runtime_invisible_type_annotations_length = method_attribute_length; - runtime_invisible_type_annotations = cfs->get_u1_buffer(); - assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); - cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK_(nullHandle)); + } else if (method_attribute_name == vmSymbols::tag_runtime_invisible_type_annotations()) { + if (runtime_invisible_type_annotations_exists) { + classfile_parse_error( + "Multiple RuntimeInvisibleTypeAnnotations attributes for method in class file %s", + CHECK_(nullHandle)); + } else { + runtime_invisible_type_annotations_exists = true; + } + if (PreserveAllAnnotations) { + runtime_invisible_type_annotations_length = method_attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + } + cfs->skip_u1(method_attribute_length, CHECK_(nullHandle)); } else { // Skip unknown attributes cfs->skip_u1(method_attribute_length, CHECK_(nullHandle)); @@ -2818,6 +2852,7 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio int runtime_visible_type_annotations_length = 0; u1* runtime_invisible_type_annotations = NULL; int runtime_invisible_type_annotations_length = 0; + bool runtime_invisible_type_annotations_exists = false; u1* inner_classes_attribute_start = NULL; u4 inner_classes_attribute_length = 0; u2 enclosing_method_class_index = 0; @@ -2921,16 +2956,28 @@ void ClassFileParser::parse_classfile_attributes(ClassFileParser::ClassAnnotatio parsed_bootstrap_methods_attribute = true; parse_classfile_bootstrap_methods_attribute(attribute_length, CHECK); } else if (tag == vmSymbols::tag_runtime_visible_type_annotations()) { + if (runtime_visible_type_annotations != NULL) { + classfile_parse_error( + "Multiple RuntimeVisibleTypeAnnotations attributes in class file %s", CHECK); + } runtime_visible_type_annotations_length = attribute_length; runtime_visible_type_annotations = cfs->get_u1_buffer(); assert(runtime_visible_type_annotations != NULL, "null visible type annotations"); // No need for the VM to parse Type annotations cfs->skip_u1(runtime_visible_type_annotations_length, CHECK); - } else if (PreserveAllAnnotations && tag == vmSymbols::tag_runtime_invisible_type_annotations()) { - runtime_invisible_type_annotations_length = attribute_length; - runtime_invisible_type_annotations = cfs->get_u1_buffer(); - assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); - cfs->skip_u1(runtime_invisible_type_annotations_length, CHECK); + } else if (tag == vmSymbols::tag_runtime_invisible_type_annotations()) { + if (runtime_invisible_type_annotations_exists) { + classfile_parse_error( + "Multiple RuntimeInvisibleTypeAnnotations attributes in class file %s", CHECK); + } else { + runtime_invisible_type_annotations_exists = true; + } + if (PreserveAllAnnotations) { + runtime_invisible_type_annotations_length = attribute_length; + runtime_invisible_type_annotations = cfs->get_u1_buffer(); + assert(runtime_invisible_type_annotations != NULL, "null invisible type annotations"); + } + cfs->skip_u1(attribute_length, CHECK); } else { // Unknown attribute cfs->skip_u1(attribute_length, CHECK); @@ -3948,9 +3995,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, this_klass->set_has_final_method(); } this_klass->copy_method_ordering(method_ordering, CHECK_NULL); - // The InstanceKlass::_methods_jmethod_ids cache and the - // InstanceKlass::_methods_cached_itable_indices cache are - // both managed on the assumption that the initial cache + // The InstanceKlass::_methods_jmethod_ids cache + // is managed on the assumption that the initial cache // size is equal to the number of methods in the class. If // that changes, then InstanceKlass::idnum_can_increment() // has to be changed accordingly. diff --git a/hotspot/src/share/vm/classfile/classFileParser.hpp b/hotspot/src/share/vm/classfile/classFileParser.hpp index 1b5ed30c5a6..02a4ce20dd3 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.hpp +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp @@ -125,6 +125,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { _method_LambdaForm_Compiled, _method_LambdaForm_Hidden, _sun_misc_Contended, + _field_Stable, _annotation_LIMIT }; const Location _location; @@ -143,14 +144,23 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC { assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); _annotations_present |= nth_bit((int)id); } + + void remove_annotation(ID id) { + assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob"); + _annotations_present &= ~nth_bit((int)id); + } + // Report if the annotation is present. - bool has_any_annotations() { return _annotations_present != 0; } - bool has_annotation(ID id) { return (nth_bit((int)id) & _annotations_present) != 0; } + bool has_any_annotations() const { return _annotations_present != 0; } + bool has_annotation(ID id) const { return (nth_bit((int)id) & _annotations_present) != 0; } void set_contended_group(u2 group) { _contended_group = group; } - u2 contended_group() { return _contended_group; } + u2 contended_group() const { return _contended_group; } - bool is_contended() { return has_annotation(_sun_misc_Contended); } + bool is_contended() const { return has_annotation(_sun_misc_Contended); } + + void set_stable(bool stable) { set_annotation(_field_Stable); } + bool is_stable() const { return has_annotation(_field_Stable); } }; // This class also doubles as a holder for metadata cleanup. diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 35055b4cb41..0ab350d90f8 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -1319,6 +1319,25 @@ static void clear_pending_exception_if_not_oom(TRAPS) { // The CHECK at the caller will propagate the exception out } +/** + * Returns if the given method should be compiled when doing compile-the-world. + * + * TODO: This should be a private method in a CompileTheWorld class. + */ +static bool can_be_compiled(methodHandle m, int comp_level) { + assert(CompileTheWorld, "must be"); + + // It's not valid to compile a native wrapper for MethodHandle methods + // that take a MemberName appendix since the bytecode signature is not + // correct. + vmIntrinsics::ID iid = m->intrinsic_id(); + if (MethodHandles::is_signature_polymorphic(iid) && MethodHandles::has_member_arg(iid)) { + return false; + } + + return CompilationPolicy::can_be_compiled(m, comp_level); +} + void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { int len = (int)strlen(name); if (len > 6 && strcmp(".class", name + len - 6) == 0) { @@ -1362,8 +1381,7 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { int comp_level = CompilationPolicy::policy()->initial_compile_level(); for (int n = 0; n < k->methods()->length(); n++) { methodHandle m (THREAD, k->methods()->at(n)); - if (CompilationPolicy::can_be_compiled(m, comp_level)) { - + if (can_be_compiled(m, comp_level)) { if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) { // Give sweeper a chance to keep up with CTW VM_ForceSafepoint op; @@ -1375,7 +1393,7 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { methodHandle(), 0, "CTW", THREAD); if (HAS_PENDING_EXCEPTION) { clear_pending_exception_if_not_oom(CHECK); - tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name()->as_C_string()); + tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string()); } else { _compile_the_world_method_counter++; } @@ -1391,11 +1409,13 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { methodHandle(), 0, "CTW", THREAD); if (HAS_PENDING_EXCEPTION) { clear_pending_exception_if_not_oom(CHECK); - tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name()->as_C_string()); + tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string()); } else { _compile_the_world_method_counter++; } } + } else { + tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string()); } nmethod* nm = m->code(); diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index b59fe66e062..99a45b55b6d 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -450,6 +450,10 @@ class MethodFamily : public ResourceObj { streamIndentor si(str, indent * 2); str->indent().print("Selected method: "); print_method(str, _selected_target); + Klass* method_holder = _selected_target->method_holder(); + if (!method_holder->is_interface()) { + tty->print(" : in superclass"); + } str->print_cr(""); } @@ -1141,19 +1145,23 @@ static void create_overpasses( #endif // ndef PRODUCT if (method->has_target()) { Method* selected = method->get_selected_target(); - max_stack = assemble_redirect( + if (selected->method_holder()->is_interface()) { + max_stack = assemble_redirect( &bpool, &buffer, slot->signature(), selected, CHECK); + } } else if (method->throws_exception()) { max_stack = assemble_abstract_method_error( &bpool, &buffer, method->get_exception_message(), CHECK); } - AccessFlags flags = accessFlags_from( + if (max_stack != 0) { + AccessFlags flags = accessFlags_from( JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE); - Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(), + Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(), flags, max_stack, slot->size_of_parameters(), ConstMethod::OVERPASS, CHECK); - if (m != NULL) { - overpasses.push(m); + if (m != NULL) { + overpasses.push(m); + } } } } diff --git a/hotspot/src/share/vm/classfile/javaClasses.cpp b/hotspot/src/share/vm/classfile/javaClasses.cpp index 8e94d834ad9..9331cc1246f 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.cpp +++ b/hotspot/src/share/vm/classfile/javaClasses.cpp @@ -438,6 +438,29 @@ bool java_lang_String::equals(oop java_string, jchar* chars, int len) { return true; } +bool java_lang_String::equals(oop str1, oop str2) { + assert(str1->klass() == SystemDictionary::String_klass(), + "must be java String"); + assert(str2->klass() == SystemDictionary::String_klass(), + "must be java String"); + typeArrayOop value1 = java_lang_String::value(str1); + int offset1 = java_lang_String::offset(str1); + int length1 = java_lang_String::length(str1); + typeArrayOop value2 = java_lang_String::value(str2); + int offset2 = java_lang_String::offset(str2); + int length2 = java_lang_String::length(str2); + + if (length1 != length2) { + return false; + } + for (int i = 0; i < length1; i++) { + if (value1->char_at(i + offset1) != value2->char_at(i + offset2)) { + return false; + } + } + return true; +} + void java_lang_String::print(Handle java_string, outputStream* st) { oop obj = java_string(); assert(obj->klass() == SystemDictionary::String_klass(), "must be java_string"); diff --git a/hotspot/src/share/vm/classfile/javaClasses.hpp b/hotspot/src/share/vm/classfile/javaClasses.hpp index 8a8e801f387..ffccf2f0e0c 100644 --- a/hotspot/src/share/vm/classfile/javaClasses.hpp +++ b/hotspot/src/share/vm/classfile/javaClasses.hpp @@ -182,6 +182,7 @@ class java_lang_String : AllStatic { static unsigned int hash_string(oop java_string); static bool equals(oop java_string, jchar* chars, int len); + static bool equals(oop str1, oop str2); // Conversion between '.' and '/' formats static Handle externalize_classname(Handle java_string, TRAPS) { return char_converter(java_string, '/', '.', THREAD); } diff --git a/hotspot/src/share/vm/classfile/symbolTable.cpp b/hotspot/src/share/vm/classfile/symbolTable.cpp index c00e9581759..62988c7bf4a 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.cpp +++ b/hotspot/src/share/vm/classfile/symbolTable.cpp @@ -341,7 +341,7 @@ Symbol* SymbolTable::new_permanent_symbol(const char* name, TRAPS) { Symbol* SymbolTable::basic_add(int index_arg, u1 *name, int len, unsigned int hashValue_arg, bool c_heap, TRAPS) { - assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), + assert(!Universe::heap()->is_in_reserved(name), "proposed name of symbol must be stable"); // Don't allow symbols to be created which cannot fit in a Symbol*. @@ -685,7 +685,7 @@ oop StringTable::intern(Handle string_or_null, jchar* name, if (found_string != NULL) return found_string; debug_only(StableMemoryChecker smc(name, len * sizeof(name[0]))); - assert(!Universe::heap()->is_in_reserved(name) || GC_locker::is_active(), + assert(!Universe::heap()->is_in_reserved(name), "proposed name of symbol must be stable"); Handle string; @@ -807,6 +807,8 @@ void StringTable::possibly_parallel_oops_do(OopClosure* f) { } } +// This verification is part of Universe::verify() and needs to be quick. +// See StringTable::verify_and_compare() below for exhaustive verification. void StringTable::verify() { for (int i = 0; i < the_table()->table_size(); ++i) { HashtableEntry* p = the_table()->bucket(i); @@ -825,6 +827,162 @@ void StringTable::dump(outputStream* st) { the_table()->dump_table(st, "StringTable"); } +StringTable::VerifyRetTypes StringTable::compare_entries( + int bkt1, int e_cnt1, + HashtableEntry* e_ptr1, + int bkt2, int e_cnt2, + HashtableEntry* e_ptr2) { + // These entries are sanity checked by verify_and_compare_entries() + // before this function is called. + oop str1 = e_ptr1->literal(); + oop str2 = e_ptr2->literal(); + + if (str1 == str2) { + tty->print_cr("ERROR: identical oop values (0x" PTR_FORMAT ") " + "in entry @ bucket[%d][%d] and entry @ bucket[%d][%d]", + str1, bkt1, e_cnt1, bkt2, e_cnt2); + return _verify_fail_continue; + } + + if (java_lang_String::equals(str1, str2)) { + tty->print_cr("ERROR: identical String values in entry @ " + "bucket[%d][%d] and entry @ bucket[%d][%d]", + bkt1, e_cnt1, bkt2, e_cnt2); + return _verify_fail_continue; + } + + return _verify_pass; +} + +StringTable::VerifyRetTypes StringTable::verify_entry(int bkt, int e_cnt, + HashtableEntry* e_ptr, + StringTable::VerifyMesgModes mesg_mode) { + + VerifyRetTypes ret = _verify_pass; // be optimistic + + oop str = e_ptr->literal(); + if (str == NULL) { + if (mesg_mode == _verify_with_mesgs) { + tty->print_cr("ERROR: NULL oop value in entry @ bucket[%d][%d]", bkt, + e_cnt); + } + // NULL oop means no more verifications are possible + return _verify_fail_done; + } + + if (str->klass() != SystemDictionary::String_klass()) { + if (mesg_mode == _verify_with_mesgs) { + tty->print_cr("ERROR: oop is not a String in entry @ bucket[%d][%d]", + bkt, e_cnt); + } + // not a String means no more verifications are possible + return _verify_fail_done; + } + + unsigned int h = java_lang_String::hash_string(str); + if (e_ptr->hash() != h) { + if (mesg_mode == _verify_with_mesgs) { + tty->print_cr("ERROR: broken hash value in entry @ bucket[%d][%d], " + "bkt_hash=%d, str_hash=%d", bkt, e_cnt, e_ptr->hash(), h); + } + ret = _verify_fail_continue; + } + + if (the_table()->hash_to_index(h) != bkt) { + if (mesg_mode == _verify_with_mesgs) { + tty->print_cr("ERROR: wrong index value for entry @ bucket[%d][%d], " + "str_hash=%d, hash_to_index=%d", bkt, e_cnt, h, + the_table()->hash_to_index(h)); + } + ret = _verify_fail_continue; + } + + return ret; +} + +// See StringTable::verify() above for the quick verification that is +// part of Universe::verify(). This verification is exhaustive and +// reports on every issue that is found. StringTable::verify() only +// reports on the first issue that is found. +// +// StringTable::verify_entry() checks: +// - oop value != NULL (same as verify()) +// - oop value is a String +// - hash(String) == hash in entry (same as verify()) +// - index for hash == index of entry (same as verify()) +// +// StringTable::compare_entries() checks: +// - oops are unique across all entries +// - String values are unique across all entries +// +int StringTable::verify_and_compare_entries() { + assert(StringTable_lock->is_locked(), "sanity check"); + + int fail_cnt = 0; + + // first, verify all the entries individually: + for (int bkt = 0; bkt < the_table()->table_size(); bkt++) { + HashtableEntry* e_ptr = the_table()->bucket(bkt); + for (int e_cnt = 0; e_ptr != NULL; e_ptr = e_ptr->next(), e_cnt++) { + VerifyRetTypes ret = verify_entry(bkt, e_cnt, e_ptr, _verify_with_mesgs); + if (ret != _verify_pass) { + fail_cnt++; + } + } + } + + // Optimization: if the above check did not find any failures, then + // the comparison loop below does not need to call verify_entry() + // before calling compare_entries(). If there were failures, then we + // have to call verify_entry() to see if the entry can be passed to + // compare_entries() safely. When we call verify_entry() in the loop + // below, we do so quietly to void duplicate messages and we don't + // increment fail_cnt because the failures have already been counted. + bool need_entry_verify = (fail_cnt != 0); + + // second, verify all entries relative to each other: + for (int bkt1 = 0; bkt1 < the_table()->table_size(); bkt1++) { + HashtableEntry* e_ptr1 = the_table()->bucket(bkt1); + for (int e_cnt1 = 0; e_ptr1 != NULL; e_ptr1 = e_ptr1->next(), e_cnt1++) { + if (need_entry_verify) { + VerifyRetTypes ret = verify_entry(bkt1, e_cnt1, e_ptr1, + _verify_quietly); + if (ret == _verify_fail_done) { + // cannot use the current entry to compare against other entries + continue; + } + } + + for (int bkt2 = bkt1; bkt2 < the_table()->table_size(); bkt2++) { + HashtableEntry* e_ptr2 = the_table()->bucket(bkt2); + int e_cnt2; + for (e_cnt2 = 0; e_ptr2 != NULL; e_ptr2 = e_ptr2->next(), e_cnt2++) { + if (bkt1 == bkt2 && e_cnt2 <= e_cnt1) { + // skip the entries up to and including the one that + // we're comparing against + continue; + } + + if (need_entry_verify) { + VerifyRetTypes ret = verify_entry(bkt2, e_cnt2, e_ptr2, + _verify_quietly); + if (ret == _verify_fail_done) { + // cannot compare against this entry + continue; + } + } + + // compare two entries, report and count any failures: + if (compare_entries(bkt1, e_cnt1, e_ptr1, bkt2, e_cnt2, e_ptr2) + != _verify_pass) { + fail_cnt++; + } + } + } + } + } + return fail_cnt; +} // Create a new table and using alternate hash code, populate the new table // with the existing strings. Set flag to use the alternate hash code afterwards. diff --git a/hotspot/src/share/vm/classfile/symbolTable.hpp b/hotspot/src/share/vm/classfile/symbolTable.hpp index 7a0031c9ab4..dc7d0337a0e 100644 --- a/hotspot/src/share/vm/classfile/symbolTable.hpp +++ b/hotspot/src/share/vm/classfile/symbolTable.hpp @@ -311,6 +311,26 @@ public: static void verify(); static void dump(outputStream* st); + enum VerifyMesgModes { + _verify_quietly = 0, + _verify_with_mesgs = 1 + }; + + enum VerifyRetTypes { + _verify_pass = 0, + _verify_fail_continue = 1, + _verify_fail_done = 2 + }; + + static VerifyRetTypes compare_entries(int bkt1, int e_cnt1, + HashtableEntry* e_ptr1, + int bkt2, int e_cnt2, + HashtableEntry* e_ptr2); + static VerifyRetTypes verify_entry(int bkt, int e_cnt, + HashtableEntry* e_ptr, + VerifyMesgModes mesg_mode); + static int verify_and_compare_entries(); + // Sharing static void copy_buckets(char** top, char*end) { the_table()->Hashtable::copy_buckets(top, end); diff --git a/hotspot/src/share/vm/classfile/vmSymbols.hpp b/hotspot/src/share/vm/classfile/vmSymbols.hpp index 067cf503305..f1758f86654 100644 --- a/hotspot/src/share/vm/classfile/vmSymbols.hpp +++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp @@ -270,6 +270,7 @@ template(java_lang_invoke_LambdaForm, "java/lang/invoke/LambdaForm") \ template(java_lang_invoke_ForceInline_signature, "Ljava/lang/invoke/ForceInline;") \ template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \ + template(sun_invoke_Stable_signature, "Lsun/invoke/Stable;") \ template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \ template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \ template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \ diff --git a/hotspot/src/share/vm/code/compiledIC.cpp b/hotspot/src/share/vm/code/compiledIC.cpp index e9a63b86623..489e649fadc 100644 --- a/hotspot/src/share/vm/code/compiledIC.cpp +++ b/hotspot/src/share/vm/code/compiledIC.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -160,32 +160,42 @@ address CompiledIC::stub_address() const { // High-level access to an inline cache. Guaranteed to be MT-safe. -void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) { - methodHandle method = call_info->selected_method(); - bool is_invoke_interface = (bytecode == Bytecodes::_invokeinterface && !call_info->has_vtable_index()); +bool CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS) { assert(CompiledIC_lock->is_locked() || SafepointSynchronize::is_at_safepoint(), ""); assert(!is_optimized(), "cannot set an optimized virtual call to megamorphic"); assert(is_call_to_compiled() || is_call_to_interpreted(), "going directly to megamorphic?"); address entry; - if (is_invoke_interface) { - int index = klassItable::compute_itable_index(call_info->resolved_method()()); - entry = VtableStubs::create_stub(false, index, method()); - assert(entry != NULL, "entry not computed"); + if (call_info->call_kind() == CallInfo::itable_call) { + assert(bytecode == Bytecodes::_invokeinterface, ""); + int itable_index = call_info->itable_index(); + entry = VtableStubs::find_itable_stub(itable_index); + if (entry == false) { + return false; + } +#ifdef ASSERT + int index = call_info->resolved_method()->itable_index(); + assert(index == itable_index, "CallInfo pre-computes this"); +#endif //ASSERT InstanceKlass* k = call_info->resolved_method()->method_holder(); - assert(k->is_interface(), "sanity check"); + assert(k->verify_itable_index(itable_index), "sanity check"); InlineCacheBuffer::create_transition_stub(this, k, entry); } else { - // Can be different than method->vtable_index(), due to package-private etc. + assert(call_info->call_kind() == CallInfo::vtable_call, "either itable or vtable"); + // Can be different than selected_method->vtable_index(), due to package-private etc. int vtable_index = call_info->vtable_index(); - entry = VtableStubs::create_stub(true, vtable_index, method()); - InlineCacheBuffer::create_transition_stub(this, method(), entry); + assert(call_info->resolved_klass()->verify_vtable_index(vtable_index), "sanity check"); + entry = VtableStubs::find_vtable_stub(vtable_index); + if (entry == NULL) { + return false; + } + InlineCacheBuffer::create_transition_stub(this, NULL, entry); } if (TraceICs) { ResourceMark rm; tty->print_cr ("IC@" INTPTR_FORMAT ": to megamorphic %s entry: " INTPTR_FORMAT, - instruction_address(), method->print_value_string(), entry); + instruction_address(), call_info->selected_method()->print_value_string(), entry); } // We can't check this anymore. With lazy deopt we could have already @@ -195,6 +205,7 @@ void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod // race because the IC entry was complete when we safepointed so // cleaning it immediately is harmless. // assert(is_megamorphic(), "sanity check"); + return true; } diff --git a/hotspot/src/share/vm/code/compiledIC.hpp b/hotspot/src/share/vm/code/compiledIC.hpp index 96cb0a582bb..598cbe949e2 100644 --- a/hotspot/src/share/vm/code/compiledIC.hpp +++ b/hotspot/src/share/vm/code/compiledIC.hpp @@ -226,7 +226,10 @@ class CompiledIC: public ResourceObj { // void set_to_clean(); // Can only be called during a safepoint operation void set_to_monomorphic(CompiledICInfo& info); - void set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS); + + // Returns true if successful and false otherwise. The call can fail if memory + // allocation in the code cache fails. + bool set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecode, TRAPS); static void compute_monomorphic_entry(methodHandle method, KlassHandle receiver_klass, bool is_optimized, bool static_bound, CompiledICInfo& info, TRAPS); diff --git a/hotspot/src/share/vm/code/vtableStubs.cpp b/hotspot/src/share/vm/code/vtableStubs.cpp index 0d7b39a0241..5af91a3a6ee 100644 --- a/hotspot/src/share/vm/code/vtableStubs.cpp +++ b/hotspot/src/share/vm/code/vtableStubs.cpp @@ -46,12 +46,9 @@ address VtableStub::_chunk = NULL; address VtableStub::_chunk_end = NULL; VMReg VtableStub::_receiver_location = VMRegImpl::Bad(); -static int num_vtable_chunks = 0; - void* VtableStub::operator new(size_t size, int code_size) throw() { assert(size == sizeof(VtableStub), "mismatched size"); - num_vtable_chunks++; // compute real VtableStub size (rounded to nearest word) const int real_size = round_to(code_size + sizeof(VtableStub), wordSize); // malloc them in chunks to minimize header overhead @@ -60,7 +57,7 @@ void* VtableStub::operator new(size_t size, int code_size) throw() { const int bytes = chunk_factor * real_size + pd_code_alignment(); BufferBlob* blob = BufferBlob::create("vtable chunks", bytes); if (blob == NULL) { - vm_exit_out_of_memory(bytes, OOM_MALLOC_ERROR, "CodeCache: no room for vtable chunks"); + return NULL; } _chunk = blob->content_begin(); _chunk_end = _chunk + bytes; @@ -111,7 +108,7 @@ void VtableStubs::initialize() { } -address VtableStubs::create_stub(bool is_vtable_stub, int vtable_index, Method* method) { +address VtableStubs::find_stub(bool is_vtable_stub, int vtable_index) { assert(vtable_index >= 0, "must be positive"); VtableStub* s = ShareVtableStubs ? lookup(is_vtable_stub, vtable_index) : NULL; @@ -121,6 +118,12 @@ address VtableStubs::create_stub(bool is_vtable_stub, int vtable_index, Method* } else { s = create_itable_stub(vtable_index); } + + // Creation of vtable or itable can fail if there is not enough free space in the code cache. + if (s == NULL) { + return NULL; + } + enter(is_vtable_stub, vtable_index, s); if (PrintAdapterHandlers) { tty->print_cr("Decoding VtableStub %s[%d]@%d", diff --git a/hotspot/src/share/vm/code/vtableStubs.hpp b/hotspot/src/share/vm/code/vtableStubs.hpp index aa95fee763c..06f2a67a857 100644 --- a/hotspot/src/share/vm/code/vtableStubs.hpp +++ b/hotspot/src/share/vm/code/vtableStubs.hpp @@ -121,9 +121,11 @@ class VtableStubs : AllStatic { static VtableStub* lookup (bool is_vtable_stub, int vtable_index); static void enter (bool is_vtable_stub, int vtable_index, VtableStub* s); static inline uint hash (bool is_vtable_stub, int vtable_index); + static address find_stub (bool is_vtable_stub, int vtable_index); public: - static address create_stub(bool is_vtable_stub, int vtable_index, Method* method); // return the entry point of a stub for this call + static address find_vtable_stub(int vtable_index) { return find_stub(true, vtable_index); } + static address find_itable_stub(int itable_index) { return find_stub(false, itable_index); } static bool is_entry_point(address pc); // is pc a vtable stub entry point? static bool contains(address pc); // is pc within any stub? static VtableStub* stub_containing(address pc); // stub containing pc or NULL diff --git a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp index 04b550c718b..2fc6edd34df 100644 --- a/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp +++ b/hotspot/src/share/vm/gc_implementation/concurrentMarkSweep/concurrentMarkSweepGeneration.cpp @@ -230,7 +230,7 @@ ConcurrentMarkSweepGeneration::ConcurrentMarkSweepGeneration( // depends on this property. debug_only( FreeChunk* junk = NULL; - assert(UseCompressedKlassPointers || + assert(UseCompressedClassPointers || junk->prev_addr() == (void*)(oop(junk)->klass_addr()), "Offset of FreeChunk::_prev within FreeChunk must match" " that of OopDesc::_klass within OopDesc"); @@ -1407,7 +1407,7 @@ ConcurrentMarkSweepGeneration::par_promote(int thread_num, assert(!((FreeChunk*)obj_ptr)->is_free(), "Error, block will look free but show wrong size"); OrderAccess::storestore(); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { // Copy gap missed by (aligned) header size calculation below obj->set_klass_gap(old->klass_gap()); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp index 04f8ccd0fc7..77f08f0d3a3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/concurrentMark.cpp @@ -481,9 +481,8 @@ uint ConcurrentMark::scale_parallel_threads(uint n_par_threads) { ConcurrentMark::ConcurrentMark(G1CollectedHeap* g1h, ReservedSpace heap_rs) : _g1h(g1h), - _markBitMap1(MinObjAlignment - 1), - _markBitMap2(MinObjAlignment - 1), - + _markBitMap1(log2_intptr(MinObjAlignment)), + _markBitMap2(log2_intptr(MinObjAlignment)), _parallel_marking_threads(0), _max_parallel_marking_threads(0), _sleep_factor(0.0), diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.cpp new file mode 100644 index 00000000000..7f5023b422b --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.cpp @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#include "precompiled.hpp" +#include "gc_implementation/g1/g1BiasedArray.hpp" + +#ifndef PRODUCT +void G1BiasedMappedArrayBase::verify_index(idx_t index) const { + guarantee(_base != NULL, "Array not initialized"); + guarantee(index < length(), err_msg("Index out of bounds index: "SIZE_FORMAT" length: "SIZE_FORMAT, index, length())); +} + +void G1BiasedMappedArrayBase::verify_biased_index(idx_t biased_index) const { + guarantee(_biased_base != NULL, "Array not initialized"); + guarantee(biased_index >= bias() && biased_index < (bias() + length()), + err_msg("Biased index out of bounds, index: "SIZE_FORMAT" bias: "SIZE_FORMAT" length: "SIZE_FORMAT, biased_index, bias(), length())); +} + +void G1BiasedMappedArrayBase::verify_biased_index_inclusive_end(idx_t biased_index) const { + guarantee(_biased_base != NULL, "Array not initialized"); + guarantee(biased_index >= bias() && biased_index <= (bias() + length()), + err_msg("Biased index out of inclusive bounds, index: "SIZE_FORMAT" bias: "SIZE_FORMAT" length: "SIZE_FORMAT, biased_index, bias(), length())); +} + +class TestMappedArray : public G1BiasedMappedArray { +protected: + virtual int default_value() const { return 0xBAADBABE; } +public: + static void test_biasedarray() { + const size_t REGION_SIZE_IN_WORDS = 512; + const size_t NUM_REGIONS = 20; + HeapWord* fake_heap = (HeapWord*)LP64_ONLY(0xBAAA00000) NOT_LP64(0xBA000000); // Any value that is non-zero + + TestMappedArray array; + array.initialize(fake_heap, fake_heap + REGION_SIZE_IN_WORDS * NUM_REGIONS, + REGION_SIZE_IN_WORDS * HeapWordSize); + // Check address calculation (bounds) + assert(array.bottom_address_mapped() == fake_heap, + err_msg("bottom mapped address should be "PTR_FORMAT", but is "PTR_FORMAT, fake_heap, array.bottom_address_mapped())); + assert(array.end_address_mapped() == (fake_heap + REGION_SIZE_IN_WORDS * NUM_REGIONS), "must be"); + + int* bottom = array.address_mapped_to(fake_heap); + assert((void*)bottom == (void*) array.base(), "must be"); + int* end = array.address_mapped_to(fake_heap + REGION_SIZE_IN_WORDS * NUM_REGIONS); + assert((void*)end == (void*)(array.base() + array.length()), "must be"); + // The entire array should contain default value elements + for (int* current = bottom; current < end; current++) { + assert(*current == array.default_value(), "must be"); + } + + // Test setting values in the table + + HeapWord* region_start_address = fake_heap + REGION_SIZE_IN_WORDS * (NUM_REGIONS / 2); + HeapWord* region_end_address = fake_heap + (REGION_SIZE_IN_WORDS * (NUM_REGIONS / 2) + REGION_SIZE_IN_WORDS - 1); + + // Set/get by address tests: invert some value; first retrieve one + int actual_value = array.get_by_index(NUM_REGIONS / 2); + array.set_by_index(NUM_REGIONS / 2, ~actual_value); + // Get the same value by address, should correspond to the start of the "region" + int value = array.get_by_address(region_start_address); + assert(value == ~actual_value, "must be"); + // Get the same value by address, at one HeapWord before the start + value = array.get_by_address(region_start_address - 1); + assert(value == array.default_value(), "must be"); + // Get the same value by address, at the end of the "region" + value = array.get_by_address(region_end_address); + assert(value == ~actual_value, "must be"); + // Make sure the next value maps to another index + value = array.get_by_address(region_end_address + 1); + assert(value == array.default_value(), "must be"); + + // Reset the value in the array + array.set_by_address(region_start_address + (region_end_address - region_start_address) / 2, actual_value); + + // The entire array should have the default value again + for (int* current = bottom; current < end; current++) { + assert(*current == array.default_value(), "must be"); + } + + // Set/get by index tests: invert some value + idx_t index = NUM_REGIONS / 2; + actual_value = array.get_by_index(index); + array.set_by_index(index, ~actual_value); + + value = array.get_by_index(index); + assert(value == ~actual_value, "must be"); + + value = array.get_by_index(index - 1); + assert(value == array.default_value(), "must be"); + + value = array.get_by_index(index + 1); + assert(value == array.default_value(), "must be"); + + array.set_by_index(0, 0); + value = array.get_by_index(0); + assert(value == 0, "must be"); + + array.set_by_index(array.length() - 1, 0); + value = array.get_by_index(array.length() - 1); + assert(value == 0, "must be"); + + array.set_by_index(index, 0); + + // The array should have three zeros, and default values otherwise + size_t num_zeros = 0; + for (int* current = bottom; current < end; current++) { + assert(*current == array.default_value() || *current == 0, "must be"); + if (*current == 0) { + num_zeros++; + } + } + assert(num_zeros == 3, "must be"); + } +}; + +void TestG1BiasedArray_test() { + TestMappedArray::test_biasedarray(); +} + +#endif diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.hpp new file mode 100644 index 00000000000..f80c70b4e36 --- /dev/null +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BiasedArray.hpp @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ + +#ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP +#define SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP + +#include "utilities/debug.hpp" +#include "memory/allocation.inline.hpp" + +// Implements the common base functionality for arrays that contain provisions +// for accessing its elements using a biased index. +// The element type is defined by the instantiating the template. +class G1BiasedMappedArrayBase VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; +public: + typedef size_t idx_t; +protected: + address _base; // the real base address + size_t _length; // the length of the array + address _biased_base; // base address biased by "bias" elements + size_t _bias; // the bias, i.e. the offset biased_base is located to the right in elements + uint _shift_by; // the amount of bits to shift right when mapping to an index of the array. + +protected: + + G1BiasedMappedArrayBase() : _base(NULL), _length(0), _biased_base(NULL), + _bias(0), _shift_by(0) { } + + // Allocate a new array, generic version. + static address create_new_base_array(size_t length, size_t elem_size) { + assert(length > 0, "just checking"); + assert(elem_size > 0, "just checking"); + return NEW_C_HEAP_ARRAY(u_char, length * elem_size, mtGC); + } + + // Initialize the members of this class. The biased start address of this array + // is the bias (in elements) multiplied by the element size. + void initialize_base(address base, size_t length, size_t bias, size_t elem_size, uint shift_by) { + assert(base != NULL, "just checking"); + assert(length > 0, "just checking"); + assert(shift_by < sizeof(uintptr_t) * 8, err_msg("Shifting by %zd, larger than word size?", shift_by)); + _base = base; + _length = length; + _biased_base = base - (bias * elem_size); + _bias = bias; + _shift_by = shift_by; + } + + // Allocate and initialize this array to cover the heap addresses in the range + // of [bottom, end). + void initialize(HeapWord* bottom, HeapWord* end, size_t target_elem_size_in_bytes, size_t mapping_granularity_in_bytes) { + assert(mapping_granularity_in_bytes > 0, "just checking"); + assert(is_power_of_2(mapping_granularity_in_bytes), + err_msg("mapping granularity must be power of 2, is %zd", mapping_granularity_in_bytes)); + assert((uintptr_t)bottom % mapping_granularity_in_bytes == 0, + err_msg("bottom mapping area address must be a multiple of mapping granularity %zd, is "PTR_FORMAT, + mapping_granularity_in_bytes, bottom)); + assert((uintptr_t)end % mapping_granularity_in_bytes == 0, + err_msg("end mapping area address must be a multiple of mapping granularity %zd, is "PTR_FORMAT, + mapping_granularity_in_bytes, end)); + size_t num_target_elems = (end - bottom) / (mapping_granularity_in_bytes / HeapWordSize); + idx_t bias = (uintptr_t)bottom / mapping_granularity_in_bytes; + address base = create_new_base_array(num_target_elems, target_elem_size_in_bytes); + initialize_base(base, num_target_elems, bias, target_elem_size_in_bytes, log2_intptr(mapping_granularity_in_bytes)); + } + + size_t bias() const { return _bias; } + uint shift_by() const { return _shift_by; } + + void verify_index(idx_t index) const PRODUCT_RETURN; + void verify_biased_index(idx_t biased_index) const PRODUCT_RETURN; + void verify_biased_index_inclusive_end(idx_t biased_index) const PRODUCT_RETURN; + +public: + // Return the length of the array in elements. + size_t length() const { return _length; } +}; + +// Array that provides biased access and mapping from (valid) addresses in the +// heap into this array. +template +class G1BiasedMappedArray : public G1BiasedMappedArrayBase { +public: + typedef G1BiasedMappedArrayBase::idx_t idx_t; + + T* base() const { return (T*)G1BiasedMappedArrayBase::_base; } + // Return the element of the given array at the given index. Assume + // the index is valid. This is a convenience method that does sanity + // checking on the index. + T get_by_index(idx_t index) const { + verify_index(index); + return this->base()[index]; + } + + // Set the element of the given array at the given index to the + // given value. Assume the index is valid. This is a convenience + // method that does sanity checking on the index. + void set_by_index(idx_t index, T value) { + verify_index(index); + this->base()[index] = value; + } + + // The raw biased base pointer. + T* biased_base() const { return (T*)G1BiasedMappedArrayBase::_biased_base; } + + // Return the element of the given array that covers the given word in the + // heap. Assumes the index is valid. + T get_by_address(HeapWord* value) const { + idx_t biased_index = ((uintptr_t)value) >> this->shift_by(); + this->verify_biased_index(biased_index); + return biased_base()[biased_index]; + } + + // Set the value of the array entry that corresponds to the given array. + void set_by_address(HeapWord * address, T value) { + idx_t biased_index = ((uintptr_t)address) >> this->shift_by(); + this->verify_biased_index(biased_index); + biased_base()[biased_index] = value; + } + +protected: + // Returns the address of the element the given address maps to + T* address_mapped_to(HeapWord* address) { + idx_t biased_index = ((uintptr_t)address) >> this->shift_by(); + this->verify_biased_index_inclusive_end(biased_index); + return biased_base() + biased_index; + } + +public: + // Return the smallest address (inclusive) in the heap that this array covers. + HeapWord* bottom_address_mapped() const { + return (HeapWord*) ((uintptr_t)this->bias() << this->shift_by()); + } + + // Return the highest address (exclusive) in the heap that this array covers. + HeapWord* end_address_mapped() const { + return (HeapWord*) ((uintptr_t)(this->bias() + this->length()) << this->shift_by()); + } + +protected: + virtual T default_value() const = 0; + // Set all elements of the given array to the given value. + void clear() { + T value = default_value(); + for (idx_t i = 0; i < length(); i++) { + set_by_index(i, value); + } + } +public: + G1BiasedMappedArray() {} + + // Allocate and initialize this array to cover the heap addresses in the range + // of [bottom, end). + void initialize(HeapWord* bottom, HeapWord* end, size_t mapping_granularity) { + G1BiasedMappedArrayBase::initialize(bottom, end, sizeof(T), mapping_granularity); + this->clear(); + } +}; + +#endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1BIASEDARRAY_HPP diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp index f75e518facc..31972bf3c4e 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.cpp @@ -33,8 +33,8 @@ void G1CardCounts::clear_range(size_t from_card_num, size_t to_card_num) { if (has_count_table()) { - check_card_num(from_card_num, - err_msg("from card num out of range: "SIZE_FORMAT, from_card_num)); + assert(from_card_num >= 0 && from_card_num < _committed_max_card_num, + err_msg("from card num out of range: "SIZE_FORMAT, from_card_num)); assert(from_card_num < to_card_num, err_msg("Wrong order? from: " SIZE_FORMAT ", to: "SIZE_FORMAT, from_card_num, to_card_num)); diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp index fd516c0b90e..129b3b0d232 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CardCounts.hpp @@ -72,25 +72,21 @@ class G1CardCounts: public CHeapObj { return has_reserved_count_table() && _committed_max_card_num > 0; } - void check_card_num(size_t card_num, const char* msg) { - assert(card_num >= 0 && card_num < _committed_max_card_num, msg); - } - size_t ptr_2_card_num(const jbyte* card_ptr) { assert(card_ptr >= _ct_bot, - err_msg("Inavalied card pointer: " + err_msg("Invalid card pointer: " "card_ptr: " PTR_FORMAT ", " "_ct_bot: " PTR_FORMAT, card_ptr, _ct_bot)); size_t card_num = pointer_delta(card_ptr, _ct_bot, sizeof(jbyte)); - check_card_num(card_num, - err_msg("card pointer out of range: " PTR_FORMAT, card_ptr)); + assert(card_num >= 0 && card_num < _committed_max_card_num, + err_msg("card pointer out of range: " PTR_FORMAT, card_ptr)); return card_num; } jbyte* card_num_2_ptr(size_t card_num) { - check_card_num(card_num, - err_msg("card num out of range: "SIZE_FORMAT, card_num)); + assert(card_num >= 0 && card_num < _committed_max_card_num, + err_msg("card num out of range: "SIZE_FORMAT, card_num)); return (jbyte*) (_ct_bot + card_num); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index bd01ec3b602..0ecfd3ab3bb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2069,8 +2069,10 @@ jint G1CollectedHeap::initialize() { _g1_storage.initialize(g1_rs, 0); _g1_committed = MemRegion((HeapWord*)_g1_storage.low(), (size_t) 0); _hrs.initialize((HeapWord*) _g1_reserved.start(), - (HeapWord*) _g1_reserved.end(), - _expansion_regions); + (HeapWord*) _g1_reserved.end()); + assert(_hrs.max_length() == _expansion_regions, + err_msg("max length: %u expansion regions: %u", + _hrs.max_length(), _expansion_regions)); // Do later initialization work for concurrent refinement. _cg1r->init(); @@ -2191,6 +2193,10 @@ jint G1CollectedHeap::initialize() { return JNI_OK; } +size_t G1CollectedHeap::conservative_max_heap_alignment() { + return HeapRegion::max_region_size(); +} + void G1CollectedHeap::ref_processing_init() { // Reference processing in G1 currently works as follows: // diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp index aecaa5e97ac..747b2326236 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.hpp @@ -1092,6 +1092,9 @@ public: // specified by the policy object. jint initialize(); + // Return the (conservative) maximum heap alignment for any G1 heap + static size_t conservative_max_heap_alignment(); + // Initialize weak reference processing. virtual void ref_processing_init(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index e66268885e3..726acbfcdc0 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -149,6 +149,10 @@ void HeapRegionDCTOC::walk_mem_region_with_cl(MemRegion mr, // many regions in the heap (based on the min heap size). #define TARGET_REGION_NUMBER 2048 +size_t HeapRegion::max_region_size() { + return (size_t)MAX_REGION_SIZE; +} + void HeapRegion::setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size) { uintx region_size = G1HeapRegionSize; if (FLAG_IS_DEFAULT(G1HeapRegionSize)) { diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 097c0b54380..ad2b0649795 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -355,6 +355,8 @@ class HeapRegion: public G1OffsetTableContigSpace { ~((1 << (size_t) LogOfHRGrainBytes) - 1); } + static size_t max_region_size(); + // It sets up the heap region size (GrainBytes / GrainWords), as // well as other related fields that are based on the heap region // size (LogOfHRGrainBytes / LogOfHRGrainWords / diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp index dade3dfdfcf..eaa8e10f38d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.cpp @@ -71,27 +71,16 @@ uint HeapRegionSeq::find_contiguous_from(uint from, uint num) { // Public -void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end, - uint max_length) { +void HeapRegionSeq::initialize(HeapWord* bottom, HeapWord* end) { assert((uintptr_t) bottom % HeapRegion::GrainBytes == 0, "bottom should be heap region aligned"); assert((uintptr_t) end % HeapRegion::GrainBytes == 0, "end should be heap region aligned"); - _length = 0; - _heap_bottom = bottom; - _heap_end = end; - _region_shift = HeapRegion::LogOfHRGrainBytes; _next_search_index = 0; _allocated_length = 0; - _max_length = max_length; - _regions = NEW_C_HEAP_ARRAY(HeapRegion*, max_length, mtGC); - memset(_regions, 0, (size_t) max_length * sizeof(HeapRegion*)); - _regions_biased = _regions - ((uintx) bottom >> _region_shift); - - assert(&_regions[0] == &_regions_biased[addr_to_index_biased(bottom)], - "bottom should be included in the region with index 0"); + _regions.initialize(bottom, end, HeapRegion::GrainBytes); } MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, @@ -101,15 +90,15 @@ MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, G1CollectedHeap* g1h = G1CollectedHeap::heap(); HeapWord* next_bottom = old_end; - assert(_heap_bottom <= next_bottom, "invariant"); + assert(heap_bottom() <= next_bottom, "invariant"); while (next_bottom < new_end) { - assert(next_bottom < _heap_end, "invariant"); + assert(next_bottom < heap_end(), "invariant"); uint index = length(); - assert(index < _max_length, "otherwise we cannot expand further"); + assert(index < max_length(), "otherwise we cannot expand further"); if (index == 0) { // We have not allocated any regions so far - assert(next_bottom == _heap_bottom, "invariant"); + assert(next_bottom == heap_bottom(), "invariant"); } else { // next_bottom should match the end of the last/previous region assert(next_bottom == at(index - 1)->end(), "invariant"); @@ -122,8 +111,8 @@ MemRegion HeapRegionSeq::expand_by(HeapWord* old_end, // allocation failed, we bail out and return what we have done so far return MemRegion(old_end, next_bottom); } - assert(_regions[index] == NULL, "invariant"); - _regions[index] = new_hr; + assert(_regions.get_by_index(index) == NULL, "invariant"); + _regions.set_by_index(index, new_hr); increment_allocated_length(); } // Have to increment the length first, otherwise we will get an @@ -228,26 +217,26 @@ uint HeapRegionSeq::shrink_by(uint num_regions_to_remove) { #ifndef PRODUCT void HeapRegionSeq::verify_optional() { - guarantee(_length <= _allocated_length, + guarantee(length() <= _allocated_length, err_msg("invariant: _length: %u _allocated_length: %u", - _length, _allocated_length)); - guarantee(_allocated_length <= _max_length, + length(), _allocated_length)); + guarantee(_allocated_length <= max_length(), err_msg("invariant: _allocated_length: %u _max_length: %u", - _allocated_length, _max_length)); - guarantee(_next_search_index <= _length, + _allocated_length, max_length())); + guarantee(_next_search_index <= length(), err_msg("invariant: _next_search_index: %u _length: %u", - _next_search_index, _length)); + _next_search_index, length())); - HeapWord* prev_end = _heap_bottom; + HeapWord* prev_end = heap_bottom(); for (uint i = 0; i < _allocated_length; i += 1) { - HeapRegion* hr = _regions[i]; + HeapRegion* hr = _regions.get_by_index(i); guarantee(hr != NULL, err_msg("invariant: i: %u", i)); guarantee(hr->bottom() == prev_end, err_msg("invariant i: %u "HR_FORMAT" prev_end: "PTR_FORMAT, i, HR_FORMAT_PARAMS(hr), prev_end)); guarantee(hr->hrs_index() == i, err_msg("invariant: i: %u hrs_index(): %u", i, hr->hrs_index())); - if (i < _length) { + if (i < length()) { // Asserts will fire if i is >= _length HeapWord* addr = hr->bottom(); guarantee(addr_to_region(addr) == hr, "sanity"); @@ -265,8 +254,8 @@ void HeapRegionSeq::verify_optional() { prev_end = hr->end(); } } - for (uint i = _allocated_length; i < _max_length; i += 1) { - guarantee(_regions[i] == NULL, err_msg("invariant i: %u", i)); + for (uint i = _allocated_length; i < max_length(); i += 1) { + guarantee(_regions.get_by_index(i) == NULL, err_msg("invariant i: %u", i)); } } #endif // PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp index b7a58f76a7f..b0c3eb48a0b 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.hpp @@ -25,10 +25,17 @@ #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP #define SHARE_VM_GC_IMPLEMENTATION_G1_HEAPREGIONSEQ_HPP +#include "gc_implementation/g1/g1BiasedArray.hpp" + class HeapRegion; class HeapRegionClosure; class FreeRegionList; +class G1HeapRegionTable : public G1BiasedMappedArray { + protected: + virtual HeapRegion* default_value() const { return NULL; } +}; + // This class keeps track of the region metadata (i.e., HeapRegion // instances). They are kept in the _regions array in address // order. A region's index in the array corresponds to its index in @@ -44,35 +51,21 @@ class FreeRegionList; // // We keep track of three lengths: // -// * _length (returned by length()) is the number of currently +// * _committed_length (returned by length()) is the number of currently // committed regions. // * _allocated_length (not exposed outside this class) is the // number of regions for which we have HeapRegions. -// * _max_length (returned by max_length()) is the maximum number of -// regions the heap can have. +// * max_length() returns the maximum number of regions the heap can have. // -// and maintain that: _length <= _allocated_length <= _max_length +// and maintain that: _committed_length <= _allocated_length <= max_length() class HeapRegionSeq: public CHeapObj { friend class VMStructs; - // The array that holds the HeapRegions. - HeapRegion** _regions; - - // Version of _regions biased to address 0 - HeapRegion** _regions_biased; + G1HeapRegionTable _regions; // The number of regions committed in the heap. - uint _length; - - // The address of the first reserved word in the heap. - HeapWord* _heap_bottom; - - // The address of the last reserved word in the heap - 1. - HeapWord* _heap_end; - - // The log of the region byte size. - uint _region_shift; + uint _committed_length; // A hint for which index to start searching from for humongous // allocations. @@ -81,37 +74,33 @@ class HeapRegionSeq: public CHeapObj { // The number of regions for which we have allocated HeapRegions for. uint _allocated_length; - // The maximum number of regions in the heap. - uint _max_length; - // Find a contiguous set of empty regions of length num, starting // from the given index. uint find_contiguous_from(uint from, uint num); - // Map a heap address to a biased region index. Assume that the - // address is valid. - inline uintx addr_to_index_biased(HeapWord* addr) const; - void increment_allocated_length() { - assert(_allocated_length < _max_length, "pre-condition"); + assert(_allocated_length < max_length(), "pre-condition"); _allocated_length++; } void increment_length() { - assert(_length < _max_length, "pre-condition"); - _length++; + assert(length() < max_length(), "pre-condition"); + _committed_length++; } void decrement_length() { - assert(_length > 0, "pre-condition"); - _length--; + assert(length() > 0, "pre-condition"); + _committed_length--; } + HeapWord* heap_bottom() const { return _regions.bottom_address_mapped(); } + HeapWord* heap_end() const {return _regions.end_address_mapped(); } + public: // Empty contructor, we'll initialize it with the initialize() method. - HeapRegionSeq() { } + HeapRegionSeq() : _regions(), _committed_length(0), _next_search_index(0), _allocated_length(0) { } - void initialize(HeapWord* bottom, HeapWord* end, uint max_length); + void initialize(HeapWord* bottom, HeapWord* end); // Return the HeapRegion at the given index. Assume that the index // is valid. @@ -126,10 +115,10 @@ class HeapRegionSeq: public CHeapObj { inline HeapRegion* addr_to_region_unsafe(HeapWord* addr) const; // Return the number of regions that have been committed in the heap. - uint length() const { return _length; } + uint length() const { return _committed_length; } // Return the maximum number of regions in the heap. - uint max_length() const { return _max_length; } + uint max_length() const { return (uint)_regions.length(); } // Expand the sequence to reflect that the heap has grown from // old_end to new_end. Either create new HeapRegions, or re-use diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp index e840287edc7..96588dea042 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegionSeq.inline.hpp @@ -28,28 +28,16 @@ #include "gc_implementation/g1/heapRegion.hpp" #include "gc_implementation/g1/heapRegionSeq.hpp" -inline uintx HeapRegionSeq::addr_to_index_biased(HeapWord* addr) const { - assert(_heap_bottom <= addr && addr < _heap_end, - err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT, - addr, _heap_bottom, _heap_end)); - uintx index = (uintx) addr >> _region_shift; - return index; -} - inline HeapRegion* HeapRegionSeq::addr_to_region_unsafe(HeapWord* addr) const { - assert(_heap_bottom <= addr && addr < _heap_end, - err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT" end: "PTR_FORMAT, - addr, _heap_bottom, _heap_end)); - uintx index_biased = addr_to_index_biased(addr); - HeapRegion* hr = _regions_biased[index_biased]; + HeapRegion* hr = _regions.get_by_address(addr); assert(hr != NULL, "invariant"); return hr; } inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { - if (addr != NULL && addr < _heap_end) { - assert(addr >= _heap_bottom, - err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, _heap_bottom)); + if (addr != NULL && addr < heap_end()) { + assert(addr >= heap_bottom(), + err_msg("addr: "PTR_FORMAT" bottom: "PTR_FORMAT, addr, heap_bottom())); return addr_to_region_unsafe(addr); } return NULL; @@ -57,7 +45,7 @@ inline HeapRegion* HeapRegionSeq::addr_to_region(HeapWord* addr) const { inline HeapRegion* HeapRegionSeq::at(uint index) const { assert(index < length(), "pre-condition"); - HeapRegion* hr = _regions[index]; + HeapRegion* hr = _regions.get_by_index(index); assert(hr != NULL, "sanity"); assert(hr->hrs_index() == index, "sanity"); return hr; diff --git a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp index 1f6d9b21388..958317166ea 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/ptrQueue.hpp @@ -38,6 +38,7 @@ class PtrQueueSet; class PtrQueue VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; protected: // The ptr queue set to which this queue belongs. diff --git a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp index 5507dee5f80..9268eb78ef4 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/vmStructs_g1.hpp @@ -31,10 +31,17 @@ #define VM_STRUCTS_G1(nonstatic_field, static_field) \ \ - static_field(HeapRegion, GrainBytes, size_t) \ + static_field(HeapRegion, GrainBytes, size_t) \ + static_field(HeapRegion, LogOfHRGrainBytes, int) \ \ - nonstatic_field(HeapRegionSeq, _regions, HeapRegion**) \ - nonstatic_field(HeapRegionSeq, _length, uint) \ + nonstatic_field(G1HeapRegionTable, _base, address) \ + nonstatic_field(G1HeapRegionTable, _length, size_t) \ + nonstatic_field(G1HeapRegionTable, _biased_base, address) \ + nonstatic_field(G1HeapRegionTable, _bias, size_t) \ + nonstatic_field(G1HeapRegionTable, _shift_by, uint) \ + \ + nonstatic_field(HeapRegionSeq, _regions, G1HeapRegionTable) \ + nonstatic_field(HeapRegionSeq, _committed_length, uint) \ \ nonstatic_field(G1CollectedHeap, _hrs, HeapRegionSeq) \ nonstatic_field(G1CollectedHeap, _g1_committed, MemRegion) \ @@ -57,6 +64,8 @@ #define VM_TYPES_G1(declare_type, declare_toplevel_type) \ \ + declare_toplevel_type(G1HeapRegionTable) \ + \ declare_type(G1CollectedHeap, SharedHeap) \ \ declare_type(HeapRegion, ContiguousSpace) \ diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp index b4b8c1ae9bb..e5637687e84 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/generationSizer.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,9 +68,6 @@ class GenerationSizer : public TwoGenerationCollectorPolicy { size_t min_old_gen_size() { return _min_gen1_size; } size_t old_gen_size() { return _initial_gen1_size; } size_t max_old_gen_size() { return _max_gen1_size; } - - size_t metaspace_size() { return MetaspaceSize; } - size_t max_metaspace_size() { return MaxMetaspaceSize; } }; #endif // SHARE_VM_GC_IMPLEMENTATION_PARALLELSCAVENGE_GENERATIONSIZER_HPP diff --git a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp index 11ef5325120..4e458efa903 100644 --- a/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp +++ b/hotspot/src/share/vm/gc_implementation/parallelScavenge/parallelScavengeHeap.hpp @@ -86,6 +86,11 @@ class ParallelScavengeHeap : public CollectedHeap { set_alignment(_old_gen_alignment, intra_heap_alignment()); } + // Return the (conservative) maximum heap alignment + static size_t conservative_max_heap_alignment() { + return intra_heap_alignment(); + } + // For use by VM operations enum CollectionType { Scavenge, @@ -122,7 +127,7 @@ class ParallelScavengeHeap : public CollectedHeap { // The alignment used for eden and survivors within the young gen // and for boundary between young gen and old gen. - size_t intra_heap_alignment() const { return 64 * K * HeapWordSize; } + static size_t intra_heap_alignment() { return 64 * K * HeapWordSize; } size_t capacity() const; size_t used() const; diff --git a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp index cf7cd3ae0f2..0fb6d7fa23e 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/allocationStats.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,9 @@ #define SHARE_VM_GC_IMPLEMENTATION_SHARED_ALLOCATIONSTATS_HPP #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS -#include "gc_implementation/shared/gcUtil.hpp" #include "memory/allocation.hpp" #include "utilities/globalDefinitions.hpp" -#endif // INCLUDE_ALL_GCS +#include "gc_implementation/shared/gcUtil.hpp" class AllocationStats VALUE_OBJ_CLASS_SPEC { // A duration threshold (in ms) used to filter diff --git a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp index 034d319b078..0b855e7f674 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/hSpaceCounters.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,11 +26,9 @@ #define SHARE_VM_GC_IMPLEMENTATION_SHARED_HSPACECOUNTERS_HPP #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS #include "gc_implementation/shared/generationCounters.hpp" #include "memory/generation.hpp" #include "runtime/perfData.hpp" -#endif // INCLUDE_ALL_GCS // A HSpaceCounter is a holder class for performance counters // that track a collections (logical spaces) in a heap; diff --git a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp index 3af380049bb..3f5364b79c0 100644 --- a/hotspot/src/share/vm/gc_interface/collectedHeap.cpp +++ b/hotspot/src/share/vm/gc_interface/collectedHeap.cpp @@ -87,15 +87,15 @@ MetaspaceSummary CollectedHeap::create_metaspace_summary() { const MetaspaceSizes meta_space( MetaspaceAux::allocated_capacity_bytes(), MetaspaceAux::allocated_used_bytes(), - MetaspaceAux::reserved_in_bytes()); + MetaspaceAux::reserved_bytes()); const MetaspaceSizes data_space( MetaspaceAux::allocated_capacity_bytes(Metaspace::NonClassType), MetaspaceAux::allocated_used_bytes(Metaspace::NonClassType), - MetaspaceAux::reserved_in_bytes(Metaspace::NonClassType)); + MetaspaceAux::reserved_bytes(Metaspace::NonClassType)); const MetaspaceSizes class_space( MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType), MetaspaceAux::allocated_used_bytes(Metaspace::ClassType), - MetaspaceAux::reserved_in_bytes(Metaspace::ClassType)); + MetaspaceAux::reserved_bytes(Metaspace::ClassType)); return MetaspaceSummary(meta_space, data_space, class_space); } diff --git a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp index 4a3019f867f..4c082597b22 100644 --- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp +++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp @@ -496,15 +496,15 @@ IRT_END IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecodes::Code bytecode)) // resolve field - FieldAccessInfo info; + fieldDescriptor info; constantPoolHandle pool(thread, method(thread)->constants()); bool is_put = (bytecode == Bytecodes::_putfield || bytecode == Bytecodes::_putstatic); bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic); { JvmtiHideSingleStepping jhss(thread); - LinkResolver::resolve_field(info, pool, get_index_u2_cpcache(thread, bytecode), - bytecode, false, CHECK); + LinkResolver::resolve_field_access(info, pool, get_index_u2_cpcache(thread, bytecode), + bytecode, CHECK); } // end JvmtiHideSingleStepping // check if link resolution caused cpCache to be updated @@ -524,7 +524,7 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode // class is intitialized. This is required so that access to the static // field will call the initialization function every time until the class // is completely initialized ala. in 2.17.5 in JVM Specification. - InstanceKlass *klass = InstanceKlass::cast(info.klass()()); + InstanceKlass* klass = InstanceKlass::cast(info.field_holder()); bool uninitialized_static = ((bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic) && !klass->is_initialized()); Bytecodes::Code get_code = (Bytecodes::Code)0; @@ -539,9 +539,9 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_get_put(JavaThread* thread, Bytecode cache_entry(thread)->set_field( get_code, put_code, - info.klass(), - info.field_index(), - info.field_offset(), + info.field_holder(), + info.index(), + info.offset(), state, info.access_flags().is_final(), info.access_flags().is_volatile(), @@ -686,29 +686,55 @@ IRT_ENTRY(void, InterpreterRuntime::resolve_invoke(JavaThread* thread, Bytecodes if (already_resolved(thread)) return; if (bytecode == Bytecodes::_invokeinterface) { - if (TraceItables && Verbose) { ResourceMark rm(thread); tty->print_cr("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() == SystemDictionary::Object_klass()) { // NOTE: THIS IS A FIX FOR A CORNER CASE in the JVM spec - // (see also cpCacheOop.cpp for details) + // (see also CallInfo::set_interface for details) + assert(info.call_kind() == CallInfo::vtable_call || + info.call_kind() == CallInfo::direct_call, ""); methodHandle rm = info.resolved_method(); assert(rm->is_final() || info.has_vtable_index(), "should have been set already"); - cache_entry(thread)->set_method(bytecode, rm, info.vtable_index()); + } else if (!info.resolved_method()->has_itable_index()) { + // Resolved something like CharSequence.toString. Use vtable not itable. + assert(info.call_kind() != CallInfo::itable_call, ""); } else { // Setup itable entry - int index = klassItable::compute_itable_index(info.resolved_method()()); - cache_entry(thread)->set_interface_call(info.resolved_method(), index); + assert(info.call_kind() == CallInfo::itable_call, ""); + int index = info.resolved_method()->itable_index(); + assert(info.itable_index() == index, ""); } } else { - cache_entry(thread)->set_method( + assert(info.call_kind() == CallInfo::direct_call || + info.call_kind() == CallInfo::vtable_call, ""); + } +#endif + switch (info.call_kind()) { + case CallInfo::direct_call: + cache_entry(thread)->set_direct_call( + bytecode, + info.resolved_method()); + break; + case CallInfo::vtable_call: + cache_entry(thread)->set_vtable_call( bytecode, info.resolved_method(), info.vtable_index()); + break; + case CallInfo::itable_call: + cache_entry(thread)->set_itable_call( + bytecode, + info.resolved_method(), + info.itable_index()); + break; + default: ShouldNotReachHere(); } } IRT_END diff --git a/hotspot/src/share/vm/interpreter/linkResolver.cpp b/hotspot/src/share/vm/interpreter/linkResolver.cpp index b0bd678b597..44ac9e0862d 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.cpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp @@ -46,19 +46,6 @@ #include "runtime/thread.inline.hpp" #include "runtime/vmThread.hpp" -//------------------------------------------------------------------------------------------------------------------------ -// Implementation of FieldAccessInfo - -void FieldAccessInfo::set(KlassHandle klass, Symbol* name, int field_index, int field_offset, -BasicType field_type, AccessFlags access_flags) { - _klass = klass; - _name = name; - _field_index = field_index; - _field_offset = field_offset; - _field_type = field_type; - _access_flags = access_flags; -} - //------------------------------------------------------------------------------------------------------------------------ // Implementation of CallInfo @@ -66,26 +53,25 @@ BasicType field_type, AccessFlags access_flags) { void CallInfo::set_static(KlassHandle resolved_klass, methodHandle resolved_method, TRAPS) { int vtable_index = Method::nonvirtual_vtable_index; - set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK); + set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); } -void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, TRAPS) { +void CallInfo::set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index, TRAPS) { // This is only called for interface methods. If the resolved_method // comes from java/lang/Object, it can be the subject of a virtual call, so // we should pick the vtable index from the resolved method. - // Other than that case, there is no valid vtable index to specify. - int vtable_index = Method::invalid_vtable_index; - if (resolved_method->method_holder() == SystemDictionary::Object_klass()) { - assert(resolved_method->vtable_index() == selected_method->vtable_index(), "sanity check"); - vtable_index = resolved_method->vtable_index(); - } - set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); + // In that case, the caller must call set_virtual instead of set_interface. + assert(resolved_method->method_holder()->is_interface(), ""); + assert(itable_index == resolved_method()->itable_index(), ""); + set_common(resolved_klass, selected_klass, resolved_method, selected_method, CallInfo::itable_call, itable_index, CHECK); } void CallInfo::set_virtual(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, "valid index"); - set_common(resolved_klass, selected_klass, resolved_method, selected_method, vtable_index, CHECK); + assert(vtable_index < 0 || !resolved_method->has_vtable_index() || vtable_index == resolved_method->vtable_index(), ""); + CallKind kind = (vtable_index >= 0 && !resolved_method->can_be_statically_bound() ? CallInfo::vtable_call : CallInfo::direct_call); + set_common(resolved_klass, selected_klass, resolved_method, selected_method, kind, vtable_index, CHECK); assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call"); } @@ -98,20 +84,29 @@ void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix resolved_method->is_compiled_lambda_form(), "linkMethod must return one of these"); int vtable_index = Method::nonvirtual_vtable_index; - assert(resolved_method->vtable_index() == vtable_index, ""); - set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK); + assert(!resolved_method->has_vtable_index(), ""); + set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, CallInfo::direct_call, vtable_index, CHECK); _resolved_appendix = resolved_appendix; _resolved_method_type = resolved_method_type; } -void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) { +void CallInfo::set_common(KlassHandle resolved_klass, + KlassHandle selected_klass, + methodHandle resolved_method, + methodHandle selected_method, + CallKind kind, + int index, + TRAPS) { assert(resolved_method->signature() == selected_method->signature(), "signatures must correspond"); _resolved_klass = resolved_klass; _selected_klass = selected_klass; _resolved_method = resolved_method; _selected_method = selected_method; - _vtable_index = vtable_index; + _call_kind = kind; + _call_index = index; _resolved_appendix = Handle(); + DEBUG_ONLY(verify()); // verify before making side effects + if (CompilationPolicy::must_be_compiled(selected_method)) { // This path is unusual, mostly used by the '-Xcomp' stress test mode. @@ -138,6 +133,65 @@ void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass } } +// utility query for unreflecting a method +CallInfo::CallInfo(Method* resolved_method, Klass* resolved_klass) { + Klass* resolved_method_holder = resolved_method->method_holder(); + if (resolved_klass == NULL) { // 2nd argument defaults to holder of 1st + resolved_klass = resolved_method_holder; + } + _resolved_klass = resolved_klass; + _selected_klass = resolved_klass; + _resolved_method = resolved_method; + _selected_method = resolved_method; + // classify: + CallKind kind = CallInfo::unknown_kind; + int index = resolved_method->vtable_index(); + if (resolved_method->can_be_statically_bound()) { + kind = CallInfo::direct_call; + } else if (!resolved_method_holder->is_interface()) { + // Could be an Object method inherited into an interface, but still a vtable call. + kind = CallInfo::vtable_call; + } else if (!resolved_klass->is_interface()) { + // A miranda method. Compute the vtable index. + ResourceMark rm; + klassVtable* vt = InstanceKlass::cast(resolved_klass)->vtable(); + index = vt->index_of_miranda(resolved_method->name(), + resolved_method->signature()); + kind = CallInfo::vtable_call; + } else { + // A regular interface call. + kind = CallInfo::itable_call; + index = resolved_method->itable_index(); + } + assert(index == Method::nonvirtual_vtable_index || index >= 0, err_msg("bad index %d", index)); + _call_kind = kind; + _call_index = index; + _resolved_appendix = Handle(); + DEBUG_ONLY(verify()); +} + +#ifdef ASSERT +void CallInfo::verify() { + switch (call_kind()) { // the meaning and allowed value of index depends on kind + case CallInfo::direct_call: + if (_call_index == Method::nonvirtual_vtable_index) break; + // else fall through to check vtable index: + case CallInfo::vtable_call: + assert(resolved_klass()->verify_vtable_index(_call_index), ""); + break; + case CallInfo::itable_call: + assert(resolved_method()->method_holder()->verify_itable_index(_call_index), ""); + break; + case CallInfo::unknown_kind: + assert(call_kind() != CallInfo::unknown_kind, "CallInfo must be set"); + break; + default: + fatal(err_msg_res("Unexpected call kind %d", call_kind())); + } +} +#endif //ASSERT + + //------------------------------------------------------------------------------------------------------------------------ // Klass resolution @@ -163,13 +217,6 @@ void LinkResolver::resolve_klass(KlassHandle& result, constantPoolHandle pool, i result = KlassHandle(THREAD, result_oop); } -void LinkResolver::resolve_klass_no_update(KlassHandle& result, constantPoolHandle pool, int index, TRAPS) { - Klass* result_oop = - ConstantPool::klass_ref_at_if_loaded_check(pool, index, CHECK); - result = KlassHandle(THREAD, result_oop); -} - - //------------------------------------------------------------------------------------------------------------------------ // Method resolution // @@ -360,7 +407,12 @@ void LinkResolver::check_method_accessability(KlassHandle ref_klass, void LinkResolver::resolve_method_statically(methodHandle& resolved_method, KlassHandle& resolved_klass, Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS) { - + // This method is used only + // (1) in C2 from InlineTree::ok_to_inline (via ciMethod::check_call), + // and + // (2) in Bytecode_invoke::static_target + // It appears to fail when applied to an invokeinterface call site. + // FIXME: Remove this method and ciMethod::check_call; refactor to use the other LinkResolver entry points. // resolve klass if (code == Bytecodes::_invokedynamic) { resolved_klass = SystemDictionary::MethodHandle_klass(); @@ -580,45 +632,49 @@ void LinkResolver::check_field_accessability(KlassHandle ref_klass, } } -void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, TRAPS) { - resolve_field(result, pool, index, byte, check_only, true, CHECK); +void LinkResolver::resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS) { + // Load these early in case the resolve of the containing klass fails + Symbol* field = pool->name_ref_at(index); + Symbol* sig = pool->signature_ref_at(index); + + // resolve specified klass + KlassHandle resolved_klass; + resolve_klass(resolved_klass, pool, index, CHECK); + + KlassHandle current_klass(THREAD, pool->pool_holder()); + resolve_field(result, resolved_klass, field, sig, current_klass, byte, true, true, CHECK); } -void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS) { +void LinkResolver::resolve_field(fieldDescriptor& fd, KlassHandle resolved_klass, Symbol* field, Symbol* sig, + KlassHandle current_klass, Bytecodes::Code byte, bool check_access, bool initialize_class, + TRAPS) { assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic || - byte == Bytecodes::_getfield || byte == Bytecodes::_putfield, "bad bytecode"); + byte == Bytecodes::_getfield || byte == Bytecodes::_putfield || + (byte == Bytecodes::_nop && !check_access), "bad field access bytecode"); bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic); bool is_put = (byte == Bytecodes::_putfield || byte == Bytecodes::_putstatic); - // resolve specified klass - KlassHandle resolved_klass; - if (update_pool) { - resolve_klass(resolved_klass, pool, index, CHECK); - } else { - resolve_klass_no_update(resolved_klass, pool, index, CHECK); - } - // Load these early in case the resolve of the containing klass fails - Symbol* field = pool->name_ref_at(index); - Symbol* sig = pool->signature_ref_at(index); // Check if there's a resolved klass containing the field - if( resolved_klass.is_null() ) { + if (resolved_klass.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); } // Resolve instance field - fieldDescriptor fd; // find_field initializes fd if found KlassHandle sel_klass(THREAD, InstanceKlass::cast(resolved_klass())->find_field(field, sig, &fd)); // check if field exists; i.e., if a klass containing the field def has been selected - if (sel_klass.is_null()){ + if (sel_klass.is_null()) { ResourceMark rm(THREAD); THROW_MSG(vmSymbols::java_lang_NoSuchFieldError(), field->as_C_string()); } + if (!check_access) + // Access checking may be turned off when calling from within the VM. + return; + // check access - KlassHandle ref_klass(THREAD, pool->pool_holder()); - check_field_accessability(ref_klass, resolved_klass, sel_klass, fd, CHECK); + check_field_accessability(current_klass, resolved_klass, sel_klass, fd, CHECK); // check for errors if (is_static != fd.is_static()) { @@ -629,7 +685,7 @@ void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle poo } // Final fields can only be accessed from its own class. - if (is_put && fd.access_flags().is_final() && sel_klass() != pool->pool_holder()) { + if (is_put && fd.access_flags().is_final() && sel_klass() != current_klass()) { THROW(vmSymbols::java_lang_IllegalAccessError()); } @@ -639,19 +695,18 @@ void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle poo // // note 2: we don't want to force initialization if we are just checking // if the field access is legal; e.g., during compilation - if (is_static && !check_only) { + if (is_static && initialize_class) { sel_klass->initialize(CHECK); } - { + if (sel_klass() != current_klass()) { HandleMark hm(THREAD); - Handle ref_loader (THREAD, InstanceKlass::cast(ref_klass())->class_loader()); + Handle ref_loader (THREAD, InstanceKlass::cast(current_klass())->class_loader()); Handle sel_loader (THREAD, InstanceKlass::cast(sel_klass())->class_loader()); - Symbol* signature_ref = pool->signature_ref_at(index); { ResourceMark rm(THREAD); Symbol* failed_type_symbol = - SystemDictionary::check_signature_loaders(signature_ref, + SystemDictionary::check_signature_loaders(sig, ref_loader, sel_loader, false, CHECK); @@ -677,9 +732,6 @@ void LinkResolver::resolve_field(FieldAccessInfo& result, constantPoolHandle poo // return information. note that the klass is set to the actual klass containing the // field, otherwise access of static fields in superclasses will not work. - KlassHandle holder (THREAD, fd.field_holder()); - Symbol* name = fd.name(); - result.set(holder, name, fd.index(), fd.offset(), fd.field_type(), fd.access_flags()); } @@ -906,10 +958,6 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, THROW(vmSymbols::java_lang_NullPointerException()); } - // Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s - // has not been rewritten, and the vtable initialized. - assert(resolved_method->method_holder()->is_linked(), "must be linked"); - // Virtual methods cannot be resolved before its klass has been linked, for otherwise the Method*'s // has not been rewritten, and the vtable initialized. Make sure to do this after the nullcheck, since // a missing receiver might result in a bogus lookup. @@ -920,6 +968,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, vtable_index = vtable_index_of_miranda_method(resolved_klass, resolved_method->name(), resolved_method->signature(), CHECK); + assert(vtable_index >= 0 , "we should have valid vtable index at this point"); InstanceKlass* inst = InstanceKlass::cast(recv_klass()); @@ -927,6 +976,7 @@ void LinkResolver::runtime_resolve_virtual_method(CallInfo& result, } else { // at this point we are sure that resolved_method is virtual and not // a miranda method; therefore, it must have a valid vtable index. + assert(!resolved_method->has_itable_index(), ""); vtable_index = resolved_method->vtable_index(); // We could get a negative vtable_index for final methods, // because as an optimization they are they are never put in the vtable, @@ -1006,6 +1056,12 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand lookup_instance_method_in_klasses(sel_method, recv_klass, resolved_method->name(), resolved_method->signature(), CHECK); + if (sel_method.is_null() && !check_null_and_abstract) { + // In theory this is a harmless placeholder value, but + // in practice leaving in null affects the nsk default method tests. + // This needs further study. + sel_method = resolved_method; + } // check if method exists if (sel_method.is_null()) { ResourceMark rm(THREAD); @@ -1046,7 +1102,14 @@ void LinkResolver::runtime_resolve_interface_method(CallInfo& result, methodHand sel_method->signature())); } // setup result - result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, CHECK); + if (!resolved_method->has_itable_index()) { + int vtable_index = resolved_method->vtable_index(); + assert(vtable_index == sel_method->vtable_index(), "sanity check"); + result.set_virtual(resolved_klass, recv_klass, resolved_method, sel_method, vtable_index, CHECK); + return; + } + int itable_index = resolved_method()->itable_index(); + result.set_interface(resolved_klass, recv_klass, resolved_method, sel_method, itable_index, CHECK); } @@ -1293,7 +1356,8 @@ void LinkResolver::resolve_invokedynamic(CallInfo& result, constantPoolHandle po } if (TraceMethodHandles) { - tty->print_cr("resolve_invokedynamic #%d %s %s", + ResourceMark rm(THREAD); + tty->print_cr("resolve_invokedynamic #%d %s %s", ConstantPool::decode_invokedynamic_index(index), method_name->as_C_string(), method_signature->as_C_string()); tty->print(" BSM info: "); bootstrap_specifier->print(); @@ -1342,9 +1406,16 @@ void LinkResolver::resolve_dynamic_call(CallInfo& result, //------------------------------------------------------------------------------------------------------------------------ #ifndef PRODUCT -void FieldAccessInfo::print() { +void CallInfo::print() { ResourceMark rm; - tty->print_cr("Field %s@%d", name()->as_C_string(), field_offset()); + const char* kindstr = "unknown"; + switch (_call_kind) { + case direct_call: kindstr = "direct"; break; + case vtable_call: kindstr = "vtable"; break; + case itable_call: kindstr = "itable"; break; + } + tty->print_cr("Call %s@%d %s", kindstr, _call_index, + _resolved_method.is_null() ? "(none)" : _resolved_method->name_and_sig_as_C_string()); } #endif diff --git a/hotspot/src/share/vm/interpreter/linkResolver.hpp b/hotspot/src/share/vm/interpreter/linkResolver.hpp index 4054eeb35ef..0fb551a23a8 100644 --- a/hotspot/src/share/vm/interpreter/linkResolver.hpp +++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,63 +30,54 @@ // All the necessary definitions for run-time link resolution. -// LinkInfo & its subclasses provide all the information gathered -// for a particular link after resolving it. A link is any reference +// CallInfo provides all the information gathered for a particular +// linked call site after resolving it. A link is any reference // made from within the bytecodes of a method to an object outside of // that method. If the info is invalid, the link has not been resolved // successfully. -class LinkInfo VALUE_OBJ_CLASS_SPEC { -}; - - -// Link information for getfield/putfield & getstatic/putstatic bytecodes. - -class FieldAccessInfo: public LinkInfo { - protected: - KlassHandle _klass; - Symbol* _name; - AccessFlags _access_flags; - int _field_index; // original index in the klass - int _field_offset; - BasicType _field_type; - +class CallInfo VALUE_OBJ_CLASS_SPEC { public: - void set(KlassHandle klass, Symbol* name, int field_index, int field_offset, - BasicType field_type, AccessFlags access_flags); - KlassHandle klass() const { return _klass; } - Symbol* name() const { return _name; } - int field_index() const { return _field_index; } - int field_offset() const { return _field_offset; } - BasicType field_type() const { return _field_type; } - AccessFlags access_flags() const { return _access_flags; } - - // debugging - void print() PRODUCT_RETURN; -}; - - -// Link information for all calls. - -class CallInfo: public LinkInfo { + // Ways that a method call might be selected (or not) based on receiver type. + // Note that an invokevirtual instruction might be linked with no_dispatch, + // and an invokeinterface instruction might be linked with any of the three options + enum CallKind { + direct_call, // jump into resolved_method (must be concrete) + vtable_call, // select recv.klass.method_at_vtable(index) + itable_call, // select recv.klass.method_at_itable(resolved_method.holder, index) + unknown_kind = -1 + }; private: - KlassHandle _resolved_klass; // static receiver klass + KlassHandle _resolved_klass; // static receiver klass, resolved from a symbolic reference KlassHandle _selected_klass; // dynamic receiver class (same as static, or subklass) methodHandle _resolved_method; // static target method methodHandle _selected_method; // dynamic (actual) target method - int _vtable_index; // vtable index of selected method + CallKind _call_kind; // kind of call (static(=bytecode static/special + + // others inferred), vtable, itable) + int _call_index; // vtable or itable index of selected class method (if any) Handle _resolved_appendix; // extra argument in constant pool (if CPCE::has_appendix) Handle _resolved_method_type; // MethodType (for invokedynamic and invokehandle call sites) void set_static( KlassHandle resolved_klass, methodHandle resolved_method , TRAPS); - void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method , TRAPS); + void set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int itable_index , TRAPS); void set_virtual( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS); void set_handle( methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS); - void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index , TRAPS); + void set_common( KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, CallKind kind, int index, TRAPS); friend class LinkResolver; public: + CallInfo() { +#ifndef PRODUCT + _call_kind = CallInfo::unknown_kind; + _call_index = Method::garbage_vtable_index; +#endif //PRODUCT + } + + // utility to extract an effective CallInfo from a method and an optional receiver limit + // does not queue the method for compilation + CallInfo(Method* resolved_method, Klass* resolved_klass = NULL); + KlassHandle resolved_klass() const { return _resolved_klass; } KlassHandle selected_klass() const { return _selected_klass; } methodHandle resolved_method() const { return _resolved_method; } @@ -95,21 +86,43 @@ class CallInfo: public LinkInfo { Handle resolved_method_type() const { return _resolved_method_type; } BasicType result_type() const { return selected_method()->result_type(); } - bool has_vtable_index() const { return _vtable_index >= 0; } - bool is_statically_bound() const { return _vtable_index == Method::nonvirtual_vtable_index; } + CallKind call_kind() const { return _call_kind; } + int call_index() const { return _call_index; } int vtable_index() const { // Even for interface calls the vtable index could be non-negative. // See CallInfo::set_interface. assert(has_vtable_index() || is_statically_bound(), ""); - return _vtable_index; + assert(call_kind() == vtable_call || call_kind() == direct_call, ""); + // The returned value is < 0 if the call is statically bound. + // But, the returned value may be >= 0 even if the kind is direct_call. + // It is up to the caller to decide which way to go. + return _call_index; } + int itable_index() const { + assert(call_kind() == itable_call, ""); + // The returned value is always >= 0, a valid itable index. + return _call_index; + } + + // debugging +#ifdef ASSERT + bool has_vtable_index() const { return _call_index >= 0 && _call_kind != CallInfo::itable_call; } + bool is_statically_bound() const { return _call_index == Method::nonvirtual_vtable_index; } +#endif //ASSERT + void verify() PRODUCT_RETURN; + void print() PRODUCT_RETURN; }; +// Link information for getfield/putfield & getstatic/putstatic bytecodes +// is represented using a fieldDescriptor. // The LinkResolver is used to resolve constant-pool references at run-time. // It does all necessary link-time checks & throws exceptions if necessary. class LinkResolver: AllStatic { + friend class klassVtable; + friend class klassItable; + private: static void lookup_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); @@ -120,7 +133,6 @@ class LinkResolver: AllStatic { static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS); static void resolve_klass (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); - static void resolve_klass_no_update (KlassHandle& result, constantPoolHandle pool, int index, TRAPS); // no update of constantPool entry static void resolve_pool (KlassHandle& resolved_klass, Symbol*& method_name, Symbol*& method_signature, KlassHandle& current_klass, constantPoolHandle pool, int index, TRAPS); @@ -148,9 +160,16 @@ class LinkResolver: AllStatic { Bytecodes::Code code, constantPoolHandle pool, int index, TRAPS); // runtime/static resolving for fields - static void resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, TRAPS); - // takes an extra bool argument "update_pool" to decide whether to update the constantPool during klass resolution. - static void resolve_field(FieldAccessInfo& result, constantPoolHandle pool, int index, Bytecodes::Code byte, bool check_only, bool update_pool, TRAPS); + static void resolve_field_access(fieldDescriptor& result, constantPoolHandle pool, int index, Bytecodes::Code byte, TRAPS); + static void resolve_field(fieldDescriptor& result, KlassHandle resolved_klass, Symbol* field_name, Symbol* field_signature, + KlassHandle current_klass, Bytecodes::Code access_kind, bool check_access, bool initialize_class, TRAPS); + + // source of access_kind codes: + static Bytecodes::Code field_access_kind(bool is_static, bool is_put) { + return (is_static + ? (is_put ? Bytecodes::_putstatic : Bytecodes::_getstatic) + : (is_put ? Bytecodes::_putfield : Bytecodes::_getfield )); + } // runtime resolving: // resolved_klass = specified class (i.e., static receiver class) diff --git a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp index 8ed2b61a921..bfe1d1b4ca8 100644 --- a/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp +++ b/hotspot/src/share/vm/memory/binaryTreeDictionary.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,10 +33,10 @@ #include "runtime/globals.hpp" #include "utilities/ostream.hpp" #include "utilities/macros.hpp" +#include "gc_implementation/shared/spaceDecorator.hpp" #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/adaptiveFreeList.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" -#include "gc_implementation/shared/spaceDecorator.hpp" #include "gc_implementation/concurrentMarkSweep/freeChunk.hpp" #endif // INCLUDE_ALL_GCS diff --git a/hotspot/src/share/vm/memory/collectorPolicy.cpp b/hotspot/src/share/vm/memory/collectorPolicy.cpp index 6a1967daeda..0728997b769 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.cpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.cpp @@ -47,6 +47,11 @@ // CollectorPolicy methods. +// Align down. If the aligning result in 0, return 'alignment'. +static size_t restricted_align_down(size_t size, size_t alignment) { + return MAX2(alignment, align_size_down_(size, alignment)); +} + void CollectorPolicy::initialize_flags() { assert(max_alignment() >= min_alignment(), err_msg("max_alignment: " SIZE_FORMAT " less than min_alignment: " SIZE_FORMAT, @@ -59,18 +64,24 @@ void CollectorPolicy::initialize_flags() { vm_exit_during_initialization("Incompatible initial and maximum heap sizes specified"); } - if (MetaspaceSize > MaxMetaspaceSize) { - MaxMetaspaceSize = MetaspaceSize; - } - MetaspaceSize = MAX2(min_alignment(), align_size_down_(MetaspaceSize, min_alignment())); - // Don't increase Metaspace size limit above specified. - MaxMetaspaceSize = align_size_down(MaxMetaspaceSize, max_alignment()); - if (MetaspaceSize > MaxMetaspaceSize) { - MetaspaceSize = MaxMetaspaceSize; + if (!is_size_aligned(MaxMetaspaceSize, max_alignment())) { + FLAG_SET_ERGO(uintx, MaxMetaspaceSize, + restricted_align_down(MaxMetaspaceSize, max_alignment())); } - MinMetaspaceExpansion = MAX2(min_alignment(), align_size_down_(MinMetaspaceExpansion, min_alignment())); - MaxMetaspaceExpansion = MAX2(min_alignment(), align_size_down_(MaxMetaspaceExpansion, min_alignment())); + if (MetaspaceSize > MaxMetaspaceSize) { + FLAG_SET_ERGO(uintx, MetaspaceSize, MaxMetaspaceSize); + } + + if (!is_size_aligned(MetaspaceSize, min_alignment())) { + FLAG_SET_ERGO(uintx, MetaspaceSize, + restricted_align_down(MetaspaceSize, min_alignment())); + } + + assert(MetaspaceSize <= MaxMetaspaceSize, "Must be"); + + MinMetaspaceExpansion = restricted_align_down(MinMetaspaceExpansion, min_alignment()); + MaxMetaspaceExpansion = restricted_align_down(MaxMetaspaceExpansion, min_alignment()); MinHeapDeltaBytes = align_size_up(MinHeapDeltaBytes, min_alignment()); @@ -145,6 +156,30 @@ void CollectorPolicy::cleared_all_soft_refs() { _all_soft_refs_clear = true; } +size_t CollectorPolicy::compute_max_alignment() { + // The card marking array and the offset arrays for old generations are + // committed in os pages as well. Make sure they are entirely full (to + // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 + // byte entry and the os page size is 4096, the maximum heap size should + // be 512*4096 = 2MB aligned. + + // There is only the GenRemSet in Hotspot and only the GenRemSet::CardTable + // is supported. + // Requirements of any new remembered set implementations must be added here. + size_t alignment = GenRemSet::max_alignment_constraint(GenRemSet::CardTable); + + // Parallel GC does its own alignment of the generations to avoid requiring a + // large page (256M on some platforms) for the permanent generation. The + // other collectors should also be updated to do their own alignment and then + // this use of lcm() should be removed. + if (UseLargePages && !UseParallelGC) { + // in presence of large pages we have to make sure that our + // alignment is large page aware + alignment = lcm(os::large_page_size(), alignment); + } + + return alignment; +} // GenCollectorPolicy methods. @@ -175,29 +210,6 @@ void GenCollectorPolicy::initialize_size_policy(size_t init_eden_size, GCTimeRatio); } -size_t GenCollectorPolicy::compute_max_alignment() { - // The card marking array and the offset arrays for old generations are - // committed in os pages as well. Make sure they are entirely full (to - // avoid partial page problems), e.g. if 512 bytes heap corresponds to 1 - // byte entry and the os page size is 4096, the maximum heap size should - // be 512*4096 = 2MB aligned. - size_t alignment = GenRemSet::max_alignment_constraint(rem_set_name()); - - // Parallel GC does its own alignment of the generations to avoid requiring a - // large page (256M on some platforms) for the permanent generation. The - // other collectors should also be updated to do their own alignment and then - // this use of lcm() should be removed. - if (UseLargePages && !UseParallelGC) { - // in presence of large pages we have to make sure that our - // alignment is large page aware - alignment = lcm(os::large_page_size(), alignment); - } - - assert(alignment >= min_alignment(), "Must be"); - - return alignment; -} - void GenCollectorPolicy::initialize_flags() { // All sizes must be multiples of the generation granularity. set_min_alignment((uintx) Generation::GenGrain); diff --git a/hotspot/src/share/vm/memory/collectorPolicy.hpp b/hotspot/src/share/vm/memory/collectorPolicy.hpp index 4acf7ba780c..73fd177d7ba 100644 --- a/hotspot/src/share/vm/memory/collectorPolicy.hpp +++ b/hotspot/src/share/vm/memory/collectorPolicy.hpp @@ -98,6 +98,9 @@ class CollectorPolicy : public CHeapObj { {} public: + // Return maximum heap alignment that may be imposed by the policy + static size_t compute_max_alignment(); + void set_min_alignment(size_t align) { _min_alignment = align; } size_t min_alignment() { return _min_alignment; } void set_max_alignment(size_t align) { _max_alignment = align; } @@ -234,9 +237,6 @@ class GenCollectorPolicy : public CollectorPolicy { // Try to allocate space by expanding the heap. virtual HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab); - // compute max heap alignment - size_t compute_max_alignment(); - // Scale the base_size by NewRation according to // result = base_size / (NewRatio + 1) // and align by min_alignment() diff --git a/hotspot/src/share/vm/memory/gcLocker.cpp b/hotspot/src/share/vm/memory/gcLocker.cpp index eda728b7047..1b0c94ee171 100644 --- a/hotspot/src/share/vm/memory/gcLocker.cpp +++ b/hotspot/src/share/vm/memory/gcLocker.cpp @@ -122,7 +122,7 @@ void GC_locker::jni_unlock(JavaThread* thread) { // strictly needed. It's added here to make it clear that // the GC will NOT be performed if any other caller // of GC_locker::lock() still needs GC locked. - if (!is_active()) { + if (!is_active_internal()) { _doing_gc = true; { // Must give up the lock while at a safepoint diff --git a/hotspot/src/share/vm/memory/gcLocker.hpp b/hotspot/src/share/vm/memory/gcLocker.hpp index 8ede8fb275b..45b8a8f89e7 100644 --- a/hotspot/src/share/vm/memory/gcLocker.hpp +++ b/hotspot/src/share/vm/memory/gcLocker.hpp @@ -88,7 +88,7 @@ class GC_locker: public AllStatic { public: // Accessors static bool is_active() { - assert(_needs_gc || SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); + assert(SafepointSynchronize::is_at_safepoint(), "only read at safepoint"); return is_active_internal(); } static bool needs_gc() { return _needs_gc; } diff --git a/hotspot/src/share/vm/memory/genCollectedHeap.hpp b/hotspot/src/share/vm/memory/genCollectedHeap.hpp index 9ab9d1991df..8f814132a78 100644 --- a/hotspot/src/share/vm/memory/genCollectedHeap.hpp +++ b/hotspot/src/share/vm/memory/genCollectedHeap.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -148,6 +148,11 @@ public: return gen_policy()->size_policy(); } + // Return the (conservative) maximum heap alignment + static size_t conservative_max_heap_alignment() { + return Generation::GenGrain; + } + size_t capacity() const; size_t used() const; diff --git a/hotspot/src/share/vm/memory/metablock.cpp b/hotspot/src/share/vm/memory/metablock.cpp index 450d2c3193d..b6c6947e1ac 100644 --- a/hotspot/src/share/vm/memory/metablock.cpp +++ b/hotspot/src/share/vm/memory/metablock.cpp @@ -50,13 +50,6 @@ // Chunks, change Chunks so that they can be allocated out of a VirtualSpace. size_t Metablock::_min_block_byte_size = sizeof(Metablock); -#ifdef ASSERT -size_t Metablock::_overhead = - Chunk::aligned_overhead_size(sizeof(Metablock)) / BytesPerWord; -#else -size_t Metablock::_overhead = 0; -#endif - // New blocks returned by the Metaspace are zero initialized. // We should fix the constructors to not assume this instead. Metablock* Metablock::initialize(MetaWord* p, size_t word_size) { diff --git a/hotspot/src/share/vm/memory/metablock.hpp b/hotspot/src/share/vm/memory/metablock.hpp index 220d3614818..fa4c6c0b445 100644 --- a/hotspot/src/share/vm/memory/metablock.hpp +++ b/hotspot/src/share/vm/memory/metablock.hpp @@ -48,7 +48,6 @@ class Metablock VALUE_OBJ_CLASS_SPEC { } _header; } _block; static size_t _min_block_byte_size; - static size_t _overhead; typedef union block_t Block; typedef struct header_t Header; @@ -73,7 +72,6 @@ class Metablock VALUE_OBJ_CLASS_SPEC { void set_prev(Metablock* v) { _block._header._prev = v; } static size_t min_block_byte_size() { return _min_block_byte_size; } - static size_t overhead() { return _overhead; } bool is_free() { return header()->_word_size != 0; } void clear_next() { set_next(NULL); } diff --git a/hotspot/src/share/vm/memory/metaspace.cpp b/hotspot/src/share/vm/memory/metaspace.cpp index cd46888c9c2..06f3d09378a 100644 --- a/hotspot/src/share/vm/memory/metaspace.cpp +++ b/hotspot/src/share/vm/memory/metaspace.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" #include "gc_interface/collectedHeap.hpp" +#include "memory/allocation.hpp" #include "memory/binaryTreeDictionary.hpp" #include "memory/freeList.hpp" #include "memory/collectorPolicy.hpp" @@ -51,7 +52,7 @@ const bool metaspace_slow_verify = false; // Parameters for stress mode testing const uint metadata_deallocate_a_lot_block = 10; const uint metadata_deallocate_a_lock_chunk = 3; -size_t const allocation_from_dictionary_limit = 64 * K; +size_t const allocation_from_dictionary_limit = 4 * K; MetaWord* last_allocated = 0; @@ -111,7 +112,7 @@ typedef class FreeList ChunkList; // Has three lists of free chunks, and a total size and // count that includes all three -class ChunkManager VALUE_OBJ_CLASS_SPEC { +class ChunkManager : public CHeapObj { // Free list of chunks of different sizes. // SpecializedChunk @@ -158,7 +159,12 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC { public: - ChunkManager() : _free_chunks_total(0), _free_chunks_count(0) {} + ChunkManager(size_t specialized_size, size_t small_size, size_t medium_size) + : _free_chunks_total(0), _free_chunks_count(0) { + _free_chunks[SpecializedIndex].set_size(specialized_size); + _free_chunks[SmallIndex].set_size(small_size); + _free_chunks[MediumIndex].set_size(medium_size); + } // add or delete (return) a chunk to the global freelist. Metachunk* chunk_freelist_allocate(size_t word_size); @@ -177,8 +183,8 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC { void return_chunks(ChunkIndex index, Metachunk* chunks); // Total of the space in the free chunks list - size_t free_chunks_total(); - size_t free_chunks_total_in_bytes(); + size_t free_chunks_total_words(); + size_t free_chunks_total_bytes(); // Number of chunks in the free chunks list size_t free_chunks_count(); @@ -219,7 +225,7 @@ class ChunkManager VALUE_OBJ_CLASS_SPEC { void locked_print_free_chunks(outputStream* st); void locked_print_sum_free_chunks(outputStream* st); - void print_on(outputStream* st); + void print_on(outputStream* st) const; }; // Used to manage the free list of Metablocks (a block corresponds @@ -228,6 +234,10 @@ class BlockFreelist VALUE_OBJ_CLASS_SPEC { BlockTreeDictionary* _dictionary; static Metablock* initialize_free_chunk(MetaWord* p, size_t word_size); + // Only allocate and split from freelist if the size of the allocation + // is at least 1/4th the size of the available block. + const static int WasteMultiplier = 4; + // Accessors BlockTreeDictionary* dictionary() const { return _dictionary; } @@ -272,11 +282,6 @@ class VirtualSpaceNode : public CHeapObj { // VirtualSpace Metachunk* first_chunk() { return (Metachunk*) bottom(); } - void inc_container_count(); -#ifdef ASSERT - uint container_count_slow(); -#endif - public: VirtualSpaceNode(size_t byte_size); @@ -287,6 +292,10 @@ class VirtualSpaceNode : public CHeapObj { MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } + size_t reserved_words() const { return _virtual_space.reserved_size() / BytesPerWord; } + size_t expanded_words() const { return _virtual_space.committed_size() / BytesPerWord; } + size_t committed_words() const { return _virtual_space.actual_committed_size() / BytesPerWord; } + // address of next available space in _virtual_space; // Accessors VirtualSpaceNode* next() { return _next; } @@ -306,8 +315,10 @@ class VirtualSpaceNode : public CHeapObj { void inc_top(size_t word_size) { _top += word_size; } uintx container_count() { return _container_count; } + void inc_container_count(); void dec_container_count(); #ifdef ASSERT + uint container_count_slow(); void verify_container_count(); #endif @@ -323,12 +334,10 @@ class VirtualSpaceNode : public CHeapObj { // Allocate a chunk from the virtual space and return it. Metachunk* get_chunk_vs(size_t chunk_word_size); - Metachunk* get_chunk_vs_with_expand(size_t chunk_word_size); // Expands/shrinks the committed space in a virtual space. Delegates // to Virtualspace bool expand_by(size_t words, bool pre_touch = false); - bool shrink_by(size_t words); // In preparation for deleting this node, remove all the chunks // in the node from any freelist. @@ -336,8 +345,6 @@ class VirtualSpaceNode : public CHeapObj { #ifdef ASSERT // Debug support - static void verify_virtual_space_total(); - static void verify_virtual_space_count(); void mangle(); #endif @@ -417,16 +424,17 @@ class VirtualSpaceList : public CHeapObj { VirtualSpaceNode* _virtual_space_list; // virtual space currently being used for allocations VirtualSpaceNode* _current_virtual_space; - // Free chunk list for all other metadata - ChunkManager _chunk_manager; // Can this virtual list allocate >1 spaces? Also, used to determine // whether to allocate unlimited small chunks in this virtual space bool _is_class; - bool can_grow() const { return !is_class() || !UseCompressedKlassPointers; } + bool can_grow() const { return !is_class() || !UseCompressedClassPointers; } - // Sum of space in all virtual spaces and number of virtual spaces - size_t _virtual_space_total; + // Sum of reserved and committed memory in the virtual spaces + size_t _reserved_words; + size_t _committed_words; + + // Number of virtual spaces size_t _virtual_space_count; ~VirtualSpaceList(); @@ -440,7 +448,7 @@ class VirtualSpaceList : public CHeapObj { _current_virtual_space = v; } - void link_vs(VirtualSpaceNode* new_entry, size_t vs_word_size); + void link_vs(VirtualSpaceNode* new_entry); // Get another virtual space and add it to the list. This // is typically prompted by a failed attempt to allocate a chunk @@ -457,6 +465,8 @@ class VirtualSpaceList : public CHeapObj { size_t grow_chunks_by_words, size_t medium_chunk_bunch); + bool expand_by(VirtualSpaceNode* node, size_t word_size, bool pre_touch = false); + // Get the first chunk for a Metaspace. Used for // special cases such as the boot class loader, reflection // class loader and anonymous class loader. @@ -466,28 +476,25 @@ class VirtualSpaceList : public CHeapObj { return _current_virtual_space; } - ChunkManager* chunk_manager() { return &_chunk_manager; } bool is_class() const { return _is_class; } // Allocate the first virtualspace. void initialize(size_t word_size); - size_t virtual_space_total() { return _virtual_space_total; } + size_t reserved_words() { return _reserved_words; } + size_t reserved_bytes() { return reserved_words() * BytesPerWord; } + size_t committed_words() { return _committed_words; } + size_t committed_bytes() { return committed_words() * BytesPerWord; } - void inc_virtual_space_total(size_t v); - void dec_virtual_space_total(size_t v); + void inc_reserved_words(size_t v); + void dec_reserved_words(size_t v); + void inc_committed_words(size_t v); + void dec_committed_words(size_t v); void inc_virtual_space_count(); void dec_virtual_space_count(); // Unlink empty VirtualSpaceNodes and free it. - void purge(); - - // Used and capacity in the entire list of virtual spaces. - // These are global values shared by all Metaspaces - size_t capacity_words_sum(); - size_t capacity_bytes_sum() { return capacity_words_sum() * BytesPerWord; } - size_t used_words_sum(); - size_t used_bytes_sum() { return used_words_sum() * BytesPerWord; } + void purge(ChunkManager* chunk_manager); bool contains(const void *ptr); @@ -568,18 +575,12 @@ class SpaceManager : public CHeapObj { // Type of metadata allocated. Metaspace::MetadataType _mdtype; - // Chunk related size - size_t _medium_chunk_bunch; - // List of chunks in use by this SpaceManager. Allocations // are done from the current chunk. The list is used for deallocating // chunks when the SpaceManager is freed. Metachunk* _chunks_in_use[NumberOfInUseLists]; Metachunk* _current_chunk; - // Virtual space where allocation comes from. - VirtualSpaceList* _vs_list; - // Number of small chunks to allocate to a manager // If class space manager, small chunks are unlimited static uint const _small_chunk_limit; @@ -612,7 +613,9 @@ class SpaceManager : public CHeapObj { } Metaspace::MetadataType mdtype() { return _mdtype; } - VirtualSpaceList* vs_list() const { return _vs_list; } + + VirtualSpaceList* vs_list() const { return Metaspace::get_space_list(_mdtype); } + ChunkManager* chunk_manager() const { return Metaspace::get_chunk_manager(_mdtype); } Metachunk* current_chunk() const { return _current_chunk; } void set_current_chunk(Metachunk* v) { @@ -623,6 +626,7 @@ class SpaceManager : public CHeapObj { // Add chunk to the list of chunks in use void add_chunk(Metachunk* v, bool make_current); + void retire_current_chunk(); Mutex* lock() const { return _lock; } @@ -633,18 +637,19 @@ class SpaceManager : public CHeapObj { public: SpaceManager(Metaspace::MetadataType mdtype, - Mutex* lock, - VirtualSpaceList* vs_list); + Mutex* lock); ~SpaceManager(); enum ChunkMultiples { MediumChunkMultiple = 4 }; + bool is_class() { return _mdtype == Metaspace::ClassType; } + // Accessors size_t specialized_chunk_size() { return SpecializedChunk; } - size_t small_chunk_size() { return (size_t) vs_list()->is_class() ? ClassSmallChunk : SmallChunk; } - size_t medium_chunk_size() { return (size_t) vs_list()->is_class() ? ClassMediumChunk : MediumChunk; } + size_t small_chunk_size() { return (size_t) is_class() ? ClassSmallChunk : SmallChunk; } + size_t medium_chunk_size() { return (size_t) is_class() ? ClassMediumChunk : MediumChunk; } size_t medium_chunk_bunch() { return medium_chunk_size() * MediumChunkMultiple; } size_t allocated_blocks_words() const { return _allocated_blocks_words; } @@ -722,9 +727,7 @@ class SpaceManager : public CHeapObj { // MinChunkSize is a placeholder for the real minimum size JJJ size_t byte_size = word_size * BytesPerWord; - size_t byte_size_with_overhead = byte_size + Metablock::overhead(); - - size_t raw_bytes_size = MAX2(byte_size_with_overhead, + size_t raw_bytes_size = MAX2(byte_size, Metablock::min_block_byte_size()); raw_bytes_size = ARENA_ALIGN(raw_bytes_size); size_t raw_word_size = raw_bytes_size / BytesPerWord; @@ -749,7 +752,7 @@ void VirtualSpaceNode::inc_container_count() { _container_count++; assert(_container_count == container_count_slow(), err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT - "container_count_slow() " SIZE_FORMAT, + " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); } @@ -762,7 +765,7 @@ void VirtualSpaceNode::dec_container_count() { void VirtualSpaceNode::verify_container_count() { assert(_container_count == container_count_slow(), err_msg("Inconsistency in countainer_count _container_count " SIZE_FORMAT - "container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); + " container_count_slow() " SIZE_FORMAT, _container_count, container_count_slow())); } #endif @@ -807,12 +810,25 @@ MetaWord* BlockFreelist::get_block(size_t word_size) { } Metablock* free_block = - dictionary()->get_chunk(word_size, FreeBlockDictionary::exactly); + dictionary()->get_chunk(word_size, FreeBlockDictionary::atLeast); if (free_block == NULL) { return NULL; } - return (MetaWord*) free_block; + const size_t block_size = free_block->size(); + if (block_size > WasteMultiplier * word_size) { + return_block((MetaWord*)free_block, block_size); + return NULL; + } + + MetaWord* new_block = (MetaWord*)free_block; + assert(block_size >= word_size, "Incorrect size of block from freelist"); + const size_t unused = block_size - word_size; + if (unused >= TreeChunk::min_size()) { + return_block(new_block + word_size, unused); + } + + return new_block; } void BlockFreelist::print_on(outputStream* st) const { @@ -855,9 +871,9 @@ Metachunk* VirtualSpaceNode::take_from_committed(size_t chunk_word_size) { if (!is_available(chunk_word_size)) { if (TraceMetadataChunkAllocation) { - tty->print("VirtualSpaceNode::take_from_committed() not available %d words ", chunk_word_size); + gclog_or_tty->print("VirtualSpaceNode::take_from_committed() not available %d words ", chunk_word_size); // Dump some information about the virtual space that is nearly full - print_on(tty); + print_on(gclog_or_tty); } return NULL; } @@ -878,20 +894,11 @@ bool VirtualSpaceNode::expand_by(size_t words, bool pre_touch) { if (TraceMetavirtualspaceAllocation && !result) { gclog_or_tty->print_cr("VirtualSpaceNode::expand_by() failed " "for byte size " SIZE_FORMAT, bytes); - virtual_space()->print(); + virtual_space()->print_on(gclog_or_tty); } return result; } -// Shrink the virtual space (commit more of the reserved space) -bool VirtualSpaceNode::shrink_by(size_t words) { - size_t bytes = words * BytesPerWord; - virtual_space()->shrink_by(bytes); - return true; -} - -// Add another chunk to the chunk list. - Metachunk* VirtualSpaceNode::get_chunk_vs(size_t chunk_word_size) { assert_lock_strong(SpaceManager::expand_lock()); Metachunk* result = take_from_committed(chunk_word_size); @@ -901,23 +908,6 @@ Metachunk* VirtualSpaceNode::get_chunk_vs(size_t chunk_word_size) { return result; } -Metachunk* VirtualSpaceNode::get_chunk_vs_with_expand(size_t chunk_word_size) { - assert_lock_strong(SpaceManager::expand_lock()); - - Metachunk* new_chunk = get_chunk_vs(chunk_word_size); - - if (new_chunk == NULL) { - // Only a small part of the virtualspace is committed when first - // allocated so committing more here can be expected. - size_t page_size_words = os::vm_page_size() / BytesPerWord; - size_t aligned_expand_vs_by_words = align_size_up(chunk_word_size, - page_size_words); - expand_by(aligned_expand_vs_by_words, false); - new_chunk = get_chunk_vs(chunk_word_size); - } - return new_chunk; -} - bool VirtualSpaceNode::initialize() { if (!_rs.is_reserved()) { @@ -977,13 +967,22 @@ VirtualSpaceList::~VirtualSpaceList() { } } -void VirtualSpaceList::inc_virtual_space_total(size_t v) { +void VirtualSpaceList::inc_reserved_words(size_t v) { assert_lock_strong(SpaceManager::expand_lock()); - _virtual_space_total = _virtual_space_total + v; + _reserved_words = _reserved_words + v; } -void VirtualSpaceList::dec_virtual_space_total(size_t v) { +void VirtualSpaceList::dec_reserved_words(size_t v) { assert_lock_strong(SpaceManager::expand_lock()); - _virtual_space_total = _virtual_space_total - v; + _reserved_words = _reserved_words - v; +} + +void VirtualSpaceList::inc_committed_words(size_t v) { + assert_lock_strong(SpaceManager::expand_lock()); + _committed_words = _committed_words + v; +} +void VirtualSpaceList::dec_committed_words(size_t v) { + assert_lock_strong(SpaceManager::expand_lock()); + _committed_words = _committed_words - v; } void VirtualSpaceList::inc_virtual_space_count() { @@ -1011,7 +1010,7 @@ void ChunkManager::remove_chunk(Metachunk* chunk) { // Walk the list of VirtualSpaceNodes and delete // nodes with a 0 container_count. Remove Metachunks in // the node from their respective freelists. -void VirtualSpaceList::purge() { +void VirtualSpaceList::purge(ChunkManager* chunk_manager) { assert_lock_strong(SpaceManager::expand_lock()); // Don't use a VirtualSpaceListIterator because this // list is being changed and a straightforward use of an iterator is not safe. @@ -1033,8 +1032,9 @@ void VirtualSpaceList::purge() { prev_vsl->set_next(vsl->next()); } - vsl->purge(chunk_manager()); - dec_virtual_space_total(vsl->reserved()->word_size()); + vsl->purge(chunk_manager); + dec_reserved_words(vsl->reserved_words()); + dec_committed_words(vsl->committed_words()); dec_virtual_space_count(); purged_vsl = vsl; delete vsl; @@ -1054,49 +1054,16 @@ void VirtualSpaceList::purge() { #endif } -size_t VirtualSpaceList::used_words_sum() { - size_t allocated_by_vs = 0; - VirtualSpaceListIterator iter(virtual_space_list()); - while (iter.repeat()) { - VirtualSpaceNode* vsl = iter.get_next(); - // Sum used region [bottom, top) in each virtualspace - allocated_by_vs += vsl->used_words_in_vs(); - } - assert(allocated_by_vs >= chunk_manager()->free_chunks_total(), - err_msg("Total in free chunks " SIZE_FORMAT - " greater than total from virtual_spaces " SIZE_FORMAT, - allocated_by_vs, chunk_manager()->free_chunks_total())); - size_t used = - allocated_by_vs - chunk_manager()->free_chunks_total(); - return used; -} - -// Space available in all MetadataVirtualspaces allocated -// for metadata. This is the upper limit on the capacity -// of chunks allocated out of all the MetadataVirtualspaces. -size_t VirtualSpaceList::capacity_words_sum() { - size_t capacity = 0; - VirtualSpaceListIterator iter(virtual_space_list()); - while (iter.repeat()) { - VirtualSpaceNode* vsl = iter.get_next(); - capacity += vsl->capacity_words_in_vs(); - } - return capacity; -} - VirtualSpaceList::VirtualSpaceList(size_t word_size ) : _is_class(false), _virtual_space_list(NULL), _current_virtual_space(NULL), - _virtual_space_total(0), + _reserved_words(0), + _committed_words(0), _virtual_space_count(0) { MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); bool initialization_succeeded = grow_vs(word_size); - - _chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk); - _chunk_manager.free_chunks(SmallIndex)->set_size(SmallChunk); - _chunk_manager.free_chunks(MediumIndex)->set_size(MediumChunk); assert(initialization_succeeded, " VirtualSpaceList initialization should not fail"); } @@ -1105,17 +1072,15 @@ VirtualSpaceList::VirtualSpaceList(ReservedSpace rs) : _is_class(true), _virtual_space_list(NULL), _current_virtual_space(NULL), - _virtual_space_total(0), + _reserved_words(0), + _committed_words(0), _virtual_space_count(0) { MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); VirtualSpaceNode* class_entry = new VirtualSpaceNode(rs); bool succeeded = class_entry->initialize(); - _chunk_manager.free_chunks(SpecializedIndex)->set_size(SpecializedChunk); - _chunk_manager.free_chunks(SmallIndex)->set_size(ClassSmallChunk); - _chunk_manager.free_chunks(MediumIndex)->set_size(ClassMediumChunk); assert(succeeded, " VirtualSpaceList initialization should not fail"); - link_vs(class_entry, rs.size()/BytesPerWord); + link_vs(class_entry); } size_t VirtualSpaceList::free_bytes() { @@ -1130,7 +1095,7 @@ bool VirtualSpaceList::grow_vs(size_t vs_word_size) { } // Reserve the space size_t vs_byte_size = vs_word_size * BytesPerWord; - assert(vs_byte_size % os::vm_page_size() == 0, "Not aligned"); + assert(vs_byte_size % os::vm_allocation_granularity() == 0, "Not aligned"); // Allocate the meta virtual space and initialize it. VirtualSpaceNode* new_entry = new VirtualSpaceNode(vs_byte_size); @@ -1138,44 +1103,53 @@ bool VirtualSpaceList::grow_vs(size_t vs_word_size) { delete new_entry; return false; } else { + assert(new_entry->reserved_words() == vs_word_size, "Must be"); // ensure lock-free iteration sees fully initialized node OrderAccess::storestore(); - link_vs(new_entry, vs_word_size); + link_vs(new_entry); return true; } } -void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry, size_t vs_word_size) { +void VirtualSpaceList::link_vs(VirtualSpaceNode* new_entry) { if (virtual_space_list() == NULL) { set_virtual_space_list(new_entry); } else { current_virtual_space()->set_next(new_entry); } set_current_virtual_space(new_entry); - inc_virtual_space_total(vs_word_size); + inc_reserved_words(new_entry->reserved_words()); + inc_committed_words(new_entry->committed_words()); inc_virtual_space_count(); #ifdef ASSERT new_entry->mangle(); #endif if (TraceMetavirtualspaceAllocation && Verbose) { VirtualSpaceNode* vsl = current_virtual_space(); - vsl->print_on(tty); + vsl->print_on(gclog_or_tty); } } +bool VirtualSpaceList::expand_by(VirtualSpaceNode* node, size_t word_size, bool pre_touch) { + size_t before = node->committed_words(); + + bool result = node->expand_by(word_size, pre_touch); + + size_t after = node->committed_words(); + + // after and before can be the same if the memory was pre-committed. + assert(after >= before, "Must be"); + inc_committed_words(after - before); + + return result; +} + Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size, size_t grow_chunks_by_words, size_t medium_chunk_bunch) { - // Get a chunk from the chunk freelist - Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words); - - if (next != NULL) { - next->container()->inc_container_count(); - } else { - // Allocate a chunk out of the current virtual space. - next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words); - } + // Allocate a chunk out of the current virtual space. + Metachunk* next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words); if (next == NULL) { // Not enough room in current virtual space. Try to commit @@ -1186,18 +1160,27 @@ Metachunk* VirtualSpaceList::get_new_chunk(size_t word_size, size_t aligned_expand_vs_by_words = align_size_up(expand_vs_by_words, page_size_words); bool vs_expanded = - current_virtual_space()->expand_by(aligned_expand_vs_by_words, false); + expand_by(current_virtual_space(), aligned_expand_vs_by_words); if (!vs_expanded) { // Should the capacity of the metaspaces be expanded for // this allocation? If it's the virtual space for classes and is // being used for CompressedHeaders, don't allocate a new virtualspace. if (can_grow() && MetaspaceGC::should_expand(this, word_size)) { // Get another virtual space. - size_t grow_vs_words = - MAX2((size_t)VirtualSpaceSize, aligned_expand_vs_by_words); + size_t allocation_aligned_expand_words = + align_size_up(aligned_expand_vs_by_words, os::vm_allocation_granularity() / BytesPerWord); + size_t grow_vs_words = + MAX2((size_t)VirtualSpaceSize, allocation_aligned_expand_words); if (grow_vs(grow_vs_words)) { // Got it. It's on the list now. Get a chunk from it. - next = current_virtual_space()->get_chunk_vs_with_expand(grow_chunks_by_words); + assert(current_virtual_space()->expanded_words() == 0, + "New virtual space nodes should not have expanded"); + + size_t grow_chunks_by_words_aligned = align_size_up(grow_chunks_by_words, + page_size_words); + // We probably want to expand by aligned_expand_vs_by_words here. + expand_by(current_virtual_space(), grow_chunks_by_words_aligned); + next = current_virtual_space()->get_chunk_vs(grow_chunks_by_words); } } else { // Allocation will fail and induce a GC @@ -1307,8 +1290,9 @@ bool MetaspaceGC::should_expand(VirtualSpaceList* vsl, size_t word_size) { // reserved space, because this is a larger space prereserved for compressed // class pointers. if (!FLAG_IS_DEFAULT(MaxMetaspaceSize)) { - size_t real_allocated = Metaspace::space_list()->virtual_space_total() + - MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType); + size_t nonclass_allocated = MetaspaceAux::reserved_bytes(Metaspace::NonClassType); + size_t class_allocated = MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType); + size_t real_allocated = nonclass_allocated + class_allocated; if (real_allocated >= MaxMetaspaceSize) { return false; } @@ -1501,15 +1485,15 @@ void Metadebug::deallocate_chunk_a_lot(SpaceManager* sm, if (dummy_chunk == NULL) { break; } - vsl->chunk_manager()->chunk_freelist_deallocate(dummy_chunk); + sm->chunk_manager()->chunk_freelist_deallocate(dummy_chunk); if (TraceMetadataChunkAllocation && Verbose) { gclog_or_tty->print("Metadebug::deallocate_chunk_a_lot: %d) ", sm->sum_count_in_chunks_in_use()); dummy_chunk->print_on(gclog_or_tty); gclog_or_tty->print_cr(" Free chunks total %d count %d", - vsl->chunk_manager()->free_chunks_total(), - vsl->chunk_manager()->free_chunks_count()); + sm->chunk_manager()->free_chunks_total_words(), + sm->chunk_manager()->free_chunks_count()); } } } else { @@ -1565,12 +1549,12 @@ bool Metadebug::test_metadata_failure() { // ChunkManager methods -size_t ChunkManager::free_chunks_total() { +size_t ChunkManager::free_chunks_total_words() { return _free_chunks_total; } -size_t ChunkManager::free_chunks_total_in_bytes() { - return free_chunks_total() * BytesPerWord; +size_t ChunkManager::free_chunks_total_bytes() { + return free_chunks_total_words() * BytesPerWord; } size_t ChunkManager::free_chunks_count() { @@ -1698,9 +1682,9 @@ void ChunkManager::chunk_freelist_deallocate(Metachunk* chunk) { assert_lock_strong(SpaceManager::expand_lock()); slow_locked_verify(); if (TraceMetadataChunkAllocation) { - tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk " - PTR_FORMAT " size " SIZE_FORMAT, - chunk, chunk->word_size()); + gclog_or_tty->print_cr("ChunkManager::chunk_freelist_deallocate: chunk " + PTR_FORMAT " size " SIZE_FORMAT, + chunk, chunk->word_size()); } free_chunks_put(chunk); } @@ -1729,9 +1713,9 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { dec_free_chunks_total(chunk->capacity_word_size()); if (TraceMetadataChunkAllocation && Verbose) { - tty->print_cr("ChunkManager::free_chunks_get: free_list " - PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, - free_list, chunk, chunk->word_size()); + gclog_or_tty->print_cr("ChunkManager::free_chunks_get: free_list " + PTR_FORMAT " head " PTR_FORMAT " size " SIZE_FORMAT, + free_list, chunk, chunk->word_size()); } } else { chunk = humongous_dictionary()->get_chunk( @@ -1741,10 +1725,10 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { if (chunk != NULL) { if (TraceMetadataHumongousAllocation) { size_t waste = chunk->word_size() - word_size; - tty->print_cr("Free list allocate humongous chunk size " SIZE_FORMAT - " for requested size " SIZE_FORMAT - " waste " SIZE_FORMAT, - chunk->word_size(), word_size, waste); + gclog_or_tty->print_cr("Free list allocate humongous chunk size " + SIZE_FORMAT " for requested size " SIZE_FORMAT + " waste " SIZE_FORMAT, + chunk->word_size(), word_size, waste); } // Chunk is being removed from the chunks free list. dec_free_chunks_total(chunk->capacity_word_size()); @@ -1761,6 +1745,8 @@ Metachunk* ChunkManager::free_chunks_get(size_t word_size) { // work. chunk->set_is_free(false); #endif + chunk->container()->inc_container_count(); + slow_locked_verify(); return chunk; } @@ -1786,18 +1772,18 @@ Metachunk* ChunkManager::chunk_freelist_allocate(size_t word_size) { } else { list_count = humongous_dictionary()->total_count(); } - tty->print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " - PTR_FORMAT " size " SIZE_FORMAT " count " SIZE_FORMAT " ", - this, chunk, chunk->word_size(), list_count); - locked_print_free_chunks(tty); + gclog_or_tty->print("ChunkManager::chunk_freelist_allocate: " PTR_FORMAT " chunk " + PTR_FORMAT " size " SIZE_FORMAT " count " SIZE_FORMAT " ", + this, chunk, chunk->word_size(), list_count); + locked_print_free_chunks(gclog_or_tty); } return chunk; } -void ChunkManager::print_on(outputStream* out) { +void ChunkManager::print_on(outputStream* out) const { if (PrintFLSStatistics != 0) { - humongous_dictionary()->report_statistics(); + const_cast(this)->humongous_dictionary()->report_statistics(); } } @@ -1944,8 +1930,8 @@ void SpaceManager::locked_print_chunks_in_use_on(outputStream* st) const { } } - vs_list()->chunk_manager()->locked_print_free_chunks(st); - vs_list()->chunk_manager()->locked_print_sum_free_chunks(st); + chunk_manager()->locked_print_free_chunks(st); + chunk_manager()->locked_print_sum_free_chunks(st); } size_t SpaceManager::calc_chunk_size(size_t word_size) { @@ -2049,9 +2035,7 @@ void SpaceManager::print_on(outputStream* st) const { } SpaceManager::SpaceManager(Metaspace::MetadataType mdtype, - Mutex* lock, - VirtualSpaceList* vs_list) : - _vs_list(vs_list), + Mutex* lock) : _mdtype(mdtype), _allocated_blocks_words(0), _allocated_chunks_words(0), @@ -2137,9 +2121,7 @@ SpaceManager::~SpaceManager() { MutexLockerEx fcl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); - ChunkManager* chunk_manager = vs_list()->chunk_manager(); - - chunk_manager->slow_locked_verify(); + chunk_manager()->slow_locked_verify(); dec_total_from_size_metrics(); @@ -2153,8 +2135,8 @@ SpaceManager::~SpaceManager() { // Have to update before the chunks_in_use lists are emptied // below. - chunk_manager->inc_free_chunks_total(allocated_chunks_words(), - sum_count_in_chunks_in_use()); + chunk_manager()->inc_free_chunks_total(allocated_chunks_words(), + sum_count_in_chunks_in_use()); // Add all the chunks in use by this space manager // to the global list of free chunks. @@ -2169,11 +2151,11 @@ SpaceManager::~SpaceManager() { chunk_size_name(i)); } Metachunk* chunks = chunks_in_use(i); - chunk_manager->return_chunks(i, chunks); + chunk_manager()->return_chunks(i, chunks); set_chunks_in_use(i, NULL); if (TraceMetadataChunkAllocation && Verbose) { gclog_or_tty->print_cr("updated freelist count %d %s", - chunk_manager->free_chunks(i)->count(), + chunk_manager()->free_chunks(i)->count(), chunk_size_name(i)); } assert(i != HumongousIndex, "Humongous chunks are handled explicitly later"); @@ -2210,16 +2192,16 @@ SpaceManager::~SpaceManager() { humongous_chunks->word_size(), HumongousChunkGranularity)); Metachunk* next_humongous_chunks = humongous_chunks->next(); humongous_chunks->container()->dec_container_count(); - chunk_manager->humongous_dictionary()->return_chunk(humongous_chunks); + chunk_manager()->humongous_dictionary()->return_chunk(humongous_chunks); humongous_chunks = next_humongous_chunks; } if (TraceMetadataChunkAllocation && Verbose) { gclog_or_tty->print_cr(""); gclog_or_tty->print_cr("updated dictionary count %d %s", - chunk_manager->humongous_dictionary()->total_count(), + chunk_manager()->humongous_dictionary()->total_count(), chunk_size_name(HumongousIndex)); } - chunk_manager->slow_locked_verify(); + chunk_manager()->slow_locked_verify(); } const char* SpaceManager::chunk_size_name(ChunkIndex index) const { @@ -2278,6 +2260,7 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { ChunkIndex index = ChunkManager::list_index(new_chunk->word_size()); if (index != HumongousIndex) { + retire_current_chunk(); set_current_chunk(new_chunk); new_chunk->set_next(chunks_in_use(index)); set_chunks_in_use(index, new_chunk); @@ -2307,23 +2290,35 @@ void SpaceManager::add_chunk(Metachunk* new_chunk, bool make_current) { gclog_or_tty->print("SpaceManager::add_chunk: %d) ", sum_count_in_chunks_in_use()); new_chunk->print_on(gclog_or_tty); - if (vs_list() != NULL) { - vs_list()->chunk_manager()->locked_print_free_chunks(tty); + chunk_manager()->locked_print_free_chunks(gclog_or_tty); + } +} + +void SpaceManager::retire_current_chunk() { + if (current_chunk() != NULL) { + size_t remaining_words = current_chunk()->free_word_size(); + if (remaining_words >= TreeChunk::min_size()) { + block_freelists()->return_block(current_chunk()->allocate(remaining_words), remaining_words); + inc_used_metrics(remaining_words); } } } Metachunk* SpaceManager::get_new_chunk(size_t word_size, size_t grow_chunks_by_words) { + // Get a chunk from the chunk freelist + Metachunk* next = chunk_manager()->chunk_freelist_allocate(grow_chunks_by_words); - Metachunk* next = vs_list()->get_new_chunk(word_size, - grow_chunks_by_words, - medium_chunk_bunch()); + if (next == NULL) { + next = vs_list()->get_new_chunk(word_size, + grow_chunks_by_words, + medium_chunk_bunch()); + } - if (TraceMetadataHumongousAllocation && + if (TraceMetadataHumongousAllocation && next != NULL && SpaceManager::is_humongous(next->word_size())) { - gclog_or_tty->print_cr(" new humongous chunk word size " PTR_FORMAT, - next->word_size()); + gclog_or_tty->print_cr(" new humongous chunk word size " + PTR_FORMAT, next->word_size()); } return next; @@ -2441,9 +2436,6 @@ void SpaceManager::dump(outputStream* const out) const { curr = curr->next()) { out->print("%d) ", i++); curr->print_on(out); - if (TraceMetadataChunkAllocation && Verbose) { - block_freelists()->print_on(out); - } curr_total += curr->word_size(); used += curr->used_word_size(); capacity += curr->capacity_word_size(); @@ -2451,6 +2443,10 @@ void SpaceManager::dump(outputStream* const out) const { } } + if (TraceMetadataChunkAllocation && Verbose) { + block_freelists()->print_on(out); + } + size_t free = current_chunk() == NULL ? 0 : current_chunk()->free_word_size(); // Free space isn't wasted. waste -= free; @@ -2538,13 +2534,13 @@ size_t MetaspaceAux::used_bytes_slow(Metaspace::MetadataType mdtype) { return used * BytesPerWord; } -size_t MetaspaceAux::free_in_bytes(Metaspace::MetadataType mdtype) { +size_t MetaspaceAux::free_bytes_slow(Metaspace::MetadataType mdtype) { size_t free = 0; ClassLoaderDataGraphMetaspaceIterator iter; while (iter.repeat()) { Metaspace* msp = iter.get_next(); if (msp != NULL) { - free += msp->free_words(mdtype); + free += msp->free_words_slow(mdtype); } } return free * BytesPerWord; @@ -2567,34 +2563,55 @@ size_t MetaspaceAux::capacity_bytes_slow(Metaspace::MetadataType mdtype) { return capacity * BytesPerWord; } -size_t MetaspaceAux::reserved_in_bytes(Metaspace::MetadataType mdtype) { - VirtualSpaceList* list = Metaspace::get_space_list(mdtype); - return list == NULL ? 0 : list->virtual_space_total(); +size_t MetaspaceAux::capacity_bytes_slow() { +#ifdef PRODUCT + // Use allocated_capacity_bytes() in PRODUCT instead of this function. + guarantee(false, "Should not call capacity_bytes_slow() in the PRODUCT"); +#endif + size_t class_capacity = capacity_bytes_slow(Metaspace::ClassType); + size_t non_class_capacity = capacity_bytes_slow(Metaspace::NonClassType); + assert(allocated_capacity_bytes() == class_capacity + non_class_capacity, + err_msg("bad accounting: allocated_capacity_bytes() " SIZE_FORMAT + " class_capacity + non_class_capacity " SIZE_FORMAT + " class_capacity " SIZE_FORMAT " non_class_capacity " SIZE_FORMAT, + allocated_capacity_bytes(), class_capacity + non_class_capacity, + class_capacity, non_class_capacity)); + + return class_capacity + non_class_capacity; } -size_t MetaspaceAux::min_chunk_size() { return Metaspace::first_chunk_word_size(); } - -size_t MetaspaceAux::free_chunks_total(Metaspace::MetadataType mdtype) { +size_t MetaspaceAux::reserved_bytes(Metaspace::MetadataType mdtype) { VirtualSpaceList* list = Metaspace::get_space_list(mdtype); - if (list == NULL) { + return list == NULL ? 0 : list->reserved_bytes(); +} + +size_t MetaspaceAux::committed_bytes(Metaspace::MetadataType mdtype) { + VirtualSpaceList* list = Metaspace::get_space_list(mdtype); + return list == NULL ? 0 : list->committed_bytes(); +} + +size_t MetaspaceAux::min_chunk_size_words() { return Metaspace::first_chunk_word_size(); } + +size_t MetaspaceAux::free_chunks_total_words(Metaspace::MetadataType mdtype) { + ChunkManager* chunk_manager = Metaspace::get_chunk_manager(mdtype); + if (chunk_manager == NULL) { return 0; } - ChunkManager* chunk = list->chunk_manager(); - chunk->slow_verify(); - return chunk->free_chunks_total(); + chunk_manager->slow_verify(); + return chunk_manager->free_chunks_total_words(); } -size_t MetaspaceAux::free_chunks_total_in_bytes(Metaspace::MetadataType mdtype) { - return free_chunks_total(mdtype) * BytesPerWord; +size_t MetaspaceAux::free_chunks_total_bytes(Metaspace::MetadataType mdtype) { + return free_chunks_total_words(mdtype) * BytesPerWord; } -size_t MetaspaceAux::free_chunks_total() { - return free_chunks_total(Metaspace::ClassType) + - free_chunks_total(Metaspace::NonClassType); +size_t MetaspaceAux::free_chunks_total_words() { + return free_chunks_total_words(Metaspace::ClassType) + + free_chunks_total_words(Metaspace::NonClassType); } -size_t MetaspaceAux::free_chunks_total_in_bytes() { - return free_chunks_total() * BytesPerWord; +size_t MetaspaceAux::free_chunks_total_bytes() { + return free_chunks_total_words() * BytesPerWord; } void MetaspaceAux::print_metaspace_change(size_t prev_metadata_used) { @@ -2605,14 +2622,14 @@ void MetaspaceAux::print_metaspace_change(size_t prev_metadata_used) { "(" SIZE_FORMAT ")", prev_metadata_used, allocated_used_bytes(), - reserved_in_bytes()); + reserved_bytes()); } else { gclog_or_tty->print(" " SIZE_FORMAT "K" "->" SIZE_FORMAT "K" "(" SIZE_FORMAT "K)", - prev_metadata_used / K, - allocated_used_bytes() / K, - reserved_in_bytes()/ K); + prev_metadata_used/K, + allocated_used_bytes()/K, + reserved_bytes()/K); } gclog_or_tty->print("]"); @@ -2625,14 +2642,14 @@ void MetaspaceAux::print_on(outputStream* out) { out->print_cr(" Metaspace total " SIZE_FORMAT "K, used " SIZE_FORMAT "K," " reserved " SIZE_FORMAT "K", - allocated_capacity_bytes()/K, allocated_used_bytes()/K, reserved_in_bytes()/K); + allocated_capacity_bytes()/K, allocated_used_bytes()/K, reserved_bytes()/K); out->print_cr(" data space " SIZE_FORMAT "K, used " SIZE_FORMAT "K," " reserved " SIZE_FORMAT "K", allocated_capacity_bytes(nct)/K, allocated_used_bytes(nct)/K, - reserved_in_bytes(nct)/K); + reserved_bytes(nct)/K); if (Metaspace::using_class_space()) { Metaspace::MetadataType ct = Metaspace::ClassType; out->print_cr(" class space " @@ -2640,17 +2657,17 @@ void MetaspaceAux::print_on(outputStream* out) { " reserved " SIZE_FORMAT "K", allocated_capacity_bytes(ct)/K, allocated_used_bytes(ct)/K, - reserved_in_bytes(ct)/K); + reserved_bytes(ct)/K); } } // Print information for class space and data space separately. // This is almost the same as above. void MetaspaceAux::print_on(outputStream* out, Metaspace::MetadataType mdtype) { - size_t free_chunks_capacity_bytes = free_chunks_total_in_bytes(mdtype); + size_t free_chunks_capacity_bytes = free_chunks_total_bytes(mdtype); size_t capacity_bytes = capacity_bytes_slow(mdtype); size_t used_bytes = used_bytes_slow(mdtype); - size_t free_bytes = free_in_bytes(mdtype); + size_t free_bytes = free_bytes_slow(mdtype); size_t used_and_free = used_bytes + free_bytes + free_chunks_capacity_bytes; out->print_cr(" Chunk accounting: used in chunks " SIZE_FORMAT @@ -2732,9 +2749,9 @@ void MetaspaceAux::dump(outputStream* out) { } void MetaspaceAux::verify_free_chunks() { - Metaspace::space_list()->chunk_manager()->verify(); + Metaspace::chunk_manager_metadata()->verify(); if (Metaspace::using_class_space()) { - Metaspace::class_space_list()->chunk_manager()->verify(); + Metaspace::chunk_manager_class()->verify(); } } @@ -2805,6 +2822,9 @@ Metaspace::~Metaspace() { VirtualSpaceList* Metaspace::_space_list = NULL; VirtualSpaceList* Metaspace::_class_space_list = NULL; +ChunkManager* Metaspace::_chunk_manager_metadata = NULL; +ChunkManager* Metaspace::_chunk_manager_class = NULL; + #define VIRTUALSPACEMULTIPLIER 2 #ifdef _LP64 @@ -2836,7 +2856,7 @@ void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address // to work with compressed klass pointers. bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) { assert(cds_base != 0 && UseSharedSpaces, "Only use with CDS"); - assert(UseCompressedKlassPointers, "Only use with CompressedKlassPtrs"); + assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs"); address lower_base = MIN2((address)metaspace_base, cds_base); address higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()), (address)(metaspace_base + class_metaspace_size())); @@ -2846,7 +2866,7 @@ bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cd // Try to allocate the metaspace at the requested addr. void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) { assert(using_class_space(), "called improperly"); - assert(UseCompressedKlassPointers, "Only use with CompressedKlassPtrs"); + assert(UseCompressedClassPointers, "Only use with CompressedKlassPtrs"); assert(class_metaspace_size() < KlassEncodingMetaspaceMax, "Metaspace size is too big"); @@ -2869,9 +2889,9 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a // If no successful allocation then try to allocate the space anywhere. If // that fails then OOM doom. At this point we cannot try allocating the - // metaspace as if UseCompressedKlassPointers is off because too much - // initialization has happened that depends on UseCompressedKlassPointers. - // So, UseCompressedKlassPointers cannot be turned off at this point. + // metaspace as if UseCompressedClassPointers is off because too much + // initialization has happened that depends on UseCompressedClassPointers. + // So, UseCompressedClassPointers cannot be turned off at this point. if (!metaspace_rs.is_reserved()) { metaspace_rs = ReservedSpace(class_metaspace_size(), os::vm_allocation_granularity(), false); @@ -2904,14 +2924,15 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a } } -// For UseCompressedKlassPointers the class space is reserved above the top of +// For UseCompressedClassPointers the class space is reserved above the top of // the Java heap. The argument passed in is at the base of the compressed space. void Metaspace::initialize_class_space(ReservedSpace rs) { // The reserved space size may be bigger because of alignment, esp with UseLargePages - assert(rs.size() >= ClassMetaspaceSize, - err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), ClassMetaspaceSize)); + assert(rs.size() >= CompressedClassSpaceSize, + err_msg(SIZE_FORMAT " != " UINTX_FORMAT, rs.size(), CompressedClassSpaceSize)); assert(using_class_space(), "Must be using class space"); _class_space_list = new VirtualSpaceList(rs); + _chunk_manager_class = new ChunkManager(SpecializedChunk, ClassSmallChunk, ClassMediumChunk); } #endif @@ -2921,7 +2942,7 @@ void Metaspace::global_initialize() { int max_alignment = os::vm_page_size(); size_t cds_total = 0; - set_class_metaspace_size(align_size_up(ClassMetaspaceSize, + set_class_metaspace_size(align_size_up(CompressedClassSpaceSize, os::vm_allocation_granularity())); MetaspaceShared::set_max_alignment(max_alignment); @@ -2937,12 +2958,13 @@ void Metaspace::global_initialize() { // remainder is the misc code and data chunks. cds_total = FileMapInfo::shared_spaces_size(); _space_list = new VirtualSpaceList(cds_total/wordSize); + _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk); #ifdef _LP64 // Set the compressed klass pointer base so that decoding of these pointers works // properly when creating the shared archive. - assert(UseCompressedOops && UseCompressedKlassPointers, - "UseCompressedOops and UseCompressedKlassPointers must be set"); + assert(UseCompressedOops && UseCompressedClassPointers, + "UseCompressedOops and UseCompressedClassPointers must be set"); Universe::set_narrow_klass_base((address)_space_list->current_virtual_space()->bottom()); if (TraceMetavirtualspaceAllocation && Verbose) { gclog_or_tty->print_cr("Setting_narrow_klass_base to Address: " PTR_FORMAT, @@ -2979,7 +3001,7 @@ void Metaspace::global_initialize() { } #ifdef _LP64 - // If UseCompressedKlassPointers is set then allocate the metaspace area + // If UseCompressedClassPointers is set then allocate the metaspace area // above the heap and above the CDS area (if it exists). if (using_class_space()) { if (UseSharedSpaces) { @@ -2997,22 +3019,37 @@ void Metaspace::global_initialize() { // on the medium chunk list. The next chunk will be small and progress // from there. This size calculated by -version. _first_class_chunk_word_size = MIN2((size_t)MediumChunk*6, - (ClassMetaspaceSize/BytesPerWord)*2); + (CompressedClassSpaceSize/BytesPerWord)*2); _first_class_chunk_word_size = align_word_size_up(_first_class_chunk_word_size); // Arbitrarily set the initial virtual space to a multiple // of the boot class loader size. size_t word_size = VIRTUALSPACEMULTIPLIER * first_chunk_word_size(); // Initialize the list of virtual spaces. _space_list = new VirtualSpaceList(word_size); + _chunk_manager_metadata = new ChunkManager(SpecializedChunk, SmallChunk, MediumChunk); } } +Metachunk* Metaspace::get_initialization_chunk(MetadataType mdtype, + size_t chunk_word_size, + size_t chunk_bunch) { + // Get a chunk from the chunk freelist + Metachunk* chunk = get_chunk_manager(mdtype)->chunk_freelist_allocate(chunk_word_size); + if (chunk != NULL) { + return chunk; + } + + return get_space_list(mdtype)->get_initialization_chunk(chunk_word_size, chunk_bunch); +} + void Metaspace::initialize(Mutex* lock, MetaspaceType type) { assert(space_list() != NULL, "Metadata VirtualSpaceList has not been initialized"); + assert(chunk_manager_metadata() != NULL, + "Metadata ChunkManager has not been initialized"); - _vsm = new SpaceManager(NonClassType, lock, space_list()); + _vsm = new SpaceManager(NonClassType, lock); if (_vsm == NULL) { return; } @@ -3021,11 +3058,13 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) { vsm()->get_initial_chunk_sizes(type, &word_size, &class_word_size); if (using_class_space()) { - assert(class_space_list() != NULL, - "Class VirtualSpaceList has not been initialized"); + assert(class_space_list() != NULL, + "Class VirtualSpaceList has not been initialized"); + assert(chunk_manager_class() != NULL, + "Class ChunkManager has not been initialized"); // Allocate SpaceManager for classes. - _class_vsm = new SpaceManager(ClassType, lock, class_space_list()); + _class_vsm = new SpaceManager(ClassType, lock); if (_class_vsm == NULL) { return; } @@ -3034,9 +3073,9 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) { MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); // Allocate chunk for metadata objects - Metachunk* new_chunk = - space_list()->get_initialization_chunk(word_size, - vsm()->medium_chunk_bunch()); + Metachunk* new_chunk = get_initialization_chunk(NonClassType, + word_size, + vsm()->medium_chunk_bunch()); assert(!DumpSharedSpaces || new_chunk != NULL, "should have enough space for both chunks"); if (new_chunk != NULL) { // Add to this manager's list of chunks in use and current_chunk(). @@ -3045,9 +3084,9 @@ void Metaspace::initialize(Mutex* lock, MetaspaceType type) { // Allocate chunk for class metadata objects if (using_class_space()) { - Metachunk* class_chunk = - class_space_list()->get_initialization_chunk(class_word_size, - class_vsm()->medium_chunk_bunch()); + Metachunk* class_chunk = get_initialization_chunk(ClassType, + class_word_size, + class_vsm()->medium_chunk_bunch()); if (class_chunk != NULL) { class_vsm()->add_chunk(class_chunk, true); } @@ -3064,7 +3103,7 @@ size_t Metaspace::align_word_size_up(size_t word_size) { MetaWord* Metaspace::allocate(size_t word_size, MetadataType mdtype) { // DumpSharedSpaces doesn't use class metadata area (yet) - // Also, don't use class_vsm() unless UseCompressedKlassPointers is true. + // Also, don't use class_vsm() unless UseCompressedClassPointers is true. if (mdtype == ClassType && using_class_space()) { return class_vsm()->allocate(word_size); } else { @@ -3103,7 +3142,7 @@ size_t Metaspace::used_words_slow(MetadataType mdtype) const { } } -size_t Metaspace::free_words(MetadataType mdtype) const { +size_t Metaspace::free_words_slow(MetadataType mdtype) const { if (mdtype == ClassType) { return using_class_space() ? class_vsm()->sum_free_in_chunks_in_use() : 0; } else { @@ -3213,7 +3252,7 @@ Metablock* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size, MetaspaceAux::dump(gclog_or_tty); } // -XX:+HeapDumpOnOutOfMemoryError and -XX:OnOutOfMemoryError support - const char* space_string = (mdtype == ClassType) ? "Class Metadata space" : + const char* space_string = (mdtype == ClassType) ? "Compressed class space" : "Metadata space"; report_java_out_of_memory(space_string); @@ -3264,12 +3303,16 @@ void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) { } } +void Metaspace::purge(MetadataType mdtype) { + get_space_list(mdtype)->purge(get_chunk_manager(mdtype)); +} + void Metaspace::purge() { MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); - space_list()->purge(); + purge(NonClassType); if (using_class_space()) { - class_space_list()->purge(); + purge(ClassType); } } @@ -3311,3 +3354,70 @@ void Metaspace::dump(outputStream* const out) const { class_vsm()->dump(out); } } + +/////////////// Unit tests /////////////// + +#ifndef PRODUCT + +class TestMetaspaceAuxTest : AllStatic { + public: + static void test_reserved() { + size_t reserved = MetaspaceAux::reserved_bytes(); + + assert(reserved > 0, "assert"); + + size_t committed = MetaspaceAux::committed_bytes(); + assert(committed <= reserved, "assert"); + + size_t reserved_metadata = MetaspaceAux::reserved_bytes(Metaspace::NonClassType); + assert(reserved_metadata > 0, "assert"); + assert(reserved_metadata <= reserved, "assert"); + + if (UseCompressedClassPointers) { + size_t reserved_class = MetaspaceAux::reserved_bytes(Metaspace::ClassType); + assert(reserved_class > 0, "assert"); + assert(reserved_class < reserved, "assert"); + } + } + + static void test_committed() { + size_t committed = MetaspaceAux::committed_bytes(); + + assert(committed > 0, "assert"); + + size_t reserved = MetaspaceAux::reserved_bytes(); + assert(committed <= reserved, "assert"); + + size_t committed_metadata = MetaspaceAux::committed_bytes(Metaspace::NonClassType); + assert(committed_metadata > 0, "assert"); + assert(committed_metadata <= committed, "assert"); + + if (UseCompressedClassPointers) { + size_t committed_class = MetaspaceAux::committed_bytes(Metaspace::ClassType); + assert(committed_class > 0, "assert"); + assert(committed_class < committed, "assert"); + } + } + + static void test_virtual_space_list_large_chunk() { + VirtualSpaceList* vs_list = new VirtualSpaceList(os::vm_allocation_granularity()); + MutexLockerEx cl(SpaceManager::expand_lock(), Mutex::_no_safepoint_check_flag); + // A size larger than VirtualSpaceSize (256k) and add one page to make it _not_ be + // vm_allocation_granularity aligned on Windows. + size_t large_size = (size_t)(2*256*K + (os::vm_page_size()/BytesPerWord)); + large_size += (os::vm_page_size()/BytesPerWord); + vs_list->get_new_chunk(large_size, large_size, 0); + } + + static void test() { + test_reserved(); + test_committed(); + test_virtual_space_list_large_chunk(); + } +}; + +void TestMetaspaceAux_test() { + TestMetaspaceAuxTest::test(); +} + +#endif diff --git a/hotspot/src/share/vm/memory/metaspace.hpp b/hotspot/src/share/vm/memory/metaspace.hpp index 88f089494d3..29c07e15179 100644 --- a/hotspot/src/share/vm/memory/metaspace.hpp +++ b/hotspot/src/share/vm/memory/metaspace.hpp @@ -56,12 +56,15 @@ // +-------------------+ // +class ChunkManager; class ClassLoaderData; class Metablock; +class Metachunk; class MetaWord; class Mutex; class outputStream; class SpaceManager; +class VirtualSpaceList; // Metaspaces each have a SpaceManager and allocations // are done by the SpaceManager. Allocations are done @@ -76,8 +79,6 @@ class SpaceManager; // allocate() method returns a block for use as a // quantum of metadata. -class VirtualSpaceList; - class Metaspace : public CHeapObj { friend class VMStructs; friend class SpaceManager; @@ -102,6 +103,10 @@ class Metaspace : public CHeapObj { private: void initialize(Mutex* lock, MetaspaceType type); + Metachunk* get_initialization_chunk(MetadataType mdtype, + size_t chunk_word_size, + size_t chunk_bunch); + // Align up the word size to the allocation word size static size_t align_word_size_up(size_t); @@ -134,6 +139,10 @@ class Metaspace : public CHeapObj { static VirtualSpaceList* _space_list; static VirtualSpaceList* _class_space_list; + static ChunkManager* _chunk_manager_metadata; + static ChunkManager* _chunk_manager_class; + + public: static VirtualSpaceList* space_list() { return _space_list; } static VirtualSpaceList* class_space_list() { return _class_space_list; } static VirtualSpaceList* get_space_list(MetadataType mdtype) { @@ -141,6 +150,14 @@ class Metaspace : public CHeapObj { return mdtype == ClassType ? class_space_list() : space_list(); } + static ChunkManager* chunk_manager_metadata() { return _chunk_manager_metadata; } + static ChunkManager* chunk_manager_class() { return _chunk_manager_class; } + static ChunkManager* get_chunk_manager(MetadataType mdtype) { + assert(mdtype != MetadataTypeCount, "MetadaTypeCount can't be used as mdtype"); + return mdtype == ClassType ? chunk_manager_class() : chunk_manager_metadata(); + } + + private: // This is used by DumpSharedSpaces only, where only _vsm is used. So we will // maintain a single list for now. void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size); @@ -182,9 +199,8 @@ class Metaspace : public CHeapObj { char* bottom() const; size_t used_words_slow(MetadataType mdtype) const; - size_t free_words(MetadataType mdtype) const; + size_t free_words_slow(MetadataType mdtype) const; size_t capacity_words_slow(MetadataType mdtype) const; - size_t waste_words(MetadataType mdtype) const; size_t used_bytes_slow(MetadataType mdtype) const; size_t capacity_bytes_slow(MetadataType mdtype) const; @@ -200,6 +216,7 @@ class Metaspace : public CHeapObj { void dump(outputStream* const out) const; // Free empty virtualspaces + static void purge(MetadataType mdtype); static void purge(); void print_on(outputStream* st) const; @@ -213,27 +230,22 @@ class Metaspace : public CHeapObj { void iterate(AllocRecordClosure *closure); - // Return TRUE only if UseCompressedKlassPointers is True and DumpSharedSpaces is False. + // Return TRUE only if UseCompressedClassPointers is True and DumpSharedSpaces is False. static bool using_class_space() { - return NOT_LP64(false) LP64_ONLY(UseCompressedKlassPointers && !DumpSharedSpaces); + return NOT_LP64(false) LP64_ONLY(UseCompressedClassPointers && !DumpSharedSpaces); } }; class MetaspaceAux : AllStatic { - static size_t free_chunks_total(Metaspace::MetadataType mdtype); - - public: - // Statistics for class space and data space in metaspace. + static size_t free_chunks_total_words(Metaspace::MetadataType mdtype); // These methods iterate over the classloader data graph // for the given Metaspace type. These are slow. static size_t used_bytes_slow(Metaspace::MetadataType mdtype); - static size_t free_in_bytes(Metaspace::MetadataType mdtype); + static size_t free_bytes_slow(Metaspace::MetadataType mdtype); static size_t capacity_bytes_slow(Metaspace::MetadataType mdtype); - - // Iterates over the virtual space list. - static size_t reserved_in_bytes(Metaspace::MetadataType mdtype); + static size_t capacity_bytes_slow(); // Running sum of space in all Metachunks that has been // allocated to a Metaspace. This is used instead of @@ -263,17 +275,16 @@ class MetaspaceAux : AllStatic { } // Used by MetaspaceCounters - static size_t free_chunks_total(); - static size_t free_chunks_total_in_bytes(); - static size_t free_chunks_total_in_bytes(Metaspace::MetadataType mdtype); + static size_t free_chunks_total_words(); + static size_t free_chunks_total_bytes(); + static size_t free_chunks_total_bytes(Metaspace::MetadataType mdtype); static size_t allocated_capacity_words(Metaspace::MetadataType mdtype) { return _allocated_capacity_words[mdtype]; } static size_t allocated_capacity_words() { - return _allocated_capacity_words[Metaspace::NonClassType] + - (Metaspace::using_class_space() ? - _allocated_capacity_words[Metaspace::ClassType] : 0); + return allocated_capacity_words(Metaspace::NonClassType) + + allocated_capacity_words(Metaspace::ClassType); } static size_t allocated_capacity_bytes(Metaspace::MetadataType mdtype) { return allocated_capacity_words(mdtype) * BytesPerWord; @@ -286,9 +297,8 @@ class MetaspaceAux : AllStatic { return _allocated_used_words[mdtype]; } static size_t allocated_used_words() { - return _allocated_used_words[Metaspace::NonClassType] + - (Metaspace::using_class_space() ? - _allocated_used_words[Metaspace::ClassType] : 0); + return allocated_used_words(Metaspace::NonClassType) + + allocated_used_words(Metaspace::ClassType); } static size_t allocated_used_bytes(Metaspace::MetadataType mdtype) { return allocated_used_words(mdtype) * BytesPerWord; @@ -300,31 +310,22 @@ class MetaspaceAux : AllStatic { static size_t free_bytes(); static size_t free_bytes(Metaspace::MetadataType mdtype); - // Total capacity in all Metaspaces - static size_t capacity_bytes_slow() { -#ifdef PRODUCT - // Use allocated_capacity_bytes() in PRODUCT instead of this function. - guarantee(false, "Should not call capacity_bytes_slow() in the PRODUCT"); -#endif - size_t class_capacity = capacity_bytes_slow(Metaspace::ClassType); - size_t non_class_capacity = capacity_bytes_slow(Metaspace::NonClassType); - assert(allocated_capacity_bytes() == class_capacity + non_class_capacity, - err_msg("bad accounting: allocated_capacity_bytes() " SIZE_FORMAT - " class_capacity + non_class_capacity " SIZE_FORMAT - " class_capacity " SIZE_FORMAT " non_class_capacity " SIZE_FORMAT, - allocated_capacity_bytes(), class_capacity + non_class_capacity, - class_capacity, non_class_capacity)); - - return class_capacity + non_class_capacity; + static size_t reserved_bytes(Metaspace::MetadataType mdtype); + static size_t reserved_bytes() { + return reserved_bytes(Metaspace::ClassType) + + reserved_bytes(Metaspace::NonClassType); } - // Total space reserved in all Metaspaces - static size_t reserved_in_bytes() { - return reserved_in_bytes(Metaspace::ClassType) + - reserved_in_bytes(Metaspace::NonClassType); + static size_t committed_bytes(Metaspace::MetadataType mdtype); + static size_t committed_bytes() { + return committed_bytes(Metaspace::ClassType) + + committed_bytes(Metaspace::NonClassType); } - static size_t min_chunk_size(); + static size_t min_chunk_size_words(); + static size_t min_chunk_size_bytes() { + return min_chunk_size_words() * BytesPerWord; + } // Print change in used metadata. static void print_metaspace_change(size_t prev_metadata_used); diff --git a/hotspot/src/share/vm/memory/metaspaceCounters.cpp b/hotspot/src/share/vm/memory/metaspaceCounters.cpp index eb7bebd28b6..60e26b8c714 100644 --- a/hotspot/src/share/vm/memory/metaspaceCounters.cpp +++ b/hotspot/src/share/vm/memory/metaspaceCounters.cpp @@ -65,26 +65,25 @@ class MetaspacePerfCounters: public CHeapObj { MetaspacePerfCounters* MetaspaceCounters::_perf_counters = NULL; -size_t MetaspaceCounters::calculate_capacity() { - // The total capacity is the sum of - // 1) capacity of Metachunks in use by all Metaspaces - // 2) unused space at the end of each Metachunk - // 3) space in the freelist - size_t total_capacity = MetaspaceAux::allocated_capacity_bytes() - + MetaspaceAux::free_bytes() + MetaspaceAux::free_chunks_total_in_bytes(); - return total_capacity; +size_t MetaspaceCounters::used() { + return MetaspaceAux::allocated_used_bytes(); +} + +size_t MetaspaceCounters::capacity() { + return MetaspaceAux::committed_bytes(); +} + +size_t MetaspaceCounters::max_capacity() { + return MetaspaceAux::reserved_bytes(); } void MetaspaceCounters::initialize_performance_counters() { if (UsePerfData) { assert(_perf_counters == NULL, "Should only be initialized once"); - size_t min_capacity = MetaspaceAux::min_chunk_size(); - size_t capacity = calculate_capacity(); - size_t max_capacity = MetaspaceAux::reserved_in_bytes(); - size_t used = MetaspaceAux::allocated_used_bytes(); - - _perf_counters = new MetaspacePerfCounters("metaspace", min_capacity, capacity, max_capacity, used); + size_t min_capacity = 0; + _perf_counters = new MetaspacePerfCounters("metaspace", min_capacity, + capacity(), max_capacity(), used()); } } @@ -92,31 +91,29 @@ void MetaspaceCounters::update_performance_counters() { if (UsePerfData) { assert(_perf_counters != NULL, "Should be initialized"); - size_t capacity = calculate_capacity(); - size_t max_capacity = MetaspaceAux::reserved_in_bytes(); - size_t used = MetaspaceAux::allocated_used_bytes(); - - _perf_counters->update(capacity, max_capacity, used); + _perf_counters->update(capacity(), max_capacity(), used()); } } MetaspacePerfCounters* CompressedClassSpaceCounters::_perf_counters = NULL; -size_t CompressedClassSpaceCounters::calculate_capacity() { - return MetaspaceAux::allocated_capacity_bytes(_class_type) + - MetaspaceAux::free_bytes(_class_type) + - MetaspaceAux::free_chunks_total_in_bytes(_class_type); +size_t CompressedClassSpaceCounters::used() { + return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); +} + +size_t CompressedClassSpaceCounters::capacity() { + return MetaspaceAux::committed_bytes(Metaspace::ClassType); +} + +size_t CompressedClassSpaceCounters::max_capacity() { + return MetaspaceAux::reserved_bytes(Metaspace::ClassType); } void CompressedClassSpaceCounters::update_performance_counters() { - if (UsePerfData && UseCompressedKlassPointers) { + if (UsePerfData && UseCompressedClassPointers) { assert(_perf_counters != NULL, "Should be initialized"); - size_t capacity = calculate_capacity(); - size_t max_capacity = MetaspaceAux::reserved_in_bytes(_class_type); - size_t used = MetaspaceAux::allocated_used_bytes(_class_type); - - _perf_counters->update(capacity, max_capacity, used); + _perf_counters->update(capacity(), max_capacity(), used()); } } @@ -125,13 +122,10 @@ void CompressedClassSpaceCounters::initialize_performance_counters() { assert(_perf_counters == NULL, "Should only be initialized once"); const char* ns = "compressedclassspace"; - if (UseCompressedKlassPointers) { - size_t min_capacity = MetaspaceAux::min_chunk_size(); - size_t capacity = calculate_capacity(); - size_t max_capacity = MetaspaceAux::reserved_in_bytes(_class_type); - size_t used = MetaspaceAux::allocated_used_bytes(_class_type); - - _perf_counters = new MetaspacePerfCounters(ns, min_capacity, capacity, max_capacity, used); + if (UseCompressedClassPointers) { + size_t min_capacity = 0; + _perf_counters = new MetaspacePerfCounters(ns, min_capacity, capacity(), + max_capacity(), used()); } else { _perf_counters = new MetaspacePerfCounters(ns, 0, 0, 0, 0); } diff --git a/hotspot/src/share/vm/memory/metaspaceCounters.hpp b/hotspot/src/share/vm/memory/metaspaceCounters.hpp index 5b481d59b4d..0fa991291a1 100644 --- a/hotspot/src/share/vm/memory/metaspaceCounters.hpp +++ b/hotspot/src/share/vm/memory/metaspaceCounters.hpp @@ -25,13 +25,15 @@ #ifndef SHARE_VM_MEMORY_METASPACECOUNTERS_HPP #define SHARE_VM_MEMORY_METASPACECOUNTERS_HPP -#include "memory/metaspace.hpp" +#include "memory/allocation.hpp" class MetaspacePerfCounters; class MetaspaceCounters: public AllStatic { static MetaspacePerfCounters* _perf_counters; - static size_t calculate_capacity(); + static size_t used(); + static size_t capacity(); + static size_t max_capacity(); public: static void initialize_performance_counters(); @@ -40,8 +42,9 @@ class MetaspaceCounters: public AllStatic { class CompressedClassSpaceCounters: public AllStatic { static MetaspacePerfCounters* _perf_counters; - static size_t calculate_capacity(); - static const Metaspace::MetadataType _class_type = Metaspace::ClassType; + static size_t used(); + static size_t capacity(); + static size_t max_capacity(); public: static void initialize_performance_counters(); diff --git a/hotspot/src/share/vm/memory/metaspaceShared.cpp b/hotspot/src/share/vm/memory/metaspaceShared.cpp index 2a9873957a8..ef51c926662 100644 --- a/hotspot/src/share/vm/memory/metaspaceShared.cpp +++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp @@ -103,9 +103,10 @@ static void calculate_fingerprints() { if (k->oop_is_instance()) { InstanceKlass* ik = InstanceKlass::cast(k); for (int i = 0; i < ik->methods()->length(); i++) { - ResourceMark rm; Method* m = ik->methods()->at(i); - (new Fingerprinter(m))->fingerprint(); + Fingerprinter fp(m); + // The side effect of this call sets method's fingerprint field. + fp.fingerprint(); } } } diff --git a/hotspot/src/share/vm/memory/universe.cpp b/hotspot/src/share/vm/memory/universe.cpp index 143c0c00c45..1f632ae478f 100644 --- a/hotspot/src/share/vm/memory/universe.cpp +++ b/hotspot/src/share/vm/memory/universe.cpp @@ -602,7 +602,7 @@ oop Universe::gen_out_of_memory_error(oop default_err) { } } -static intptr_t non_oop_bits = 0; +intptr_t Universe::_non_oop_bits = 0; void* Universe::non_oop_word() { // Neither the high bits nor the low bits of this value is allowed @@ -616,11 +616,11 @@ void* Universe::non_oop_word() { // Using the OS-supplied non-memory-address word (usually 0 or -1) // will take care of the high bits, however many there are. - if (non_oop_bits == 0) { - non_oop_bits = (intptr_t)os::non_memory_address_word() | 1; + if (_non_oop_bits == 0) { + _non_oop_bits = (intptr_t)os::non_memory_address_word() | 1; } - return (void*)non_oop_bits; + return (void*)_non_oop_bits; } jint universe_init() { @@ -872,13 +872,16 @@ jint Universe::initialize_heap() { // Reserve the Java heap, which is now the same for all GCs. ReservedSpace Universe::reserve_heap(size_t heap_size, size_t alignment) { + assert(alignment <= Arguments::conservative_max_heap_alignment(), + err_msg("actual alignment "SIZE_FORMAT" must be within maximum heap alignment "SIZE_FORMAT, + alignment, Arguments::conservative_max_heap_alignment())); size_t total_reserved = align_size_up(heap_size, alignment); assert(!UseCompressedOops || (total_reserved <= (OopEncodingHeapMax - os::vm_page_size())), "heap size is too big for compressed oops"); bool use_large_pages = UseLargePages && is_size_aligned(alignment, os::large_page_size()); assert(!UseLargePages - || UseParallelOldGC + || UseParallelGC || use_large_pages, "Wrong alignment to use large pages"); char* addr = Universe::preferred_heap_base(total_reserved, alignment, Universe::UnscaledNarrowOop); @@ -1028,7 +1031,7 @@ bool universe_post_init() { msg = java_lang_String::create_from_str("Metadata space", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_metaspace, msg()); - msg = java_lang_String::create_from_str("Class Metadata space", CHECK_false); + msg = java_lang_String::create_from_str("Compressed class space", CHECK_false); java_lang_Throwable::set_message(Universe::_out_of_memory_error_class_metaspace, msg()); msg = java_lang_String::create_from_str("Requested array size exceeds VM limit", CHECK_false); diff --git a/hotspot/src/share/vm/memory/universe.hpp b/hotspot/src/share/vm/memory/universe.hpp index a8b541d03a1..a891d2a11ce 100644 --- a/hotspot/src/share/vm/memory/universe.hpp +++ b/hotspot/src/share/vm/memory/universe.hpp @@ -179,9 +179,11 @@ class Universe: AllStatic { // The particular choice of collected heap. static CollectedHeap* _collectedHeap; + static intptr_t _non_oop_bits; + // For UseCompressedOops. static struct NarrowPtrStruct _narrow_oop; - // For UseCompressedKlassPointers. + // For UseCompressedClassPointers. static struct NarrowPtrStruct _narrow_klass; static address _narrow_ptrs_base; @@ -229,7 +231,7 @@ class Universe: AllStatic { _narrow_oop._base = base; } static void set_narrow_klass_base(address base) { - assert(UseCompressedKlassPointers, "no compressed klass ptrs?"); + assert(UseCompressedClassPointers, "no compressed klass ptrs?"); _narrow_klass._base = base; } static void set_narrow_oop_use_implicit_null_checks(bool use) { @@ -353,7 +355,7 @@ class Universe: AllStatic { static int narrow_oop_shift() { return _narrow_oop._shift; } static bool narrow_oop_use_implicit_null_checks() { return _narrow_oop._use_implicit_null_checks; } - // For UseCompressedKlassPointers + // For UseCompressedClassPointers static address narrow_klass_base() { return _narrow_klass._base; } static bool is_narrow_klass_base(void* addr) { return (narrow_klass_base() == (address)addr); } static int narrow_klass_shift() { return _narrow_klass._shift; } diff --git a/hotspot/src/share/vm/oops/arrayOop.hpp b/hotspot/src/share/vm/oops/arrayOop.hpp index 806b7b7289a..0e5ceffe35a 100644 --- a/hotspot/src/share/vm/oops/arrayOop.hpp +++ b/hotspot/src/share/vm/oops/arrayOop.hpp @@ -65,7 +65,7 @@ class arrayOopDesc : public oopDesc { // declared nonstatic fields in arrayOopDesc if not compressed, otherwise // it occupies the second half of the _klass field in oopDesc. static int length_offset_in_bytes() { - return UseCompressedKlassPointers ? klass_gap_offset_in_bytes() : + return UseCompressedClassPointers ? klass_gap_offset_in_bytes() : sizeof(arrayOopDesc); } diff --git a/hotspot/src/share/vm/oops/constantPool.cpp b/hotspot/src/share/vm/oops/constantPool.cpp index 8033d7e3850..66493a879e1 100644 --- a/hotspot/src/share/vm/oops/constantPool.cpp +++ b/hotspot/src/share/vm/oops/constantPool.cpp @@ -108,16 +108,16 @@ objArrayOop ConstantPool::resolved_references() const { void ConstantPool::initialize_resolved_references(ClassLoaderData* loader_data, intStack reference_map, int constant_pool_map_length, - TRAPS) { + TRAPS) { // Initialized the resolved object cache. int map_length = reference_map.length(); if (map_length > 0) { // Only need mapping back to constant pool entries. The map isn't used for - // invokedynamic resolved_reference entries. The constant pool cache index - // has the mapping back to both the constant pool and to the resolved - // reference index. + // invokedynamic resolved_reference entries. For invokedynamic entries, + // the constant pool cache index has the mapping back to both the constant + // pool and to the resolved reference index. if (constant_pool_map_length > 0) { - Array* om = MetadataFactory::new_array(loader_data, map_length, CHECK); + Array* om = MetadataFactory::new_array(loader_data, constant_pool_map_length, CHECK); for (int i = 0; i < constant_pool_map_length; i++) { int x = reference_map.at(i); @@ -182,16 +182,9 @@ oop ConstantPool::lock() { int ConstantPool::cp_to_object_index(int cp_index) { // this is harder don't do this so much. - for (int i = 0; i< reference_map()->length(); i++) { - if (reference_map()->at(i) == cp_index) return i; - // Zero entry is divider between constant pool indices for strings, - // method handles and method types. After that the index is a constant - // pool cache index for invokedynamic. Stop when zero (which can never - // be a constant pool index) - if (reference_map()->at(i) == 0) break; - } - // We might not find the index. - return _no_index_sentinel; + int i = reference_map()->find(cp_index); + // We might not find the index for jsr292 call. + return (i < 0) ? _no_index_sentinel : i; } Klass* ConstantPool::klass_at_impl(constantPoolHandle this_oop, int which, TRAPS) { @@ -396,32 +389,6 @@ Klass* ConstantPool::klass_ref_at_if_loaded(constantPoolHandle this_oop, int whi } -// This is an interface for the compiler that allows accessing non-resolved entries -// in the constant pool - but still performs the validations tests. Must be used -// in a pre-parse of the compiler - to determine what it can do and not do. -// Note: We cannot update the ConstantPool from the vm_thread. -Klass* ConstantPool::klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int index, TRAPS) { - int which = this_oop->klass_ref_index_at(index); - CPSlot entry = this_oop->slot_at(which); - if (entry.is_resolved()) { - assert(entry.get_klass()->is_klass(), "must be"); - return entry.get_klass(); - } else { - assert(entry.is_unresolved(), "must be either symbol or klass"); - Symbol* name = entry.get_symbol(); - oop loader = this_oop->pool_holder()->class_loader(); - oop protection_domain = this_oop->pool_holder()->protection_domain(); - Handle h_loader(THREAD, loader); - Handle h_prot (THREAD, protection_domain); - KlassHandle k(THREAD, SystemDictionary::find(name, h_loader, h_prot, THREAD)); - - // Do access check for klasses - if( k.not_null() ) verify_constant_pool_resolve(this_oop, k, CHECK_NULL); - return k(); - } -} - - Method* ConstantPool::method_at_if_loaded(constantPoolHandle cpool, int which) { if (cpool->cache() == NULL) return NULL; // nothing to load yet @@ -866,8 +833,7 @@ oop ConstantPool::string_at_impl(constantPoolHandle this_oop, int which, int obj // If the string has already been interned, this entry will be non-null oop str = this_oop->resolved_references()->obj_at(obj_index); if (str != NULL) return str; - - Symbol* sym = this_oop->unresolved_string_at(which); + Symbol* sym = this_oop->unresolved_string_at(which); str = StringTable::intern(sym, CHECK_(NULL)); this_oop->string_at_put(which, obj_index, str); assert(java_lang_String::is_instance(str), "must be string"); @@ -1645,9 +1611,11 @@ jint ConstantPool::cpool_entry_size(jint idx) { case JVM_CONSTANT_UnresolvedClassInError: case JVM_CONSTANT_StringIndex: case JVM_CONSTANT_MethodType: + case JVM_CONSTANT_MethodTypeInError: return 3; case JVM_CONSTANT_MethodHandle: + case JVM_CONSTANT_MethodHandleInError: return 4; //tag, ref_kind, ref_index case JVM_CONSTANT_Integer: @@ -1828,8 +1796,8 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodHandle: case JVM_CONSTANT_MethodHandleInError: { *bytes = JVM_CONSTANT_MethodHandle; - int kind = method_handle_ref_kind_at(idx); - idx1 = method_handle_index_at(idx); + int kind = method_handle_ref_kind_at_error_ok(idx); + idx1 = method_handle_index_at_error_ok(idx); *(bytes+1) = (unsigned char) kind; Bytes::put_Java_u2((address) (bytes+2), idx1); DBG(printf("JVM_CONSTANT_MethodHandle: %d %hd", kind, idx1)); @@ -1838,7 +1806,7 @@ int ConstantPool::copy_cpool_bytes(int cpool_size, case JVM_CONSTANT_MethodType: case JVM_CONSTANT_MethodTypeInError: { *bytes = JVM_CONSTANT_MethodType; - idx1 = method_type_index_at(idx); + idx1 = method_type_index_at_error_ok(idx); Bytes::put_Java_u2((address) (bytes+1), idx1); DBG(printf("JVM_CONSTANT_MethodType: %hd", idx1)); break; @@ -2026,12 +1994,12 @@ void ConstantPool::print_entry_on(const int index, outputStream* st) { break; case JVM_CONSTANT_MethodHandle : case JVM_CONSTANT_MethodHandleInError : - st->print("ref_kind=%d", method_handle_ref_kind_at(index)); - st->print(" ref_index=%d", method_handle_index_at(index)); + st->print("ref_kind=%d", method_handle_ref_kind_at_error_ok(index)); + st->print(" ref_index=%d", method_handle_index_at_error_ok(index)); break; case JVM_CONSTANT_MethodType : case JVM_CONSTANT_MethodTypeInError : - st->print("signature_index=%d", method_type_index_at(index)); + st->print("signature_index=%d", method_type_index_at_error_ok(index)); break; case JVM_CONSTANT_InvokeDynamic : { diff --git a/hotspot/src/share/vm/oops/constantPool.hpp b/hotspot/src/share/vm/oops/constantPool.hpp index eca2dcd9c56..47a51a835e2 100644 --- a/hotspot/src/share/vm/oops/constantPool.hpp +++ b/hotspot/src/share/vm/oops/constantPool.hpp @@ -231,7 +231,6 @@ class ConstantPool : public Metadata { static int cache_offset_in_bytes() { return offset_of(ConstantPool, _cache); } static int pool_holder_offset_in_bytes() { return offset_of(ConstantPool, _pool_holder); } static int resolved_references_offset_in_bytes() { return offset_of(ConstantPool, _resolved_references); } - static int reference_map_offset_in_bytes() { return offset_of(ConstantPool, _reference_map); } // Storing constants @@ -475,18 +474,42 @@ class ConstantPool : public Metadata { return *int_at_addr(which); } - int method_handle_ref_kind_at(int which) { - assert(tag_at(which).is_method_handle(), "Corrupted constant pool"); + private: + int method_handle_ref_kind_at(int which, bool error_ok) { + assert(tag_at(which).is_method_handle() || + (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); return extract_low_short_from_int(*int_at_addr(which)); // mask out unwanted ref_index bits } - int method_handle_index_at(int which) { - assert(tag_at(which).is_method_handle(), "Corrupted constant pool"); + int method_handle_index_at(int which, bool error_ok) { + assert(tag_at(which).is_method_handle() || + (error_ok && tag_at(which).is_method_handle_in_error()), "Corrupted constant pool"); return extract_high_short_from_int(*int_at_addr(which)); // shift out unwanted ref_kind bits } - int method_type_index_at(int which) { - assert(tag_at(which).is_method_type(), "Corrupted constant pool"); + int method_type_index_at(int which, bool error_ok) { + assert(tag_at(which).is_method_type() || + (error_ok && tag_at(which).is_method_type_in_error()), "Corrupted constant pool"); return *int_at_addr(which); } + public: + int method_handle_ref_kind_at(int which) { + return method_handle_ref_kind_at(which, false); + } + int method_handle_ref_kind_at_error_ok(int which) { + return method_handle_ref_kind_at(which, true); + } + int method_handle_index_at(int which) { + return method_handle_index_at(which, false); + } + int method_handle_index_at_error_ok(int which) { + return method_handle_index_at(which, true); + } + int method_type_index_at(int which) { + return method_type_index_at(which, false); + } + int method_type_index_at_error_ok(int which) { + return method_type_index_at(which, true); + } + // Derived queries: Symbol* method_handle_name_ref_at(int which) { int member = method_handle_index_at(which); @@ -730,8 +753,6 @@ class ConstantPool : public Metadata { static oop method_type_at_if_loaded (constantPoolHandle this_oop, int which); static Klass* klass_at_if_loaded (constantPoolHandle this_oop, int which); static Klass* klass_ref_at_if_loaded (constantPoolHandle this_oop, int which); - // Same as above - but does LinkResolving. - static Klass* klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS); // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the // future by other Java code. These take constant pool indices rather than diff --git a/hotspot/src/share/vm/oops/cpCache.cpp b/hotspot/src/share/vm/oops/cpCache.cpp index 9e2b83c2caf..9d358955025 100644 --- a/hotspot/src/share/vm/oops/cpCache.cpp +++ b/hotspot/src/share/vm/oops/cpCache.cpp @@ -140,9 +140,10 @@ void ConstantPoolCacheEntry::set_parameter_size(int value) { err_msg("size must not change: parameter_size=%d, value=%d", parameter_size(), value)); } -void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, - methodHandle method, - int vtable_index) { +void ConstantPoolCacheEntry::set_direct_or_vtable_call(Bytecodes::Code invoke_code, + methodHandle method, + int vtable_index) { + bool is_vtable_call = (vtable_index >= 0); // FIXME: split this method on this boolean assert(method->interpreter_entry() != NULL, "should have been set at this point"); assert(!method->is_obsolete(), "attempt to write obsolete method to cpCache"); @@ -160,7 +161,8 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, // ...and fall through as if we were handling invokevirtual: case Bytecodes::_invokevirtual: { - if (method->can_be_statically_bound()) { + if (!is_vtable_call) { + assert(method->can_be_statically_bound(), ""); // set_f2_as_vfinal_method checks if is_vfinal flag is true. set_method_flags(as_TosState(method->result_type()), ( 1 << is_vfinal_shift) | @@ -169,6 +171,7 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, method()->size_of_parameters()); set_f2_as_vfinal_method(method()); } else { + assert(!method->can_be_statically_bound(), ""); assert(vtable_index >= 0, "valid index"); assert(!method->is_final_method(), "sanity"); set_method_flags(as_TosState(method->result_type()), @@ -182,6 +185,7 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, case Bytecodes::_invokespecial: case Bytecodes::_invokestatic: + assert(!is_vtable_call, ""); // Note: Read and preserve the value of the is_vfinal flag on any // invokevirtual bytecode shared with this constant pool cache entry. // It is cheap and safe to consult is_vfinal() at all times. @@ -232,8 +236,22 @@ void ConstantPoolCacheEntry::set_method(Bytecodes::Code invoke_code, NOT_PRODUCT(verify(tty)); } +void ConstantPoolCacheEntry::set_direct_call(Bytecodes::Code invoke_code, methodHandle method) { + int index = Method::nonvirtual_vtable_index; + // index < 0; FIXME: inline and customize set_direct_or_vtable_call + set_direct_or_vtable_call(invoke_code, method, index); +} -void ConstantPoolCacheEntry::set_interface_call(methodHandle method, int index) { +void ConstantPoolCacheEntry::set_vtable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { + // either the method is a miranda or its holder should accept the given index + assert(method->method_holder()->is_interface() || method->method_holder()->verify_vtable_index(index), ""); + // index >= 0; FIXME: inline and customize set_direct_or_vtable_call + set_direct_or_vtable_call(invoke_code, method, index); +} + +void ConstantPoolCacheEntry::set_itable_call(Bytecodes::Code invoke_code, methodHandle method, int index) { + assert(method->method_holder()->verify_itable_index(index), ""); + assert(invoke_code == Bytecodes::_invokeinterface, ""); InstanceKlass* interf = method->method_holder(); assert(interf->is_interface(), "must be an interface"); assert(!method->is_final_method(), "interfaces do not have final methods; cannot link to one here"); diff --git a/hotspot/src/share/vm/oops/cpCache.hpp b/hotspot/src/share/vm/oops/cpCache.hpp index c15b4a54bd6..77c0deb9d8f 100644 --- a/hotspot/src/share/vm/oops/cpCache.hpp +++ b/hotspot/src/share/vm/oops/cpCache.hpp @@ -219,15 +219,29 @@ class ConstantPoolCacheEntry VALUE_OBJ_CLASS_SPEC { Klass* root_klass // needed by the GC to dirty the klass ); - void set_method( // sets entry to resolved method entry + private: + void set_direct_or_vtable_call( Bytecodes::Code invoke_code, // the bytecode used for invoking the method methodHandle method, // the method/prototype if any (NULL, otherwise) int vtable_index // the vtable index if any, else negative ); - void set_interface_call( - methodHandle method, // Resolved method - int index // Method index into interface + public: + void set_direct_call( // sets entry to exact concrete method entry + Bytecodes::Code invoke_code, // the bytecode used for invoking the method + methodHandle method // the method to call + ); + + void set_vtable_call( // sets entry to vtable index + Bytecodes::Code invoke_code, // the bytecode used for invoking the method + methodHandle method, // resolved method which declares the vtable index + int vtable_index // the vtable index + ); + + void set_itable_call( + Bytecodes::Code invoke_code, // the bytecode used; must be invokeinterface + methodHandle method, // the resolved interface method + int itable_index // index into itable for the method ); void set_method_handle( diff --git a/hotspot/src/share/vm/oops/fieldInfo.hpp b/hotspot/src/share/vm/oops/fieldInfo.hpp index 5da8ed9628a..6763c42d127 100644 --- a/hotspot/src/share/vm/oops/fieldInfo.hpp +++ b/hotspot/src/share/vm/oops/fieldInfo.hpp @@ -240,6 +240,14 @@ class FieldInfo VALUE_OBJ_CLASS_SPEC { return (access_flags() & JVM_ACC_FIELD_INTERNAL) != 0; } + bool is_stable() const { + return (access_flags() & JVM_ACC_FIELD_STABLE) != 0; + } + void set_stable(bool z) { + if (z) _shorts[access_flags_offset] |= JVM_ACC_FIELD_STABLE; + else _shorts[access_flags_offset] &= ~JVM_ACC_FIELD_STABLE; + } + Symbol* lookup_symbol(int symbol_index) const { assert(is_internal(), "only internal fields"); return vmSymbols::symbol_at((vmSymbols::SID)symbol_index); diff --git a/hotspot/src/share/vm/oops/fieldStreams.hpp b/hotspot/src/share/vm/oops/fieldStreams.hpp index acc590c970c..17f1b0a8585 100644 --- a/hotspot/src/share/vm/oops/fieldStreams.hpp +++ b/hotspot/src/share/vm/oops/fieldStreams.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ #include "oops/instanceKlass.hpp" #include "oops/fieldInfo.hpp" +#include "runtime/fieldDescriptor.hpp" // The is the base class for iteration over the fields array // describing the declared fields in the class. Several subclasses @@ -43,8 +44,10 @@ class FieldStreamBase : public StackObj { int _index; int _limit; int _generic_signature_slot; + fieldDescriptor _fd_buf; FieldInfo* field() const { return FieldInfo::from_field_array(_fields, _index); } + InstanceKlass* field_holder() const { return _constants->pool_holder(); } int init_generic_signature_start_slot() { int length = _fields->length(); @@ -102,6 +105,7 @@ class FieldStreamBase : public StackObj { _index = 0; _limit = klass->java_fields_count(); init_generic_signature_start_slot(); + assert(klass == field_holder(), ""); } FieldStreamBase(instanceKlassHandle klass) { _fields = klass->fields(); @@ -109,6 +113,7 @@ class FieldStreamBase : public StackObj { _index = 0; _limit = klass->java_fields_count(); init_generic_signature_start_slot(); + assert(klass == field_holder(), ""); } // accessors @@ -180,6 +185,12 @@ class FieldStreamBase : public StackObj { return field()->contended_group(); } + // bridge to a heavier API: + fieldDescriptor& field_descriptor() const { + fieldDescriptor& field = const_cast(_fd_buf); + field.reinitialize(field_holder(), _index); + return field; + } }; // Iterate over only the internal fields diff --git a/hotspot/src/share/vm/oops/instanceKlass.cpp b/hotspot/src/share/vm/oops/instanceKlass.cpp index 29c77a07ccb..e56e80664f6 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.cpp +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp @@ -286,7 +286,6 @@ InstanceKlass::InstanceKlass(int vtable_len, init_previous_versions(); set_generic_signature_index(0); release_set_methods_jmethod_ids(NULL); - release_set_methods_cached_itable_indices(NULL); set_annotations(NULL); set_jvmti_cached_class_field_map(NULL); set_initial_method_idnum(0); @@ -1149,7 +1148,7 @@ bool InstanceKlass::find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* Symbol* f_name = fs.name(); Symbol* f_sig = fs.signature(); if (f_name == name && f_sig == sig) { - fd->initialize(const_cast(this), fs.index()); + fd->reinitialize(const_cast(this), fs.index()); return true; } } @@ -1218,7 +1217,7 @@ Klass* InstanceKlass::find_field(Symbol* name, Symbol* sig, bool is_static, fiel bool InstanceKlass::find_local_field_from_offset(int offset, bool is_static, fieldDescriptor* fd) const { for (JavaFieldStream fs(this); !fs.done(); fs.next()) { if (fs.offset() == offset) { - fd->initialize(const_cast(this), fs.index()); + fd->reinitialize(const_cast(this), fs.index()); if (fd->is_static() == is_static) return true; } } @@ -1251,8 +1250,7 @@ void InstanceKlass::methods_do(void f(Method* method)) { void InstanceKlass::do_local_static_fields(FieldClosure* cl) { for (JavaFieldStream fs(this); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { - fieldDescriptor fd; - fd.initialize(this, fs.index()); + fieldDescriptor& fd = fs.field_descriptor(); cl->do_field(&fd); } } @@ -1268,8 +1266,7 @@ void InstanceKlass::do_local_static_fields(void f(fieldDescriptor*, TRAPS), TRAP void InstanceKlass::do_local_static_fields_impl(instanceKlassHandle this_oop, void f(fieldDescriptor* fd, TRAPS), TRAPS) { for (JavaFieldStream fs(this_oop()); !fs.done(); fs.next()) { if (fs.access_flags().is_static()) { - fieldDescriptor fd; - fd.initialize(this_oop(), fs.index()); + fieldDescriptor& fd = fs.field_descriptor(); f(&fd, CHECK); } } @@ -1291,7 +1288,7 @@ void InstanceKlass::do_nonstatic_fields(FieldClosure* cl) { int* fields_sorted = NEW_C_HEAP_ARRAY(int, 2*(length+1), mtClass); int j = 0; for (int i = 0; i < length; i += 1) { - fd.initialize(this, i); + fd.reinitialize(this, i); if (!fd.is_static()) { fields_sorted[j + 0] = fd.offset(); fields_sorted[j + 1] = i; @@ -1303,7 +1300,7 @@ void InstanceKlass::do_nonstatic_fields(FieldClosure* cl) { // _sort_Fn is defined in growableArray.hpp. qsort(fields_sorted, length/2, 2*sizeof(int), (_sort_Fn)compare_fields_by_offset); for (int i = 0; i < length; i += 2) { - fd.initialize(this, fields_sorted[i + 1]); + fd.reinitialize(this, fields_sorted[i + 1]); assert(!fd.is_static() && fd.offset() == fields_sorted[i], "only nonstatic fields"); cl->do_field(&fd); } @@ -1686,87 +1683,6 @@ jmethodID InstanceKlass::jmethod_id_or_null(Method* method) { } -// Cache an itable index -void InstanceKlass::set_cached_itable_index(size_t idnum, int index) { - int* indices = methods_cached_itable_indices_acquire(); - int* to_dealloc_indices = NULL; - - // We use a double-check locking idiom here because this cache is - // performance sensitive. In the normal system, this cache only - // transitions from NULL to non-NULL which is safe because we use - // release_set_methods_cached_itable_indices() to advertise the - // new cache. A partially constructed cache should never be seen - // by a racing thread. Cache reads and writes proceed without a - // lock, but creation of the cache itself requires no leaks so a - // lock is generally acquired in that case. - // - // If the RedefineClasses() API has been used, then this cache can - // grow and we'll have transitions from non-NULL to bigger non-NULL. - // Cache creation requires no leaks and we require safety between all - // cache accesses and freeing of the old cache so a lock is generally - // acquired when the RedefineClasses() API has been used. - - if (indices == NULL || idnum_can_increment()) { - // we need a cache or the cache can grow - MutexLocker ml(JNICachedItableIndex_lock); - // reacquire the cache to see if another thread already did the work - indices = methods_cached_itable_indices_acquire(); - size_t length = 0; - // cache size is stored in element[0], other elements offset by one - if (indices == NULL || (length = (size_t)indices[0]) <= idnum) { - size_t size = MAX2(idnum+1, (size_t)idnum_allocated_count()); - int* new_indices = NEW_C_HEAP_ARRAY(int, size+1, mtClass); - new_indices[0] = (int)size; - // copy any existing entries - size_t i; - for (i = 0; i < length; i++) { - new_indices[i+1] = indices[i+1]; - } - // Set all the rest to -1 - for (i = length; i < size; i++) { - new_indices[i+1] = -1; - } - if (indices != NULL) { - // We have an old cache to delete so save it for after we - // drop the lock. - to_dealloc_indices = indices; - } - release_set_methods_cached_itable_indices(indices = new_indices); - } - - if (idnum_can_increment()) { - // this cache can grow so we have to write to it safely - indices[idnum+1] = index; - } - } else { - CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops()); - } - - if (!idnum_can_increment()) { - // The cache cannot grow and this JNI itable index value does not - // have to be unique like a jmethodID. If there is a race to set it, - // it doesn't matter. - indices[idnum+1] = index; - } - - if (to_dealloc_indices != NULL) { - // we allocated a new cache so free the old one - FreeHeap(to_dealloc_indices); - } -} - - -// Retrieve a cached itable index -int InstanceKlass::cached_itable_index(size_t idnum) { - int* indices = methods_cached_itable_indices_acquire(); - if (indices != NULL && ((size_t)indices[0]) > idnum) { - // indices exist and are long enough, retrieve possible cached - return indices[idnum+1]; - } - return -1; -} - - // // Walk the list of dependent nmethods searching for nmethods which // are dependent on the changes that were passed in and mark them for @@ -2326,12 +2242,6 @@ void InstanceKlass::release_C_heap_structures() { } } - int* indices = methods_cached_itable_indices_acquire(); - if (indices != (int*)NULL) { - release_set_methods_cached_itable_indices(NULL); - FreeHeap(indices); - } - // release dependencies nmethodBucket* b = _dependencies; _dependencies = NULL; @@ -2782,6 +2692,18 @@ static const char* state_names[] = { "allocated", "loaded", "linked", "being_initialized", "fully_initialized", "initialization_error" }; +static void print_vtable(intptr_t* start, int len, outputStream* st) { + for (int i = 0; i < len; i++) { + intptr_t e = start[i]; + st->print("%d : " INTPTR_FORMAT, i, e); + if (e != 0 && ((Metadata*)e)->is_metaspace_object()) { + st->print(" "); + ((Metadata*)e)->print_value_on(st); + } + st->cr(); + } +} + void InstanceKlass::print_on(outputStream* st) const { assert(is_klass(), "must be klass"); Klass::print_on(st); @@ -2816,7 +2738,7 @@ void InstanceKlass::print_on(outputStream* st) const { st->print(BULLET"arrays: "); array_klasses()->print_value_on_maybe_null(st); st->cr(); st->print(BULLET"methods: "); methods()->print_value_on(st); st->cr(); - if (Verbose) { + if (Verbose || WizardMode) { Array* method_array = methods(); for(int i = 0; i < method_array->length(); i++) { st->print("%d : ", i); method_array->at(i)->print_value(); st->cr(); @@ -2847,24 +2769,17 @@ void InstanceKlass::print_on(outputStream* st) const { st->print(BULLET"field annotations: "); fields_annotations()->print_value_on(st); st->cr(); st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr(); { - ResourceMark rm; - // PreviousVersionInfo objects returned via PreviousVersionWalker - // contain a GrowableArray of handles. We have to clean up the - // GrowableArray _after_ the PreviousVersionWalker destructor - // has destroyed the handles. - { - bool have_pv = false; - PreviousVersionWalker pvw((InstanceKlass*)this); - for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); - pv_info != NULL; pv_info = pvw.next_previous_version()) { - if (!have_pv) - st->print(BULLET"previous version: "); - have_pv = true; - pv_info->prev_constant_pool_handle()()->print_value_on(st); - } - if (have_pv) st->cr(); - } // pvw is cleaned up - } // rm is cleaned up + bool have_pv = false; + PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this); + for (PreviousVersionNode * pv_node = pvw.next_previous_version(); + pv_node != NULL; pv_node = pvw.next_previous_version()) { + if (!have_pv) + st->print(BULLET"previous version: "); + have_pv = true; + pv_node->prev_constant_pool()->print_value_on(st); + } + if (have_pv) st->cr(); + } // pvw is cleaned up if (generic_signature() != NULL) { st->print(BULLET"generic signature: "); @@ -2874,7 +2789,9 @@ void InstanceKlass::print_on(outputStream* st) const { st->print(BULLET"inner classes: "); inner_classes()->print_value_on(st); st->cr(); st->print(BULLET"java mirror: "); java_mirror()->print_value_on(st); st->cr(); st->print(BULLET"vtable length %d (start addr: " INTPTR_FORMAT ")", vtable_length(), start_of_vtable()); st->cr(); + if (vtable_length() > 0 && (Verbose || WizardMode)) print_vtable(start_of_vtable(), vtable_length(), st); st->print(BULLET"itable length %d (start addr: " INTPTR_FORMAT ")", itable_length(), start_of_itable()); st->cr(); + if (itable_length() > 0 && (Verbose || WizardMode)) print_vtable(start_of_itable(), itable_length(), st); st->print_cr(BULLET"---- static fields (%d words):", static_field_size()); FieldPrinter print_static_field(st); ((InstanceKlass*)this)->do_local_static_fields(&print_static_field); @@ -2896,6 +2813,7 @@ void InstanceKlass::print_on(outputStream* st) const { void InstanceKlass::print_value_on(outputStream* st) const { assert(is_klass(), "must be klass"); + if (Verbose || WizardMode) access_flags().print_on(st); name()->print_value_on(st); } @@ -3392,34 +3310,34 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh, Array* old_methods = ikh->methods(); if (cp_ref->on_stack()) { - PreviousVersionNode * pv_node = NULL; - if (emcp_method_count == 0) { + PreviousVersionNode * pv_node = NULL; + if (emcp_method_count == 0) { // non-shared ConstantPool gets a reference - pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), NULL); - RC_TRACE(0x00000400, - ("add: all methods are obsolete; flushing any EMCP refs")); - } else { - int local_count = 0; + pv_node = new PreviousVersionNode(cp_ref, NULL); + RC_TRACE(0x00000400, + ("add: all methods are obsolete; flushing any EMCP refs")); + } else { + int local_count = 0; GrowableArray* method_refs = new (ResourceObj::C_HEAP, mtClass) - GrowableArray(emcp_method_count, true); - for (int i = 0; i < old_methods->length(); i++) { - if (emcp_methods->at(i)) { - // this old method is EMCP. Save it only if it's on the stack - Method* old_method = old_methods->at(i); - if (old_method->on_stack()) { - method_refs->append(old_method); + GrowableArray(emcp_method_count, true); + for (int i = 0; i < old_methods->length(); i++) { + if (emcp_methods->at(i)) { + // this old method is EMCP. Save it only if it's on the stack + Method* old_method = old_methods->at(i); + if (old_method->on_stack()) { + method_refs->append(old_method); + } + if (++local_count >= emcp_method_count) { + // no more EMCP methods so bail out now + break; } - if (++local_count >= emcp_method_count) { - // no more EMCP methods so bail out now - break; } } - } // non-shared ConstantPool gets a reference - pv_node = new PreviousVersionNode(cp_ref, !cp_ref->is_shared(), method_refs); + pv_node = new PreviousVersionNode(cp_ref, method_refs); } // append new previous version. - _previous_versions->append(pv_node); + _previous_versions->append(pv_node); } // Since the caller is the VMThread and we are at a safepoint, this @@ -3520,6 +3438,8 @@ Method* InstanceKlass::method_with_idnum(int idnum) { return m; } } + // None found, return null for the caller to handle. + return NULL; } return m; } @@ -3536,10 +3456,9 @@ unsigned char * InstanceKlass::get_cached_class_file_bytes() { // Construct a PreviousVersionNode entry for the array hung off // the InstanceKlass. PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool, - bool prev_cp_is_weak, GrowableArray* prev_EMCP_methods) { + GrowableArray* prev_EMCP_methods) { _prev_constant_pool = prev_constant_pool; - _prev_cp_is_weak = prev_cp_is_weak; _prev_EMCP_methods = prev_EMCP_methods; } @@ -3555,99 +3474,38 @@ PreviousVersionNode::~PreviousVersionNode() { } } - -// Construct a PreviousVersionInfo entry -PreviousVersionInfo::PreviousVersionInfo(PreviousVersionNode *pv_node) { - _prev_constant_pool_handle = constantPoolHandle(); // NULL handle - _prev_EMCP_method_handles = NULL; - - ConstantPool* cp = pv_node->prev_constant_pool(); - assert(cp != NULL, "constant pool ref was unexpectedly cleared"); - if (cp == NULL) { - return; // robustness - } - - // make the ConstantPool* safe to return - _prev_constant_pool_handle = constantPoolHandle(cp); - - GrowableArray* method_refs = pv_node->prev_EMCP_methods(); - if (method_refs == NULL) { - // the InstanceKlass did not have any EMCP methods - return; - } - - _prev_EMCP_method_handles = new GrowableArray(10); - - int n_methods = method_refs->length(); - for (int i = 0; i < n_methods; i++) { - Method* method = method_refs->at(i); - assert (method != NULL, "method has been cleared"); - if (method == NULL) { - continue; // robustness - } - // make the Method* safe to return - _prev_EMCP_method_handles->append(methodHandle(method)); - } -} - - -// Destroy a PreviousVersionInfo -PreviousVersionInfo::~PreviousVersionInfo() { - // Since _prev_EMCP_method_handles is not C-heap allocated, we - // don't have to delete it. -} - - // Construct a helper for walking the previous versions array -PreviousVersionWalker::PreviousVersionWalker(InstanceKlass *ik) { +PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) { + _thread = thread; _previous_versions = ik->previous_versions(); _current_index = 0; - // _hm needs no initialization _current_p = NULL; -} - - -// Destroy a PreviousVersionWalker -PreviousVersionWalker::~PreviousVersionWalker() { - // Delete the current info just in case the caller didn't walk to - // the end of the previous versions list. No harm if _current_p is - // already NULL. - delete _current_p; - - // When _hm is destroyed, all the Handles returned in - // PreviousVersionInfo objects will be destroyed. - // Also, after this destructor is finished it will be - // safe to delete the GrowableArray allocated in the - // PreviousVersionInfo objects. + _current_constant_pool_handle = constantPoolHandle(thread, ik->constants()); } // Return the interesting information for the next previous version // of the klass. Returns NULL if there are no more previous versions. -PreviousVersionInfo* PreviousVersionWalker::next_previous_version() { +PreviousVersionNode* PreviousVersionWalker::next_previous_version() { if (_previous_versions == NULL) { // no previous versions so nothing to return return NULL; } - delete _current_p; // cleanup the previous info for the caller - _current_p = NULL; // reset to NULL so we don't delete same object twice + _current_p = NULL; // reset to NULL + _current_constant_pool_handle = NULL; int length = _previous_versions->length(); while (_current_index < length) { PreviousVersionNode * pv_node = _previous_versions->at(_current_index++); - PreviousVersionInfo * pv_info = new (ResourceObj::C_HEAP, mtClass) - PreviousVersionInfo(pv_node); - constantPoolHandle cp_h = pv_info->prev_constant_pool_handle(); - assert (!cp_h.is_null(), "null cp found in previous version"); - - // The caller will need to delete pv_info when they are done with it. - _current_p = pv_info; - return pv_info; + // Save a handle to the constant pool for this previous version, + // which keeps all the methods from being deallocated. + _current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool()); + _current_p = pv_node; + return pv_node; } - // all of the underlying nodes' info has been deleted return NULL; } // end next_previous_version() diff --git a/hotspot/src/share/vm/oops/instanceKlass.hpp b/hotspot/src/share/vm/oops/instanceKlass.hpp index 123f6b17911..c3745ee24d4 100644 --- a/hotspot/src/share/vm/oops/instanceKlass.hpp +++ b/hotspot/src/share/vm/oops/instanceKlass.hpp @@ -245,7 +245,6 @@ class InstanceKlass: public Klass { MemberNameTable* _member_names; // Member names JNIid* _jni_ids; // First JNI identifier for static fields in this class jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none - int* _methods_cached_itable_indices; // itable_index cache for JNI invoke corresponding to methods idnum, or NULL nmethodBucket* _dependencies; // list of dependent nmethods nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class BreakpointInfo* _breakpoints; // bpt lists, managed by Method* @@ -690,10 +689,6 @@ class InstanceKlass: public Klass { size_t *length_p, jmethodID* id_p); jmethodID jmethod_id_or_null(Method* method); - // cached itable index support - void set_cached_itable_index(size_t idnum, int index); - int cached_itable_index(size_t idnum); - // annotations support Annotations* annotations() const { return _annotations; } void set_annotations(Annotations* anno) { _annotations = anno; } @@ -994,11 +989,6 @@ private: void release_set_methods_jmethod_ids(jmethodID* jmeths) { OrderAccess::release_store_ptr(&_methods_jmethod_ids, jmeths); } - int* methods_cached_itable_indices_acquire() const - { return (int*)OrderAccess::load_ptr_acquire(&_methods_cached_itable_indices); } - void release_set_methods_cached_itable_indices(int* indices) - { OrderAccess::release_store_ptr(&_methods_cached_itable_indices, indices); } - // Lock during initialization public: // Lock for (1) initialization; (2) access to the ConstantPool of this class. @@ -1136,21 +1126,11 @@ class BreakpointInfo; // A collection point for interesting information about the previous -// version(s) of an InstanceKlass. This class uses weak references to -// the information so that the information may be collected as needed -// by the system. If the information is shared, then a regular -// reference must be used because a weak reference would be seen as -// collectible. A GrowableArray of PreviousVersionNodes is attached -// to the InstanceKlass as needed. See PreviousVersionWalker below. +// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes +// is attached to the InstanceKlass as needed. See PreviousVersionWalker below. class PreviousVersionNode : public CHeapObj { private: - // A shared ConstantPool is never collected so we'll always have - // a reference to it so we can update items in the cache. We'll - // have a weak reference to a non-shared ConstantPool until all - // of the methods (EMCP or obsolete) have been collected; the - // non-shared ConstantPool becomes collectible at that point. - ConstantPool* _prev_constant_pool; // regular or weak reference - bool _prev_cp_is_weak; // true if not a shared ConstantPool + ConstantPool* _prev_constant_pool; // If the previous version of the InstanceKlass doesn't have any // EMCP methods, then _prev_EMCP_methods will be NULL. If all the @@ -1159,8 +1139,8 @@ class PreviousVersionNode : public CHeapObj { GrowableArray* _prev_EMCP_methods; public: - PreviousVersionNode(ConstantPool* prev_constant_pool, bool prev_cp_is_weak, - GrowableArray* prev_EMCP_methods); + PreviousVersionNode(ConstantPool* prev_constant_pool, + GrowableArray* prev_EMCP_methods); ~PreviousVersionNode(); ConstantPool* prev_constant_pool() const { return _prev_constant_pool; @@ -1171,59 +1151,26 @@ public: }; -// A Handle-ized version of PreviousVersionNode. -class PreviousVersionInfo : public ResourceObj { - private: - constantPoolHandle _prev_constant_pool_handle; - // If the previous version of the InstanceKlass doesn't have any - // EMCP methods, then _prev_EMCP_methods will be NULL. Since the - // methods cannot be collected while we hold a handle, - // _prev_EMCP_methods should never have a length of zero. - GrowableArray* _prev_EMCP_method_handles; - -public: - PreviousVersionInfo(PreviousVersionNode *pv_node); - ~PreviousVersionInfo(); - constantPoolHandle prev_constant_pool_handle() const { - return _prev_constant_pool_handle; - } - GrowableArray* prev_EMCP_method_handles() const { - return _prev_EMCP_method_handles; - } -}; - - -// Helper object for walking previous versions. This helper cleans up -// the Handles that it allocates when the helper object is destroyed. -// The PreviousVersionInfo object returned by next_previous_version() -// is only valid until a subsequent call to next_previous_version() or -// the helper object is destroyed. +// Helper object for walking previous versions. class PreviousVersionWalker : public StackObj { private: + Thread* _thread; GrowableArray* _previous_versions; int _current_index; - // Fields for cleaning up when we are done walking the previous versions: - // A HandleMark for the PreviousVersionInfo handles: - HandleMark _hm; - // It would be nice to have a ResourceMark field in this helper also, - // but the ResourceMark code says to be careful to delete handles held - // in GrowableArrays _before_ deleting the GrowableArray. Since we - // can't guarantee the order in which the fields are destroyed, we - // have to let the creator of the PreviousVersionWalker object do - // the right thing. Also, adding a ResourceMark here causes an - // include loop. + // A pointer to the current node object so we can handle the deletes. + PreviousVersionNode* _current_p; - // A pointer to the current info object so we can handle the deletes. - PreviousVersionInfo * _current_p; + // The constant pool handle keeps all the methods in this class from being + // deallocated from the metaspace during class unloading. + constantPoolHandle _current_constant_pool_handle; public: - PreviousVersionWalker(InstanceKlass *ik); - ~PreviousVersionWalker(); + PreviousVersionWalker(Thread* thread, InstanceKlass *ik); // Return the interesting information for the next previous version // of the klass. Returns NULL if there are no more previous versions. - PreviousVersionInfo* next_previous_version(); + PreviousVersionNode* next_previous_version(); }; diff --git a/hotspot/src/share/vm/oops/instanceOop.hpp b/hotspot/src/share/vm/oops/instanceOop.hpp index 9ebb9d4720b..bdac1992e6f 100644 --- a/hotspot/src/share/vm/oops/instanceOop.hpp +++ b/hotspot/src/share/vm/oops/instanceOop.hpp @@ -37,9 +37,9 @@ class instanceOopDesc : public oopDesc { // If compressed, the offset of the fields of the instance may not be aligned. static int base_offset_in_bytes() { - // offset computation code breaks if UseCompressedKlassPointers + // offset computation code breaks if UseCompressedClassPointers // only is true - return (UseCompressedOops && UseCompressedKlassPointers) ? + return (UseCompressedOops && UseCompressedClassPointers) ? klass_gap_offset_in_bytes() : sizeof(instanceOopDesc); } diff --git a/hotspot/src/share/vm/oops/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index cf24783fbf8..22b570bbff3 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -674,13 +674,23 @@ void Klass::oop_verify_on(oop obj, outputStream* st) { #ifndef PRODUCT -void Klass::verify_vtable_index(int i) { +bool Klass::verify_vtable_index(int i) { if (oop_is_instance()) { - assert(i>=0 && i<((InstanceKlass*)this)->vtable_length()/vtableEntry::size(), "index out of bounds"); + int limit = ((InstanceKlass*)this)->vtable_length()/vtableEntry::size(); + assert(i >= 0 && i < limit, err_msg("index %d out of bounds %d", i, limit)); } else { assert(oop_is_array(), "Must be"); - assert(i>=0 && i<((ArrayKlass*)this)->vtable_length()/vtableEntry::size(), "index out of bounds"); + int limit = ((ArrayKlass*)this)->vtable_length()/vtableEntry::size(); + assert(i >= 0 && i < limit, err_msg("index %d out of bounds %d", i, limit)); } + return true; +} + +bool Klass::verify_itable_index(int i) { + assert(oop_is_instance(), ""); + int method_count = klassItable::method_count_for_interface(this); + assert(i >= 0 && i < method_count, "index out of bounds"); + return true; } #endif diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 83bf44561b2..9855fdd3233 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -699,7 +699,8 @@ class Klass : public Metadata { void verify(bool check_dictionary = true) { verify_on(tty, check_dictionary); } #ifndef PRODUCT - void verify_vtable_index(int index); + bool verify_vtable_index(int index); + bool verify_itable_index(int index); #endif virtual void oop_verify_on(oop obj, outputStream* st); diff --git a/hotspot/src/share/vm/oops/klassVtable.cpp b/hotspot/src/share/vm/oops/klassVtable.cpp index ebc6e0aea88..7105368840f 100644 --- a/hotspot/src/share/vm/oops/klassVtable.cpp +++ b/hotspot/src/share/vm/oops/klassVtable.cpp @@ -47,11 +47,12 @@ inline InstanceKlass* klassVtable::ik() const { // this function computes the vtable size (including the size needed for miranda -// methods) and the number of miranda methods in this class +// methods) and the number of miranda methods in this class. // Note on Miranda methods: Let's say there is a class C that implements -// interface I. Let's say there is a method m in I that neither C nor any -// of its super classes implement (i.e there is no method of any access, with -// the same name and signature as m), then m is a Miranda method which is +// interface I, and none of C's superclasses implements I. +// Let's say there is an abstract method m in I that neither C +// nor any of its super classes implement (i.e there is no method of any access, +// with the same name and signature as m), then m is a Miranda method which is // entered as a public abstract method in C's vtable. From then on it should // treated as any other public method in C for method over-ride purposes. void klassVtable::compute_vtable_size_and_num_mirandas( @@ -111,10 +112,13 @@ void klassVtable::compute_vtable_size_and_num_mirandas( } int klassVtable::index_of(Method* m, int len) const { - assert(m->vtable_index() >= 0, "do not ask this of non-vtable methods"); + assert(m->has_vtable_index(), "do not ask this of non-vtable methods"); return m->vtable_index(); } +// Copy super class's vtable to the first part (prefix) of this class's vtable, +// and return the number of entries copied. Expects that 'super' is the Java +// super class (arrays can have "array" super classes that must be skipped). int klassVtable::initialize_from_super(KlassHandle super) { if (super.is_null()) { return 0; @@ -139,14 +143,14 @@ int klassVtable::initialize_from_super(KlassHandle super) { } } -// Revised lookup semantics introduced 1.3 (Kestral beta) +// +// Revised lookup semantics introduced 1.3 (Kestrel beta) void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { // Note: Arrays can have intermediate array supers. Use java_super to skip them. KlassHandle super (THREAD, klass()->java_super()); int nofNewEntries = 0; - if (PrintVtables && !klass()->oop_is_array()) { ResourceMark rm(THREAD); tty->print_cr("Initializing: %s", _klass->name()->as_C_string()); @@ -174,8 +178,10 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { int len = methods->length(); int initialized = super_vtable_len; - // update_inherited_vtable can stop for gc - ensure using handles + // Check each of this class's methods against super; + // if override, replace in copy of super vtable, otherwise append to end for (int i = 0; i < len; i++) { + // update_inherited_vtable can stop for gc - ensure using handles HandleMark hm(THREAD); assert(methods->at(i)->is_method(), "must be a Method*"); methodHandle mh(THREAD, methods->at(i)); @@ -189,11 +195,11 @@ void klassVtable::initialize_vtable(bool checkconstraints, TRAPS) { } } - // add miranda methods; it will also update the value of initialized - fill_in_mirandas(&initialized); + // add miranda methods to end of vtable. + initialized = fill_in_mirandas(initialized); // In class hierarchies where the accessibility is not increasing (i.e., going from private -> - // package_private -> publicprotected), the vtable might actually be smaller than our initial + // package_private -> public/protected), the vtable might actually be smaller than our initial // calculation. assert(initialized <= _length, "vtable initialization failed"); for(;initialized < _length; initialized++) { @@ -248,14 +254,8 @@ InstanceKlass* klassVtable::find_transitive_override(InstanceKlass* initialsuper return superk; } -// Methods that are "effectively" final don't need vtable entries. -bool method_is_effectively_final( - AccessFlags klass_flags, methodHandle target) { - return target->is_final() || klass_flags.is_final() && !target->is_overpass(); -} - // Update child's copy of super vtable for overrides -// OR return true if a new vtable entry is required +// OR return true if a new vtable entry is required. // Only called for InstanceKlass's, i.e. not for arrays // If that changed, could not use _klass as handle for klass bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle target_method, int super_vtable_len, @@ -263,6 +263,7 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar ResourceMark rm; bool allocate_new = true; assert(klass->oop_is_instance(), "must be InstanceKlass"); + assert(klass == target_method()->method_holder(), "caller resp."); // Initialize the method's vtable index to "nonvirtual". // If we allocate a vtable entry, we will update it to a non-negative number. @@ -273,11 +274,17 @@ bool klassVtable::update_inherited_vtable(InstanceKlass* klass, methodHandle tar return false; } - if (method_is_effectively_final(klass->access_flags(), target_method)) { + if (target_method->is_final_method(klass->access_flags())) { // a final method never needs a new entry; final methods can be statically // resolved and they have to be present in the vtable only if they override // a super's method, in which case they re-use its entry allocate_new = false; + } else if (klass->is_interface()) { + allocate_new = false; // see note below in needs_new_vtable_entry + // An interface never allocates new vtable slots, only inherits old ones. + // This method will either be assigned its own itable index later, + // or be assigned an inherited vtable index in the loop below. + target_method()->set_vtable_index(Method::pending_itable_index); } // we need a new entry if there is no superclass @@ -411,8 +418,14 @@ bool klassVtable::needs_new_vtable_entry(methodHandle target_method, Symbol* classname, AccessFlags class_flags, TRAPS) { + if (class_flags.is_interface()) { + // Interfaces do not use vtables, so there is no point to assigning + // a vtable index to any of their methods. If we refrain from doing this, + // we can use Method::_vtable_index to hold the itable index + return false; + } - if (method_is_effectively_final(class_flags, target_method) || + if (target_method->is_final_method(class_flags) || // a final method never needs a new entry; final methods can be statically // resolved and they have to be present in the vtable only if they override // a super's method, in which case they re-use its entry @@ -500,7 +513,8 @@ int klassVtable::index_of_miranda(Symbol* name, Symbol* signature) { return Method::invalid_vtable_index; } -// check if an entry is miranda +// check if an entry at an index is miranda +// requires that method m at entry be declared ("held") by an interface. bool klassVtable::is_miranda_entry_at(int i) { Method* m = method_at(i); Klass* method_holder = m->method_holder(); @@ -516,7 +530,9 @@ bool klassVtable::is_miranda_entry_at(int i) { return false; } -// check if a method is a miranda method, given a class's methods table and it's super +// check if a method is a miranda method, given a class's methods table and its super +// "miranda" means not static, not defined by this class, and not defined +// in super unless it is private and therefore inaccessible to this class. // the caller must make sure that the method belongs to an interface implemented by the class bool klassVtable::is_miranda(Method* m, Array* class_methods, Klass* super) { if (m->is_static()) { @@ -541,6 +557,14 @@ bool klassVtable::is_miranda(Method* m, Array* class_methods, Klass* su return false; } +// Scans current_interface_methods for miranda methods that do not +// already appear in new_mirandas and are also not defined-and-non-private +// in super (superclass). These mirandas are added to all_mirandas if it is +// not null; in addition, those that are not duplicates of miranda methods +// inherited by super from its interfaces are added to new_mirandas. +// Thus, new_mirandas will be the set of mirandas that this class introduces, +// all_mirandas will be the set of all mirandas applicable to this class +// including all defined in superclasses. void klassVtable::add_new_mirandas_to_lists( GrowableArray* new_mirandas, GrowableArray* all_mirandas, Array* current_interface_methods, Array* class_methods, @@ -599,17 +623,22 @@ void klassVtable::get_mirandas(GrowableArray* new_mirandas, } } -// fill in mirandas -void klassVtable::fill_in_mirandas(int* initialized) { +// Discover miranda methods ("miranda" = "interface abstract, no binding"), +// and append them into the vtable starting at index initialized, +// return the new value of initialized. +int klassVtable::fill_in_mirandas(int initialized) { GrowableArray mirandas(20); get_mirandas(&mirandas, NULL, ik()->super(), ik()->methods(), ik()->local_interfaces()); for (int i = 0; i < mirandas.length(); i++) { - put_method_at(mirandas.at(i), *initialized); - ++(*initialized); + put_method_at(mirandas.at(i), initialized); + ++initialized; } + return initialized; } +// Copy this class's vtable to the vtable beginning at start. +// Used to copy superclass vtable to prefix of subclass's vtable. void klassVtable::copy_vtable_to(vtableEntry* start) { Copy::disjoint_words((HeapWord*)table(), (HeapWord*)start, _length * vtableEntry::size()); } @@ -723,6 +752,12 @@ static int initialize_count = 0; // Initialization void klassItable::initialize_itable(bool checkconstraints, TRAPS) { + if (_klass->is_interface()) { + // This needs to go after vtable indexes are assigned but + // before implementors need to know the number of itable indexes. + assign_itable_indexes_for_interface(_klass()); + } + // Cannot be setup doing bootstrapping, interfaces don't have // itables, and klass with only ones entry have empty itables if (Universe::is_bootstrapping() || @@ -754,45 +789,89 @@ void klassItable::initialize_itable(bool checkconstraints, TRAPS) { } +inline bool interface_method_needs_itable_index(Method* m) { + if (m->is_static()) return false; // e.g., Stream.empty + if (m->is_initializer()) return false; // or + // If an interface redeclares a method from java.lang.Object, + // it should already have a vtable index, don't touch it. + // e.g., CharSequence.toString (from initialize_vtable) + // if (m->has_vtable_index()) return false; // NO! + return true; +} + +int klassItable::assign_itable_indexes_for_interface(Klass* klass) { + // an interface does not have an itable, but its methods need to be numbered + if (TraceItables) tty->print_cr("%3d: Initializing itable for interface %s", ++initialize_count, + klass->name()->as_C_string()); + Array* methods = InstanceKlass::cast(klass)->methods(); + int nof_methods = methods->length(); + int ime_num = 0; + for (int i = 0; i < nof_methods; i++) { + Method* m = methods->at(i); + if (interface_method_needs_itable_index(m)) { + assert(!m->is_final_method(), "no final interface methods"); + // If m is already assigned a vtable index, do not disturb it. + if (!m->has_vtable_index()) { + assert(m->vtable_index() == Method::pending_itable_index, "set by initialize_vtable"); + m->set_itable_index(ime_num); + // Progress to next itable entry + ime_num++; + } + } + } + assert(ime_num == method_count_for_interface(klass), "proper sizing"); + return ime_num; +} + +int klassItable::method_count_for_interface(Klass* interf) { + assert(interf->oop_is_instance(), "must be"); + assert(interf->is_interface(), "must be"); + Array* methods = InstanceKlass::cast(interf)->methods(); + int nof_methods = methods->length(); + while (nof_methods > 0) { + Method* m = methods->at(nof_methods-1); + if (m->has_itable_index()) { + int length = m->itable_index() + 1; +#ifdef ASSERT + while (nof_methods = 0) { + m = methods->at(--nof_methods); + assert(!m->has_itable_index() || m->itable_index() < length, ""); + } +#endif //ASSERT + return length; // return the rightmost itable index, plus one + } + nof_methods -= 1; + } + // no methods have itable indexes + return 0; +} + + void klassItable::initialize_itable_for_interface(int method_table_offset, KlassHandle interf_h, bool checkconstraints, TRAPS) { Array* methods = InstanceKlass::cast(interf_h())->methods(); int nof_methods = methods->length(); HandleMark hm; - KlassHandle klass = _klass; assert(nof_methods > 0, "at least one method must exist for interface to be in vtable"); Handle interface_loader (THREAD, InstanceKlass::cast(interf_h())->class_loader()); - int ime_num = 0; - // Skip first Method* if it is a class initializer - int i = methods->at(0)->is_static_initializer() ? 1 : 0; - - // m, method_name, method_signature, klass reset each loop so they - // don't need preserving across check_signature_loaders call - // methods needs a handle in case of gc from check_signature_loaders - for(; i < nof_methods; i++) { + int ime_count = method_count_for_interface(interf_h()); + for (int i = 0; i < nof_methods; i++) { Method* m = methods->at(i); - Symbol* method_name = m->name(); - Symbol* method_signature = m->signature(); - - // This is same code as in Linkresolver::lookup_instance_method_in_klasses - Method* target = klass->uncached_lookup_method(method_name, method_signature); - while (target != NULL && target->is_static()) { - // continue with recursive lookup through the superclass - Klass* super = target->method_holder()->super(); - target = (super == NULL) ? (Method*)NULL : super->uncached_lookup_method(method_name, method_signature); + methodHandle target; + if (m->has_itable_index()) { + LinkResolver::lookup_instance_method_in_klasses(target, _klass, m->name(), m->signature(), CHECK); } if (target == NULL || !target->is_public() || target->is_abstract()) { // Entry do not resolve. Leave it empty } else { // Entry did resolve, check loader constraints before initializing // if checkconstraints requested - methodHandle target_h (THREAD, target); // preserve across gc if (checkconstraints) { Handle method_holder_loader (THREAD, target->method_holder()->class_loader()); if (method_holder_loader() != interface_loader()) { ResourceMark rm(THREAD); Symbol* failed_type_symbol = - SystemDictionary::check_signature_loaders(method_signature, + SystemDictionary::check_signature_loaders(m->signature(), method_holder_loader, interface_loader, true, CHECK); @@ -803,9 +882,9 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass "and the class loader (instance of %s) for interface " "%s have different Class objects for the type %s " "used in the signature"; - char* sig = target_h()->name_and_sig_as_C_string(); + char* sig = target()->name_and_sig_as_C_string(); const char* loader1 = SystemDictionary::loader_name(method_holder_loader()); - char* current = klass->name()->as_C_string(); + char* current = _klass->name()->as_C_string(); const char* loader2 = SystemDictionary::loader_name(interface_loader()); char* iface = InstanceKlass::cast(interf_h())->name()->as_C_string(); char* failed_type_name = failed_type_symbol->as_C_string(); @@ -821,10 +900,10 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass } // ime may have moved during GC so recalculate address - itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target_h()); + int ime_num = m->itable_index(); + assert(ime_num < ime_count, "oob"); + itableOffsetEntry::method_entry(_klass(), method_table_offset)[ime_num].initialize(target()); } - // Progress to next entry - ime_num++; } } @@ -913,20 +992,22 @@ class InterfaceVisiterClosure : public StackObj { virtual void doit(Klass* intf, int method_count) = 0; }; -// Visit all interfaces with at-least one method (excluding ) +// Visit all interfaces with at least one itable method void visit_all_interfaces(Array* transitive_intf, InterfaceVisiterClosure *blk) { // Handle array argument for(int i = 0; i < transitive_intf->length(); i++) { Klass* intf = transitive_intf->at(i); assert(intf->is_interface(), "sanity check"); - // Find no. of methods excluding a - int method_count = InstanceKlass::cast(intf)->methods()->length(); - if (method_count > 0) { - Method* m = InstanceKlass::cast(intf)->methods()->at(0); - assert(m != NULL && m->is_method(), "sanity check"); - if (m->name() == vmSymbols::object_initializer_name()) { - method_count--; + // Find no. of itable methods + int method_count = 0; + // method_count = klassItable::method_count_for_interface(intf); + Array* methods = InstanceKlass::cast(intf)->methods(); + if (methods->length() > 0) { + for (int i = methods->length(); --i >= 0; ) { + if (interface_method_needs_itable_index(methods->at(i))) { + method_count++; + } } } @@ -1024,40 +1105,26 @@ void klassItable::setup_itable_offset_table(instanceKlassHandle klass) { } -// m must be a method in an interface -int klassItable::compute_itable_index(Method* m) { - InstanceKlass* intf = m->method_holder(); - assert(intf->is_interface(), "sanity check"); - Array* methods = intf->methods(); - int index = 0; - while(methods->at(index) != m) { - index++; - assert(index < methods->length(), "should find index for resolve_invoke"); - } - // Adjust for , which is left out of table if first method - if (methods->length() > 0 && methods->at(0)->is_static_initializer()) { - index--; - } - return index; -} - - -// inverse to compute_itable_index +// inverse to itable_index Method* klassItable::method_for_itable_index(Klass* intf, int itable_index) { assert(InstanceKlass::cast(intf)->is_interface(), "sanity check"); + assert(intf->verify_itable_index(itable_index), ""); Array* methods = InstanceKlass::cast(intf)->methods(); - int index = itable_index; - // Adjust for , which is left out of table if first method - if (methods->length() > 0 && methods->at(0)->is_static_initializer()) { - index++; - } - - if (itable_index < 0 || index >= methods->length()) + if (itable_index < 0 || itable_index >= method_count_for_interface(intf)) return NULL; // help caller defend against bad indexes + int index = itable_index; Method* m = methods->at(index); - assert(compute_itable_index(m) == itable_index, "correct inverse"); + int index2 = -1; + while (!m->has_itable_index() || + (index2 = m->itable_index()) != itable_index) { + assert(index2 < itable_index, "monotonic"); + if (++index == methods->length()) + return NULL; + m = methods->at(index); + } + assert(m->itable_index() == itable_index, "correct inverse"); return m; } diff --git a/hotspot/src/share/vm/oops/klassVtable.hpp b/hotspot/src/share/vm/oops/klassVtable.hpp index 01495e35d90..06d55af2566 100644 --- a/hotspot/src/share/vm/oops/klassVtable.hpp +++ b/hotspot/src/share/vm/oops/klassVtable.hpp @@ -124,7 +124,7 @@ class klassVtable : public ResourceObj { // support for miranda methods bool is_miranda_entry_at(int i); - void fill_in_mirandas(int* initialized); + int fill_in_mirandas(int initialized); static bool is_miranda(Method* m, Array* class_methods, Klass* super); static void add_new_mirandas_to_lists( GrowableArray* new_mirandas, @@ -150,6 +150,8 @@ class klassVtable : public ResourceObj { // from_compiled_code_entry_point -> nmethod entry point // from_interpreter_entry_point -> i2cadapter class vtableEntry VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; + public: // size in words static int size() { @@ -288,12 +290,12 @@ class klassItable : public ResourceObj { #endif // INCLUDE_JVMTI // Setup of itable + static int assign_itable_indexes_for_interface(Klass* klass); + static int method_count_for_interface(Klass* klass); static int compute_itable_size(Array* transitive_interfaces); static void setup_itable_offset_table(instanceKlassHandle klass); // Resolving of method to index - static int compute_itable_index(Method* m); - // ...and back again: static Method* method_for_itable_index(Klass* klass, int itable_index); // Debugging/Statistics diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index b8e60a774f3..30631fa3b61 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -509,24 +509,31 @@ bool Method::compute_has_loops_flag() { return _access_flags.has_loops(); } +bool Method::is_final_method(AccessFlags class_access_flags) const { + // or "does_not_require_vtable_entry" + // overpass can occur, is not final (reuses vtable entry) + // private methods get vtable entries for backward class compatibility. + if (is_overpass()) return false; + return is_final() || class_access_flags.is_final(); +} bool Method::is_final_method() const { - // %%% Should return true for private methods also, - // since there is no way to override them. - return is_final() || method_holder()->is_final(); + return is_final_method(method_holder()->access_flags()); } - -bool Method::is_strict_method() const { - return is_strict(); -} - - -bool Method::can_be_statically_bound() const { - if (is_final_method()) return true; +bool Method::can_be_statically_bound(AccessFlags class_access_flags) const { + if (is_final_method(class_access_flags)) return true; +#ifdef ASSERT + bool is_nonv = (vtable_index() == nonvirtual_vtable_index); + if (class_access_flags.is_interface()) assert(is_nonv == is_static(), err_msg("is_nonv=%s", is_nonv)); +#endif + assert(valid_vtable_index() || valid_itable_index(), "method must be linked before we ask this question"); return vtable_index() == nonvirtual_vtable_index; } +bool Method::can_be_statically_bound() const { + return can_be_statically_bound(method_holder()->access_flags()); +} bool Method::is_accessor() const { if (code_size() != 5) return false; @@ -967,7 +974,7 @@ bool Method::is_overridden_in(Klass* k) const { assert(ik->is_subclass_of(method_holder()), "should be subklass"); assert(ik->vtable() != NULL, "vtable should exist"); - if (vtable_index() == nonvirtual_vtable_index) { + if (!has_vtable_index()) { return false; } else { Method* vt_m = ik->method_at_vtable(vtable_index()); @@ -1959,7 +1966,7 @@ void Method::print_on(outputStream* st) const { void Method::print_value_on(outputStream* st) const { assert(is_method(), "must be method"); - st->print_cr(internal_name()); + st->print(internal_name()); print_address_on(st); st->print(" "); name()->print_value_on(st); @@ -1967,6 +1974,7 @@ void Method::print_value_on(outputStream* st) const { signature()->print_value_on(st); st->print(" in "); method_holder()->print_value_on(st); + if (WizardMode) st->print("#%d", _vtable_index); if (WizardMode) st->print("[%d,%d]", size_of_parameters(), max_locals()); if (WizardMode && code() != NULL) st->print(" ((nmethod*)%p)", code()); } diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index faaf5105994..02d2253b80a 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -448,16 +448,22 @@ class Method : public Metadata { enum VtableIndexFlag { // Valid vtable indexes are non-negative (>= 0). // These few negative values are used as sentinels. - highest_unused_vtable_index_value = -5, + itable_index_max = -10, // first itable index, growing downward + pending_itable_index = -9, // itable index will be assigned invalid_vtable_index = -4, // distinct from any valid vtable index garbage_vtable_index = -3, // not yet linked; no vtable layout yet nonvirtual_vtable_index = -2 // there is no need for vtable dispatch // 6330203 Note: Do not use -1, which was overloaded with many meanings. }; DEBUG_ONLY(bool valid_vtable_index() const { return _vtable_index >= nonvirtual_vtable_index; }) - int vtable_index() const { assert(valid_vtable_index(), ""); - return _vtable_index; } + bool has_vtable_index() const { return _vtable_index >= 0; } + int vtable_index() const { return _vtable_index; } void set_vtable_index(int index) { _vtable_index = index; } + DEBUG_ONLY(bool valid_itable_index() const { return _vtable_index <= pending_itable_index; }) + bool has_itable_index() const { return _vtable_index <= itable_index_max; } + int itable_index() const { assert(valid_itable_index(), ""); + return itable_index_max - _vtable_index; } + void set_itable_index(int index) { _vtable_index = itable_index_max - index; assert(valid_itable_index(), ""); } // interpreter entry address interpreter_entry() const { return _i2i_entry; } @@ -560,10 +566,11 @@ class Method : public Metadata { // checks method and its method holder bool is_final_method() const; - bool is_strict_method() const; + bool is_final_method(AccessFlags class_access_flags) const; // true if method needs no dynamic dispatch (final and/or no vtable entry) bool can_be_statically_bound() const; + bool can_be_statically_bound(AccessFlags class_access_flags) const; // returns true if the method has any backward branches. bool has_loops() { @@ -740,10 +747,6 @@ class Method : public Metadata { // so handles are not used to avoid deadlock. jmethodID find_jmethod_id_or_null() { return method_holder()->jmethod_id_or_null(this); } - // JNI static invoke cached itable index accessors - int cached_itable_index() { return method_holder()->cached_itable_index(method_idnum()); } - void set_cached_itable_index(int index) { method_holder()->set_cached_itable_index(method_idnum(), index); } - // Support for inlining of intrinsic methods vmIntrinsics::ID intrinsic_id() const { return (vmIntrinsics::ID) _intrinsic_id; } void set_intrinsic_id(vmIntrinsics::ID id) { _intrinsic_id = (u1) id; } diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index 765b91c142c..7ff9b2bbb6d 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -72,6 +72,8 @@ class ProfileData; // // Overlay for generic profiling data. class DataLayout VALUE_OBJ_CLASS_SPEC { + friend class VMStructs; + private: // Every data layout begins with a header. This header // contains a tag, which is used to indicate the size/layout diff --git a/hotspot/src/share/vm/oops/oop.inline.hpp b/hotspot/src/share/vm/oops/oop.inline.hpp index 9a6c1e1787b..f1823f2e2b1 100644 --- a/hotspot/src/share/vm/oops/oop.inline.hpp +++ b/hotspot/src/share/vm/oops/oop.inline.hpp @@ -69,7 +69,7 @@ inline markOop oopDesc::cas_set_mark(markOop new_mark, markOop old_mark) { } inline Klass* oopDesc::klass() const { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { return Klass::decode_klass_not_null(_metadata._compressed_klass); } else { return _metadata._klass; @@ -78,7 +78,7 @@ inline Klass* oopDesc::klass() const { inline Klass* oopDesc::klass_or_null() const volatile { // can be NULL in CMS - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { return Klass::decode_klass(_metadata._compressed_klass); } else { return _metadata._klass; @@ -86,19 +86,19 @@ inline Klass* oopDesc::klass_or_null() const volatile { } inline int oopDesc::klass_gap_offset_in_bytes() { - assert(UseCompressedKlassPointers, "only applicable to compressed klass pointers"); + assert(UseCompressedClassPointers, "only applicable to compressed klass pointers"); return oopDesc::klass_offset_in_bytes() + sizeof(narrowKlass); } inline Klass** oopDesc::klass_addr() { // Only used internally and with CMS and will not work with // UseCompressedOops - assert(!UseCompressedKlassPointers, "only supported with uncompressed klass pointers"); + assert(!UseCompressedClassPointers, "only supported with uncompressed klass pointers"); return (Klass**) &_metadata._klass; } inline narrowKlass* oopDesc::compressed_klass_addr() { - assert(UseCompressedKlassPointers, "only called by compressed klass pointers"); + assert(UseCompressedClassPointers, "only called by compressed klass pointers"); return &_metadata._compressed_klass; } @@ -106,7 +106,7 @@ inline void oopDesc::set_klass(Klass* k) { // since klasses are promoted no store check is needed assert(Universe::is_bootstrapping() || k != NULL, "must be a real Klass*"); assert(Universe::is_bootstrapping() || k->is_klass(), "not a Klass*"); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { *compressed_klass_addr() = Klass::encode_klass_not_null(k); } else { *klass_addr() = k; @@ -118,7 +118,7 @@ inline int oopDesc::klass_gap() const { } inline void oopDesc::set_klass_gap(int v) { - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { *(int*)(((intptr_t)this) + klass_gap_offset_in_bytes()) = v; } } @@ -126,7 +126,7 @@ inline void oopDesc::set_klass_gap(int v) { inline void oopDesc::set_klass_to_list_ptr(oop k) { // This is only to be used during GC, for from-space objects, so no // barrier is needed. - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { _metadata._compressed_klass = (narrowKlass)encode_heap_oop(k); // may be null (parnew overflow handling) } else { _metadata._klass = (Klass*)(address)k; @@ -135,7 +135,7 @@ inline void oopDesc::set_klass_to_list_ptr(oop k) { inline oop oopDesc::list_ptr_from_klass() { // This is only to be used during GC, for from-space objects. - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { return decode_heap_oop((narrowOop)_metadata._compressed_klass); } else { // Special case for GC diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index f9db8d39974..e747c464607 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -45,7 +45,7 @@ // in the SymbolTable bucket (the _literal field in HashtableEntry) // that points to the Symbol. All other stores of a Symbol* // to a field of a persistent variable (e.g., the _name filed in -// FieldAccessInfo or _ptr in a CPSlot) is reference counted. +// fieldDescriptor or _ptr in a CPSlot) is reference counted. // // 1) The lookup of a "name" in the SymbolTable either creates a Symbol F for // "name" and returns a pointer to F or finds a pre-existing Symbol F for diff --git a/hotspot/src/share/vm/opto/bytecodeInfo.cpp b/hotspot/src/share/vm/opto/bytecodeInfo.cpp index 45ba8d758b0..2ba7b1cf3b4 100644 --- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp +++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp @@ -123,7 +123,7 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, // Allows targeted inlining if(callee_method->should_inline()) { *wci_result = *(WarmCallInfo::always_hot()); - if (PrintInlining && Verbose) { + if (C->print_inlining() && Verbose) { CompileTask::print_inline_indent(inline_level()); tty->print_cr("Inlined method is hot: "); } @@ -137,7 +137,7 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, if(callee_method->interpreter_throwout_count() > InlineThrowCount && size < InlineThrowMaxSize ) { wci_result->set_profit(wci_result->profit() * 100); - if (PrintInlining && Verbose) { + if (C->print_inlining() && Verbose) { CompileTask::print_inline_indent(inline_level()); tty->print_cr("Inlined method with many throws (throws=%d):", callee_method->interpreter_throwout_count()); } @@ -491,7 +491,7 @@ void InlineTree::print_inlining(ciMethod* callee_method, int caller_bci, C->log()->inline_fail(inline_msg); } } - if (PrintInlining) { + if (C->print_inlining()) { C->print_inlining(callee_method, inline_level(), caller_bci, inline_msg); if (callee_method == NULL) tty->print(" callee not monotonic or profiled"); if (Verbose && callee_method) { @@ -540,7 +540,7 @@ WarmCallInfo* InlineTree::ok_to_inline(ciMethod* callee_method, JVMState* jvms, #ifndef PRODUCT if (UseOldInlining && InlineWarmCalls - && (PrintOpto || PrintOptoInlining || PrintInlining)) { + && (PrintOpto || C->print_inlining())) { bool cold = wci.is_cold(); bool hot = !cold && wci.is_hot(); bool old_cold = !success; @@ -617,7 +617,7 @@ InlineTree *InlineTree::build_inline_tree_for_callee( ciMethod* callee_method, J callee_method->is_compiled_lambda_form()) { max_inline_level_adjust += 1; // don't count method handle calls from java.lang.invoke implem } - if (max_inline_level_adjust != 0 && PrintInlining && (Verbose || WizardMode)) { + if (max_inline_level_adjust != 0 && C->print_inlining() && (Verbose || WizardMode)) { CompileTask::print_inline_indent(inline_level()); tty->print_cr(" \\-> discounting inline depth"); } diff --git a/hotspot/src/share/vm/opto/c2_globals.hpp b/hotspot/src/share/vm/opto/c2_globals.hpp index 15d8befbbac..cf9a82092fd 100644 --- a/hotspot/src/share/vm/opto/c2_globals.hpp +++ b/hotspot/src/share/vm/opto/c2_globals.hpp @@ -421,7 +421,7 @@ product(bool, UseDivMod, true, \ "Use combined DivMod instruction if available") \ \ - product(intx, MinJumpTableSize, 18, \ + product_pd(intx, MinJumpTableSize, \ "Minimum number of targets in a generated jump table") \ \ product(intx, MaxJumpTableSize, 65000, \ @@ -448,6 +448,9 @@ product(bool, EliminateAutoBox, true, \ "Control optimizations for autobox elimination") \ \ + experimental(bool, UseImplicitStableValues, false, \ + "Mark well-known stable fields as such (e.g. String.value)") \ + \ product(intx, AutoBoxCacheMax, 128, \ "Sets max value cached by the java.lang.Integer autobox cache") \ \ diff --git a/hotspot/src/share/vm/opto/callGenerator.hpp b/hotspot/src/share/vm/opto/callGenerator.hpp index 0f6b2d16590..a1616de4dc7 100644 --- a/hotspot/src/share/vm/opto/callGenerator.hpp +++ b/hotspot/src/share/vm/opto/callGenerator.hpp @@ -159,8 +159,9 @@ class CallGenerator : public ResourceObj { virtual void print_inlining_late(const char* msg) { ShouldNotReachHere(); } static void print_inlining(Compile* C, ciMethod* callee, int inline_level, int bci, const char* msg) { - if (PrintInlining) + if (C->print_inlining()) { C->print_inlining(callee, inline_level, bci, msg); + } } }; diff --git a/hotspot/src/share/vm/opto/cfgnode.cpp b/hotspot/src/share/vm/opto/cfgnode.cpp index 4185ada5d1c..36347fb9202 100644 --- a/hotspot/src/share/vm/opto/cfgnode.cpp +++ b/hotspot/src/share/vm/opto/cfgnode.cpp @@ -1932,7 +1932,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { #ifdef _LP64 // Push DecodeN/DecodeNKlass down through phi. // The rest of phi graph will transform by split EncodeP node though phis up. - if ((UseCompressedOops || UseCompressedKlassPointers) && can_reshape && progress == NULL) { + if ((UseCompressedOops || UseCompressedClassPointers) && can_reshape && progress == NULL) { bool may_push = true; bool has_decodeN = false; bool is_decodeN = false; diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index a1a0e1c1fb7..492bf384f2f 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -122,40 +122,23 @@ double LRG::score() const { return score; } -LRG_List::LRG_List( uint max ) : _cnt(max), _max(max), _lidxs(NEW_RESOURCE_ARRAY(uint,max)) { - memset( _lidxs, 0, sizeof(uint)*max ); -} - -void LRG_List::extend( uint nidx, uint lidx ) { - _nesting.check(); - if( nidx >= _max ) { - uint size = 16; - while( size <= nidx ) size <<=1; - _lidxs = REALLOC_RESOURCE_ARRAY( uint, _lidxs, _max, size ); - _max = size; - } - while( _cnt <= nidx ) - _lidxs[_cnt++] = 0; - _lidxs[nidx] = lidx; -} - #define NUMBUCKS 3 // Straight out of Tarjan's union-find algorithm uint LiveRangeMap::find_compress(uint lrg) { uint cur = lrg; - uint next = _uf_map[cur]; + uint next = _uf_map.at(cur); while (next != cur) { // Scan chain of equivalences assert( next < cur, "always union smaller"); cur = next; // until find a fixed-point - next = _uf_map[cur]; + next = _uf_map.at(cur); } // Core of union-find algorithm: update chain of // equivalences to be equal to the root. while (lrg != next) { - uint tmp = _uf_map[lrg]; - _uf_map.map(lrg, next); + uint tmp = _uf_map.at(lrg); + _uf_map.at_put(lrg, next); lrg = tmp; } return lrg; @@ -165,10 +148,10 @@ uint LiveRangeMap::find_compress(uint lrg) { void LiveRangeMap::reset_uf_map(uint max_lrg_id) { _max_lrg_id= max_lrg_id; // Force the Union-Find mapping to be at least this large - _uf_map.extend(_max_lrg_id, 0); + _uf_map.at_put_grow(_max_lrg_id, 0); // Initialize it to be the ID mapping. for (uint i = 0; i < _max_lrg_id; ++i) { - _uf_map.map(i, i); + _uf_map.at_put(i, i); } } @@ -176,12 +159,12 @@ void LiveRangeMap::reset_uf_map(uint max_lrg_id) { // the Union-Find mapping after this call. void LiveRangeMap::compress_uf_map_for_nodes() { // For all Nodes, compress mapping - uint unique = _names.Size(); + uint unique = _names.length(); for (uint i = 0; i < unique; ++i) { - uint lrg = _names[i]; + uint lrg = _names.at(i); uint compressed_lrg = find(lrg); if (lrg != compressed_lrg) { - _names.map(i, compressed_lrg); + _names.at_put(i, compressed_lrg); } } } @@ -198,11 +181,11 @@ uint LiveRangeMap::find_const(uint lrg) const { return lrg; } - uint next = _uf_map[lrg]; + uint next = _uf_map.at(lrg); while (next != lrg) { // Scan chain of equivalences assert(next < lrg, "always union smaller"); lrg = next; // until find a fixed-point - next = _uf_map[lrg]; + next = _uf_map.at(lrg); } return next; } @@ -215,7 +198,7 @@ PhaseChaitin::PhaseChaitin(uint unique, PhaseCFG &cfg, Matcher &matcher) NULL #endif ) - , _lrg_map(unique) + , _lrg_map(Thread::current()->resource_area(), unique) , _live(0) , _spilled_once(Thread::current()->resource_area()) , _spilled_twice(Thread::current()->resource_area()) @@ -692,6 +675,7 @@ void PhaseChaitin::de_ssa() { _lrg_map.map(n->_idx, rm.is_NotEmpty() ? lr_counter++ : 0); } } + // Reset the Union-Find mapping to be identity _lrg_map.reset_uf_map(lr_counter); } diff --git a/hotspot/src/share/vm/opto/chaitin.hpp b/hotspot/src/share/vm/opto/chaitin.hpp index c951024ee75..41276efa5ca 100644 --- a/hotspot/src/share/vm/opto/chaitin.hpp +++ b/hotspot/src/share/vm/opto/chaitin.hpp @@ -283,8 +283,8 @@ private: // Straight out of Tarjan's union-find algorithm uint find_compress(const Node *node) { - uint lrg_id = find_compress(_names[node->_idx]); - _names.map(node->_idx, lrg_id); + uint lrg_id = find_compress(_names.at(node->_idx)); + _names.at_put(node->_idx, lrg_id); return lrg_id; } @@ -305,40 +305,40 @@ public: } uint size() const { - return _names.Size(); + return _names.length(); } uint live_range_id(uint idx) const { - return _names[idx]; + return _names.at(idx); } uint live_range_id(const Node *node) const { - return _names[node->_idx]; + return _names.at(node->_idx); } uint uf_live_range_id(uint lrg_id) const { - return _uf_map[lrg_id]; + return _uf_map.at(lrg_id); } void map(uint idx, uint lrg_id) { - _names.map(idx, lrg_id); + _names.at_put(idx, lrg_id); } void uf_map(uint dst_lrg_id, uint src_lrg_id) { - _uf_map.map(dst_lrg_id, src_lrg_id); + _uf_map.at_put(dst_lrg_id, src_lrg_id); } void extend(uint idx, uint lrg_id) { - _names.extend(idx, lrg_id); + _names.at_put_grow(idx, lrg_id); } void uf_extend(uint dst_lrg_id, uint src_lrg_id) { - _uf_map.extend(dst_lrg_id, src_lrg_id); + _uf_map.at_put_grow(dst_lrg_id, src_lrg_id); } - LiveRangeMap(uint unique) - : _names(unique) - , _uf_map(unique) + LiveRangeMap(Arena* arena, uint unique) + : _names(arena, unique, unique, 0) + , _uf_map(arena, unique, unique, 0) , _max_lrg_id(0) {} uint find_id( const Node *n ) { @@ -355,14 +355,14 @@ public: void compress_uf_map_for_nodes(); uint find(uint lidx) { - uint uf_lidx = _uf_map[lidx]; + uint uf_lidx = _uf_map.at(lidx); return (uf_lidx == lidx) ? uf_lidx : find_compress(lidx); } // Convert a Node into a Live Range Index - a lidx uint find(const Node *node) { uint lidx = live_range_id(node); - uint uf_lidx = _uf_map[lidx]; + uint uf_lidx = _uf_map.at(lidx); return (uf_lidx == lidx) ? uf_lidx : find_compress(node); } @@ -371,10 +371,10 @@ public: // Like Find above, but no path compress, so bad asymptotic behavior uint find_const(const Node *node) const { - if(node->_idx >= _names.Size()) { + if(node->_idx >= (uint)_names.length()) { return 0; // not mapped, usual for debug dump } - return find_const(_names[node->_idx]); + return find_const(_names.at(node->_idx)); } }; diff --git a/hotspot/src/share/vm/opto/coalesce.hpp b/hotspot/src/share/vm/opto/coalesce.hpp index a6359af101c..3a361b25f11 100644 --- a/hotspot/src/share/vm/opto/coalesce.hpp +++ b/hotspot/src/share/vm/opto/coalesce.hpp @@ -29,7 +29,6 @@ class LoopTree; class LRG; -class LRG_List; class Matcher; class PhaseIFG; class PhaseCFG; diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index b426bcce1a2..0fed4e06c72 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -654,7 +654,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr _inlining_progress(false), _inlining_incrementally(false), _print_inlining_list(NULL), - _print_inlining(0) { + _print_inlining_idx(0) { C = this; CompileWrapper cw(this); @@ -679,6 +679,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr set_print_assembly(print_opto_assembly); set_parsed_irreducible_loop(false); #endif + set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining)); + set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics")); if (ProfileTraps) { // Make sure the method being compiled gets its own MDO, @@ -710,7 +712,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr PhaseGVN gvn(node_arena(), estimated_size); set_initial_gvn(&gvn); - if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) { + if (print_inlining() || print_intrinsics()) { _print_inlining_list = new (comp_arena())GrowableArray(comp_arena(), 1, 1, PrintInliningBuffer()); } { // Scope for timing the parser @@ -937,7 +939,7 @@ Compile::Compile( ciEnv* ci_env, _inlining_progress(false), _inlining_incrementally(false), _print_inlining_list(NULL), - _print_inlining(0) { + _print_inlining_idx(0) { C = this; #ifndef PRODUCT @@ -1297,6 +1299,10 @@ const TypePtr *Compile::flatten_alias_type( const TypePtr *tj ) const { // Array pointers need some flattening const TypeAryPtr *ta = tj->isa_aryptr(); + if (ta && ta->is_stable()) { + // Erase stability property for alias analysis. + tj = ta = ta->cast_to_stable(false); + } if( ta && is_known_inst ) { if ( offset != Type::OffsetBot && offset > arrayOopDesc::length_offset_in_bytes() ) { @@ -1497,6 +1503,7 @@ void Compile::AliasType::Init(int i, const TypePtr* at) { _index = i; _adr_type = at; _field = NULL; + _element = NULL; _is_rewritable = true; // default const TypeOopPtr *atoop = (at != NULL) ? at->isa_oopptr() : NULL; if (atoop != NULL && atoop->is_known_instance()) { @@ -1615,6 +1622,16 @@ Compile::AliasType* Compile::find_alias_type(const TypePtr* adr_type, bool no_cr && flat->is_instptr()->klass() == env()->Class_klass()) alias_type(idx)->set_rewritable(false); } + if (flat->isa_aryptr()) { +#ifdef ASSERT + const int header_size_min = arrayOopDesc::base_offset_in_bytes(T_BYTE); + // (T_BYTE has the weakest alignment and size restrictions...) + assert(flat->offset() < header_size_min, "array body reference must be OffsetBot"); +#endif + if (flat->offset() == TypePtr::OffsetBot) { + alias_type(idx)->set_element(flat->is_aryptr()->elem()); + } + } if (flat->isa_klassptr()) { if (flat->offset() == in_bytes(Klass::super_check_offset_offset())) alias_type(idx)->set_rewritable(false); @@ -1677,7 +1694,7 @@ Compile::AliasType* Compile::alias_type(ciField* field) { else t = TypeOopPtr::make_from_klass_raw(field->holder()); AliasType* atp = alias_type(t->add_offset(field->offset_in_bytes()), field); - assert(field->is_final() == !atp->is_rewritable(), "must get the rewritable bits correct"); + assert((field->is_final() || field->is_stable()) == !atp->is_rewritable(), "must get the rewritable bits correct"); return atp; } @@ -2631,7 +2648,7 @@ void Compile::final_graph_reshaping_impl( Node *n, Final_Reshape_Counts &frc) { addp->in(AddPNode::Base) == n->in(AddPNode::Base), "Base pointers must match" ); #ifdef _LP64 - if ((UseCompressedOops || UseCompressedKlassPointers) && + if ((UseCompressedOops || UseCompressedClassPointers) && addp->Opcode() == Op_ConP && addp == n->in(AddPNode::Base) && n->in(AddPNode::Offset)->is_Con()) { @@ -3018,7 +3035,7 @@ void Compile::final_graph_reshaping_walk( Node_Stack &nstack, Node *root, Final_ // Skip next transformation if compressed oops are not used. if ((UseCompressedOops && !Matcher::gen_narrow_oop_implicit_null_checks()) || - (!UseCompressedOops && !UseCompressedKlassPointers)) + (!UseCompressedOops && !UseCompressedClassPointers)) return; // Go over safepoints nodes to skip DecodeN/DecodeNKlass nodes for debug edges. @@ -3596,7 +3613,7 @@ void Compile::ConstantTable::fill_jump_table(CodeBuffer& cb, MachConstantNode* n } void Compile::dump_inlining() { - if (PrintInlining || PrintIntrinsics NOT_PRODUCT( || PrintOptoInlining)) { + if (print_inlining() || print_intrinsics()) { // Print inlining message for candidates that we couldn't inline // for lack of space or non constant receiver for (int i = 0; i < _late_inlines.length(); i++) { @@ -3620,7 +3637,7 @@ void Compile::dump_inlining() { } } for (int i = 0; i < _print_inlining_list->length(); i++) { - tty->print(_print_inlining_list->at(i).ss()->as_string()); + tty->print(_print_inlining_list->adr_at(i)->ss()->as_string()); } } } diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 60787464bd0..631372efabc 100644 --- a/hotspot/src/share/vm/opto/compile.hpp +++ b/hotspot/src/share/vm/opto/compile.hpp @@ -72,6 +72,7 @@ class Scope; class StartNode; class SafePointNode; class JVMState; +class Type; class TypeData; class TypePtr; class TypeOopPtr; @@ -119,6 +120,7 @@ class Compile : public Phase { int _index; // unique index, used with MergeMemNode const TypePtr* _adr_type; // normalized address type ciField* _field; // relevant instance field, or null if none + const Type* _element; // relevant array element type, or null if none bool _is_rewritable; // false if the memory is write-once only int _general_index; // if this is type is an instance, the general // type that this is an instance of @@ -129,6 +131,7 @@ class Compile : public Phase { int index() const { return _index; } const TypePtr* adr_type() const { return _adr_type; } ciField* field() const { return _field; } + const Type* element() const { return _element; } bool is_rewritable() const { return _is_rewritable; } bool is_volatile() const { return (_field ? _field->is_volatile() : false); } int general_index() const { return (_general_index != 0) ? _general_index : _index; } @@ -137,7 +140,14 @@ class Compile : public Phase { void set_field(ciField* f) { assert(!_field,""); _field = f; - if (f->is_final()) _is_rewritable = false; + if (f->is_final() || f->is_stable()) { + // In the case of @Stable, multiple writes are possible but may be assumed to be no-ops. + _is_rewritable = false; + } + } + void set_element(const Type* e) { + assert(_element == NULL, ""); + _element = e; } void print_on(outputStream* st) PRODUCT_RETURN; @@ -302,6 +312,8 @@ class Compile : public Phase { bool _do_method_data_update; // True if we generate code to update MethodData*s int _AliasLevel; // Locally-adjusted version of AliasLevel flag. bool _print_assembly; // True if we should dump assembly code for this compilation + bool _print_inlining; // True if we should print inlining for this compilation + bool _print_intrinsics; // True if we should print intrinsics for this compilation #ifndef PRODUCT bool _trace_opto_output; bool _parsed_irreducible_loop; // True if ciTypeFlow detected irreducible loops during parsing @@ -404,7 +416,7 @@ class Compile : public Phase { }; GrowableArray* _print_inlining_list; - int _print_inlining; + int _print_inlining_idx; // Only keep nodes in the expensive node list that need to be optimized void cleanup_expensive_nodes(PhaseIterGVN &igvn); @@ -416,24 +428,24 @@ class Compile : public Phase { public: outputStream* print_inlining_stream() const { - return _print_inlining_list->at(_print_inlining).ss(); + return _print_inlining_list->adr_at(_print_inlining_idx)->ss(); } void print_inlining_skip(CallGenerator* cg) { - if (PrintInlining) { - _print_inlining_list->at(_print_inlining).set_cg(cg); - _print_inlining++; - _print_inlining_list->insert_before(_print_inlining, PrintInliningBuffer()); + if (_print_inlining) { + _print_inlining_list->adr_at(_print_inlining_idx)->set_cg(cg); + _print_inlining_idx++; + _print_inlining_list->insert_before(_print_inlining_idx, PrintInliningBuffer()); } } void print_inlining_insert(CallGenerator* cg) { - if (PrintInlining) { + if (_print_inlining) { for (int i = 0; i < _print_inlining_list->length(); i++) { - if (_print_inlining_list->at(i).cg() == cg) { + if (_print_inlining_list->adr_at(i)->cg() == cg) { _print_inlining_list->insert_before(i+1, PrintInliningBuffer()); - _print_inlining = i+1; - _print_inlining_list->at(i).set_cg(NULL); + _print_inlining_idx = i+1; + _print_inlining_list->adr_at(i)->set_cg(NULL); return; } } @@ -562,6 +574,10 @@ class Compile : public Phase { int AliasLevel() const { return _AliasLevel; } bool print_assembly() const { return _print_assembly; } void set_print_assembly(bool z) { _print_assembly = z; } + bool print_inlining() const { return _print_inlining; } + void set_print_inlining(bool z) { _print_inlining = z; } + bool print_intrinsics() const { return _print_intrinsics; } + void set_print_intrinsics(bool z) { _print_intrinsics = z; } // check the CompilerOracle for special behaviours for this compile bool method_has_option(const char * option) { return method() != NULL && method()->has_option(option); diff --git a/hotspot/src/share/vm/opto/connode.cpp b/hotspot/src/share/vm/opto/connode.cpp index eb343a822e5..b59025ad4f3 100644 --- a/hotspot/src/share/vm/opto/connode.cpp +++ b/hotspot/src/share/vm/opto/connode.cpp @@ -630,7 +630,7 @@ const Type *EncodePKlassNode::Value( PhaseTransform *phase ) const { if (t == Type::TOP) return Type::TOP; assert (t != TypePtr::NULL_PTR, "null klass?"); - assert(UseCompressedKlassPointers && t->isa_klassptr(), "only klass ptr here"); + assert(UseCompressedClassPointers && t->isa_klassptr(), "only klass ptr here"); return t->make_narrowklass(); } diff --git a/hotspot/src/share/vm/opto/doCall.cpp b/hotspot/src/share/vm/opto/doCall.cpp index e55a01ba638..8784bbe2dc5 100644 --- a/hotspot/src/share/vm/opto/doCall.cpp +++ b/hotspot/src/share/vm/opto/doCall.cpp @@ -41,9 +41,9 @@ #include "runtime/sharedRuntime.hpp" void trace_type_profile(Compile* C, ciMethod *method, int depth, int bci, ciMethod *prof_method, ciKlass *prof_klass, int site_count, int receiver_count) { - if (TraceTypeProfile || PrintInlining NOT_PRODUCT(|| PrintOptoInlining)) { + if (TraceTypeProfile || C->print_inlining()) { outputStream* out = tty; - if (!PrintInlining) { + if (!C->print_inlining()) { if (NOT_PRODUCT(!PrintOpto &&) !PrintCompilation) { method->print_short_name(); tty->cr(); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index 18772dfd0a8..dcdd104ee72 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -3825,8 +3825,13 @@ Node* GraphKit::load_String_value(Node* ctrl, Node* str) { TypeAry::make(TypeInt::CHAR,TypeInt::POS), ciTypeArrayKlass::make(T_CHAR), true, 0); int value_field_idx = C->get_alias_index(value_field_type); - return make_load(ctrl, basic_plus_adr(str, str, value_offset), - value_type, T_OBJECT, value_field_idx); + Node* load = make_load(ctrl, basic_plus_adr(str, str, value_offset), + value_type, T_OBJECT, value_field_idx); + // String.value field is known to be @Stable. + if (UseImplicitStableValues) { + load = cast_array_to_stable(load, value_type); + } + return load; } void GraphKit::store_String_offset(Node* ctrl, Node* str, Node* value) { @@ -3844,9 +3849,6 @@ void GraphKit::store_String_value(Node* ctrl, Node* str, Node* value) { const TypeInstPtr* string_type = TypeInstPtr::make(TypePtr::NotNull, C->env()->String_klass(), false, NULL, 0); const TypePtr* value_field_type = string_type->add_offset(value_offset); - const TypeAryPtr* value_type = TypeAryPtr::make(TypePtr::NotNull, - TypeAry::make(TypeInt::CHAR,TypeInt::POS), - ciTypeArrayKlass::make(T_CHAR), true, 0); int value_field_idx = C->get_alias_index(value_field_type); store_to_memory(ctrl, basic_plus_adr(str, value_offset), value, T_OBJECT, value_field_idx); @@ -3861,3 +3863,9 @@ void GraphKit::store_String_length(Node* ctrl, Node* str, Node* value) { store_to_memory(ctrl, basic_plus_adr(str, count_offset), value, T_INT, count_field_idx); } + +Node* GraphKit::cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type) { + // Reify the property as a CastPP node in Ideal graph to comply with monotonicity + // assumption of CCP analysis. + return _gvn.transform(new(C) CastPPNode(ary, ary_type->cast_to_stable(true))); +} diff --git a/hotspot/src/share/vm/opto/graphKit.hpp b/hotspot/src/share/vm/opto/graphKit.hpp index e9d102cb6c5..1fd4e86d2e7 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -836,6 +836,9 @@ class GraphKit : public Phase { // Insert a loop predicate into the graph void add_predicate(int nargs = 0); void add_predicate_impl(Deoptimization::DeoptReason reason, int nargs); + + // Produce new array node of stable type + Node* cast_array_to_stable(Node* ary, const TypeAryPtr* ary_type); }; // Helper class to support building of control flow branches. Upon diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 60525d73ef7..902ed5919f3 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -543,7 +543,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { Compile* C = kit.C; int nodes = C->unique(); #ifndef PRODUCT - if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { char buf[1000]; const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); tty->print_cr("Intrinsic %s", str); @@ -554,7 +554,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { // Try to inline the intrinsic. if (kit.try_to_inline()) { - if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { + if (C->print_intrinsics() || C->print_inlining()) { C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); @@ -570,7 +570,7 @@ JVMState* LibraryIntrinsic::generate(JVMState* jvms) { } // The intrinsic bailed out - if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { + if (C->print_intrinsics() || C->print_inlining()) { if (jvms->has_method()) { // Not a root compile. const char* msg = is_virtual() ? "failed to inline (intrinsic, virtual)" : "failed to inline (intrinsic)"; @@ -592,7 +592,7 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { int nodes = C->unique(); #ifndef PRODUCT assert(is_predicted(), "sanity"); - if ((PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { char buf[1000]; const char* str = vmIntrinsics::short_name_as_C_string(intrinsic_id(), buf, sizeof(buf)); tty->print_cr("Predicate for intrinsic %s", str); @@ -603,7 +603,7 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { Node* slow_ctl = kit.try_to_predicate(); if (!kit.failing()) { - if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { + if (C->print_intrinsics() || C->print_inlining()) { C->print_inlining(callee, jvms->depth() - 1, bci, is_virtual() ? "(intrinsic, virtual)" : "(intrinsic)"); } C->gather_intrinsic_statistics(intrinsic_id(), is_virtual(), Compile::_intrinsic_worked); @@ -617,7 +617,7 @@ Node* LibraryIntrinsic::generate_predicate(JVMState* jvms) { } // The intrinsic bailed out - if (PrintIntrinsics || PrintInlining NOT_PRODUCT( || PrintOptoInlining) ) { + if (C->print_intrinsics() || C->print_inlining()) { if (jvms->has_method()) { // Not a root compile. const char* msg = "failed to generate predicate for intrinsic"; @@ -1280,6 +1280,11 @@ Node* LibraryCallKit::string_indexOf(Node* string_object, ciTypeArray* target_ar const TypeAry* target_array_type = TypeAry::make(TypeInt::CHAR, TypeInt::make(0, target_length, Type::WidenMin)); const TypeAryPtr* target_type = TypeAryPtr::make(TypePtr::BotPTR, target_array_type, target_array->klass(), true, Type::OffsetBot); + // String.value field is known to be @Stable. + if (UseImplicitStableValues) { + target = cast_array_to_stable(target, target_type); + } + IdealKit kit(this, false, true); #define __ kit. Node* zero = __ ConI(0); @@ -2294,7 +2299,7 @@ const TypeOopPtr* LibraryCallKit::sharpen_unsafe_type(Compile::AliasType* alias_ const TypeOopPtr* tjp = TypeOopPtr::make_from_klass(sharpened_klass); #ifndef PRODUCT - if (PrintIntrinsics || PrintInlining || PrintOptoInlining) { + if (C->print_intrinsics() || C->print_inlining()) { tty->print(" from base type: "); adr_type->dump(); tty->print(" sharpened value: "); tjp->dump(); } @@ -3255,7 +3260,7 @@ bool LibraryCallKit::inline_native_Class_query(vmIntrinsics::ID id) { if (mirror_con == NULL) return false; // cannot happen? #ifndef PRODUCT - if (PrintIntrinsics || PrintInlining || PrintOptoInlining) { + if (C->print_intrinsics() || C->print_inlining()) { ciType* k = mirror_con->java_mirror_type(); if (k) { tty->print("Inlining %s on constant Class ", vmIntrinsics::name_at(intrinsic_id())); @@ -3729,6 +3734,8 @@ Node* LibraryCallKit::generate_virtual_guard(Node* obj_klass, RegionNode* slow_region) { ciMethod* method = callee(); int vtable_index = method->vtable_index(); + assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, + err_msg_res("bad index %d", vtable_index)); // Get the Method* out of the appropriate vtable entry. int entry_offset = (InstanceKlass::vtable_start_offset() + vtable_index*vtableEntry::size()) * wordSize + @@ -3779,6 +3786,8 @@ LibraryCallKit::generate_method_call(vmIntrinsics::ID method_id, bool is_virtual // so the vtable index is fixed. // No need to use the linkResolver to get it. vtable_index = method->vtable_index(); + assert(vtable_index >= 0 || vtable_index == Method::nonvirtual_vtable_index, + err_msg_res("bad index %d", vtable_index)); } slow_call = new(C) CallDynamicJavaNode(tf, SharedRuntime::get_resolve_virtual_call_stub(), @@ -3943,14 +3952,14 @@ bool LibraryCallKit::inline_native_getClass() { // caller sensitive methods. bool LibraryCallKit::inline_native_Reflection_getCallerClass() { #ifndef PRODUCT - if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { tty->print_cr("Attempting to inline sun.reflect.Reflection.getCallerClass"); } #endif if (!jvms()->has_method()) { #ifndef PRODUCT - if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { tty->print_cr(" Bailing out because intrinsic was inlined at top level"); } #endif @@ -3974,7 +3983,7 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { // Frame 0 and 1 must be caller sensitive (see JVM_GetCallerClass). if (!m->caller_sensitive()) { #ifndef PRODUCT - if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { tty->print_cr(" Bailing out: CallerSensitive annotation expected at frame %d", n); } #endif @@ -3990,7 +3999,7 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { set_result(makecon(TypeInstPtr::make(caller_mirror))); #ifndef PRODUCT - if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { tty->print_cr(" Succeeded: caller = %d) %s.%s, JVMS depth = %d", n, caller_klass->name()->as_utf8(), caller_jvms->method()->name()->as_utf8(), jvms()->depth()); tty->print_cr(" JVM state at this point:"); for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) { @@ -4006,7 +4015,7 @@ bool LibraryCallKit::inline_native_Reflection_getCallerClass() { } #ifndef PRODUCT - if ((PrintIntrinsics || PrintInlining || PrintOptoInlining) && Verbose) { + if ((C->print_intrinsics() || C->print_inlining()) && Verbose) { tty->print_cr(" Bailing out because caller depth exceeded inlining depth = %d", jvms()->depth()); tty->print_cr(" JVM state at this point:"); for (int i = jvms()->depth(), n = 1; i >= 1; i--, n++) { @@ -4199,7 +4208,7 @@ void LibraryCallKit::copy_to_clone(Node* obj, Node* alloc_obj, Node* obj_size, b // 12 - 64-bit VM, compressed klass // 16 - 64-bit VM, normal klass if (base_off % BytesPerLong != 0) { - assert(UseCompressedKlassPointers, ""); + assert(UseCompressedClassPointers, ""); if (is_array) { // Exclude length to copy by 8 bytes words. base_off += sizeof(int); diff --git a/hotspot/src/share/vm/opto/live.cpp b/hotspot/src/share/vm/opto/live.cpp index 280d22204c2..02bbb1b97ab 100644 --- a/hotspot/src/share/vm/opto/live.cpp +++ b/hotspot/src/share/vm/opto/live.cpp @@ -91,7 +91,7 @@ void PhaseLive::compute(uint maxlrg) { break; } - uint r = _names[n->_idx]; + uint r = _names.at(n->_idx); assert(!def_outside->member(r), "Use of external LRG overlaps the same LRG defined in this block"); def->insert( r ); use->remove( r ); @@ -100,7 +100,7 @@ void PhaseLive::compute(uint maxlrg) { Node *nk = n->in(k); uint nkidx = nk->_idx; if (_cfg.get_block_for_node(nk) != block) { - uint u = _names[nkidx]; + uint u = _names.at(nkidx); use->insert(u); DEBUG_ONLY(def_outside->insert(u);) } @@ -112,7 +112,7 @@ void PhaseLive::compute(uint maxlrg) { #endif // Remove anything defined by Phis and the block start instruction for (uint k = i; k > 0; k--) { - uint r = _names[block->get_node(k - 1)->_idx]; + uint r = _names.at(block->get_node(k - 1)->_idx); def->insert(r); use->remove(r); } @@ -124,7 +124,7 @@ void PhaseLive::compute(uint maxlrg) { // PhiNode uses go in the live-out set of prior blocks. for (uint k = i; k > 0; k--) { - add_liveout(p, _names[block->get_node(k-1)->in(l)->_idx], first_pass); + add_liveout(p, _names.at(block->get_node(k-1)->in(l)->_idx), first_pass); } } freeset(block); @@ -256,7 +256,7 @@ void PhaseLive::dump( const Block *b ) const { tty->print("LiveOut: "); _live[b->_pre_order-1].dump(); uint cnt = b->number_of_nodes(); for( uint i=0; iprint("L%d/", _names[b->get_node(i)->_idx] ); + tty->print("L%d/", _names.at(b->get_node(i)->_idx)); b->get_node(i)->dump(); } tty->print("\n"); @@ -321,7 +321,7 @@ void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const { #ifdef _LP64 UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_CastPP || UseCompressedOops && check->as_Mach()->ideal_Opcode() == Op_DecodeN || - UseCompressedKlassPointers && check->as_Mach()->ideal_Opcode() == Op_DecodeNKlass || + UseCompressedClassPointers && check->as_Mach()->ideal_Opcode() == Op_DecodeNKlass || #endif check->as_Mach()->ideal_Opcode() == Op_LoadP || check->as_Mach()->ideal_Opcode() == Op_LoadKlass)) { diff --git a/hotspot/src/share/vm/opto/live.hpp b/hotspot/src/share/vm/opto/live.hpp index c2ebe758cf8..e449bb3f3a6 100644 --- a/hotspot/src/share/vm/opto/live.hpp +++ b/hotspot/src/share/vm/opto/live.hpp @@ -40,27 +40,7 @@ class IndexSet; //------------------------------LRG_List--------------------------------------- // Map Node indices to Live RanGe indices. // Array lookup in the optimized case. -class LRG_List : public ResourceObj { - friend class VMStructs; - uint _cnt, _max; - uint* _lidxs; - ReallocMark _nesting; // assertion check for reallocations -public: - LRG_List( uint max ); - - uint lookup( uint nidx ) const { - return _lidxs[nidx]; - } - uint operator[] (uint nidx) const { return lookup(nidx); } - - void map( uint nidx, uint lidx ) { - assert( nidx < _cnt, "oob" ); - _lidxs[nidx] = lidx; - } - void extend( uint nidx, uint lidx ); - - uint Size() const { return _cnt; } -}; +typedef GrowableArray LRG_List; //------------------------------PhaseLive-------------------------------------- // Compute live-in/live-out diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 137c529ed0c..06bf9e608c0 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -2191,7 +2191,7 @@ void PhaseMacroExpand::expand_lock_node(LockNode *lock) { Node* k_adr = basic_plus_adr(obj, oopDesc::klass_offset_in_bytes()); klass_node = transform_later( LoadKlassNode::make(_igvn, mem, k_adr, _igvn.type(k_adr)->is_ptr()) ); #ifdef _LP64 - if (UseCompressedKlassPointers && klass_node->is_DecodeNKlass()) { + if (UseCompressedClassPointers && klass_node->is_DecodeNKlass()) { assert(klass_node->in(1)->Opcode() == Op_LoadNKlass, "sanity"); klass_node->in(1)->init_req(0, ctrl); } else diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index aa03b5ff6c5..49694b6e92e 100644 --- a/hotspot/src/share/vm/opto/memnode.cpp +++ b/hotspot/src/share/vm/opto/memnode.cpp @@ -962,6 +962,19 @@ uint LoadNode::hash() const { return (uintptr_t)in(Control) + (uintptr_t)in(Memory) + (uintptr_t)in(Address); } +static bool skip_through_membars(Compile::AliasType* atp, const TypeInstPtr* tp, bool eliminate_boxing) { + if ((atp != NULL) && (atp->index() >= Compile::AliasIdxRaw)) { + bool non_volatile = (atp->field() != NULL) && !atp->field()->is_volatile(); + bool is_stable_ary = FoldStableValues && + (tp != NULL) && (tp->isa_aryptr() != NULL) && + tp->isa_aryptr()->is_stable(); + + return (eliminate_boxing && non_volatile) || is_stable_ary; + } + + return false; +} + //---------------------------can_see_stored_value------------------------------ // This routine exists to make sure this set of tests is done the same // everywhere. We need to make a coordinated change: first LoadNode::Ideal @@ -976,11 +989,9 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { const TypeInstPtr* tp = phase->type(ld_adr)->isa_instptr(); Compile::AliasType* atp = (tp != NULL) ? phase->C->alias_type(tp) : NULL; // This is more general than load from boxing objects. - if (phase->C->eliminate_boxing() && (atp != NULL) && - (atp->index() >= Compile::AliasIdxRaw) && - (atp->field() != NULL) && !atp->field()->is_volatile()) { + if (skip_through_membars(atp, tp, phase->C->eliminate_boxing())) { uint alias_idx = atp->index(); - bool final = atp->field()->is_final(); + bool final = !atp->is_rewritable(); Node* result = NULL; Node* current = st; // Skip through chains of MemBarNodes checking the MergeMems for @@ -1015,7 +1026,6 @@ Node* MemNode::can_see_stored_value(Node* st, PhaseTransform* phase) const { } } - // Loop around twice in the case Load -> Initialize -> Store. // (See PhaseIterGVN::add_users_to_worklist, which knows about this case.) for (int trip = 0; trip <= 1; trip++) { @@ -1577,6 +1587,40 @@ LoadNode::load_array_final_field(const TypeKlassPtr *tkls, return NULL; } +// Try to constant-fold a stable array element. +static const Type* fold_stable_ary_elem(const TypeAryPtr* ary, int off, BasicType loadbt) { + assert(ary->is_stable(), "array should be stable"); + + if (ary->const_oop() != NULL) { + // 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()) { + const Type* con_type = Type::make_from_constant(con); + if (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(); + con_type = con_type->is_aryptr()->cast_to_stable(true, dim-1); + } + if (loadbt == T_NARROWOOP && con_type->isa_oopptr()) { + con_type = con_type->make_narrowoop(); + } +#ifndef PRODUCT + if (TraceIterativeGVN) { + tty->print("FoldStableValues: array element [off=%d]: con_type=", off); + con_type->dump(); tty->cr(); + } +#endif //PRODUCT + return con_type; + } + } + } + + return NULL; +} + //------------------------------Value----------------------------------------- const Type *LoadNode::Value( PhaseTransform *phase ) const { // Either input is TOP ==> the result is TOP @@ -1591,8 +1635,31 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { Compile* C = phase->C; // Try to guess loaded type from pointer type - if (tp->base() == Type::AryPtr) { - const Type *t = tp->is_aryptr()->elem(); + if (tp->isa_aryptr()) { + const TypeAryPtr* ary = tp->is_aryptr(); + const Type *t = ary->elem(); + + // Determine whether the reference is beyond the header or not, by comparing + // the offset against the offset of the start of the array's data. + // Different array types begin at slightly different offsets (12 vs. 16). + // We choose T_BYTE as an example base type that is least restrictive + // as to alignment, which will therefore produce the smallest + // possible base offset. + const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE); + const bool off_beyond_header = ((uint)off >= (uint)min_base_off); + + // Try to constant-fold a stable array element. + if (FoldStableValues && ary->is_stable()) { + // Make sure the reference is not into the header + if (off_beyond_header && off != Type::OffsetBot) { + assert(adr->is_AddP() && adr->in(AddPNode::Offset)->is_Con(), "offset is a constant"); + const Type* con_type = fold_stable_ary_elem(ary, off, memory_type()); + if (con_type != NULL) { + return con_type; + } + } + } + // Don't do this for integer types. There is only potential profit if // the element type t is lower than _type; that is, for int types, if _type is // more restrictive than t. This only happens here if one is short and the other @@ -1613,14 +1680,7 @@ const Type *LoadNode::Value( PhaseTransform *phase ) const { && Opcode() != Op_LoadKlass && Opcode() != Op_LoadNKlass) { // t might actually be lower than _type, if _type is a unique // concrete subclass of abstract class t. - // Make sure the reference is not into the header, by comparing - // the offset against the offset of the start of the array's data. - // Different array types begin at slightly different offsets (12 vs. 16). - // We choose T_BYTE as an example base type that is least restrictive - // as to alignment, which will therefore produce the smallest - // possible base offset. - const int min_base_off = arrayOopDesc::base_offset_in_bytes(T_BYTE); - if ((uint)off >= (uint)min_base_off) { // is the offset beyond the header? + if (off_beyond_header) { // is the offset beyond the header? const Type* jt = t->join(_type); // In any case, do not allow the join, per se, to empty out the type. if (jt->empty() && !t->empty()) { @@ -1971,7 +2031,7 @@ Node *LoadKlassNode::make( PhaseGVN& gvn, Node *mem, Node *adr, const TypePtr* a assert(adr_type != NULL, "expecting TypeKlassPtr"); #ifdef _LP64 if (adr_type->is_ptr_to_narrowklass()) { - assert(UseCompressedKlassPointers, "no compressed klasses"); + assert(UseCompressedClassPointers, "no compressed klasses"); Node* load_klass = gvn.transform(new (C) LoadNKlassNode(ctl, mem, adr, at, tk->make_narrowklass())); return new (C) DecodeNKlassNode(load_klass, load_klass->bottom_type()->make_ptr()); } @@ -2309,7 +2369,7 @@ StoreNode* StoreNode::make( PhaseGVN& gvn, Node* ctl, Node* mem, Node* adr, cons val = gvn.transform(new (C) EncodePNode(val, val->bottom_type()->make_narrowoop())); return new (C) StoreNNode(ctl, mem, adr, adr_type, val); } else if (adr->bottom_type()->is_ptr_to_narrowklass() || - (UseCompressedKlassPointers && val->bottom_type()->isa_klassptr() && + (UseCompressedClassPointers && val->bottom_type()->isa_klassptr() && adr->bottom_type()->isa_rawptr())) { val = gvn.transform(new (C) EncodePKlassNode(val, val->bottom_type()->make_narrowklass())); return new (C) StoreNKlassNode(ctl, mem, adr, adr_type, val); diff --git a/hotspot/src/share/vm/opto/parse.hpp b/hotspot/src/share/vm/opto/parse.hpp index 91025bf56fb..ea01b08475e 100644 --- a/hotspot/src/share/vm/opto/parse.hpp +++ b/hotspot/src/share/vm/opto/parse.hpp @@ -518,7 +518,7 @@ class Parse : public GraphKit { // loading from a constant field or the constant pool // returns false if push failed (non-perm field constants only, not ldcs) - bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false); + bool push_constant(ciConstant con, bool require_constant = false, bool is_autobox_cache = false, const Type* basic_type = NULL); // implementation of object creation bytecodes void emit_guard_for_new(ciInstanceKlass* klass); diff --git a/hotspot/src/share/vm/opto/parse3.cpp b/hotspot/src/share/vm/opto/parse3.cpp index 28eb0580bad..8c545f3ece5 100644 --- a/hotspot/src/share/vm/opto/parse3.cpp +++ b/hotspot/src/share/vm/opto/parse3.cpp @@ -147,7 +147,15 @@ void Parse::do_field_access(bool is_get, bool is_field) { void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { // Does this field have a constant value? If so, just push the value. if (field->is_constant()) { - // final field + // final or stable field + const Type* stable_type = NULL; + if (FoldStableValues && field->is_stable()) { + stable_type = Type::get_const_type(field->type()); + if (field->type()->is_array_klass()) { + int stable_dimension = field->type()->as_array_klass()->dimension(); + stable_type = stable_type->is_aryptr()->cast_to_stable(true, stable_dimension); + } + } if (field->is_static()) { // final static field if (C->eliminate_boxing()) { @@ -167,11 +175,10 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { } } } - if (push_constant(field->constant_value())) + if (push_constant(field->constant_value(), false, false, stable_type)) return; - } - else { - // final non-static field + } else { + // final or stable non-static field // Treat final non-static fields of trusted classes (classes in // java.lang.invoke and sun.invoke packages and subpackages) as // compile time constants. @@ -179,8 +186,12 @@ void Parse::do_get_xxx(Node* obj, ciField* field, bool is_field) { const TypeOopPtr* oop_ptr = obj->bottom_type()->isa_oopptr(); ciObject* constant_oop = oop_ptr->const_oop(); ciConstant constant = field->constant_value_of(constant_oop); - if (push_constant(constant, true)) - return; + if (FoldStableValues && field->is_stable() && constant.is_null_or_zero()) { + // fall through to field load; the field is not yet initialized + } else { + if (push_constant(constant, true, false, stable_type)) + return; + } } } } @@ -301,7 +312,8 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { // Note the presence of writes to final non-static fields, so that we // can insert a memory barrier later on to keep the writes from floating // out of the constructor. - if (is_field && field->is_final()) { + // Any method can write a @Stable field; insert memory barriers after those also. + if (is_field && (field->is_final() || field->is_stable())) { set_wrote_final(true); // Preserve allocation ptr to create precedent edge to it in membar // generated on exit from constructor. @@ -314,35 +326,21 @@ void Parse::do_put_xxx(Node* obj, ciField* field, bool is_field) { } -bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache) { + +bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_autobox_cache, const Type* stable_type) { + const Type* con_type = Type::make_from_constant(constant, require_constant, is_autobox_cache); switch (constant.basic_type()) { - case T_BOOLEAN: push( intcon(constant.as_boolean()) ); break; - case T_INT: push( intcon(constant.as_int()) ); break; - case T_CHAR: push( intcon(constant.as_char()) ); break; - case T_BYTE: push( intcon(constant.as_byte()) ); break; - case T_SHORT: push( intcon(constant.as_short()) ); break; - case T_FLOAT: push( makecon(TypeF::make(constant.as_float())) ); break; - case T_DOUBLE: push_pair( makecon(TypeD::make(constant.as_double())) ); break; - case T_LONG: push_pair( longcon(constant.as_long()) ); break; case T_ARRAY: - case T_OBJECT: { + case T_OBJECT: // cases: // can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0) // should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2) // An oop is not scavengable if it is in the perm gen. - ciObject* oop_constant = constant.as_object(); - if (oop_constant->is_null_object()) { - push( zerocon(T_OBJECT) ); - break; - } else if (require_constant || oop_constant->should_be_constant()) { - push( makecon(TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache)) ); - break; - } else { - // we cannot inline the oop, but we can use it later to narrow a type - return false; - } - } - case T_ILLEGAL: { + if (stable_type != NULL && con_type != NULL && con_type->isa_oopptr()) + con_type = con_type->join(stable_type); + break; + + case T_ILLEGAL: // Invalid ciConstant returned due to OutOfMemoryError in the CI assert(C->env()->failing(), "otherwise should not see this"); // These always occur because of object types; we are going to @@ -350,17 +348,16 @@ bool Parse::push_constant(ciConstant constant, bool require_constant, bool is_au push( zerocon(T_OBJECT) ); return false; } - default: - ShouldNotReachHere(); - return false; - } - // success + if (con_type == NULL) + // we cannot inline the oop, but we can use it later to narrow a type + return false; + + push_node(constant.basic_type(), makecon(con_type)); return true; } - //============================================================================= void Parse::do_anewarray() { bool will_link; diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index fabcf1cad16..e25c529a886 100644 --- a/hotspot/src/share/vm/opto/type.cpp +++ b/hotspot/src/share/vm/opto/type.cpp @@ -189,6 +189,38 @@ const Type* Type::get_typeflow_type(ciType* type) { } +//-----------------------make_from_constant------------------------------------ +const Type* Type::make_from_constant(ciConstant constant, + bool require_constant, bool is_autobox_cache) { + switch (constant.basic_type()) { + case T_BOOLEAN: return TypeInt::make(constant.as_boolean()); + case T_CHAR: return TypeInt::make(constant.as_char()); + case T_BYTE: return TypeInt::make(constant.as_byte()); + case T_SHORT: return TypeInt::make(constant.as_short()); + case T_INT: return TypeInt::make(constant.as_int()); + case T_LONG: return TypeLong::make(constant.as_long()); + case T_FLOAT: return TypeF::make(constant.as_float()); + case T_DOUBLE: return TypeD::make(constant.as_double()); + case T_ARRAY: + case T_OBJECT: + { + // cases: + // can_be_constant = (oop not scavengable || ScavengeRootsInCode != 0) + // should_be_constant = (oop not scavengable || ScavengeRootsInCode >= 2) + // An oop is not scavengable if it is in the perm gen. + ciObject* oop_constant = constant.as_object(); + if (oop_constant->is_null_object()) { + return Type::get_zero_type(T_OBJECT); + } else if (require_constant || oop_constant->should_be_constant()) { + return TypeOopPtr::make_from_constant(oop_constant, require_constant, is_autobox_cache); + } + } + } + // Fall through to failure + return NULL; +} + + //------------------------------make------------------------------------------- // Create a simple Type, with default empty symbol sets. Then hashcons it // and look for an existing copy in the type dictionary. @@ -1824,12 +1856,12 @@ inline const TypeInt* normalize_array_size(const TypeInt* size) { } //------------------------------make------------------------------------------- -const TypeAry *TypeAry::make( const Type *elem, const TypeInt *size) { +const TypeAry* TypeAry::make(const Type* elem, const TypeInt* size, bool stable) { if (UseCompressedOops && elem->isa_oopptr()) { elem = elem->make_narrowoop(); } size = normalize_array_size(size); - return (TypeAry*)(new TypeAry(elem,size))->hashcons(); + return (TypeAry*)(new TypeAry(elem,size,stable))->hashcons(); } //------------------------------meet------------------------------------------- @@ -1850,7 +1882,8 @@ const Type *TypeAry::xmeet( const Type *t ) const { case Array: { // Meeting 2 arrays? const TypeAry *a = t->is_ary(); return TypeAry::make(_elem->meet(a->_elem), - _size->xmeet(a->_size)->is_int()); + _size->xmeet(a->_size)->is_int(), + _stable & a->_stable); } case Top: break; @@ -1863,7 +1896,7 @@ const Type *TypeAry::xmeet( const Type *t ) const { const Type *TypeAry::xdual() const { const TypeInt* size_dual = _size->dual()->is_int(); size_dual = normalize_array_size(size_dual); - return new TypeAry( _elem->dual(), size_dual); + return new TypeAry(_elem->dual(), size_dual, !_stable); } //------------------------------eq--------------------------------------------- @@ -1871,13 +1904,14 @@ const Type *TypeAry::xdual() const { bool TypeAry::eq( const Type *t ) const { const TypeAry *a = (const TypeAry*)t; return _elem == a->_elem && + _stable == a->_stable && _size == a->_size; } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeAry::hash(void) const { - return (intptr_t)_elem + (intptr_t)_size; + return (intptr_t)_elem + (intptr_t)_size + (_stable ? 43 : 0); } //----------------------interface_vs_oop--------------------------------------- @@ -1894,6 +1928,7 @@ bool TypeAry::interface_vs_oop(const Type *t) const { //------------------------------dump2------------------------------------------ #ifndef PRODUCT void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const { + if (_stable) st->print("stable:"); _elem->dump2(d, depth, st); st->print("["); _size->dump2(d, depth, st); @@ -2381,7 +2416,7 @@ TypeOopPtr::TypeOopPtr( TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int #ifdef _LP64 if (_offset != 0) { if (_offset == oopDesc::klass_offset_in_bytes()) { - _is_ptr_to_narrowklass = UseCompressedKlassPointers; + _is_ptr_to_narrowklass = UseCompressedClassPointers; } else if (klass() == NULL) { // Array with unknown body type assert(this->isa_aryptr(), "only arrays without klass"); @@ -3457,11 +3492,39 @@ const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const { assert(new_size != NULL, ""); new_size = narrow_size_type(new_size); if (new_size == size()) return this; - const TypeAry* new_ary = TypeAry::make(elem(), new_size); + const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable()); return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id); } +//------------------------------cast_to_stable--------------------------------- +const TypeAryPtr* TypeAryPtr::cast_to_stable(bool stable, int stable_dimension) const { + if (stable_dimension <= 0 || (stable_dimension == 1 && stable == this->is_stable())) + return this; + + const Type* elem = this->elem(); + const TypePtr* elem_ptr = elem->make_ptr(); + + if (stable_dimension > 1 && elem_ptr != NULL && elem_ptr->isa_aryptr()) { + // If this is widened from a narrow oop, TypeAry::make will re-narrow it. + elem = elem_ptr = elem_ptr->is_aryptr()->cast_to_stable(stable, stable_dimension - 1); + } + + const TypeAry* new_ary = TypeAry::make(elem, size(), stable); + + return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id); +} + +//-----------------------------stable_dimension-------------------------------- +int TypeAryPtr::stable_dimension() const { + if (!is_stable()) return 0; + int dim = 1; + const TypePtr* elem_ptr = elem()->make_ptr(); + if (elem_ptr != NULL && elem_ptr->isa_aryptr()) + dim += elem_ptr->is_aryptr()->stable_dimension(); + return dim; +} + //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeAryPtr::eq( const Type *t ) const { @@ -3570,7 +3633,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { // Something like byte[int+] meets char[int+]. // This must fall to bottom, not (int[-128..65535])[int+]. instance_id = InstanceBot; - tary = TypeAry::make(Type::BOTTOM, tary->_size); + tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); } } else // Non integral arrays. // Must fall to bottom if exact klasses in upper lattice @@ -3584,7 +3647,7 @@ const Type *TypeAryPtr::xmeet( const Type *t ) const { (tap ->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) || // 'this' is exact and super or unrelated: (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { - tary = TypeAry::make(Type::BOTTOM, tary->_size); + tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); return make( NotNull, NULL, tary, lazy_klass, false, off, InstanceBot ); } diff --git a/hotspot/src/share/vm/opto/type.hpp b/hotspot/src/share/vm/opto/type.hpp index 55d98bd5e51..d4832591843 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.hpp @@ -372,6 +372,10 @@ public: // Mapping from CI type system to compiler type: static const Type* get_typeflow_type(ciType* type); + static const Type* make_from_constant(ciConstant constant, + bool require_constant = false, + bool is_autobox_cache = false); + private: // support arrays static const BasicType _basic_type[]; @@ -588,8 +592,8 @@ public: //------------------------------TypeAry---------------------------------------- // Class of Array Types class TypeAry : public Type { - TypeAry( const Type *elem, const TypeInt *size) : Type(Array), - _elem(elem), _size(size) {} + TypeAry(const Type* elem, const TypeInt* size, bool stable) : Type(Array), + _elem(elem), _size(size), _stable(stable) {} public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -599,10 +603,11 @@ public: private: const Type *_elem; // Element type of array const TypeInt *_size; // Elements in array + const bool _stable; // Are elements @Stable? friend class TypeAryPtr; public: - static const TypeAry *make( const Type *elem, const TypeInt *size); + static const TypeAry* make(const Type* elem, const TypeInt* size, bool stable = false); virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. @@ -988,6 +993,7 @@ public: const TypeAry* ary() const { return _ary; } const Type* elem() const { return _ary->_elem; } const TypeInt* size() const { return _ary->_size; } + bool is_stable() const { return _ary->_stable; } bool is_autobox_cache() const { return _is_autobox_cache; } @@ -1011,6 +1017,9 @@ public: virtual const Type *xmeet( const Type *t ) const; virtual const Type *xdual() const; // Compute dual right now. + const TypeAryPtr* cast_to_stable(bool stable, int stable_dimension = 1) const; + int stable_dimension() const; + // Convenience common pre-built types. static const TypeAryPtr *RANGE; static const TypeAryPtr *OOPS; diff --git a/hotspot/src/share/vm/prims/jni.cpp b/hotspot/src/share/vm/prims/jni.cpp index ea44e2c6679..cbd7860a092 100644 --- a/hotspot/src/share/vm/prims/jni.cpp +++ b/hotspot/src/share/vm/prims/jni.cpp @@ -1336,6 +1336,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive if (call_type == JNI_VIRTUAL) { // jni_GetMethodID makes sure class is linked and initialized // so m should have a valid vtable index. + assert(!m->has_itable_index(), ""); int vtbl_index = m->vtable_index(); if (vtbl_index != Method::nonvirtual_vtable_index) { Klass* k = h_recv->klass(); @@ -1355,12 +1356,7 @@ static void jni_invoke_nonstatic(JNIEnv *env, JavaValue* result, jobject receive // interface call KlassHandle h_holder(THREAD, holder); - int itbl_index = m->cached_itable_index(); - if (itbl_index == -1) { - itbl_index = klassItable::compute_itable_index(m); - m->set_cached_itable_index(itbl_index); - // the above may have grabbed a lock, 'm' and anything non-handlized can't be used again - } + int itbl_index = m->itable_index(); Klass* k = h_recv->klass(); selected_method = InstanceKlass::cast(k)->method_at_itable(h_holder(), itbl_index, CHECK); } @@ -5037,6 +5033,7 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { #include "gc_implementation/g1/heapRegionRemSet.hpp" #endif #include "utilities/quickSort.hpp" +#include "utilities/ostream.hpp" #if INCLUDE_VM_STRUCTS #include "runtime/vmStructs.hpp" #endif @@ -5048,22 +5045,31 @@ _JNI_IMPORT_OR_EXPORT_ jint JNICALL JNI_GetDefaultJavaVMInitArgs(void *args_) { // Forward declaration void TestReservedSpace_test(); void TestReserveMemorySpecial_test(); +void TestVirtualSpace_test(); +void TestMetaspaceAux_test(); +#if INCLUDE_ALL_GCS +void TestG1BiasedArray_test(); +#endif void execute_internal_vm_tests() { if (ExecuteInternalVMTests) { tty->print_cr("Running internal VM tests"); run_unit_test(TestReservedSpace_test()); run_unit_test(TestReserveMemorySpecial_test()); + run_unit_test(TestVirtualSpace_test()); + run_unit_test(TestMetaspaceAux_test()); run_unit_test(GlobalDefinitions::test_globals()); run_unit_test(GCTimerAllTest::all()); run_unit_test(arrayOopDesc::test_max_array_length()); run_unit_test(CollectedHeap::test_is_in()); run_unit_test(QuickSort::test_quick_sort()); run_unit_test(AltHashing::test_alt_hash()); + run_unit_test(test_loggc_filename()); #if INCLUDE_VM_STRUCTS run_unit_test(VMStructs::test()); #endif #if INCLUDE_ALL_GCS + run_unit_test(TestG1BiasedArray_test()); run_unit_test(HeapRegionRemSet::test_prt()); #endif tty->print_cr("All internal VM tests passed"); diff --git a/hotspot/src/share/vm/prims/jvm.cpp b/hotspot/src/share/vm/prims/jvm.cpp index caed2d13612..d4fa736bdd9 100644 --- a/hotspot/src/share/vm/prims/jvm.cpp +++ b/hotspot/src/share/vm/prims/jvm.cpp @@ -1824,7 +1824,7 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } if (!publicOnly || fs.access_flags().is_public()) { - fd.initialize(k(), fs.index()); + fd.reinitialize(k(), fs.index()); oop field = Reflection::new_field(&fd, UseNewReflection, CHECK_NULL); result->obj_at_put(out_idx, field); ++out_idx; @@ -1835,16 +1835,27 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredFields(JNIEnv *env, jclass ofClass, } JVM_END -JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)) -{ - JVMWrapper("JVM_GetClassDeclaredMethods"); +static bool select_method(methodHandle method, bool want_constructor) { + if (want_constructor) { + return (method->is_initializer() && !method->is_static()); + } else { + return (!method->is_initializer() && !method->is_overpass()); + } +} + +static jobjectArray get_class_declared_methods_helper( + JNIEnv *env, + jclass ofClass, jboolean publicOnly, + bool want_constructor, + Klass* klass, TRAPS) { + JvmtiVMObjectAllocEventCollector oam; // Exclude primitive types and array types if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), 0, CHECK_NULL); + oop res = oopFactory::new_objArray(klass, 0, CHECK_NULL); return (jobjectArray) JNIHandles::make_local(env, res); } @@ -1855,87 +1866,67 @@ JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, Array* methods = k->methods(); int methods_length = methods->length(); + + // Save original method_idnum in case of redefinition, which can change + // the idnum of obsolete methods. The new method will have the same idnum + // but if we refresh the methods array, the counts will be wrong. + ResourceMark rm(THREAD); + GrowableArray* idnums = new GrowableArray(methods_length); int num_methods = 0; - int i; - for (i = 0; i < methods_length; i++) { + for (int i = 0; i < methods_length; i++) { methodHandle method(THREAD, methods->at(i)); - if (!method->is_initializer() && !method->is_overpass()) { + if (select_method(method, want_constructor)) { if (!publicOnly || method->is_public()) { + idnums->push(method->method_idnum()); ++num_methods; } } } // Allocate result - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Method_klass(), num_methods, CHECK_NULL); + objArrayOop r = oopFactory::new_objArray(klass, num_methods, CHECK_NULL); objArrayHandle result (THREAD, r); - int out_idx = 0; - for (i = 0; i < methods_length; i++) { - methodHandle method(THREAD, methods->at(i)); - if (!method->is_initializer() && !method->is_overpass()) { - if (!publicOnly || method->is_public()) { - oop m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL); - result->obj_at_put(out_idx, m); - ++out_idx; + // Now just put the methods that we selected above, but go by their idnum + // in case of redefinition. The methods can be redefined at any safepoint, + // so above when allocating the oop array and below when creating reflect + // objects. + for (int i = 0; i < num_methods; i++) { + methodHandle method(THREAD, k->method_with_idnum(idnums->at(i))); + if (method.is_null()) { + // Method may have been deleted and seems this API can handle null + // Otherwise should probably put a method that throws NSME + result->obj_at_put(i, NULL); + } else { + oop m; + if (want_constructor) { + m = Reflection::new_constructor(method, CHECK_NULL); + } else { + m = Reflection::new_method(method, UseNewReflection, false, CHECK_NULL); } + result->obj_at_put(i, m); } } - assert(out_idx == num_methods, "just checking"); + return (jobjectArray) JNIHandles::make_local(env, result()); } + +JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredMethods(JNIEnv *env, jclass ofClass, jboolean publicOnly)) +{ + JVMWrapper("JVM_GetClassDeclaredMethods"); + return get_class_declared_methods_helper(env, ofClass, publicOnly, + /*want_constructor*/ false, + SystemDictionary::reflect_Method_klass(), THREAD); +} JVM_END JVM_ENTRY(jobjectArray, JVM_GetClassDeclaredConstructors(JNIEnv *env, jclass ofClass, jboolean publicOnly)) { JVMWrapper("JVM_GetClassDeclaredConstructors"); - JvmtiVMObjectAllocEventCollector oam; - - // Exclude primitive types and array types - if (java_lang_Class::is_primitive(JNIHandles::resolve_non_null(ofClass)) - || java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))->oop_is_array()) { - // Return empty array - oop res = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), 0 , CHECK_NULL); - return (jobjectArray) JNIHandles::make_local(env, res); - } - - instanceKlassHandle k(THREAD, java_lang_Class::as_Klass(JNIHandles::resolve_non_null(ofClass))); - - // Ensure class is linked - k->link_class(CHECK_NULL); - - Array* methods = k->methods(); - int methods_length = methods->length(); - int num_constructors = 0; - - int i; - for (i = 0; i < methods_length; i++) { - methodHandle method(THREAD, methods->at(i)); - if (method->is_initializer() && !method->is_static()) { - if (!publicOnly || method->is_public()) { - ++num_constructors; - } - } - } - - // Allocate result - objArrayOop r = oopFactory::new_objArray(SystemDictionary::reflect_Constructor_klass(), num_constructors, CHECK_NULL); - objArrayHandle result(THREAD, r); - - int out_idx = 0; - for (i = 0; i < methods_length; i++) { - methodHandle method(THREAD, methods->at(i)); - if (method->is_initializer() && !method->is_static()) { - if (!publicOnly || method->is_public()) { - oop m = Reflection::new_constructor(method, CHECK_NULL); - result->obj_at_put(out_idx, m); - ++out_idx; - } - } - } - assert(out_idx == num_constructors, "just checking"); - return (jobjectArray) JNIHandles::make_local(env, result()); + return get_class_declared_methods_helper(env, ofClass, publicOnly, + /*want_constructor*/ true, + SystemDictionary::reflect_Constructor_klass(), THREAD); } JVM_END diff --git a/hotspot/src/share/vm/prims/jvmti.xml b/hotspot/src/share/vm/prims/jvmti.xml index 87a28ae0cfc..98a0a0640aa 100644 --- a/hotspot/src/share/vm/prims/jvmti.xml +++ b/hotspot/src/share/vm/prims/jvmti.xml @@ -458,8 +458,10 @@ the same name from being loaded dynamically.

    The VM will invoke the Agent_OnUnload_L function of the agent, if such - a function is exported, at the same point during startup as it would - have called the dynamic entry point Agent_OnUnLoad. + a function is exported, at the same point during VM execution as it would + have called the dynamic entry point Agent_OnUnLoad. A statically loaded + agent cannot be unloaded. The Agent_OnUnload_L function will still be + called to do any other agent shutdown related tasks. If a statically linked agent L exports a function called Agent_OnUnLoad_L and a function called Agent_OnUnLoad, the Agent_OnUnLoad function will be ignored. diff --git a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp index 929dcf22260..265154683ba 100644 --- a/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp +++ b/hotspot/src/share/vm/prims/jvmtiEnvBase.hpp @@ -406,7 +406,11 @@ public: VMOp_Type type() const { return VMOp_GetCurrentContendedMonitor; } jvmtiError result() { return _result; } void doit() { - _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); + _result = JVMTI_ERROR_THREAD_NOT_ALIVE; + if (Threads::includes(_java_thread) && !_java_thread->is_exiting() && + _java_thread->threadObj() != NULL) { + _result = ((JvmtiEnvBase *)_env)->get_current_contended_monitor(_calling_thread,_java_thread,_owned_monitor_ptr); + } } }; diff --git a/hotspot/src/share/vm/prims/jvmtiImpl.cpp b/hotspot/src/share/vm/prims/jvmtiImpl.cpp index 6f8b41297a4..0fcd1ba94ed 100644 --- a/hotspot/src/share/vm/prims/jvmtiImpl.cpp +++ b/hotspot/src/share/vm/prims/jvmtiImpl.cpp @@ -273,59 +273,49 @@ void JvmtiBreakpoint::each_method_version_do(method_action meth_act) { // add/remove breakpoint to/from versions of the method that // are EMCP. Directly or transitively obsolete methods are - // not saved in the PreviousVersionInfo. + // not saved in the PreviousVersionNodes. Thread *thread = Thread::current(); instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder()); Symbol* m_name = _method->name(); Symbol* m_signature = _method->signature(); - { - ResourceMark rm(thread); - // PreviousVersionInfo objects returned via PreviousVersionWalker - // contain a GrowableArray of handles. We have to clean up the - // GrowableArray _after_ the PreviousVersionWalker destructor - // has destroyed the handles. - { - // search previous versions if they exist - PreviousVersionWalker pvw((InstanceKlass *)ikh()); - for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); - pv_info != NULL; pv_info = pvw.next_previous_version()) { - GrowableArray* methods = - pv_info->prev_EMCP_method_handles(); + // search previous versions if they exist + PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh()); + for (PreviousVersionNode * pv_node = pvw.next_previous_version(); + pv_node != NULL; pv_node = pvw.next_previous_version()) { + GrowableArray* methods = pv_node->prev_EMCP_methods(); - if (methods == NULL) { - // We have run into a PreviousVersion generation where - // all methods were made obsolete during that generation's - // RedefineClasses() operation. At the time of that - // operation, all EMCP methods were flushed so we don't - // have to go back any further. - // - // A NULL methods array is different than an empty methods - // array. We cannot infer any optimizations about older - // generations from an empty methods array for the current - // generation. - break; - } + if (methods == NULL) { + // We have run into a PreviousVersion generation where + // all methods were made obsolete during that generation's + // RedefineClasses() operation. At the time of that + // operation, all EMCP methods were flushed so we don't + // have to go back any further. + // + // A NULL methods array is different than an empty methods + // array. We cannot infer any optimizations about older + // generations from an empty methods array for the current + // generation. + break; + } - for (int i = methods->length() - 1; i >= 0; i--) { - methodHandle method = methods->at(i); - // obsolete methods that are running are not deleted from - // previous version array, but they are skipped here. - if (!method->is_obsolete() && - method->name() == m_name && - method->signature() == m_signature) { - RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)", - meth_act == &Method::set_breakpoint ? "sett" : "clear", - method->name()->as_C_string(), - method->signature()->as_C_string())); + for (int i = methods->length() - 1; i >= 0; i--) { + Method* method = methods->at(i); + // obsolete methods that are running are not deleted from + // previous version array, but they are skipped here. + if (!method->is_obsolete() && + method->name() == m_name && + method->signature() == m_signature) { + RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)", + meth_act == &Method::set_breakpoint ? "sett" : "clear", + method->name()->as_C_string(), + method->signature()->as_C_string())); - ((Method*)method()->*meth_act)(_bci); - break; - } - } + (method->*meth_act)(_bci); + break; } - } // pvw is cleaned up - } // rm is cleaned up + } + } } void JvmtiBreakpoint::set() { diff --git a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp index 803cf9a7545..34254d6b13e 100644 --- a/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp +++ b/hotspot/src/share/vm/prims/jvmtiRedefineClasses.cpp @@ -1072,8 +1072,17 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { } res = merge_cp_and_rewrite(the_class, scratch_class, THREAD); - if (res != JVMTI_ERROR_NONE) { - return res; + if (HAS_PENDING_EXCEPTION) { + Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); + // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark + RC_TRACE_WITH_THREAD(0x00000002, THREAD, + ("merge_cp_and_rewrite exception: '%s'", ex_name->as_C_string())); + CLEAR_PENDING_EXCEPTION; + if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { + return JVMTI_ERROR_OUT_OF_MEMORY; + } else { + return JVMTI_ERROR_INTERNAL; + } } if (VerifyMergedCPBytecodes) { @@ -1105,6 +1114,9 @@ jvmtiError VM_RedefineClasses::load_new_class_versions(TRAPS) { } if (HAS_PENDING_EXCEPTION) { Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); + // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark + RC_TRACE_WITH_THREAD(0x00000002, THREAD, + ("Rewriter::rewrite or link_methods exception: '%s'", ex_name->as_C_string())); CLEAR_PENDING_EXCEPTION; if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { return JVMTI_ERROR_OUT_OF_MEMORY; @@ -1395,8 +1407,8 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( ClassLoaderData* loader_data = the_class->class_loader_data(); ConstantPool* merge_cp_oop = ConstantPool::allocate(loader_data, - merge_cp_length, - THREAD); + merge_cp_length, + CHECK_(JVMTI_ERROR_OUT_OF_MEMORY)); MergeCPCleaner cp_cleaner(loader_data, merge_cp_oop); HandleMark hm(THREAD); // make sure handles are cleared before @@ -1472,7 +1484,8 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // Replace the new constant pool with a shrunken copy of the // merged constant pool - set_new_constant_pool(loader_data, scratch_class, merge_cp, merge_cp_length, THREAD); + set_new_constant_pool(loader_data, scratch_class, merge_cp, merge_cp_length, + CHECK_(JVMTI_ERROR_OUT_OF_MEMORY)); // The new constant pool replaces scratch_cp so have cleaner clean it up. // It can't be cleaned up while there are handles to it. cp_cleaner.add_scratch_cp(scratch_cp()); @@ -1502,7 +1515,8 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite( // merged constant pool so now the rewritten bytecodes have // valid references; the previous new constant pool will get // GCed. - set_new_constant_pool(loader_data, scratch_class, merge_cp, merge_cp_length, THREAD); + set_new_constant_pool(loader_data, scratch_class, merge_cp, merge_cp_length, + CHECK_(JVMTI_ERROR_OUT_OF_MEMORY)); // The new constant pool replaces scratch_cp so have cleaner clean it up. // It can't be cleaned up while there are handles to it. cp_cleaner.add_scratch_cp(scratch_cp()); @@ -1590,11 +1604,23 @@ bool VM_RedefineClasses::rewrite_cp_refs_in_methods( for (int i = methods->length() - 1; i >= 0; i--) { methodHandle method(THREAD, methods->at(i)); methodHandle new_method; - rewrite_cp_refs_in_method(method, &new_method, CHECK_false); + rewrite_cp_refs_in_method(method, &new_method, THREAD); if (!new_method.is_null()) { // the method has been replaced so save the new method version + // even in the case of an exception. original method is on the + // deallocation list. methods->at_put(i, new_method()); } + if (HAS_PENDING_EXCEPTION) { + Symbol* ex_name = PENDING_EXCEPTION->klass()->name(); + // RC_TRACE_WITH_THREAD macro has an embedded ResourceMark + RC_TRACE_WITH_THREAD(0x00000002, THREAD, + ("rewrite_cp_refs_in_method exception: '%s'", ex_name->as_C_string())); + // Need to clear pending exception here as the super caller sets + // the JVMTI_ERROR_INTERNAL if the returned value is false. + CLEAR_PENDING_EXCEPTION; + return false; + } } return true; @@ -1674,10 +1700,7 @@ void VM_RedefineClasses::rewrite_cp_refs_in_method(methodHandle method, Pause_No_Safepoint_Verifier pnsv(&nsv); // ldc is 2 bytes and ldc_w is 3 bytes - m = rc.insert_space_at(bci, 3, inst_buffer, THREAD); - if (m.is_null() || HAS_PENDING_EXCEPTION) { - guarantee(false, "insert_space_at() failed"); - } + m = rc.insert_space_at(bci, 3, inst_buffer, CHECK); } // return the new method so that the caller can update @@ -2487,8 +2510,8 @@ void VM_RedefineClasses::set_new_constant_pool( // scratch_cp is a merged constant pool and has enough space for a // worst case merge situation. We want to associate the minimum // sized constant pool with the klass to save space. - constantPoolHandle smaller_cp(THREAD, - ConstantPool::allocate(loader_data, scratch_cp_length, THREAD)); + ConstantPool* cp = ConstantPool::allocate(loader_data, scratch_cp_length, CHECK); + constantPoolHandle smaller_cp(THREAD, cp); // preserve version() value in the smaller copy int version = scratch_cp->version(); @@ -2500,6 +2523,11 @@ void VM_RedefineClasses::set_new_constant_pool( smaller_cp->set_pool_holder(scratch_class()); scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD); + if (HAS_PENDING_EXCEPTION) { + // Exception is handled in the caller + loader_data->add_to_deallocate_list(smaller_cp()); + return; + } scratch_cp = smaller_cp; // attach new constant pool to klass @@ -2779,28 +2807,20 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { &trace_name_printed); } } - { - ResourceMark rm(_thread); - // PreviousVersionInfo objects returned via PreviousVersionWalker - // contain a GrowableArray of handles. We have to clean up the - // GrowableArray _after_ the PreviousVersionWalker destructor - // has destroyed the handles. - { - // the previous versions' constant pool caches may need adjustment - PreviousVersionWalker pvw(ik); - for (PreviousVersionInfo * pv_info = pvw.next_previous_version(); - pv_info != NULL; pv_info = pvw.next_previous_version()) { - other_cp = pv_info->prev_constant_pool_handle(); - cp_cache = other_cp->cache(); - if (cp_cache != NULL) { - cp_cache->adjust_method_entries(_matching_old_methods, - _matching_new_methods, - _matching_methods_length, - &trace_name_printed); - } - } - } // pvw is cleaned up - } // rm is cleaned up + + // the previous versions' constant pool caches may need adjustment + PreviousVersionWalker pvw(_thread, ik); + for (PreviousVersionNode * pv_node = pvw.next_previous_version(); + pv_node != NULL; pv_node = pvw.next_previous_version()) { + other_cp = pv_node->prev_constant_pool(); + cp_cache = other_cp->cache(); + if (cp_cache != NULL) { + cp_cache->adjust_method_entries(_matching_old_methods, + _matching_new_methods, + _matching_methods_length, + &trace_name_printed); + } + } } } @@ -2914,10 +2934,9 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete( // obsolete methods need a unique idnum u2 num = InstanceKlass::cast(_the_class_oop)->next_method_idnum(); if (num != ConstMethod::UNSET_IDNUM) { -// u2 old_num = old_method->method_idnum(); old_method->set_method_idnum(num); -// TO DO: attach obsolete annotations to obsolete method's new idnum } + // With tracing we try not to "yack" too much. The position of // this trace assumes there are fewer obsolete methods than // EMCP methods. @@ -2930,7 +2949,7 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete( for (int i = 0; i < _deleted_methods_length; ++i) { Method* old_method = _deleted_methods[i]; - assert(old_method->vtable_index() < 0, + assert(!old_method->has_vtable_index(), "cannot delete methods with vtable entries");; // Mark all deleted methods as old and obsolete diff --git a/hotspot/src/share/vm/prims/methodHandles.cpp b/hotspot/src/share/vm/prims/methodHandles.cpp index ac1c796eb31..88b82b358e6 100644 --- a/hotspot/src/share/vm/prims/methodHandles.cpp +++ b/hotspot/src/share/vm/prims/methodHandles.cpp @@ -127,25 +127,37 @@ Handle MethodHandles::new_MemberName(TRAPS) { } oop MethodHandles::init_MemberName(Handle mname, Handle target) { + // This method is used from java.lang.invoke.MemberName constructors. + // It fills in the new MemberName from a java.lang.reflect.Member. Thread* thread = Thread::current(); oop target_oop = target(); Klass* target_klass = target_oop->klass(); if (target_klass == SystemDictionary::reflect_Field_klass()) { oop clazz = java_lang_reflect_Field::clazz(target_oop); // fd.field_holder() int slot = java_lang_reflect_Field::slot(target_oop); // fd.index() - int mods = java_lang_reflect_Field::modifiers(target_oop); - oop type = java_lang_reflect_Field::type(target_oop); - oop name = java_lang_reflect_Field::name(target_oop); KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - intptr_t offset = InstanceKlass::cast(k())->field_offset(slot); - return init_field_MemberName(mname, k, accessFlags_from(mods), type, name, offset); + if (!k.is_null() && k->oop_is_instance()) { + fieldDescriptor fd(InstanceKlass::cast(k()), slot); + oop mname2 = init_field_MemberName(mname, fd); + if (mname2 != NULL) { + // Since we have the reified name and type handy, add them to the result. + if (java_lang_invoke_MemberName::name(mname2) == NULL) + java_lang_invoke_MemberName::set_name(mname2, java_lang_reflect_Field::name(target_oop)); + if (java_lang_invoke_MemberName::type(mname2) == NULL) + java_lang_invoke_MemberName::set_type(mname2, java_lang_reflect_Field::type(target_oop)); + } + return mname2; + } } else if (target_klass == SystemDictionary::reflect_Method_klass()) { oop clazz = java_lang_reflect_Method::clazz(target_oop); int slot = java_lang_reflect_Method::slot(target_oop); KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); if (!k.is_null() && k->oop_is_instance()) { Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); - return init_method_MemberName(mname, m, true, k); + if (m == NULL || is_signature_polymorphic(m->intrinsic_id())) + return NULL; // do not resolve unless there is a concrete signature + CallInfo info(m, k()); + return init_method_MemberName(mname, info); } } else if (target_klass == SystemDictionary::reflect_Constructor_klass()) { oop clazz = java_lang_reflect_Constructor::clazz(target_oop); @@ -153,65 +165,50 @@ oop MethodHandles::init_MemberName(Handle mname, Handle target) { KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); if (!k.is_null() && k->oop_is_instance()) { Method* m = InstanceKlass::cast(k())->method_with_idnum(slot); - return init_method_MemberName(mname, m, false, k); - } - } else if (target_klass == SystemDictionary::MemberName_klass()) { - // Note: This only works if the MemberName has already been resolved. - oop clazz = java_lang_invoke_MemberName::clazz(target_oop); - int flags = java_lang_invoke_MemberName::flags(target_oop); - Metadata* vmtarget=java_lang_invoke_MemberName::vmtarget(target_oop); - intptr_t vmindex = java_lang_invoke_MemberName::vmindex(target_oop); - KlassHandle k(thread, java_lang_Class::as_Klass(clazz)); - int ref_kind = (flags >> REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK; - if (vmtarget == NULL) return NULL; // not resolved - if ((flags & IS_FIELD) != 0) { - assert(vmtarget->is_klass(), "field vmtarget is Klass*"); - int basic_mods = (ref_kind_is_static(ref_kind) ? JVM_ACC_STATIC : 0); - // FIXME: how does k (receiver_limit) contribute? - KlassHandle k_vmtarget(thread, (Klass*)vmtarget); - return init_field_MemberName(mname, k_vmtarget, accessFlags_from(basic_mods), NULL, NULL, vmindex); - } else if ((flags & (IS_METHOD | IS_CONSTRUCTOR)) != 0) { - assert(vmtarget->is_method(), "method or constructor vmtarget is Method*"); - return init_method_MemberName(mname, (Method*)vmtarget, ref_kind_does_dispatch(ref_kind), k); - } else { - return NULL; + if (m == NULL) return NULL; + CallInfo info(m, k()); + return init_method_MemberName(mname, info); } } return NULL; } -oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispatch, - KlassHandle receiver_limit_h) { - Klass* receiver_limit = receiver_limit_h(); - AccessFlags mods = m->access_flags(); - int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); - int vmindex = Method::nonvirtual_vtable_index; // implies never any dispatch - Klass* mklass = m->method_holder(); - if (receiver_limit == NULL) - receiver_limit = mklass; - if (m->is_initializer()) { - flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); - } else if (mods.is_static()) { - flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); - } else if (receiver_limit != mklass && - !receiver_limit->is_subtype_of(mklass)) { - return NULL; // bad receiver limit - } else if (do_dispatch && receiver_limit->is_interface() && - mklass->is_interface()) { +oop MethodHandles::init_method_MemberName(Handle mname, CallInfo& info) { + assert(info.resolved_appendix().is_null(), "only normal methods here"); + KlassHandle receiver_limit = info.resolved_klass(); + methodHandle m = info.resolved_method(); + int flags = (jushort)( m->access_flags().as_short() & JVM_RECOGNIZED_METHOD_MODIFIERS ); + int vmindex = Method::invalid_vtable_index; + + switch (info.call_kind()) { + case CallInfo::itable_call: + vmindex = info.itable_index(); + // More importantly, the itable index only works with the method holder. + receiver_limit = m->method_holder(); + assert(receiver_limit->verify_itable_index(vmindex), ""); flags |= IS_METHOD | (JVM_REF_invokeInterface << REFERENCE_KIND_SHIFT); - receiver_limit = mklass; // ignore passed-in limit; interfaces are interconvertible - vmindex = klassItable::compute_itable_index(m); - } else if (do_dispatch && mklass != receiver_limit && mklass->is_interface()) { + break; + + case CallInfo::vtable_call: + vmindex = info.vtable_index(); flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); - // it is a miranda method, so m->vtable_index is not what we want - ResourceMark rm; - klassVtable* vt = InstanceKlass::cast(receiver_limit)->vtable(); - vmindex = vt->index_of_miranda(m->name(), m->signature()); - } else if (!do_dispatch || m->can_be_statically_bound()) { - flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); - } else { - flags |= IS_METHOD | (JVM_REF_invokeVirtual << REFERENCE_KIND_SHIFT); - vmindex = m->vtable_index(); + assert(receiver_limit->is_subtype_of(m->method_holder()), "virtual call must be type-safe"); + break; + + case CallInfo::direct_call: + vmindex = Method::nonvirtual_vtable_index; + if (m->is_static()) { + flags |= IS_METHOD | (JVM_REF_invokeStatic << REFERENCE_KIND_SHIFT); + } else if (m->is_initializer()) { + flags |= IS_CONSTRUCTOR | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); + assert(receiver_limit == m->method_holder(), "constructor call must be exactly typed"); + } else { + flags |= IS_METHOD | (JVM_REF_invokeSpecial << REFERENCE_KIND_SHIFT); + assert(receiver_limit->is_subtype_of(m->method_holder()), "special call must be type-safe"); + } + break; + + default: assert(false, "bad CallInfo"); return NULL; } // @CallerSensitive annotation detected @@ -221,7 +218,7 @@ oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispa oop mname_oop = mname(); java_lang_invoke_MemberName::set_flags( mname_oop, flags); - java_lang_invoke_MemberName::set_vmtarget(mname_oop, m); + java_lang_invoke_MemberName::set_vmtarget(mname_oop, m()); java_lang_invoke_MemberName::set_vmindex( mname_oop, vmindex); // vtable/itable index java_lang_invoke_MemberName::set_clazz( mname_oop, receiver_limit->java_mirror()); // Note: name and type can be lazily computed by resolve_MemberName, @@ -237,59 +234,19 @@ oop MethodHandles::init_method_MemberName(Handle mname, Method* m, bool do_dispa return mname(); } -Handle MethodHandles::init_method_MemberName(Handle mname, CallInfo& info, TRAPS) { - Handle empty; - if (info.resolved_appendix().not_null()) { - // The resolved MemberName must not be accompanied by an appendix argument, - // since there is no way to bind this value into the MemberName. - // Caller is responsible to prevent this from happening. - THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty); - } - methodHandle m = info.resolved_method(); - KlassHandle defc = info.resolved_klass(); - int vmindex = Method::invalid_vtable_index; - if (defc->is_interface() && m->method_holder()->is_interface()) { - // static interface methods do not reference vtable or itable - if (m->is_static()) { - vmindex = Method::nonvirtual_vtable_index; - } - // interface methods invoked via invokespecial also - // do not reference vtable or itable. - int ref_kind = ((java_lang_invoke_MemberName::flags(mname()) >> - REFERENCE_KIND_SHIFT) & REFERENCE_KIND_MASK); - if (ref_kind == JVM_REF_invokeSpecial) { - vmindex = Method::nonvirtual_vtable_index; - } - // If neither m is static nor ref_kind is invokespecial, - // set it to itable index. - if (vmindex == Method::invalid_vtable_index) { - // LinkResolver does not report itable indexes! (fix this?) - vmindex = klassItable::compute_itable_index(m()); - } - } else if (m->can_be_statically_bound()) { - // LinkResolver reports vtable index even for final methods! - vmindex = Method::nonvirtual_vtable_index; - } else { - vmindex = info.vtable_index(); - } - oop res = init_method_MemberName(mname, m(), (vmindex >= 0), defc()); - assert(res == NULL || (java_lang_invoke_MemberName::vmindex(res) == vmindex), ""); - return Handle(THREAD, res); -} - -oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder, - AccessFlags mods, oop type, oop name, - intptr_t offset, bool is_setter) { - int flags = (jushort)( mods.as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ); - flags |= IS_FIELD | ((mods.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT); +oop MethodHandles::init_field_MemberName(Handle mname, fieldDescriptor& fd, bool is_setter) { + int flags = (jushort)( fd.access_flags().as_short() & JVM_RECOGNIZED_FIELD_MODIFIERS ); + flags |= IS_FIELD | ((fd.is_static() ? JVM_REF_getStatic : JVM_REF_getField) << REFERENCE_KIND_SHIFT); if (is_setter) flags += ((JVM_REF_putField - JVM_REF_getField) << REFERENCE_KIND_SHIFT); - Metadata* vmtarget = field_holder(); - int vmindex = offset; // determines the field uniquely when combined with static bit + Metadata* vmtarget = fd.field_holder(); + int vmindex = fd.offset(); // determines the field uniquely when combined with static bit oop mname_oop = mname(); java_lang_invoke_MemberName::set_flags(mname_oop, flags); java_lang_invoke_MemberName::set_vmtarget(mname_oop, vmtarget); java_lang_invoke_MemberName::set_vmindex(mname_oop, vmindex); - java_lang_invoke_MemberName::set_clazz(mname_oop, field_holder->java_mirror()); + java_lang_invoke_MemberName::set_clazz(mname_oop, fd.field_holder()->java_mirror()); + oop type = field_signature_type_or_null(fd.signature()); + oop name = field_name_or_null(fd.name()); if (name != NULL) java_lang_invoke_MemberName::set_name(mname_oop, name); if (type != NULL) @@ -305,19 +262,6 @@ oop MethodHandles::init_field_MemberName(Handle mname, KlassHandle field_holder, return mname(); } -Handle MethodHandles::init_field_MemberName(Handle mname, FieldAccessInfo& info, TRAPS) { - return Handle(); -#if 0 // FIXME - KlassHandle field_holder = info.klass(); - intptr_t field_offset = info.field_offset(); - return init_field_MemberName(mname_oop, field_holder(), - info.access_flags(), - type, name, - field_offset, false /*is_setter*/); -#endif -} - - // JVM 2.9 Special Methods: // A method is signature polymorphic if and only if all of the following conditions hold : // * It is declared in the java.lang.invoke.MethodHandle class. @@ -573,12 +517,12 @@ static oop object_java_mirror() { return SystemDictionary::Object_klass()->java_mirror(); } -static oop field_name_or_null(Symbol* s) { +oop MethodHandles::field_name_or_null(Symbol* s) { if (s == NULL) return NULL; return StringTable::lookup(s); } -static oop field_signature_type_or_null(Symbol* s) { +oop MethodHandles::field_signature_type_or_null(Symbol* s) { if (s == NULL) return NULL; BasicType bt = FieldType::basic_type(s); if (is_java_primitive(bt)) { @@ -701,7 +645,14 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) { return empty; } } - return init_method_MemberName(mname, result, THREAD); + if (result.resolved_appendix().not_null()) { + // The resolved MemberName must not be accompanied by an appendix argument, + // since there is no way to bind this value into the MemberName. + // Caller is responsible to prevent this from happening. + THROW_MSG_(vmSymbols::java_lang_InternalError(), "appendix", empty); + } + oop mname2 = init_method_MemberName(mname, result); + return Handle(THREAD, mname2); } case IS_CONSTRUCTOR: { @@ -719,22 +670,21 @@ Handle MethodHandles::resolve_MemberName(Handle mname, TRAPS) { } } assert(result.is_statically_bound(), ""); - return init_method_MemberName(mname, result, THREAD); + oop mname2 = init_method_MemberName(mname, result); + return Handle(THREAD, mname2); } case IS_FIELD: { - // This is taken from LinkResolver::resolve_field, sans access checks. - fieldDescriptor fd; // find_field initializes fd if found - KlassHandle sel_klass(THREAD, InstanceKlass::cast(defc())->find_field(name, type, &fd)); - // check if field exists; i.e., if a klass containing the field def has been selected - if (sel_klass.is_null()) return empty; // should not happen - oop type = field_signature_type_or_null(fd.signature()); - oop name = field_name_or_null(fd.name()); - bool is_setter = (ref_kind_is_valid(ref_kind) && ref_kind_is_setter(ref_kind)); - mname = Handle(THREAD, - init_field_MemberName(mname, sel_klass, - fd.access_flags(), type, name, fd.offset(), is_setter)); - return mname; + fieldDescriptor result; // find_field initializes fd if found + { + assert(!HAS_PENDING_EXCEPTION, ""); + LinkResolver::resolve_field(result, defc, name, type, KlassHandle(), Bytecodes::_nop, false, false, THREAD); + if (HAS_PENDING_EXCEPTION) { + return empty; + } + } + oop mname2 = init_field_MemberName(mname, result, ref_kind_is_setter(ref_kind)); + return Handle(THREAD, mname2); } default: THROW_MSG_(vmSymbols::java_lang_InternalError(), "unrecognized MemberName format", empty); @@ -793,7 +743,6 @@ void MethodHandles::expand_MemberName(Handle mname, int suppress, TRAPS) { } case IS_FIELD: { - // This is taken from LinkResolver::resolve_field, sans access checks. assert(vmtarget->is_klass(), "field vmtarget is Klass*"); if (!((Klass*) vmtarget)->oop_is_instance()) break; instanceKlassHandle defc(THREAD, (Klass*) vmtarget); @@ -872,11 +821,7 @@ int MethodHandles::find_MemberNames(KlassHandle k, Handle result(thread, results->obj_at(rfill++)); if (!java_lang_invoke_MemberName::is_instance(result())) return -99; // caller bug! - oop type = field_signature_type_or_null(st.signature()); - oop name = field_name_or_null(st.name()); - oop saved = MethodHandles::init_field_MemberName(result, st.klass(), - st.access_flags(), type, name, - st.offset()); + oop saved = MethodHandles::init_field_MemberName(result, st.field_descriptor()); if (saved != result()) results->obj_at_put(rfill-1, saved); // show saved instance to user } else if (++overflow >= overflow_limit) { @@ -926,7 +871,8 @@ int MethodHandles::find_MemberNames(KlassHandle k, Handle result(thread, results->obj_at(rfill++)); if (!java_lang_invoke_MemberName::is_instance(result())) return -99; // caller bug! - oop saved = MethodHandles::init_method_MemberName(result, m, true, NULL); + CallInfo info(m); + oop saved = MethodHandles::init_method_MemberName(result, info); if (saved != result()) results->obj_at_put(rfill-1, saved); // show saved instance to user } else if (++overflow >= overflow_limit) { @@ -1227,7 +1173,8 @@ JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname x = ((Klass*) vmtarget)->java_mirror(); } else if (vmtarget->is_method()) { Handle mname2 = MethodHandles::new_MemberName(CHECK_NULL); - x = MethodHandles::init_method_MemberName(mname2, (Method*)vmtarget, false, NULL); + CallInfo info((Method*)vmtarget); + x = MethodHandles::init_method_MemberName(mname2, info); } result->obj_at_put(1, x); return JNIHandles::make_local(env, result()); diff --git a/hotspot/src/share/vm/prims/methodHandles.hpp b/hotspot/src/share/vm/prims/methodHandles.hpp index 50ce7af86ea..7ae7bd36fb5 100644 --- a/hotspot/src/share/vm/prims/methodHandles.hpp +++ b/hotspot/src/share/vm/prims/methodHandles.hpp @@ -49,19 +49,18 @@ class MethodHandles: AllStatic { // Adapters. static MethodHandlesAdapterBlob* _adapter_code; + // utility functions for reifying names and types + static oop field_name_or_null(Symbol* s); + static oop field_signature_type_or_null(Symbol* s); + public: // working with member names static Handle resolve_MemberName(Handle mname, TRAPS); // compute vmtarget/vmindex from name/type static void expand_MemberName(Handle mname, int suppress, TRAPS); // expand defc/name/type if missing static Handle new_MemberName(TRAPS); // must be followed by init_MemberName static oop init_MemberName(Handle mname_h, Handle target_h); // compute vmtarget/vmindex from target - static oop init_method_MemberName(Handle mname_h, Method* m, bool do_dispatch, - KlassHandle receiver_limit_h); - static oop init_field_MemberName(Handle mname_h, KlassHandle field_holder_h, - AccessFlags mods, oop type, oop name, - intptr_t offset, bool is_setter = false); - static Handle init_method_MemberName(Handle mname_h, CallInfo& info, TRAPS); - static Handle init_field_MemberName(Handle mname_h, FieldAccessInfo& info, TRAPS); + static oop init_field_MemberName(Handle mname_h, fieldDescriptor& fd, bool is_setter = false); + static oop init_method_MemberName(Handle mname_h, CallInfo& info); static int method_ref_kind(Method* m, bool do_dispatch_if_possible = true); static int find_MemberNames(KlassHandle k, Symbol* name, Symbol* sig, int mflags, KlassHandle caller, diff --git a/hotspot/src/share/vm/prims/whitebox.cpp b/hotspot/src/share/vm/prims/whitebox.cpp index 0f5607e22b2..6f6a2000a3f 100644 --- a/hotspot/src/share/vm/prims/whitebox.cpp +++ b/hotspot/src/share/vm/prims/whitebox.cpp @@ -33,6 +33,7 @@ #include "prims/whitebox.hpp" #include "prims/wbtestmethods/parserTests.hpp" +#include "runtime/arguments.hpp" #include "runtime/interfaceSupport.hpp" #include "runtime/os.hpp" #include "utilities/debug.hpp" @@ -94,6 +95,11 @@ WB_ENTRY(jboolean, WB_IsClassAlive(JNIEnv* env, jobject target, jstring name)) return closure.found(); WB_END +WB_ENTRY(jlong, WB_GetCompressedOopsMaxHeapSize(JNIEnv* env, jobject o)) { + return (jlong)Arguments::max_heap_for_compressed_oops(); +} +WB_END + WB_ENTRY(void, WB_PrintHeapSizes(JNIEnv* env, jobject o)) { CollectorPolicy * p = Universe::heap()->collector_policy(); gclog_or_tty->print_cr("Minimum heap "SIZE_FORMAT" Initial heap " @@ -436,6 +442,8 @@ static JNINativeMethod methods[] = { CC"(Ljava/lang/String;[Lsun/hotspot/parser/DiagnosticCommand;)[Ljava/lang/Object;", (void*) &WB_ParseCommandLine }, + {CC"getCompressedOopsMaxHeapSize", CC"()J", + (void*)&WB_GetCompressedOopsMaxHeapSize}, {CC"printHeapSizes", CC"()V", (void*)&WB_PrintHeapSizes }, #if INCLUDE_ALL_GCS {CC"g1InConcurrentMark", CC"()Z", (void*)&WB_G1InConcurrentMark}, diff --git a/hotspot/src/share/vm/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index d8a6f90eeef..10aaededfd9 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -28,6 +28,7 @@ #include "compiler/compilerOracle.hpp" #include "memory/allocation.inline.hpp" #include "memory/cardTableRS.hpp" +#include "memory/genCollectedHeap.hpp" #include "memory/referenceProcessor.hpp" #include "memory/universe.inline.hpp" #include "oops/oop.inline.hpp" @@ -54,6 +55,8 @@ #endif #if INCLUDE_ALL_GCS #include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp" +#include "gc_implementation/g1/g1CollectedHeap.inline.hpp" +#include "gc_implementation/parallelScavenge/parallelScavengeHeap.hpp" #endif // INCLUDE_ALL_GCS // Note: This is a special bug reporting site for the JVM @@ -90,6 +93,7 @@ char* Arguments::_java_command = NULL; SystemProperty* Arguments::_system_properties = NULL; const char* Arguments::_gc_log_filename = NULL; bool Arguments::_has_profile = false; +size_t Arguments::_conservative_max_heap_alignment = 0; uintx Arguments::_min_heap_size = 0; Arguments::Mode Arguments::_mode = _mixed; bool Arguments::_java_compiler = false; @@ -1096,6 +1100,7 @@ void Arguments::set_mode_flags(Mode mode) { } } +#if defined(COMPILER2) || defined(_LP64) || !INCLUDE_CDS // Conflict: required to use shared spaces (-Xshare:on), but // incompatible command line options were chosen. @@ -1108,6 +1113,7 @@ static void no_shared_spaces() { FLAG_SET_DEFAULT(UseSharedSpaces, false); } } +#endif void Arguments::set_tiered_flags() { // With tiered, set default policy to AdvancedThresholdPolicy, which is 3. @@ -1391,10 +1397,17 @@ bool verify_object_alignment() { return true; } -inline uintx max_heap_for_compressed_oops() { +uintx Arguments::max_heap_for_compressed_oops() { // Avoid sign flip. assert(OopEncodingHeapMax > (uint64_t)os::vm_page_size(), "Unusual page size"); - LP64_ONLY(return OopEncodingHeapMax - os::vm_page_size()); + // We need to fit both the NULL page and the heap into the memory budget, while + // keeping alignment constraints of the heap. To guarantee the latter, as the + // NULL page is located before the heap, we pad the NULL page to the conservative + // maximum alignment that the GC may ever impose upon the heap. + size_t displacement_due_to_null_page = align_size_up_(os::vm_page_size(), + Arguments::conservative_max_heap_alignment()); + + LP64_ONLY(return OopEncodingHeapMax - displacement_due_to_null_page); NOT_LP64(ShouldNotReachHere(); return 0); } @@ -1439,7 +1452,7 @@ void Arguments::set_use_compressed_oops() { if (UseCompressedOops && !FLAG_IS_DEFAULT(UseCompressedOops)) { warning("Max heap size too large for Compressed Oops"); FLAG_SET_DEFAULT(UseCompressedOops, false); - FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + FLAG_SET_DEFAULT(UseCompressedClassPointers, false); } } #endif // _LP64 @@ -1452,22 +1465,22 @@ void Arguments::set_use_compressed_oops() { void Arguments::set_use_compressed_klass_ptrs() { #ifndef ZERO #ifdef _LP64 - // UseCompressedOops must be on for UseCompressedKlassPointers to be on. + // UseCompressedOops must be on for UseCompressedClassPointers to be on. if (!UseCompressedOops) { - if (UseCompressedKlassPointers) { - warning("UseCompressedKlassPointers requires UseCompressedOops"); + if (UseCompressedClassPointers) { + warning("UseCompressedClassPointers requires UseCompressedOops"); } - FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + FLAG_SET_DEFAULT(UseCompressedClassPointers, false); } else { - // Turn on UseCompressedKlassPointers too - if (FLAG_IS_DEFAULT(UseCompressedKlassPointers)) { - FLAG_SET_ERGO(bool, UseCompressedKlassPointers, true); + // Turn on UseCompressedClassPointers too + if (FLAG_IS_DEFAULT(UseCompressedClassPointers)) { + FLAG_SET_ERGO(bool, UseCompressedClassPointers, true); } - // Check the ClassMetaspaceSize to make sure we use compressed klass ptrs. - if (UseCompressedKlassPointers) { - if (ClassMetaspaceSize > KlassEncodingMetaspaceMax) { - warning("Class metaspace size is too large for UseCompressedKlassPointers"); - FLAG_SET_DEFAULT(UseCompressedKlassPointers, false); + // Check the CompressedClassSpaceSize to make sure we use compressed klass ptrs. + if (UseCompressedClassPointers) { + if (CompressedClassSpaceSize > KlassEncodingMetaspaceMax) { + warning("CompressedClassSpaceSize is too large for UseCompressedClassPointers"); + FLAG_SET_DEFAULT(UseCompressedClassPointers, false); } } } @@ -1475,6 +1488,23 @@ void Arguments::set_use_compressed_klass_ptrs() { #endif // !ZERO } +void Arguments::set_conservative_max_heap_alignment() { + // The conservative maximum required alignment for the heap is the maximum of + // the alignments imposed by several sources: any requirements from the heap + // itself, the collector policy and the maximum page size we may run the VM + // with. + size_t heap_alignment = GenCollectedHeap::conservative_max_heap_alignment(); +#if INCLUDE_ALL_GCS + if (UseParallelGC) { + heap_alignment = ParallelScavengeHeap::conservative_max_heap_alignment(); + } else if (UseG1GC) { + heap_alignment = G1CollectedHeap::conservative_max_heap_alignment(); + } +#endif // INCLUDE_ALL_GCS + _conservative_max_heap_alignment = MAX3(heap_alignment, os::max_page_size(), + CollectorPolicy::compute_max_alignment()); +} + void Arguments::set_ergonomics_flags() { if (os::is_server_class_machine()) { @@ -1492,16 +1522,20 @@ void Arguments::set_ergonomics_flags() { FLAG_SET_ERGO(bool, UseParallelGC, true); } } - // Shared spaces work fine with other GCs but causes bytecode rewriting - // to be disabled, which hurts interpreter performance and decreases - // server performance. On server class machines, keep the default - // off unless it is asked for. Future work: either add bytecode rewriting - // at link time, or rewrite bytecodes in non-shared methods. - if (!DumpSharedSpaces && !RequireSharedSpaces && - (FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) { - no_shared_spaces(); - } } +#ifdef COMPILER2 + // Shared spaces work fine with other GCs but causes bytecode rewriting + // to be disabled, which hurts interpreter performance and decreases + // server performance. When -server is specified, keep the default off + // unless it is asked for. Future work: either add bytecode rewriting + // at link time, or rewrite bytecodes in non-shared methods. + if (!DumpSharedSpaces && !RequireSharedSpaces && + (FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) { + no_shared_spaces(); + } +#endif + + set_conservative_max_heap_alignment(); #ifndef ZERO #ifdef _LP64 @@ -1839,7 +1873,7 @@ void check_gclog_consistency() { (NumberOfGCLogFiles == 0) || (GCLogFileSize == 0)) { jio_fprintf(defaultStream::output_stream(), - "To enable GC log rotation, use -Xloggc: -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles= -XX:GCLogFileSize=\n" + "To enable GC log rotation, use -Xloggc: -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles= -XX:GCLogFileSize=[k|K|m|M|g|G]\n" "where num_of_file > 0 and num_of_size > 0\n" "GC log rotation is turned off\n"); UseGCLogFileRotation = false; @@ -1853,6 +1887,51 @@ void check_gclog_consistency() { } } +// This function is called for -Xloggc:, it can be used +// to check if a given file name(or string) conforms to the following +// specification: +// A valid string only contains "[A-Z][a-z][0-9].-_%[p|t]" +// %p and %t only allowed once. We only limit usage of filename not path +bool is_filename_valid(const char *file_name) { + const char* p = file_name; + char file_sep = os::file_separator()[0]; + const char* cp; + // skip prefix path + for (cp = file_name; *cp != '\0'; cp++) { + if (*cp == '/' || *cp == file_sep) { + p = cp + 1; + } + } + + int count_p = 0; + int count_t = 0; + while (*p != '\0') { + if ((*p >= '0' && *p <= '9') || + (*p >= 'A' && *p <= 'Z') || + (*p >= 'a' && *p <= 'z') || + *p == '-' || + *p == '_' || + *p == '.') { + p++; + continue; + } + if (*p == '%') { + if(*(p + 1) == 'p') { + p += 2; + count_p ++; + continue; + } + if (*(p + 1) == 't') { + p += 2; + count_t ++; + continue; + } + } + return false; + } + return count_p < 2 && count_t < 2; +} + // Check consistency of GC selection bool Arguments::check_gc_consistency() { check_gclog_consistency(); @@ -2148,8 +2227,8 @@ bool Arguments::check_vm_args_consistency() { status = status && verify_object_alignment(); - status = status && verify_interval(ClassMetaspaceSize, 1*M, 3*G, - "ClassMetaspaceSize"); + status = status && verify_interval(CompressedClassSpaceSize, 1*M, 3*G, + "CompressedClassSpaceSize"); status = status && verify_interval(MarkStackSizeMax, 1, (max_jint - 1), "MarkStackSizeMax"); @@ -2364,21 +2443,6 @@ jint Arguments::parse_vm_init_args(const JavaVMInitArgs* args) { return result; } - if (AggressiveOpts) { - // Insert alt-rt.jar between user-specified bootclasspath - // prefix and the default bootclasspath. os::set_boot_path() - // uses meta_index_dir as the default bootclasspath directory. - const char* altclasses_jar = "alt-rt.jar"; - size_t altclasses_path_len = strlen(get_meta_index_dir()) + 1 + - strlen(altclasses_jar); - char* altclasses_path = NEW_C_HEAP_ARRAY(char, altclasses_path_len, mtInternal); - strcpy(altclasses_path, get_meta_index_dir()); - strcat(altclasses_path, altclasses_jar); - scp.add_suffix_to_prefix(altclasses_path); - scp_assembly_required = true; - FREE_C_HEAP_ARRAY(char, altclasses_path, mtInternal); - } - // Parse _JAVA_OPTIONS environment variable (if present) (mimics classic VM) result = parse_java_options_environment_variable(&scp, &scp_assembly_required); if (result != JNI_OK) { @@ -2806,6 +2870,13 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, // ostream_init_log(), when called will use this filename // to initialize a fileStream. _gc_log_filename = strdup(tail); + if (!is_filename_valid(_gc_log_filename)) { + jio_fprintf(defaultStream::output_stream(), + "Invalid file name for use with -Xloggc: Filename can only contain the " + "characters [A-Z][a-z][0-9]-_.%%[p|t] but it has been %s\n" + "Note %%p or %%t can only be used once\n", _gc_log_filename); + return JNI_EINVAL; + } FLAG_SET_CMDLINE(bool, PrintGC, true); FLAG_SET_CMDLINE(bool, PrintGCTimeStamps, true); @@ -3274,13 +3345,13 @@ void Arguments::set_shared_spaces_flags() { } UseSharedSpaces = false; #ifdef _LP64 - if (!UseCompressedOops || !UseCompressedKlassPointers) { + if (!UseCompressedOops || !UseCompressedClassPointers) { vm_exit_during_initialization( - "Cannot dump shared archive when UseCompressedOops or UseCompressedKlassPointers is off.", NULL); + "Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off.", NULL); } } else { - // UseCompressedOops and UseCompressedKlassPointers must be on for UseSharedSpaces. - if (!UseCompressedOops || !UseCompressedKlassPointers) { + // UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces. + if (!UseCompressedOops || !UseCompressedClassPointers) { no_shared_spaces(); } #endif @@ -3326,6 +3397,33 @@ static char* get_shared_archive_path() { return shared_archive_path; } +#ifndef PRODUCT +// Determine whether LogVMOutput should be implicitly turned on. +static bool use_vm_log() { + if (LogCompilation || !FLAG_IS_DEFAULT(LogFile) || + PrintCompilation || PrintInlining || PrintDependencies || PrintNativeNMethods || + PrintDebugInfo || PrintRelocations || PrintNMethods || PrintExceptionHandlers || + PrintAssembly || TraceDeoptimization || TraceDependencies || + (VerifyDependencies && FLAG_IS_CMDLINE(VerifyDependencies))) { + return true; + } + +#ifdef COMPILER1 + if (PrintC1Statistics) { + return true; + } +#endif // COMPILER1 + +#ifdef COMPILER2 + if (PrintOptoAssembly || PrintOptoStatistics) { + return true; + } +#endif // COMPILER2 + + return false; +} +#endif // PRODUCT + // Parse entry point called from JNI_CreateJavaVM jint Arguments::parse(const JavaVMInitArgs* args) { @@ -3506,6 +3604,11 @@ jint Arguments::parse(const JavaVMInitArgs* args) { no_shared_spaces(); #endif // INCLUDE_CDS + return JNI_OK; +} + +jint Arguments::apply_ergo() { + // Set flags based on ergonomics. set_ergonomics_flags(); @@ -3581,7 +3684,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) { FLAG_SET_DEFAULT(ProfileInterpreter, false); FLAG_SET_DEFAULT(UseBiasedLocking, false); LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedOops, false)); - LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedKlassPointers, false)); + LP64_ONLY(FLAG_SET_DEFAULT(UseCompressedClassPointers, false)); #endif // CC_INTERP #ifdef COMPILER2 @@ -3610,6 +3713,10 @@ jint Arguments::parse(const JavaVMInitArgs* args) { DebugNonSafepoints = true; } + if (FLAG_IS_CMDLINE(CompressedClassSpaceSize) && !UseCompressedClassPointers) { + warning("Setting CompressedClassSpaceSize has no effect when compressed class pointers are not used"); + } + #ifndef PRODUCT if (CompileTheWorld) { // Force NmethodSweeper to sweep whole CodeCache each time. @@ -3617,7 +3724,13 @@ jint Arguments::parse(const JavaVMInitArgs* args) { NmethodSweepFraction = 1; } } -#endif + + if (!LogVMOutput && FLAG_IS_DEFAULT(LogVMOutput)) { + if (use_vm_log()) { + LogVMOutput = true; + } + } +#endif // PRODUCT if (PrintCommandLineFlags) { CommandLineFlags::printSetFlags(tty); diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 43256b75082..4b2a821a5a3 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -144,7 +144,7 @@ public: void set_os_lib(void* os_lib) { _os_lib = os_lib; } AgentLibrary* next() const { return _next; } bool is_static_lib() const { return _is_static_lib; } - void set_static_lib(bool static_lib) { _is_static_lib = static_lib; } + void set_static_lib(bool is_static_lib) { _is_static_lib = is_static_lib; } bool valid() { return (_state == agent_valid); } void set_valid() { _state = agent_valid; } void set_invalid() { _state = agent_invalid; } @@ -280,6 +280,9 @@ class Arguments : AllStatic { // Option flags static bool _has_profile; static const char* _gc_log_filename; + // Value of the conservative maximum heap alignment needed + static size_t _conservative_max_heap_alignment; + static uintx _min_heap_size; // -Xrun arguments @@ -327,6 +330,7 @@ class Arguments : AllStatic { // Garbage-First (UseG1GC) static void set_g1_gc_flags(); // GC ergonomics + static void set_conservative_max_heap_alignment(); static void set_use_compressed_oops(); static void set_use_compressed_klass_ptrs(); static void set_ergonomics_flags(); @@ -430,8 +434,10 @@ class Arguments : AllStatic { static char* SharedArchivePath; public: - // Parses the arguments + // Parses the arguments, first phase static jint parse(const JavaVMInitArgs* args); + // Apply ergonomics + static jint apply_ergo(); // Adjusts the arguments after the OS have adjusted the arguments static jint adjust_after_os(); // Check for consistency in the selection of the garbage collector. @@ -445,6 +451,10 @@ class Arguments : AllStatic { // Used by os_solaris static bool process_settings_file(const char* file_name, bool should_exist, jboolean ignore_unrecognized); + static size_t conservative_max_heap_alignment() { return _conservative_max_heap_alignment; } + // Return the maximum size a heap with compressed oops can take + static size_t max_heap_for_compressed_oops(); + // return a char* array containing all options static char** jvm_flags_array() { return _jvm_flags_array; } static char** jvm_args_array() { return _jvm_args_array; } diff --git a/hotspot/src/share/vm/runtime/deoptimization.cpp b/hotspot/src/share/vm/runtime/deoptimization.cpp index 7f71c2d8b76..007bfe7aa13 100644 --- a/hotspot/src/share/vm/runtime/deoptimization.cpp +++ b/hotspot/src/share/vm/runtime/deoptimization.cpp @@ -1751,7 +1751,7 @@ int Deoptimization::trap_state_set_recompiled(int trap_state, bool z) { else return trap_state & ~DS_RECOMPILE_BIT; } //---------------------------format_trap_state--------------------------------- -// This is used for debugging and diagnostics, including hotspot.log output. +// This is used for debugging and diagnostics, including LogFile output. const char* Deoptimization::format_trap_state(char* buf, size_t buflen, int trap_state) { DeoptReason reason = trap_state_reason(trap_state); @@ -1828,7 +1828,7 @@ const char* Deoptimization::trap_action_name(int action) { return buf; } -// This is used for debugging and diagnostics, including hotspot.log output. +// This is used for debugging and diagnostics, including LogFile output. const char* Deoptimization::format_trap_request(char* buf, size_t buflen, int trap_request) { jint unloaded_class_index = trap_request_index(trap_request); diff --git a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp index 23d679494ac..79e3ddcd85d 100644 --- a/hotspot/src/share/vm/runtime/fieldDescriptor.cpp +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.cpp @@ -97,18 +97,32 @@ oop fieldDescriptor::string_initial_value(TRAPS) const { return constants()->uncached_string_at(initial_value_index(), CHECK_0); } -void fieldDescriptor::initialize(InstanceKlass* ik, int index) { - _cp = ik->constants(); +void fieldDescriptor::reinitialize(InstanceKlass* ik, int index) { + if (_cp.is_null() || field_holder() != ik) { + _cp = constantPoolHandle(Thread::current(), ik->constants()); + // _cp should now reference ik's constant pool; i.e., ik is now field_holder. + assert(field_holder() == ik, "must be already initialized to this class"); + } FieldInfo* f = ik->field(index); assert(!f->is_internal(), "regular Java fields only"); _access_flags = accessFlags_from(f->access_flags()); guarantee(f->name_index() != 0 && f->signature_index() != 0, "bad constant pool index for fieldDescriptor"); _index = index; + verify(); } #ifndef PRODUCT +void fieldDescriptor::verify() const { + if (_cp.is_null()) { + assert(_index == badInt, "constructor must be called"); // see constructor + } else { + assert(_index >= 0, "good index"); + assert(_index < field_holder()->java_fields_count(), "oob"); + } +} + void fieldDescriptor::print_on(outputStream* st) const { access_flags().print_on(st); name()->print_value_on(st); diff --git a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp index 12b75cab144..9c3101b38ba 100644 --- a/hotspot/src/share/vm/runtime/fieldDescriptor.hpp +++ b/hotspot/src/share/vm/runtime/fieldDescriptor.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -53,6 +53,13 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { } public: + fieldDescriptor() { + DEBUG_ONLY(_index = badInt); + } + fieldDescriptor(InstanceKlass* ik, int index) { + DEBUG_ONLY(_index = badInt); + reinitialize(ik, index); + } Symbol* name() const { return field()->name(_cp); } @@ -112,12 +119,13 @@ class fieldDescriptor VALUE_OBJ_CLASS_SPEC { } // Initialization - void initialize(InstanceKlass* ik, int index); + void reinitialize(InstanceKlass* ik, int index); // Print void print() { print_on(tty); } void print_on(outputStream* st) const PRODUCT_RETURN; void print_on_for(outputStream* st, oop obj) PRODUCT_RETURN; + void verify() const PRODUCT_RETURN; }; #endif // SHARE_VM_RUNTIME_FIELDDESCRIPTOR_HPP diff --git a/hotspot/src/share/vm/runtime/frame.cpp b/hotspot/src/share/vm/runtime/frame.cpp index 6f5724323cd..4fae1c8fe11 100644 --- a/hotspot/src/share/vm/runtime/frame.cpp +++ b/hotspot/src/share/vm/runtime/frame.cpp @@ -652,7 +652,7 @@ void frame::interpreter_frame_print_on(outputStream* st) const { // Return whether the frame is in the VM or os indicating a Hotspot problem. // Otherwise, it's likely a bug in the native library that the Java code calls, // hopefully indicating where to submit bugs. -static void print_C_frame(outputStream* st, char* buf, int buflen, address pc) { +void frame::print_C_frame(outputStream* st, char* buf, int buflen, address pc) { // C/C++ frame bool in_vm = os::address_is_in_vm(pc); st->print(in_vm ? "V" : "C"); diff --git a/hotspot/src/share/vm/runtime/frame.hpp b/hotspot/src/share/vm/runtime/frame.hpp index 096b467b5f8..78292c662ec 100644 --- a/hotspot/src/share/vm/runtime/frame.hpp +++ b/hotspot/src/share/vm/runtime/frame.hpp @@ -406,6 +406,7 @@ class frame VALUE_OBJ_CLASS_SPEC { void print_on(outputStream* st) const; void interpreter_frame_print_on(outputStream* st) const; void print_on_error(outputStream* st, char* buf, int buflen, bool verbose = false) const; + static void print_C_frame(outputStream* st, char* buf, int buflen, address pc); // Add annotated descriptions of memory locations belonging to this frame to values void describe(FrameValues& values, int frame_no); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index c9bcbe1f4d3..083cccd5cc4 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -443,8 +443,8 @@ class CommandLineFlags { "Use 32-bit object references in 64-bit VM " \ "lp64_product means flag is always constant in 32 bit VM") \ \ - lp64_product(bool, UseCompressedKlassPointers, false, \ - "Use 32-bit klass pointers in 64-bit VM " \ + lp64_product(bool, UseCompressedClassPointers, false, \ + "Use 32-bit class pointers in 64-bit VM " \ "lp64_product means flag is always constant in 32 bit VM") \ \ notproduct(bool, CheckCompressedOops, true, \ @@ -880,7 +880,7 @@ class CommandLineFlags { "stay alive at the expense of JVM performance") \ \ diagnostic(bool, LogCompilation, false, \ - "Log compilation activity in detail to hotspot.log or LogFile") \ + "Log compilation activity in detail to LogFile") \ \ product(bool, PrintCompilation, false, \ "Print compilations") \ @@ -2498,16 +2498,17 @@ class CommandLineFlags { "Print all VM flags with default values and descriptions and exit")\ \ diagnostic(bool, SerializeVMOutput, true, \ - "Use a mutex to serialize output to tty and hotspot.log") \ + "Use a mutex to serialize output to tty and LogFile") \ \ diagnostic(bool, DisplayVMOutput, true, \ "Display all VM output on the tty, independently of LogVMOutput") \ \ - diagnostic(bool, LogVMOutput, trueInDebug, \ - "Save VM output to hotspot.log, or to LogFile") \ + diagnostic(bool, LogVMOutput, false, \ + "Save VM output to LogFile") \ \ diagnostic(ccstr, LogFile, NULL, \ - "If LogVMOutput is on, save VM output to this file [hotspot.log]") \ + "If LogVMOutput or LogCompilation is on, save VM output to " \ + "this file [default: ./hotspot_pid%p.log] (%p replaced with pid)") \ \ product(ccstr, ErrorFile, NULL, \ "If an error occurs, save the error data to this file " \ @@ -2525,6 +2526,9 @@ class CommandLineFlags { product(bool, PrintStringTableStatistics, false, \ "print statistics about the StringTable and SymbolTable") \ \ + diagnostic(bool, VerifyStringTableAtExit, false, \ + "verify StringTable contents at exit") \ + \ notproduct(bool, PrintSymbolTableSizeHistogram, false, \ "print histogram of the symbol table") \ \ @@ -3039,9 +3043,9 @@ class CommandLineFlags { product(uintx, MaxMetaspaceSize, max_uintx, \ "Maximum size of Metaspaces (in bytes)") \ \ - product(uintx, ClassMetaspaceSize, 1*G, \ - "Maximum size of InstanceKlass area in Metaspace used for " \ - "UseCompressedKlassPointers") \ + product(uintx, CompressedClassSpaceSize, 1*G, \ + "Maximum size of class area in Metaspace when compressed " \ + "class pointers are used") \ \ product(uintx, MinHeapFreeRatio, 40, \ "Min percentage of heap free after GC to avoid expansion") \ @@ -3649,6 +3653,9 @@ class CommandLineFlags { experimental(bool, TrustFinalNonStaticFields, false, \ "trust final non-static declarations for constant folding") \ \ + experimental(bool, FoldStableValues, false, \ + "Private flag to control optimizations for stable variables") \ + \ develop(bool, TraceInvokeDynamic, false, \ "trace internal invoke dynamic operations") \ \ diff --git a/hotspot/src/share/vm/runtime/handles.hpp b/hotspot/src/share/vm/runtime/handles.hpp index dc254227971..c2ce4b38c5a 100644 --- a/hotspot/src/share/vm/runtime/handles.hpp +++ b/hotspot/src/share/vm/runtime/handles.hpp @@ -136,7 +136,7 @@ DEF_HANDLE(typeArray , is_typeArray ) // Specific Handles for different oop types #define DEF_METADATA_HANDLE(name, type) \ class name##Handle; \ - class name##Handle { \ + class name##Handle : public StackObj { \ type* _value; \ Thread* _thread; \ protected: \ @@ -175,7 +175,7 @@ DEF_METADATA_HANDLE(constantPool, ConstantPool) // Writing this class explicitly, since DEF_METADATA_HANDLE(klass) doesn't // provide the necessary Klass* <-> Klass* conversions. This Klass // could be removed when we don't have the Klass* typedef anymore. -class KlassHandle { +class KlassHandle : public StackObj { Klass* _value; protected: Klass* obj() const { return _value; } diff --git a/hotspot/src/share/vm/runtime/handles.inline.hpp b/hotspot/src/share/vm/runtime/handles.inline.hpp index 9530b127aea..5a0f3f773c2 100644 --- a/hotspot/src/share/vm/runtime/handles.inline.hpp +++ b/hotspot/src/share/vm/runtime/handles.inline.hpp @@ -79,6 +79,7 @@ inline name##Handle::name##Handle(const name##Handle &h) { \ } else { \ _thread = Thread::current(); \ } \ + assert (_thread->is_in_stack((address)this), "not on stack?"); \ _thread->metadata_handles()->push((Metadata*)_value); \ } else { \ _thread = NULL; \ @@ -95,6 +96,7 @@ inline name##Handle& name##Handle::operator=(const name##Handle &s) { \ } else { \ _thread = Thread::current(); \ } \ + assert (_thread->is_in_stack((address)this), "not on stack?"); \ _thread->metadata_handles()->push((Metadata*)_value); \ } else { \ _thread = NULL; \ diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index f995a4ee714..4d2ca5137ea 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.hpp @@ -471,16 +471,6 @@ class RuntimeHistogramElement : public HistogramElement { VM_ENTRY_BASE(result_type, header, thread) \ debug_only(VMEntryWrapper __vew;) -// Another special case for nmethod_entry_point so the nmethod that the -// interpreter is about to branch to doesn't get flushed before as we -// branch to it's interpreter_entry_point. Skip stress testing here too. -// Also we don't allow async exceptions because it is just too painful. -#define IRT_ENTRY_FOR_NMETHOD(result_type, header) \ - result_type header { \ - nmethodLocker _nmlock(nm); \ - ThreadInVMfromJavaNoAsyncException __tiv(thread); \ - VM_ENTRY_BASE(result_type, header, thread) - #define IRT_END } diff --git a/hotspot/src/share/vm/runtime/java.cpp b/hotspot/src/share/vm/runtime/java.cpp index ebc4e087578..874765fa3e5 100644 --- a/hotspot/src/share/vm/runtime/java.cpp +++ b/hotspot/src/share/vm/runtime/java.cpp @@ -544,6 +544,19 @@ void before_exit(JavaThread * thread) { // it will run into trouble when system destroys static variables. MemTracker::shutdown(MemTracker::NMT_normal); + if (VerifyStringTableAtExit) { + int fail_cnt = 0; + { + MutexLocker ml(StringTable_lock); + fail_cnt = StringTable::verify_and_compare_entries(); + } + + if (fail_cnt != 0) { + tty->print_cr("ERROR: fail_cnt=%d", fail_cnt); + guarantee(fail_cnt == 0, "unexpected StringTable verification failures"); + } + } + #undef BEFORE_EXIT_NOT_RUN #undef BEFORE_EXIT_RUNNING #undef BEFORE_EXIT_DONE diff --git a/hotspot/src/share/vm/runtime/mutexLocker.cpp b/hotspot/src/share/vm/runtime/mutexLocker.cpp index f513b7b376c..19f98cc2e4f 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.cpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.cpp @@ -45,7 +45,6 @@ Mutex* InlineCacheBuffer_lock = NULL; Mutex* VMStatistic_lock = NULL; Mutex* JNIGlobalHandle_lock = NULL; Mutex* JNIHandleBlockFreeList_lock = NULL; -Mutex* JNICachedItableIndex_lock = NULL; Mutex* MemberNameTable_lock = NULL; Mutex* JmethodIdCreation_lock = NULL; Mutex* JfieldIdCreation_lock = NULL; @@ -253,7 +252,6 @@ void mutex_init() { } def(Heap_lock , Monitor, nonleaf+1, false); def(JfieldIdCreation_lock , Mutex , nonleaf+1, true ); // jfieldID, Used in VM_Operation - def(JNICachedItableIndex_lock , Mutex , nonleaf+1, false); // Used to cache an itable index during JNI invoke def(MemberNameTable_lock , Mutex , nonleaf+1, false); // Used to protect MemberNameTable def(CompiledIC_lock , Mutex , nonleaf+2, false); // locks VtableStubs_lock, InlineCacheBuffer_lock diff --git a/hotspot/src/share/vm/runtime/mutexLocker.hpp b/hotspot/src/share/vm/runtime/mutexLocker.hpp index d98b8d890fd..361febdcdb8 100644 --- a/hotspot/src/share/vm/runtime/mutexLocker.hpp +++ b/hotspot/src/share/vm/runtime/mutexLocker.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,7 +50,6 @@ extern Mutex* InlineCacheBuffer_lock; // a lock used to guard the Inl extern Mutex* VMStatistic_lock; // a lock used to guard statistics count increment extern Mutex* JNIGlobalHandle_lock; // a lock on creating JNI global handles extern Mutex* JNIHandleBlockFreeList_lock; // a lock on the JNI handle block free list -extern Mutex* JNICachedItableIndex_lock; // a lock on caching an itable index during JNI invoke extern Mutex* MemberNameTable_lock; // a lock on the MemberNameTable updates extern Mutex* JmethodIdCreation_lock; // a lock on creating JNI method identifiers extern Mutex* JfieldIdCreation_lock; // a lock on creating JNI static field identifiers diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 0c83565195c..e2d930a1d59 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -314,6 +314,11 @@ static void signal_thread_entry(JavaThread* thread, TRAPS) { } } +void os::init_before_ergo() { + // We need to initialize large page support here because ergonomics takes some + // decisions depending on large page support and the calculated large page size. + large_page_init(); +} void os::signal_init() { if (!ReduceSignalUsage) { @@ -454,6 +459,7 @@ void* os::native_java_library() { */ void* os::find_agent_function(AgentLibrary *agent_lib, bool check_lib, const char *syms[], size_t syms_len) { + assert(agent_lib != NULL, "sanity check"); const char *lib_name; void *handle = agent_lib->os_lib(); void *entryName = NULL; @@ -484,6 +490,7 @@ bool os::find_builtin_agent(AgentLibrary *agent_lib, const char *syms[], void *proc_handle; void *save_handle; + assert(agent_lib != NULL, "sanity check"); if (agent_lib->name() == NULL) { return false; } @@ -493,14 +500,13 @@ bool os::find_builtin_agent(AgentLibrary *agent_lib, const char *syms[], // We want to look in this process' symbol table. agent_lib->set_os_lib(proc_handle); ret = find_agent_function(agent_lib, true, syms, syms_len); - agent_lib->set_os_lib(save_handle); if (ret != NULL) { // Found an entry point like Agent_OnLoad_lib_name so we have a static agent - agent_lib->set_os_lib(proc_handle); agent_lib->set_valid(); agent_lib->set_static_lib(true); return true; } + agent_lib->set_os_lib(save_handle); return false; } diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index e43d68981cb..17fcd3bdd79 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -91,6 +91,8 @@ const bool ExecMem = true; typedef void (*java_call_t)(JavaValue* value, methodHandle* method, JavaCallArguments* args, Thread* thread); class os: AllStatic { + friend class VMStructs; + public: enum { page_sizes_max = 9 }; // Size of _page_sizes array (8 plus a sentinel) @@ -139,7 +141,10 @@ class os: AllStatic { public: static void init(void); // Called before command line parsing + static void init_before_ergo(void); // Called after command line parsing + // before VM ergonomics processing. static jint init_2(void); // Called after command line parsing + // and VM ergonomics processing static void init_globals(void) { // Called from init_globals() in init.cpp init_globals_ext(); } @@ -254,6 +259,11 @@ class os: AllStatic { static size_t page_size_for_region(size_t region_min_size, size_t region_max_size, uint min_pages); + // Return the largest page size that can be used + static size_t max_page_size() { + // The _page_sizes array is sorted in descending order. + return _page_sizes[0]; + } // Methods for tracing page sizes returned by the above method; enabled by // TracePageSizes. The region_{min,max}_size parameters should be the values @@ -795,6 +805,14 @@ class os: AllStatic { #endif public: +#ifndef PLATFORM_PRINT_NATIVE_STACK + // No platform-specific code for printing the native stack. + static bool platform_print_native_stack(outputStream* st, void* context, + char *buf, int buf_size) { + return false; + } +#endif + // debugging support (mostly used by debug.cpp but also fatal error handler) static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address diff --git a/hotspot/src/share/vm/runtime/reflection.cpp b/hotspot/src/share/vm/runtime/reflection.cpp index f06a7f922aa..be29fdecfcf 100644 --- a/hotspot/src/share/vm/runtime/reflection.cpp +++ b/hotspot/src/share/vm/runtime/reflection.cpp @@ -952,7 +952,8 @@ oop Reflection::invoke(instanceKlassHandle klass, methodHandle reflected_method, } } else { // if the method can be overridden, we resolve using the vtable index. - int index = reflected_method->vtable_index(); + assert(!reflected_method->has_itable_index(), ""); + int index = reflected_method->vtable_index(); method = reflected_method; if (index != Method::nonvirtual_vtable_index) { // target_klass might be an arrayKlassOop but all vtables start at diff --git a/hotspot/src/share/vm/runtime/reflectionUtils.hpp b/hotspot/src/share/vm/runtime/reflectionUtils.hpp index d51b2ab7874..71a500976a7 100644 --- a/hotspot/src/share/vm/runtime/reflectionUtils.hpp +++ b/hotspot/src/share/vm/runtime/reflectionUtils.hpp @@ -109,6 +109,8 @@ class FieldStream : public KlassStream { private: int length() const { return _klass->java_fields_count(); } + fieldDescriptor _fd_buf; + public: FieldStream(instanceKlassHandle klass, bool local_only, bool classes_only) : KlassStream(klass, local_only, classes_only) { @@ -134,6 +136,12 @@ class FieldStream : public KlassStream { int offset() const { return _klass->field_offset( index() ); } + // bridge to a heavier API: + fieldDescriptor& field_descriptor() const { + fieldDescriptor& field = const_cast(_fd_buf); + field.reinitialize(_klass(), _index); + return field; + } }; class FilteredField : public CHeapObj { diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index d014eda2f80..17ea65ae716 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1506,8 +1506,11 @@ methodHandle SharedRuntime::handle_ic_miss_helper(JavaThread *thread, TRAPS) { info, CHECK_(methodHandle())); inline_cache->set_to_monomorphic(info); } else if (!inline_cache->is_megamorphic() && !inline_cache->is_clean()) { - // Change to megamorphic - inline_cache->set_to_megamorphic(&call_info, bc, CHECK_(methodHandle())); + // Potential change to megamorphic + bool successful = inline_cache->set_to_megamorphic(&call_info, bc, CHECK_(methodHandle())); + if (!successful) { + inline_cache->set_to_clean(); + } } else { // Either clean or megamorphic } diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp index ebecda50be0..37315aec328 100644 --- a/hotspot/src/share/vm/runtime/sweeper.cpp +++ b/hotspot/src/share/vm/runtime/sweeper.cpp @@ -269,6 +269,7 @@ void NMethodSweeper::sweep_code_cache() { // the number of nmethods changes during the sweep so the final // stage must iterate until it there are no more nmethods. int todo = (CodeCache::nof_nmethods() - _seen) / _invocations; + int swept_count = 0; assert(!SafepointSynchronize::is_at_safepoint(), "should not be in safepoint when we get here"); assert(!CodeCache_lock->owned_by_self(), "just checking"); @@ -278,6 +279,7 @@ void NMethodSweeper::sweep_code_cache() { // The last invocation iterates until there are no more nmethods for (int i = 0; (i < todo || _invocations == 1) && _current != NULL; i++) { + swept_count++; if (SafepointSynchronize::is_synchronizing()) { // Safepoint request if (PrintMethodFlushing && Verbose) { tty->print_cr("### Sweep at %d out of %d, invocation: %d, yielding to safepoint", _seen, CodeCache::nof_nmethods(), _invocations); @@ -331,7 +333,7 @@ void NMethodSweeper::sweep_code_cache() { event.set_endtime(sweep_end_counter); event.set_sweepIndex(_traversals); event.set_sweepFractionIndex(NmethodSweepFraction - _invocations + 1); - event.set_sweptCount(todo); + event.set_sweptCount(swept_count); event.set_flushedCount(_flushed_count); event.set_markedCount(_marked_count); event.set_zombifiedCount(_zombified_count); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index d5bc3a00006..a0f0bdba713 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -333,6 +333,8 @@ Thread::~Thread() { // Reclaim the objectmonitors from the omFreeList of the moribund thread. ObjectSynchronizer::omFlush (this) ; + EVENT_THREAD_DESTRUCT(this); + // stack_base can be NULL if the thread is never started or exited before // record_stack_base_and_size called. Although, we would like to ensure // that all started threads do call record_stack_base_and_size(), there is @@ -3329,6 +3331,11 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { jint parse_result = Arguments::parse(args); if (parse_result != JNI_OK) return parse_result; + os::init_before_ergo(); + + jint ergo_result = Arguments::apply_ergo(); + if (ergo_result != JNI_OK) return ergo_result; + if (PauseAtStartup) { os::pause(); } @@ -3714,7 +3721,7 @@ static OnLoadEntry_t lookup_on_load(AgentLibrary* agent, const char *on_load_sym const char *name = agent->name(); const char *msg = "Could not find agent library "; - // First check to see if agent is statcally linked into executable + // First check to see if agent is statically linked into executable if (os::find_builtin_agent(agent, on_load_symbols, num_symbol_entries)) { library = agent->os_lib(); } else if (agent->is_absolute_path()) { diff --git a/hotspot/src/share/vm/runtime/virtualspace.cpp b/hotspot/src/share/vm/runtime/virtualspace.cpp index 9e01fe0292f..98ee7635002 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.cpp +++ b/hotspot/src/share/vm/runtime/virtualspace.cpp @@ -453,6 +453,42 @@ size_t VirtualSpace::uncommitted_size() const { return reserved_size() - committed_size(); } +size_t VirtualSpace::actual_committed_size() const { + // Special VirtualSpaces commit all reserved space up front. + if (special()) { + return reserved_size(); + } + + size_t committed_low = pointer_delta(_lower_high, _low_boundary, sizeof(char)); + size_t committed_middle = pointer_delta(_middle_high, _lower_high_boundary, sizeof(char)); + size_t committed_high = pointer_delta(_upper_high, _middle_high_boundary, sizeof(char)); + +#ifdef ASSERT + size_t lower = pointer_delta(_lower_high_boundary, _low_boundary, sizeof(char)); + size_t middle = pointer_delta(_middle_high_boundary, _lower_high_boundary, sizeof(char)); + size_t upper = pointer_delta(_upper_high_boundary, _middle_high_boundary, sizeof(char)); + + if (committed_high > 0) { + assert(committed_low == lower, "Must be"); + assert(committed_middle == middle, "Must be"); + } + + if (committed_middle > 0) { + assert(committed_low == lower, "Must be"); + } + if (committed_middle < middle) { + assert(committed_high == 0, "Must be"); + } + + if (committed_low < lower) { + assert(committed_high == 0, "Must be"); + assert(committed_middle == 0, "Must be"); + } +#endif + + return committed_low + committed_middle + committed_high; +} + bool VirtualSpace::contains(const void* p) const { return low() <= (const char*) p && (const char*) p < high(); @@ -718,16 +754,19 @@ void VirtualSpace::check_for_contiguity() { assert(high() <= upper_high(), "upper high"); } -void VirtualSpace::print() { - tty->print ("Virtual space:"); - if (special()) tty->print(" (pinned in memory)"); - tty->cr(); - tty->print_cr(" - committed: " SIZE_FORMAT, committed_size()); - tty->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); - tty->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); - tty->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); +void VirtualSpace::print_on(outputStream* out) { + out->print ("Virtual space:"); + if (special()) out->print(" (pinned in memory)"); + out->cr(); + out->print_cr(" - committed: " SIZE_FORMAT, committed_size()); + out->print_cr(" - reserved: " SIZE_FORMAT, reserved_size()); + out->print_cr(" - [low, high]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low(), high()); + out->print_cr(" - [low_b, high_b]: [" INTPTR_FORMAT ", " INTPTR_FORMAT "]", low_boundary(), high_boundary()); } +void VirtualSpace::print() { + print_on(tty); +} /////////////// Unit tests /////////////// @@ -910,6 +949,109 @@ void TestReservedSpace_test() { TestReservedSpace::test_reserved_space(); } +#define assert_equals(actual, expected) \ + assert(actual == expected, \ + err_msg("Got " SIZE_FORMAT " expected " \ + SIZE_FORMAT, actual, expected)); + +#define assert_ge(value1, value2) \ + assert(value1 >= value2, \ + err_msg("'" #value1 "': " SIZE_FORMAT " '" \ + #value2 "': " SIZE_FORMAT, value1, value2)); + +#define assert_lt(value1, value2) \ + assert(value1 < value2, \ + err_msg("'" #value1 "': " SIZE_FORMAT " '" \ + #value2 "': " SIZE_FORMAT, value1, value2)); + + +class TestVirtualSpace : AllStatic { + public: + static void test_virtual_space_actual_committed_space(size_t reserve_size, size_t commit_size) { + size_t granularity = os::vm_allocation_granularity(); + size_t reserve_size_aligned = align_size_up(reserve_size, granularity); + + ReservedSpace reserved(reserve_size_aligned); + + assert(reserved.is_reserved(), "Must be"); + + VirtualSpace vs; + bool initialized = vs.initialize(reserved, 0); + assert(initialized, "Failed to initialize VirtualSpace"); + + vs.expand_by(commit_size, false); + + if (vs.special()) { + assert_equals(vs.actual_committed_size(), reserve_size_aligned); + } else { + assert_ge(vs.actual_committed_size(), commit_size); + // Approximate the commit granularity. + size_t commit_granularity = UseLargePages ? os::large_page_size() : os::vm_page_size(); + assert_lt(vs.actual_committed_size(), commit_size + commit_granularity); + } + + reserved.release(); + } + + static void test_virtual_space_actual_committed_space_one_large_page() { + if (!UseLargePages) { + return; + } + + size_t large_page_size = os::large_page_size(); + + ReservedSpace reserved(large_page_size, large_page_size, true, false); + + assert(reserved.is_reserved(), "Must be"); + + VirtualSpace vs; + bool initialized = vs.initialize(reserved, 0); + assert(initialized, "Failed to initialize VirtualSpace"); + + vs.expand_by(large_page_size, false); + + assert_equals(vs.actual_committed_size(), large_page_size); + + reserved.release(); + } + + static void test_virtual_space_actual_committed_space() { + test_virtual_space_actual_committed_space(4 * K, 0); + test_virtual_space_actual_committed_space(4 * K, 4 * K); + test_virtual_space_actual_committed_space(8 * K, 0); + test_virtual_space_actual_committed_space(8 * K, 4 * K); + test_virtual_space_actual_committed_space(8 * K, 8 * K); + test_virtual_space_actual_committed_space(12 * K, 0); + test_virtual_space_actual_committed_space(12 * K, 4 * K); + test_virtual_space_actual_committed_space(12 * K, 8 * K); + test_virtual_space_actual_committed_space(12 * K, 12 * K); + test_virtual_space_actual_committed_space(64 * K, 0); + test_virtual_space_actual_committed_space(64 * K, 32 * K); + test_virtual_space_actual_committed_space(64 * K, 64 * K); + test_virtual_space_actual_committed_space(2 * M, 0); + test_virtual_space_actual_committed_space(2 * M, 4 * K); + test_virtual_space_actual_committed_space(2 * M, 64 * K); + test_virtual_space_actual_committed_space(2 * M, 1 * M); + test_virtual_space_actual_committed_space(2 * M, 2 * M); + test_virtual_space_actual_committed_space(10 * M, 0); + test_virtual_space_actual_committed_space(10 * M, 4 * K); + test_virtual_space_actual_committed_space(10 * M, 8 * K); + test_virtual_space_actual_committed_space(10 * M, 1 * M); + test_virtual_space_actual_committed_space(10 * M, 2 * M); + test_virtual_space_actual_committed_space(10 * M, 5 * M); + test_virtual_space_actual_committed_space(10 * M, 10 * M); + } + + static void test_virtual_space() { + test_virtual_space_actual_committed_space(); + test_virtual_space_actual_committed_space_one_large_page(); + } +}; + +void TestVirtualSpace_test() { + TestVirtualSpace::test_virtual_space(); +} + #endif // PRODUCT #endif diff --git a/hotspot/src/share/vm/runtime/virtualspace.hpp b/hotspot/src/share/vm/runtime/virtualspace.hpp index bca9b6c14fc..02b14734a00 100644 --- a/hotspot/src/share/vm/runtime/virtualspace.hpp +++ b/hotspot/src/share/vm/runtime/virtualspace.hpp @@ -183,11 +183,16 @@ class VirtualSpace VALUE_OBJ_CLASS_SPEC { // Destruction ~VirtualSpace(); - // Testers (all sizes are byte sizes) - size_t committed_size() const; - size_t reserved_size() const; + // Reserved memory + size_t reserved_size() const; + // Actually committed OS memory + size_t actual_committed_size() const; + // Memory used/expanded in this virtual space + size_t committed_size() const; + // Memory left to use/expand in this virtual space size_t uncommitted_size() const; - bool contains(const void* p) const; + + bool contains(const void* p) const; // Operations // returns true on success, false otherwise @@ -198,7 +203,8 @@ class VirtualSpace VALUE_OBJ_CLASS_SPEC { void check_for_contiguity() PRODUCT_RETURN; // Debugging - void print() PRODUCT_RETURN; + void print_on(outputStream* out) PRODUCT_RETURN; + void print(); }; #endif // SHARE_VM_RUNTIME_VIRTUALSPACE_HPP diff --git a/hotspot/src/share/vm/runtime/vmStructs.cpp b/hotspot/src/share/vm/runtime/vmStructs.cpp index 7e0df23a3e1..55405b27fd4 100644 --- a/hotspot/src/share/vm/runtime/vmStructs.cpp +++ b/hotspot/src/share/vm/runtime/vmStructs.cpp @@ -315,7 +315,6 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(InstanceKlass, _breakpoints, BreakpointInfo*) \ nonstatic_field(InstanceKlass, _generic_signature_index, u2) \ nonstatic_field(InstanceKlass, _methods_jmethod_ids, jmethodID*) \ - nonstatic_field(InstanceKlass, _methods_cached_itable_indices, int*) \ volatile_nonstatic_field(InstanceKlass, _idnum_allocated_count, u2) \ nonstatic_field(InstanceKlass, _annotations, Annotations*) \ nonstatic_field(InstanceKlass, _dependencies, nmethodBucket*) \ @@ -330,11 +329,13 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(Klass, _java_mirror, oop) \ nonstatic_field(Klass, _modifier_flags, jint) \ nonstatic_field(Klass, _super, Klass*) \ + nonstatic_field(Klass, _subklass, Klass*) \ nonstatic_field(Klass, _layout_helper, jint) \ nonstatic_field(Klass, _name, Symbol*) \ nonstatic_field(Klass, _access_flags, AccessFlags) \ - nonstatic_field(Klass, _subklass, Klass*) \ + nonstatic_field(Klass, _prototype_header, markOop) \ nonstatic_field(Klass, _next_sibling, Klass*) \ + nonstatic_field(vtableEntry, _method, Method*) \ nonstatic_field(MethodData, _size, int) \ nonstatic_field(MethodData, _method, Method*) \ nonstatic_field(MethodData, _data_size, int) \ @@ -342,10 +343,15 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(MethodData, _nof_decompiles, uint) \ nonstatic_field(MethodData, _nof_overflow_recompiles, uint) \ nonstatic_field(MethodData, _nof_overflow_traps, uint) \ + nonstatic_field(MethodData, _trap_hist._array[0], u1) \ nonstatic_field(MethodData, _eflags, intx) \ nonstatic_field(MethodData, _arg_local, intx) \ nonstatic_field(MethodData, _arg_stack, intx) \ nonstatic_field(MethodData, _arg_returned, intx) \ + nonstatic_field(DataLayout, _header._struct._tag, u1) \ + nonstatic_field(DataLayout, _header._struct._flags, u1) \ + nonstatic_field(DataLayout, _header._struct._bci, u2) \ + nonstatic_field(DataLayout, _cells[0], intptr_t) \ nonstatic_field(MethodCounters, _interpreter_invocation_count, int) \ nonstatic_field(MethodCounters, _interpreter_throwout_count, u2) \ nonstatic_field(MethodCounters, _number_of_breakpoints, u2) \ @@ -357,6 +363,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(Method, _access_flags, AccessFlags) \ nonstatic_field(Method, _vtable_index, int) \ nonstatic_field(Method, _method_size, u2) \ + nonstatic_field(Method, _intrinsic_id, u1) \ nonproduct_nonstatic_field(Method, _compiled_invocation_count, int) \ volatile_nonstatic_field(Method, _code, nmethod*) \ nonstatic_field(Method, _i2i_entry, address) \ @@ -443,12 +450,19 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; static_field(Universe, _bootstrapping, bool) \ static_field(Universe, _fully_initialized, bool) \ static_field(Universe, _verify_count, int) \ + static_field(Universe, _non_oop_bits, intptr_t) \ static_field(Universe, _narrow_oop._base, address) \ static_field(Universe, _narrow_oop._shift, int) \ static_field(Universe, _narrow_oop._use_implicit_null_checks, bool) \ static_field(Universe, _narrow_klass._base, address) \ static_field(Universe, _narrow_klass._shift, int) \ \ + /******/ \ + /* os */ \ + /******/ \ + \ + static_field(os, _polling_page, address) \ + \ /**********************************************************************************/ \ /* Generation and Space hierarchies */ \ /**********************************************************************************/ \ @@ -456,6 +470,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; unchecked_nonstatic_field(ageTable, sizes, sizeof(ageTable::sizes)) \ \ nonstatic_field(BarrierSet, _max_covered_regions, int) \ + nonstatic_field(BarrierSet, _kind, BarrierSet::Name) \ nonstatic_field(BlockOffsetTable, _bottom, HeapWord*) \ nonstatic_field(BlockOffsetTable, _end, HeapWord*) \ \ @@ -495,6 +510,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(CollectedHeap, _barrier_set, BarrierSet*) \ nonstatic_field(CollectedHeap, _defer_initial_card_mark, bool) \ nonstatic_field(CollectedHeap, _is_gc_active, bool) \ + nonstatic_field(CollectedHeap, _total_collections, unsigned int) \ nonstatic_field(CompactibleSpace, _compaction_top, HeapWord*) \ nonstatic_field(CompactibleSpace, _first_dead, HeapWord*) \ nonstatic_field(CompactibleSpace, _end_of_live, HeapWord*) \ @@ -505,7 +521,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(ContiguousSpace, _saved_mark_word, HeapWord*) \ \ nonstatic_field(DefNewGeneration, _next_gen, Generation*) \ - nonstatic_field(DefNewGeneration, _tenuring_threshold, uint) \ + nonstatic_field(DefNewGeneration, _tenuring_threshold, uint) \ nonstatic_field(DefNewGeneration, _age_table, ageTable) \ nonstatic_field(DefNewGeneration, _eden_space, EdenSpace*) \ nonstatic_field(DefNewGeneration, _from_space, ContiguousSpace*) \ @@ -552,6 +568,11 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(ThreadLocalAllocBuffer, _desired_size, size_t) \ nonstatic_field(ThreadLocalAllocBuffer, _refill_waste_limit, size_t) \ static_field(ThreadLocalAllocBuffer, _target_refills, unsigned) \ + nonstatic_field(ThreadLocalAllocBuffer, _number_of_refills, unsigned) \ + nonstatic_field(ThreadLocalAllocBuffer, _fast_refill_waste, unsigned) \ + nonstatic_field(ThreadLocalAllocBuffer, _slow_refill_waste, unsigned) \ + nonstatic_field(ThreadLocalAllocBuffer, _gc_waste, unsigned) \ + nonstatic_field(ThreadLocalAllocBuffer, _slow_allocations, unsigned) \ nonstatic_field(VirtualSpace, _low_boundary, char*) \ nonstatic_field(VirtualSpace, _high_boundary, char*) \ nonstatic_field(VirtualSpace, _low, char*) \ @@ -713,6 +734,13 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; \ static_field(ClassLoaderDataGraph, _head, ClassLoaderData*) \ \ + /**********/ \ + /* Arrays */ \ + /**********/ \ + \ + nonstatic_field(Array, _length, int) \ + nonstatic_field(Array, _data[0], Klass*) \ + \ /*******************/ \ /* GrowableArrays */ \ /*******************/ \ @@ -720,7 +748,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(GenericGrowableArray, _len, int) \ nonstatic_field(GenericGrowableArray, _max, int) \ nonstatic_field(GenericGrowableArray, _arena, Arena*) \ - nonstatic_field(GrowableArray, _data, int*) \ + nonstatic_field(GrowableArray, _data, int*) \ \ /********************************/ \ /* CodeCache (NOTE: incomplete) */ \ @@ -763,7 +791,20 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* StubRoutines (NOTE: incomplete) */ \ /***********************************/ \ \ + static_field(StubRoutines, _verify_oop_count, jint) \ static_field(StubRoutines, _call_stub_return_address, address) \ + static_field(StubRoutines, _aescrypt_encryptBlock, address) \ + static_field(StubRoutines, _aescrypt_decryptBlock, address) \ + static_field(StubRoutines, _cipherBlockChaining_encryptAESCrypt, address) \ + static_field(StubRoutines, _cipherBlockChaining_decryptAESCrypt, address) \ + static_field(StubRoutines, _updateBytesCRC32, address) \ + static_field(StubRoutines, _crc_table_adr, address) \ + \ + /*****************/ \ + /* SharedRuntime */ \ + /*****************/ \ + \ + static_field(SharedRuntime, _ic_miss_blob, RuntimeStub*) \ \ /***************************************/ \ /* PcDesc and other compiled code info */ \ @@ -853,6 +894,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; volatile_nonstatic_field(Thread, _suspend_flags, uint32_t) \ nonstatic_field(Thread, _active_handles, JNIHandleBlock*) \ nonstatic_field(Thread, _tlab, ThreadLocalAllocBuffer) \ + nonstatic_field(Thread, _allocated_bytes, jlong) \ nonstatic_field(Thread, _current_pending_monitor, ObjectMonitor*) \ nonstatic_field(Thread, _current_pending_monitor_is_from_java, bool) \ nonstatic_field(Thread, _current_waiting_monitor, ObjectMonitor*) \ @@ -866,6 +908,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(JavaThread, _pending_async_exception, oop) \ volatile_nonstatic_field(JavaThread, _exception_oop, oop) \ volatile_nonstatic_field(JavaThread, _exception_pc, address) \ + volatile_nonstatic_field(JavaThread, _is_method_handle_return, int) \ nonstatic_field(JavaThread, _is_compiling, bool) \ nonstatic_field(JavaThread, _special_runtime_exit_condition, JavaThread::AsyncRequests) \ nonstatic_field(JavaThread, _saved_exception_pc, address) \ @@ -875,6 +918,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; nonstatic_field(JavaThread, _stack_size, size_t) \ nonstatic_field(JavaThread, _vframe_array_head, vframeArray*) \ nonstatic_field(JavaThread, _vframe_array_last, vframeArray*) \ + nonstatic_field(JavaThread, _satb_mark_queue, ObjPtrQueue) \ + nonstatic_field(JavaThread, _dirty_card_queue, DirtyCardQueue) \ nonstatic_field(Thread, _resource_area, ResourceArea*) \ nonstatic_field(CompilerThread, _env, ciEnv*) \ \ @@ -1187,7 +1232,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; unchecked_nonstatic_field(Array, _data, sizeof(int)) \ unchecked_nonstatic_field(Array, _data, sizeof(u1)) \ unchecked_nonstatic_field(Array, _data, sizeof(u2)) \ - unchecked_nonstatic_field(Array, _data, sizeof(Method*)) \ + unchecked_nonstatic_field(Array, _data, sizeof(Method*)) \ unchecked_nonstatic_field(Array, _data, sizeof(Klass*)) \ \ /*********************************/ \ @@ -1203,7 +1248,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* Miscellaneous fields */ \ /************************/ \ \ - nonstatic_field(CompileTask, _method, Method*) \ + nonstatic_field(CompileTask, _method, Method*) \ nonstatic_field(CompileTask, _osr_bci, int) \ nonstatic_field(CompileTask, _comp_level, int) \ nonstatic_field(CompileTask, _compile_id, uint) \ @@ -1217,7 +1262,11 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; \ nonstatic_field(vframeArrayElement, _frame, frame) \ nonstatic_field(vframeArrayElement, _bci, int) \ - nonstatic_field(vframeArrayElement, _method, Method*) \ + nonstatic_field(vframeArrayElement, _method, Method*) \ + \ + nonstatic_field(PtrQueue, _active, bool) \ + nonstatic_field(PtrQueue, _buf, void**) \ + nonstatic_field(PtrQueue, _index, size_t) \ \ nonstatic_field(AccessFlags, _flags, jint) \ nonstatic_field(elapsedTimer, _counter, jlong) \ @@ -1363,7 +1412,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* MetadataOopDesc hierarchy (NOTE: some missing) */ \ /**************************************************/ \ \ - declare_toplevel_type(CompiledICHolder) \ + declare_toplevel_type(CompiledICHolder) \ declare_toplevel_type(MetaspaceObj) \ declare_type(Metadata, MetaspaceObj) \ declare_type(Klass, Metadata) \ @@ -1374,17 +1423,20 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_type(InstanceClassLoaderKlass, InstanceKlass) \ declare_type(InstanceMirrorKlass, InstanceKlass) \ declare_type(InstanceRefKlass, InstanceKlass) \ - declare_type(ConstantPool, Metadata) \ - declare_type(ConstantPoolCache, MetaspaceObj) \ - declare_type(MethodData, Metadata) \ - declare_type(Method, Metadata) \ - declare_type(MethodCounters, MetaspaceObj) \ - declare_type(ConstMethod, MetaspaceObj) \ + declare_type(ConstantPool, Metadata) \ + declare_type(ConstantPoolCache, MetaspaceObj) \ + declare_type(MethodData, Metadata) \ + declare_type(Method, Metadata) \ + declare_type(MethodCounters, MetaspaceObj) \ + declare_type(ConstMethod, MetaspaceObj) \ + \ + declare_toplevel_type(vtableEntry) \ \ declare_toplevel_type(Symbol) \ declare_toplevel_type(Symbol*) \ declare_toplevel_type(volatile Metadata*) \ \ + declare_toplevel_type(DataLayout) \ declare_toplevel_type(nmethodBucket) \ \ /********/ \ @@ -1432,6 +1484,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_type(ModRefBarrierSet, BarrierSet) \ declare_type(CardTableModRefBS, ModRefBarrierSet) \ declare_type(CardTableModRefBSForCTRS, CardTableModRefBS) \ + declare_toplevel_type(BarrierSet::Name) \ declare_toplevel_type(GenRemSet) \ declare_type(CardTableRS, GenRemSet) \ declare_toplevel_type(BlockOffsetSharedArray) \ @@ -1450,6 +1503,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_toplevel_type(ThreadLocalAllocBuffer) \ declare_toplevel_type(VirtualSpace) \ declare_toplevel_type(WaterMark) \ + declare_toplevel_type(ObjPtrQueue) \ + declare_toplevel_type(DirtyCardQueue) \ \ /* Pointers to Garbage Collection types */ \ \ @@ -2068,6 +2123,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_toplevel_type(StubQueue*) \ declare_toplevel_type(Thread*) \ declare_toplevel_type(Universe) \ + declare_toplevel_type(os) \ declare_toplevel_type(vframeArray) \ declare_toplevel_type(vframeArrayElement) \ declare_toplevel_type(Annotations*) \ @@ -2076,6 +2132,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* Miscellaneous types */ \ /***************/ \ \ + declare_toplevel_type(PtrQueue) \ + \ /* freelist */ \ declare_toplevel_type(FreeChunk*) \ declare_toplevel_type(Metablock*) \ @@ -2106,6 +2164,7 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; /* Useful globals */ \ /******************/ \ \ + declare_preprocessor_constant("ASSERT", DEBUG_ONLY(1) NOT_DEBUG(0)) \ \ /**************/ \ /* Stack bias */ \ @@ -2122,6 +2181,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(BytesPerWord) \ declare_constant(BytesPerLong) \ \ + declare_constant(LogKlassAlignmentInBytes) \ + \ /********************************************/ \ /* Generation and Space Hierarchy Constants */ \ /********************************************/ \ @@ -2130,6 +2191,9 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; \ declare_constant(BarrierSet::ModRef) \ declare_constant(BarrierSet::CardTableModRef) \ + declare_constant(BarrierSet::CardTableExtension) \ + declare_constant(BarrierSet::G1SATBCT) \ + declare_constant(BarrierSet::G1SATBCTLogging) \ declare_constant(BarrierSet::Other) \ \ declare_constant(BlockOffsetSharedArray::LogN) \ @@ -2248,8 +2312,11 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(Klass::_primary_super_limit) \ declare_constant(Klass::_lh_instance_slow_path_bit) \ declare_constant(Klass::_lh_log2_element_size_shift) \ + declare_constant(Klass::_lh_log2_element_size_mask) \ declare_constant(Klass::_lh_element_type_shift) \ + declare_constant(Klass::_lh_element_type_mask) \ declare_constant(Klass::_lh_header_size_shift) \ + declare_constant(Klass::_lh_header_size_mask) \ declare_constant(Klass::_lh_array_tag_shift) \ declare_constant(Klass::_lh_array_tag_type_value) \ declare_constant(Klass::_lh_array_tag_obj_value) \ @@ -2268,6 +2335,12 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(ConstMethod::_has_default_annotations) \ declare_constant(ConstMethod::_has_type_annotations) \ \ + /**************/ \ + /* DataLayout */ \ + /**************/ \ + \ + declare_constant(DataLayout::cell_size) \ + \ /*************************************/ \ /* InstanceKlass enum */ \ /*************************************/ \ @@ -2402,6 +2475,13 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(Deoptimization::Reason_LIMIT) \ declare_constant(Deoptimization::Reason_RECORDED_LIMIT) \ \ + declare_constant(Deoptimization::Action_none) \ + declare_constant(Deoptimization::Action_maybe_recompile) \ + declare_constant(Deoptimization::Action_reinterpret) \ + declare_constant(Deoptimization::Action_make_not_entrant) \ + declare_constant(Deoptimization::Action_make_not_compilable) \ + declare_constant(Deoptimization::Action_LIMIT) \ + \ /*********************/ \ /* Matcher (C2 only) */ \ /*********************/ \ @@ -2468,6 +2548,16 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(vmSymbols::FIRST_SID) \ declare_constant(vmSymbols::SID_LIMIT) \ \ + /****************/ \ + /* vmIntrinsics */ \ + /****************/ \ + \ + declare_constant(vmIntrinsics::_invokeBasic) \ + declare_constant(vmIntrinsics::_linkToVirtual) \ + declare_constant(vmIntrinsics::_linkToStatic) \ + declare_constant(vmIntrinsics::_linkToSpecial) \ + declare_constant(vmIntrinsics::_linkToInterface) \ + \ /********************************/ \ /* Calling convention constants */ \ /********************************/ \ @@ -2515,6 +2605,8 @@ typedef BinaryTreeDictionary MetablockTreeDictionary; declare_constant(markOopDesc::biased_lock_bit_in_place) \ declare_constant(markOopDesc::age_mask) \ declare_constant(markOopDesc::age_mask_in_place) \ + declare_constant(markOopDesc::epoch_mask) \ + declare_constant(markOopDesc::epoch_mask_in_place) \ declare_constant(markOopDesc::hash_mask) \ declare_constant(markOopDesc::hash_mask_in_place) \ declare_constant(markOopDesc::biased_lock_alignment) \ diff --git a/hotspot/src/share/vm/runtime/vm_version.hpp b/hotspot/src/share/vm/runtime/vm_version.hpp index c901b260de5..f03b77ca326 100644 --- a/hotspot/src/share/vm/runtime/vm_version.hpp +++ b/hotspot/src/share/vm/runtime/vm_version.hpp @@ -78,7 +78,13 @@ class Abstract_VM_Version: AllStatic { static const char* jre_release_version(); // does HW support an 8-byte compare-exchange operation? - static bool supports_cx8() {return _supports_cx8;} + static bool supports_cx8() { +#ifdef SUPPORTS_NATIVE_CX8 + return true; +#else + return _supports_cx8; +#endif + } // does HW support atomic get-and-set or atomic get-and-add? Used // to guide intrinsification decisions for Unsafe atomic ops static bool supports_atomic_getset4() {return _supports_atomic_getset4;} diff --git a/hotspot/src/share/vm/services/attachListener.cpp b/hotspot/src/share/vm/services/attachListener.cpp index bf002e7fa88..e30c3eeff8c 100644 --- a/hotspot/src/share/vm/services/attachListener.cpp +++ b/hotspot/src/share/vm/services/attachListener.cpp @@ -470,7 +470,17 @@ void AttachListener::init() { vmSymbols::threadgroup_string_void_signature(), thread_group, string, - CHECK); + THREAD); + + if (HAS_PENDING_EXCEPTION) { + tty->print_cr("Exception in VM (AttachListener::init) : "); + java_lang_Throwable::print(PENDING_EXCEPTION, tty); + tty->cr(); + + CLEAR_PENDING_EXCEPTION; + + return; + } KlassHandle group(THREAD, SystemDictionary::ThreadGroup_klass()); JavaCalls::call_special(&result, @@ -479,7 +489,17 @@ void AttachListener::init() { vmSymbols::add_method_name(), vmSymbols::thread_void_signature(), thread_oop, // ARG 1 - CHECK); + THREAD); + + if (HAS_PENDING_EXCEPTION) { + tty->print_cr("Exception in VM (AttachListener::init) : "); + java_lang_Throwable::print(PENDING_EXCEPTION, tty); + tty->cr(); + + CLEAR_PENDING_EXCEPTION; + + return; + } { MutexLocker mu(Threads_lock); JavaThread* listener_thread = new JavaThread(&attach_listener_thread_entry); diff --git a/hotspot/src/share/vm/services/diagnosticArgument.cpp b/hotspot/src/share/vm/services/diagnosticArgument.cpp index 0a1c20d8a2c..51126f063b4 100644 --- a/hotspot/src/share/vm/services/diagnosticArgument.cpp +++ b/hotspot/src/share/vm/services/diagnosticArgument.cpp @@ -61,7 +61,7 @@ void GenDCmdArgument::to_string(MemorySizeArgument m, char* buf, size_t len) { } void GenDCmdArgument::to_string(char* c, char* buf, size_t len) { - jio_snprintf(buf, len, "%s", c); + jio_snprintf(buf, len, "%s", (c != NULL) ? c : ""); } void GenDCmdArgument::to_string(StringArrayArgument* f, char* buf, size_t len) { diff --git a/hotspot/src/share/vm/services/gcNotifier.cpp b/hotspot/src/share/vm/services/gcNotifier.cpp index 7d1fe5d8944..1025072339a 100644 --- a/hotspot/src/share/vm/services/gcNotifier.cpp +++ b/hotspot/src/share/vm/services/gcNotifier.cpp @@ -209,7 +209,7 @@ void GCNotifier::sendNotificationInternal(TRAPS) { GCNotificationRequest *request = getRequest(); if (request != NULL) { NotificationMark nm(request); - Handle objGcInfo = createGcInfo(request->gcManager, request->gcStatInfo, THREAD); + Handle objGcInfo = createGcInfo(request->gcManager, request->gcStatInfo, CHECK); Handle objName = java_lang_String::create_from_str(request->gcManager->name(), CHECK); Handle objAction = java_lang_String::create_from_str(request->gcAction, CHECK); diff --git a/hotspot/src/share/vm/services/memPtr.cpp b/hotspot/src/share/vm/services/memPtr.cpp index 3e124e2bde2..bc460517c58 100644 --- a/hotspot/src/share/vm/services/memPtr.cpp +++ b/hotspot/src/share/vm/services/memPtr.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,9 +34,9 @@ jint SequenceGenerator::next() { jint seq = Atomic::add(1, &_seq_number); if (seq < 0) { MemTracker::shutdown(MemTracker::NMT_sequence_overflow); + } else { + NOT_PRODUCT(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;) } - assert(seq > 0, "counter overflow"); - NOT_PRODUCT(_max_seq_number = (seq > _max_seq_number) ? seq : _max_seq_number;) return seq; } diff --git a/hotspot/src/share/vm/services/memoryPool.cpp b/hotspot/src/share/vm/services/memoryPool.cpp index 777b8b8f382..cfae726cf7b 100644 --- a/hotspot/src/share/vm/services/memoryPool.cpp +++ b/hotspot/src/share/vm/services/memoryPool.cpp @@ -260,10 +260,10 @@ MemoryUsage CodeHeapPool::get_memory_usage() { } MetaspacePool::MetaspacePool() : - MemoryPool("Metaspace", NonHeap, capacity_in_bytes(), calculate_max_size(), true, false) { } + MemoryPool("Metaspace", NonHeap, 0, calculate_max_size(), true, false) { } MemoryUsage MetaspacePool::get_memory_usage() { - size_t committed = align_size_down_(capacity_in_bytes(), os::vm_page_size()); + size_t committed = MetaspaceAux::committed_bytes(); return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); } @@ -271,26 +271,19 @@ size_t MetaspacePool::used_in_bytes() { return MetaspaceAux::allocated_used_bytes(); } -size_t MetaspacePool::capacity_in_bytes() const { - return MetaspaceAux::allocated_capacity_bytes(); -} - size_t MetaspacePool::calculate_max_size() const { - return FLAG_IS_CMDLINE(MaxMetaspaceSize) ? MaxMetaspaceSize : max_uintx; + return FLAG_IS_CMDLINE(MaxMetaspaceSize) ? MaxMetaspaceSize : + MemoryUsage::undefined_size(); } CompressedKlassSpacePool::CompressedKlassSpacePool() : - MemoryPool("Compressed Class Space", NonHeap, capacity_in_bytes(), ClassMetaspaceSize, true, false) { } + MemoryPool("Compressed Class Space", NonHeap, 0, CompressedClassSpaceSize, true, false) { } size_t CompressedKlassSpacePool::used_in_bytes() { return MetaspaceAux::allocated_used_bytes(Metaspace::ClassType); } -size_t CompressedKlassSpacePool::capacity_in_bytes() const { - return MetaspaceAux::allocated_capacity_bytes(Metaspace::ClassType); -} - MemoryUsage CompressedKlassSpacePool::get_memory_usage() { - size_t committed = align_size_down_(capacity_in_bytes(), os::vm_page_size()); + size_t committed = MetaspaceAux::committed_bytes(Metaspace::ClassType); return MemoryUsage(initial_size(), used_in_bytes(), committed, max_size()); } diff --git a/hotspot/src/share/vm/services/memoryPool.hpp b/hotspot/src/share/vm/services/memoryPool.hpp index 08efe08e838..4ec810a985f 100644 --- a/hotspot/src/share/vm/services/memoryPool.hpp +++ b/hotspot/src/share/vm/services/memoryPool.hpp @@ -224,7 +224,6 @@ public: class MetaspacePool : public MemoryPool { size_t calculate_max_size() const; - size_t capacity_in_bytes() const; public: MetaspacePool(); MemoryUsage get_memory_usage(); @@ -232,7 +231,6 @@ class MetaspacePool : public MemoryPool { }; class CompressedKlassSpacePool : public MemoryPool { - size_t capacity_in_bytes() const; public: CompressedKlassSpacePool(); MemoryUsage get_memory_usage(); diff --git a/hotspot/src/share/vm/services/memoryService.cpp b/hotspot/src/share/vm/services/memoryService.cpp index bf0fb9cad24..6508cd2086a 100644 --- a/hotspot/src/share/vm/services/memoryService.cpp +++ b/hotspot/src/share/vm/services/memoryService.cpp @@ -409,7 +409,7 @@ void MemoryService::add_metaspace_memory_pools() { mgr->add_pool(_metaspace_pool); _pools_list->append(_metaspace_pool); - if (UseCompressedKlassPointers) { + if (UseCompressedClassPointers) { _compressed_class_pool = new CompressedKlassSpacePool(); mgr->add_pool(_compressed_class_pool); _pools_list->append(_compressed_class_pool); diff --git a/hotspot/src/share/vm/services/memoryUsage.hpp b/hotspot/src/share/vm/services/memoryUsage.hpp index efc6f2966d1..9027f8e76b7 100644 --- a/hotspot/src/share/vm/services/memoryUsage.hpp +++ b/hotspot/src/share/vm/services/memoryUsage.hpp @@ -63,10 +63,12 @@ public: size_t committed() const { return _committed; } size_t max_size() const { return _maxSize; } + static size_t undefined_size() { return (size_t) -1; } + inline static jlong convert_to_jlong(size_t val) { // In the 64-bit vm, a size_t can overflow a jlong (which is signed). jlong ret; - if (val == (size_t)-1) { + if (val == undefined_size()) { ret = -1L; } else { NOT_LP64(ret = val;) diff --git a/hotspot/src/share/vm/trace/traceMacros.hpp b/hotspot/src/share/vm/trace/traceMacros.hpp index 1a6dd644935..4776e13507e 100644 --- a/hotspot/src/share/vm/trace/traceMacros.hpp +++ b/hotspot/src/share/vm/trace/traceMacros.hpp @@ -26,6 +26,7 @@ #define SHARE_VM_TRACE_TRACE_MACRO_HPP #define EVENT_THREAD_EXIT(thread) +#define EVENT_THREAD_DESTRUCT(thread) #define TRACE_INIT_ID(k) #define TRACE_DATA TraceThreadData diff --git a/hotspot/src/share/vm/utilities/accessFlags.hpp b/hotspot/src/share/vm/utilities/accessFlags.hpp index 99f9a3360f8..a3d3de99c91 100644 --- a/hotspot/src/share/vm/utilities/accessFlags.hpp +++ b/hotspot/src/share/vm/utilities/accessFlags.hpp @@ -78,11 +78,13 @@ enum { JVM_ACC_FIELD_ACCESS_WATCHED = 0x00002000, // field access is watched by JVMTI JVM_ACC_FIELD_MODIFICATION_WATCHED = 0x00008000, // field modification is watched by JVMTI JVM_ACC_FIELD_INTERNAL = 0x00000400, // internal field, same as JVM_ACC_ABSTRACT + JVM_ACC_FIELD_STABLE = 0x00000020, // @Stable field, same as JVM_ACC_SYNCHRONIZED JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE = 0x00000800, // field has generic signature JVM_ACC_FIELD_INTERNAL_FLAGS = JVM_ACC_FIELD_ACCESS_WATCHED | JVM_ACC_FIELD_MODIFICATION_WATCHED | JVM_ACC_FIELD_INTERNAL | + JVM_ACC_FIELD_STABLE | JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE, // flags accepted by set_field_flags() @@ -148,6 +150,7 @@ class AccessFlags VALUE_OBJ_CLASS_SPEC { { return (_flags & JVM_ACC_FIELD_MODIFICATION_WATCHED) != 0; } bool on_stack() const { return (_flags & JVM_ACC_ON_STACK) != 0; } bool is_internal() const { return (_flags & JVM_ACC_FIELD_INTERNAL) != 0; } + bool is_stable() const { return (_flags & JVM_ACC_FIELD_STABLE) != 0; } bool field_has_generic_signature() const { return (_flags & JVM_ACC_FIELD_HAS_GENERIC_SIGNATURE) != 0; } diff --git a/hotspot/src/share/vm/utilities/bitMap.inline.hpp b/hotspot/src/share/vm/utilities/bitMap.inline.hpp index 7bb244795fc..2171e849f8f 100644 --- a/hotspot/src/share/vm/utilities/bitMap.inline.hpp +++ b/hotspot/src/share/vm/utilities/bitMap.inline.hpp @@ -52,16 +52,16 @@ inline void BitMap::clear_bit(idx_t bit) { inline bool BitMap::par_set_bit(idx_t bit) { verify_index(bit); - volatile idx_t* const addr = word_addr(bit); - const idx_t mask = bit_mask(bit); - idx_t old_val = *addr; + volatile bm_word_t* const addr = word_addr(bit); + const bm_word_t mask = bit_mask(bit); + bm_word_t old_val = *addr; do { - const idx_t new_val = old_val | mask; + const bm_word_t new_val = old_val | mask; if (new_val == old_val) { return false; // Someone else beat us to it. } - const idx_t cur_val = (idx_t) Atomic::cmpxchg_ptr((void*) new_val, + const bm_word_t cur_val = (bm_word_t) Atomic::cmpxchg_ptr((void*) new_val, (volatile void*) addr, (void*) old_val); if (cur_val == old_val) { @@ -73,16 +73,16 @@ inline bool BitMap::par_set_bit(idx_t bit) { inline bool BitMap::par_clear_bit(idx_t bit) { verify_index(bit); - volatile idx_t* const addr = word_addr(bit); - const idx_t mask = ~bit_mask(bit); - idx_t old_val = *addr; + volatile bm_word_t* const addr = word_addr(bit); + const bm_word_t mask = ~bit_mask(bit); + bm_word_t old_val = *addr; do { - const idx_t new_val = old_val & mask; + const bm_word_t new_val = old_val & mask; if (new_val == old_val) { return false; // Someone else beat us to it. } - const idx_t cur_val = (idx_t) Atomic::cmpxchg_ptr((void*) new_val, + const bm_word_t cur_val = (bm_word_t) Atomic::cmpxchg_ptr((void*) new_val, (volatile void*) addr, (void*) old_val); if (cur_val == old_val) { diff --git a/hotspot/src/share/vm/utilities/decoder.cpp b/hotspot/src/share/vm/utilities/decoder.cpp index 5489fe6fefb..3fc934b4f32 100644 --- a/hotspot/src/share/vm/utilities/decoder.cpp +++ b/hotspot/src/share/vm/utilities/decoder.cpp @@ -24,7 +24,6 @@ #include "precompiled.hpp" #include "prims/jvm.h" -#include "runtime/mutexLocker.hpp" #include "runtime/os.hpp" #include "utilities/decoder.hpp" #include "utilities/vmError.hpp" @@ -80,6 +79,23 @@ AbstractDecoder* Decoder::create_decoder() { return decoder; } +inline bool DecoderLocker::is_first_error_thread() { + return (os::current_thread_id() == VMError::get_first_error_tid()); +} + +DecoderLocker::DecoderLocker() : + MutexLockerEx(DecoderLocker::is_first_error_thread() ? + NULL : Decoder::shared_decoder_lock(), true) { + _decoder = is_first_error_thread() ? + Decoder::get_error_handler_instance() : Decoder::get_shared_instance(); + assert(_decoder != NULL, "null decoder"); +} + +Mutex* Decoder::shared_decoder_lock() { + assert(_shared_decoder_lock != NULL, "Just check"); + return _shared_decoder_lock; +} + bool Decoder::decode(address addr, char* buf, int buflen, int* offset, const char* modulepath) { assert(_shared_decoder_lock != NULL, "Just check"); bool error_handling_thread = os::current_thread_id() == VMError::first_error_tid; diff --git a/hotspot/src/share/vm/utilities/decoder.hpp b/hotspot/src/share/vm/utilities/decoder.hpp index 0d2af80986c..0cc880f1915 100644 --- a/hotspot/src/share/vm/utilities/decoder.hpp +++ b/hotspot/src/share/vm/utilities/decoder.hpp @@ -28,6 +28,7 @@ #include "memory/allocation.hpp" #include "runtime/mutex.hpp" +#include "runtime/mutexLocker.hpp" class AbstractDecoder : public CHeapObj { public: @@ -124,6 +125,19 @@ private: protected: static Mutex* _shared_decoder_lock; + static Mutex* shared_decoder_lock(); + + friend class DecoderLocker; +}; + +class DecoderLocker : public MutexLockerEx { + AbstractDecoder* _decoder; + inline bool is_first_error_thread(); +public: + DecoderLocker(); + AbstractDecoder* decoder() { + return _decoder; + } }; #endif // SHARE_VM_UTILITIES_DECODER_HPP diff --git a/hotspot/src/share/vm/utilities/ostream.cpp b/hotspot/src/share/vm/utilities/ostream.cpp index 2f04fa0e437..e4215504a4d 100644 --- a/hotspot/src/share/vm/utilities/ostream.cpp +++ b/hotspot/src/share/vm/utilities/ostream.cpp @@ -342,7 +342,7 @@ void stringStream::write(const char* s, size_t len) { } char* stringStream::as_string() { - char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos+1); + char* copy = NEW_RESOURCE_ARRAY(char, buffer_pos + 1); strncpy(copy, buffer, buffer_pos); copy[buffer_pos] = 0; // terminating null return copy; @@ -355,14 +355,190 @@ outputStream* tty; outputStream* gclog_or_tty; extern Mutex* tty_lock; +#define EXTRACHARLEN 32 +#define CURRENTAPPX ".current" +#define FILENAMEBUFLEN 1024 +// convert YYYY-MM-DD HH:MM:SS to YYYY-MM-DD_HH-MM-SS +char* get_datetime_string(char *buf, size_t len) { + os::local_time_string(buf, len); + int i = (int)strlen(buf); + while (i-- >= 0) { + if (buf[i] == ' ') buf[i] = '_'; + else if (buf[i] == ':') buf[i] = '-'; + } + return buf; +} + +static const char* make_log_name_internal(const char* log_name, const char* force_directory, + int pid, const char* tms) { + const char* basename = log_name; + char file_sep = os::file_separator()[0]; + const char* cp; + char pid_text[32]; + + for (cp = log_name; *cp != '\0'; cp++) { + if (*cp == '/' || *cp == file_sep) { + basename = cp + 1; + } + } + const char* nametail = log_name; + // Compute buffer length + size_t buffer_length; + if (force_directory != NULL) { + buffer_length = strlen(force_directory) + strlen(os::file_separator()) + + strlen(basename) + 1; + } else { + buffer_length = strlen(log_name) + 1; + } + + // const char* star = strchr(basename, '*'); + const char* pts = strstr(basename, "%p"); + int pid_pos = (pts == NULL) ? -1 : (pts - nametail); + + if (pid_pos >= 0) { + jio_snprintf(pid_text, sizeof(pid_text), "pid%u", pid); + buffer_length += strlen(pid_text); + } + + pts = strstr(basename, "%t"); + int tms_pos = (pts == NULL) ? -1 : (pts - nametail); + if (tms_pos >= 0) { + buffer_length += strlen(tms); + } + + // Create big enough buffer. + char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); + + strcpy(buf, ""); + if (force_directory != NULL) { + strcat(buf, force_directory); + strcat(buf, os::file_separator()); + nametail = basename; // completely skip directory prefix + } + + // who is first, %p or %t? + int first = -1, second = -1; + const char *p1st = NULL; + const char *p2nd = NULL; + + if (pid_pos >= 0 && tms_pos >= 0) { + // contains both %p and %t + if (pid_pos < tms_pos) { + // case foo%pbar%tmonkey.log + first = pid_pos; + p1st = pid_text; + second = tms_pos; + p2nd = tms; + } else { + // case foo%tbar%pmonkey.log + first = tms_pos; + p1st = tms; + second = pid_pos; + p2nd = pid_text; + } + } else if (pid_pos >= 0) { + // contains %p only + first = pid_pos; + p1st = pid_text; + } else if (tms_pos >= 0) { + // contains %t only + first = tms_pos; + p1st = tms; + } + + int buf_pos = (int)strlen(buf); + const char* tail = nametail; + + if (first >= 0) { + tail = nametail + first + 2; + strncpy(&buf[buf_pos], nametail, first); + strcpy(&buf[buf_pos + first], p1st); + buf_pos = (int)strlen(buf); + if (second >= 0) { + strncpy(&buf[buf_pos], tail, second - first - 2); + strcpy(&buf[buf_pos + second - first - 2], p2nd); + tail = nametail + second + 2; + } + } + strcat(buf, tail); // append rest of name, or all of name + return buf; +} + +// log_name comes from -XX:LogFile=log_name or -Xloggc:log_name +// in log_name, %p => pipd1234 and +// %t => YYYY-MM-DD_HH-MM-SS +static const char* make_log_name(const char* log_name, const char* force_directory) { + char timestr[32]; + get_datetime_string(timestr, sizeof(timestr)); + return make_log_name_internal(log_name, force_directory, os::current_process_id(), + timestr); +} + +#ifndef PRODUCT +void test_loggc_filename() { + int pid; + char tms[32]; + char i_result[FILENAMEBUFLEN]; + const char* o_result; + get_datetime_string(tms, sizeof(tms)); + pid = os::current_process_id(); + + // test.log + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test.log", tms); + o_result = make_log_name_internal("test.log", NULL, pid, tms); + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test.log\", NULL)"); + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); + + // test-%t-%p.log + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%s-pid%u.log", tms, pid); + o_result = make_log_name_internal("test-%t-%p.log", NULL, pid, tms); + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t-%%p.log\", NULL)"); + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); + + // test-%t%p.log + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "test-%spid%u.log", tms, pid); + o_result = make_log_name_internal("test-%t%p.log", NULL, pid, tms); + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"test-%%t%%p.log\", NULL)"); + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); + + // %p%t.log + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u%s.log", pid, tms); + o_result = make_log_name_internal("%p%t.log", NULL, pid, tms); + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p%%t.log\", NULL)"); + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); + + // %p-test.log + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "pid%u-test.log", pid); + o_result = make_log_name_internal("%p-test.log", NULL, pid, tms); + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%p-test.log\", NULL)"); + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); + + // %t.log + jio_snprintf(i_result, sizeof(char)*FILENAMEBUFLEN, "%s.log", tms); + o_result = make_log_name_internal("%t.log", NULL, pid, tms); + assert(strcmp(i_result, o_result) == 0, "failed on testing make_log_name(\"%%t.log\", NULL)"); + FREE_C_HEAP_ARRAY(char, o_result, mtInternal); +} +#endif // PRODUCT + fileStream::fileStream(const char* file_name) { _file = fopen(file_name, "w"); - _need_close = true; + if (_file != NULL) { + _need_close = true; + } else { + warning("Cannot open file %s due to %s\n", file_name, strerror(errno)); + _need_close = false; + } } fileStream::fileStream(const char* file_name, const char* opentype) { _file = fopen(file_name, opentype); - _need_close = true; + if (_file != NULL) { + _need_close = true; + } else { + warning("Cannot open file %s due to %s\n", file_name, strerror(errno)); + _need_close = false; + } } void fileStream::write(const char* s, size_t len) { @@ -423,34 +599,51 @@ void fdStream::write(const char* s, size_t len) { update_position(s, len); } -rotatingFileStream::~rotatingFileStream() { +// dump vm version, os version, platform info, build id, +// memory usage and command line flags into header +void gcLogFileStream::dump_loggc_header() { + if (is_open()) { + print_cr(Abstract_VM_Version::internal_vm_info_string()); + os::print_memory_info(this); + print("CommandLine flags: "); + CommandLineFlags::printSetFlags(this); + } +} + +gcLogFileStream::~gcLogFileStream() { if (_file != NULL) { if (_need_close) fclose(_file); - _file = NULL; + _file = NULL; + } + if (_file_name != NULL) { FREE_C_HEAP_ARRAY(char, _file_name, mtInternal); _file_name = NULL; } } -rotatingFileStream::rotatingFileStream(const char* file_name) { +gcLogFileStream::gcLogFileStream(const char* file_name) { _cur_file_num = 0; _bytes_written = 0L; - _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); - jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); - _file = fopen(_file_name, "w"); - _need_close = true; + _file_name = make_log_name(file_name, NULL); + + // gc log file rotation + if (UseGCLogFileRotation && NumberOfGCLogFiles > 1) { + char tempbuf[FILENAMEBUFLEN]; + jio_snprintf(tempbuf, sizeof(tempbuf), "%s.%d" CURRENTAPPX, _file_name, _cur_file_num); + _file = fopen(tempbuf, "w"); + } else { + _file = fopen(_file_name, "w"); + } + if (_file != NULL) { + _need_close = true; + dump_loggc_header(); + } else { + warning("Cannot open file %s due to %s\n", _file_name, strerror(errno)); + _need_close = false; + } } -rotatingFileStream::rotatingFileStream(const char* file_name, const char* opentype) { - _cur_file_num = 0; - _bytes_written = 0L; - _file_name = NEW_C_HEAP_ARRAY(char, strlen(file_name)+10, mtInternal); - jio_snprintf(_file_name, strlen(file_name)+10, "%s.%d", file_name, _cur_file_num); - _file = fopen(_file_name, opentype); - _need_close = true; -} - -void rotatingFileStream::write(const char* s, size_t len) { +void gcLogFileStream::write(const char* s, size_t len) { if (_file != NULL) { size_t count = fwrite(s, 1, len, _file); _bytes_written += count; @@ -466,7 +659,12 @@ void rotatingFileStream::write(const char* s, size_t len) { // write to gc log file at safepoint. If in future, changes made for mutator threads or // concurrent GC threads to run parallel with VMThread at safepoint, write and rotate_log // must be synchronized. -void rotatingFileStream::rotate_log() { +void gcLogFileStream::rotate_log() { + char time_msg[FILENAMEBUFLEN]; + char time_str[EXTRACHARLEN]; + char current_file_name[FILENAMEBUFLEN]; + char renamed_file_name[FILENAMEBUFLEN]; + if (_bytes_written < (jlong)GCLogFileSize) { return; } @@ -481,27 +679,89 @@ void rotatingFileStream::rotate_log() { // rotate in same file rewind(); _bytes_written = 0L; + jio_snprintf(time_msg, sizeof(time_msg), "File %s rotated at %s\n", + _file_name, os::local_time_string((char *)time_str, sizeof(time_str))); + write(time_msg, strlen(time_msg)); + dump_loggc_header(); return; } - // rotate file in names file.0, file.1, file.2, ..., file. - // close current file, rotate to next file +#if defined(_WINDOWS) +#ifndef F_OK +#define F_OK 0 +#endif +#endif // _WINDOWS + + // rotate file in names extended_filename.0, extended_filename.1, ..., + // extended_filename.. Current rotation file name will + // have a form of extended_filename..current where i is the current rotation + // file number. After it reaches max file size, the file will be saved and renamed + // with .current removed from its tail. + size_t filename_len = strlen(_file_name); if (_file != NULL) { - _cur_file_num ++; - if (_cur_file_num >= NumberOfGCLogFiles) _cur_file_num = 0; - jio_snprintf(_file_name, strlen(Arguments::gc_log_filename()) + 10, "%s.%d", - Arguments::gc_log_filename(), _cur_file_num); + jio_snprintf(renamed_file_name, filename_len + EXTRACHARLEN, "%s.%d", + _file_name, _cur_file_num); + jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, + _file_name, _cur_file_num); + jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file has reached the" + " maximum size. Saved as %s\n", + os::local_time_string((char *)time_str, sizeof(time_str)), + renamed_file_name); + write(time_msg, strlen(time_msg)); + fclose(_file); _file = NULL; + + bool can_rename = true; + if (access(current_file_name, F_OK) != 0) { + // current file does not exist? + warning("No source file exists, cannot rename\n"); + can_rename = false; + } + if (can_rename) { + if (access(renamed_file_name, F_OK) == 0) { + if (remove(renamed_file_name) != 0) { + warning("Could not delete existing file %s\n", renamed_file_name); + can_rename = false; + } + } else { + // file does not exist, ok to rename + } + } + if (can_rename && rename(current_file_name, renamed_file_name) != 0) { + warning("Could not rename %s to %s\n", _file_name, renamed_file_name); + } } - _file = fopen(_file_name, "w"); + + _cur_file_num++; + if (_cur_file_num > NumberOfGCLogFiles - 1) _cur_file_num = 0; + jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, "%s.%d" CURRENTAPPX, + _file_name, _cur_file_num); + _file = fopen(current_file_name, "w"); + if (_file != NULL) { _bytes_written = 0L; _need_close = true; + // reuse current_file_name for time_msg + jio_snprintf(current_file_name, filename_len + EXTRACHARLEN, + "%s.%d", _file_name, _cur_file_num); + jio_snprintf(time_msg, sizeof(time_msg), "%s GC log file created %s\n", + os::local_time_string((char *)time_str, sizeof(time_str)), + current_file_name); + write(time_msg, strlen(time_msg)); + dump_loggc_header(); + // remove the existing file + if (access(current_file_name, F_OK) == 0) { + if (remove(current_file_name) != 0) { + warning("Could not delete existing file %s\n", current_file_name); + } + } } else { - tty->print_cr("failed to open rotation log file %s due to %s\n", + warning("failed to open rotation log file %s due to %s\n" + "Turned off GC log file rotation\n", _file_name, strerror(errno)); _need_close = false; + FLAG_SET_DEFAULT(UseGCLogFileRotation, false); } } @@ -530,69 +790,9 @@ bool defaultStream::has_log_file() { return _log_file != NULL; } -static const char* make_log_name(const char* log_name, const char* force_directory) { - const char* basename = log_name; - char file_sep = os::file_separator()[0]; - const char* cp; - for (cp = log_name; *cp != '\0'; cp++) { - if (*cp == '/' || *cp == file_sep) { - basename = cp+1; - } - } - const char* nametail = log_name; - - // Compute buffer length - size_t buffer_length; - if (force_directory != NULL) { - buffer_length = strlen(force_directory) + strlen(os::file_separator()) + - strlen(basename) + 1; - } else { - buffer_length = strlen(log_name) + 1; - } - - const char* star = strchr(basename, '*'); - int star_pos = (star == NULL) ? -1 : (star - nametail); - int skip = 1; - if (star == NULL) { - // Try %p - star = strstr(basename, "%p"); - if (star != NULL) { - skip = 2; - } - } - star_pos = (star == NULL) ? -1 : (star - nametail); - - char pid[32]; - if (star_pos >= 0) { - jio_snprintf(pid, sizeof(pid), "%u", os::current_process_id()); - buffer_length += strlen(pid); - } - - // Create big enough buffer. - char *buf = NEW_C_HEAP_ARRAY(char, buffer_length, mtInternal); - - strcpy(buf, ""); - if (force_directory != NULL) { - strcat(buf, force_directory); - strcat(buf, os::file_separator()); - nametail = basename; // completely skip directory prefix - } - - if (star_pos >= 0) { - // convert foo*bar.log or foo%pbar.log to foo123bar.log - int buf_pos = (int) strlen(buf); - strncpy(&buf[buf_pos], nametail, star_pos); - strcpy(&buf[buf_pos + star_pos], pid); - nametail += star_pos + skip; // skip prefix and pid format - } - - strcat(buf, nametail); // append rest of name, or all of name - return buf; -} - void defaultStream::init_log() { // %%% Need a MutexLocker? - const char* log_name = LogFile != NULL ? LogFile : "hotspot.log"; + const char* log_name = LogFile != NULL ? LogFile : "hotspot_pid%p.log"; const char* try_name = make_log_name(log_name, NULL); fileStream* file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); if (!file->is_open()) { @@ -603,14 +803,15 @@ void defaultStream::init_log() { // Note: This feature is for maintainer use only. No need for L10N. jio_print(warnbuf); FREE_C_HEAP_ARRAY(char, try_name, mtInternal); - try_name = make_log_name("hs_pid%p.log", os::get_temp_directory()); + try_name = make_log_name(log_name, os::get_temp_directory()); jio_snprintf(warnbuf, sizeof(warnbuf), "Warning: Forcing option -XX:LogFile=%s\n", try_name); jio_print(warnbuf); delete file; file = new(ResourceObj::C_HEAP, mtInternal) fileStream(try_name); - FREE_C_HEAP_ARRAY(char, try_name, mtInternal); } + FREE_C_HEAP_ARRAY(char, try_name, mtInternal); + if (file->is_open()) { _log_file = file; xmlStream* xs = new(ResourceObj::C_HEAP, mtInternal) xmlStream(file); @@ -877,11 +1078,8 @@ void ostream_init_log() { gclog_or_tty = tty; // default to tty if (Arguments::gc_log_filename() != NULL) { - fileStream * gclog = UseGCLogFileRotation ? - new(ResourceObj::C_HEAP, mtInternal) - rotatingFileStream(Arguments::gc_log_filename()) : - new(ResourceObj::C_HEAP, mtInternal) - fileStream(Arguments::gc_log_filename()); + fileStream * gclog = new(ResourceObj::C_HEAP, mtInternal) + gcLogFileStream(Arguments::gc_log_filename()); if (gclog->is_open()) { // now we update the time stamp of the GC log to be synced up // with tty. diff --git a/hotspot/src/share/vm/utilities/ostream.hpp b/hotspot/src/share/vm/utilities/ostream.hpp index 4d13847663e..9b1b1217b49 100644 --- a/hotspot/src/share/vm/utilities/ostream.hpp +++ b/hotspot/src/share/vm/utilities/ostream.hpp @@ -231,20 +231,24 @@ class fdStream : public outputStream { void flush() {}; }; -class rotatingFileStream : public fileStream { +class gcLogFileStream : public fileStream { protected: - char* _file_name; + const char* _file_name; jlong _bytes_written; - uintx _cur_file_num; // current logfile rotation number, from 0 to MaxGCLogFileNumbers-1 + uintx _cur_file_num; // current logfile rotation number, from 0 to NumberOfGCLogFiles-1 public: - rotatingFileStream(const char* file_name); - rotatingFileStream(const char* file_name, const char* opentype); - rotatingFileStream(FILE* file) : fileStream(file) {} - ~rotatingFileStream(); + gcLogFileStream(const char* file_name); + ~gcLogFileStream(); virtual void write(const char* c, size_t len); virtual void rotate_log(); + void dump_loggc_header(); }; +#ifndef PRODUCT +// unit test for checking -Xloggc: parsing result +void test_loggc_filename(); +#endif + void ostream_init(); void ostream_init_log(); void ostream_exit(); diff --git a/hotspot/src/share/vm/utilities/vmError.cpp b/hotspot/src/share/vm/utilities/vmError.cpp index b07404dc9b7..79769aeb3bc 100644 --- a/hotspot/src/share/vm/utilities/vmError.cpp +++ b/hotspot/src/share/vm/utilities/vmError.cpp @@ -574,6 +574,10 @@ void VMError::report(outputStream* st) { STEP(120, "(printing native stack)" ) if (_verbose) { + if (os::platform_print_native_stack(st, _context, buf, sizeof(buf))) { + // We have printed the native stack in platform-specific code + // Windows/x64 needs special handling. + } else { frame fr = _context ? os::fetch_frame_from_context(_context) : os::current_frame(); @@ -604,6 +608,7 @@ void VMError::report(outputStream* st) { st->cr(); } } + } STEP(130, "(printing Java stack)" ) diff --git a/hotspot/src/share/vm/utilities/vmError.hpp b/hotspot/src/share/vm/utilities/vmError.hpp index 1b1608bdc90..299cfaa6f3d 100644 --- a/hotspot/src/share/vm/utilities/vmError.hpp +++ b/hotspot/src/share/vm/utilities/vmError.hpp @@ -136,6 +136,10 @@ public: // check to see if fatal error reporting is in progress static bool fatal_error_in_progress() { return first_error != NULL; } + + static jlong get_first_error_tid() { + return first_error_tid; + } }; #endif // SHARE_VM_UTILITIES_VMERROR_HPP diff --git a/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp b/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp index 5a626ce7fa3..98d8f438ea4 100644 --- a/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp +++ b/hotspot/src/share/vm/utilities/yieldingWorkgroup.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,10 +26,7 @@ #define SHARE_VM_UTILITIES_YIELDINGWORKGROUP_HPP #include "utilities/macros.hpp" -#if INCLUDE_ALL_GCS #include "utilities/workgroup.hpp" -#endif // INCLUDE_ALL_GCS - // Forward declarations class YieldingFlexibleWorkGang; diff --git a/hotspot/test/TEST.groups b/hotspot/test/TEST.groups index bf5e3f088fb..bae5a9b3469 100644 --- a/hotspot/test/TEST.groups +++ b/hotspot/test/TEST.groups @@ -62,7 +62,7 @@ jdk = \ # needs_jdk = \ gc/TestG1ZeroPGCTJcmdThreadPrint.java \ - gc/metaspace/ClassMetaspaceSizeInJmapHeap.java \ + gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java \ gc/metaspace/TestMetaspacePerfCounters.java \ runtime/6819213/TestBootNativeLibraryPath.java \ runtime/6878713/Test6878713.sh \ @@ -84,6 +84,7 @@ needs_jdk = \ runtime/NMT/ThreadedVirtualAllocTestType.java \ runtime/NMT/VirtualAllocTestType.java \ runtime/RedefineObject/TestRedefineObject.java \ + runtime/XCheckJniJsig/XCheckJSig.java \ serviceability/attach/AttachWithStalePidFile.java # JRE adds further tests to compact3 @@ -159,7 +160,18 @@ needs_full_vm_compact1 = \ gc/g1/TestRegionAlignment.java \ gc/g1/TestShrinkToOneRegion.java \ gc/metaspace/G1AddMetaspaceDependency.java \ - runtime/6929067/Test6929067.sh + gc/startup_warnings/TestCMS.java \ + gc/startup_warnings/TestCMSIncrementalMode.java \ + gc/startup_warnings/TestCMSNoIncrementalMode.java \ + gc/startup_warnings/TestDefaultMaxRAMFraction.java \ + gc/startup_warnings/TestDefNewCMS.java \ + gc/startup_warnings/TestIncGC.java \ + gc/startup_warnings/TestParallelGC.java \ + gc/startup_warnings/TestParallelScavengeSerialOld.java \ + gc/startup_warnings/TestParNewCMS.java \ + gc/startup_warnings/TestParNewSerialOld.java \ + runtime/6929067/Test6929067.sh \ + runtime/SharedArchiveFile/SharedArchiveFile.java # Minimal VM on Compact 2 adds in some compact2 tests # diff --git a/hotspot/test/compiler/print/PrintInlining.java b/hotspot/test/compiler/print/PrintInlining.java new file mode 100644 index 00000000000..877d25e8c38 --- /dev/null +++ b/hotspot/test/compiler/print/PrintInlining.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8022585 + * @summary VM crashes when ran with -XX:+PrintInlining + * @run main/othervm -Xcomp -XX:+PrintInlining PrintInlining + * + */ + +public class PrintInlining { + public static void main(String[] args) { + System.out.println("Passed"); + } +} diff --git a/hotspot/test/gc/TestObjectAlignment.java b/hotspot/test/gc/TestObjectAlignment.java new file mode 100644 index 00000000000..8cfc9709f16 --- /dev/null +++ b/hotspot/test/gc/TestObjectAlignment.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestObjectAlignment + * @key gc + * @bug 8021823 + * @summary G1: Concurrent marking crashes with -XX:ObjectAlignmentInBytes>=32 in 64bit VMs + * @library /testlibrary + * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=8 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=16 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=32 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=64 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=128 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:+ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=256 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:-ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=8 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:-ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=16 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:-ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=32 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:-ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=64 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:-ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=128 + * @run main/othervm TestObjectAlignment -Xmx20M -XX:-ExplicitGCInvokesConcurrent -XX:+IgnoreUnrecognizedVMOptions -XX:ObjectAlignmentInBytes=256 + */ + +import com.oracle.java.testlibrary.ProcessTools; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class TestObjectAlignment { + + public static byte[] garbage; + + private static boolean runsOn32bit() { + return System.getProperty("sun.arch.data.model").equals("32"); + } + + public static void main(String[] args) throws Exception { + if (runsOn32bit()) { + // 32 bit VMs do not allow setting ObjectAlignmentInBytes, so there is nothing to test. We still get called. + return; + } + for (int i = 0; i < 10; i++) { + garbage = new byte[1000]; + System.gc(); + } + } +} diff --git a/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java b/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java new file mode 100644 index 00000000000..125c1aabd51 --- /dev/null +++ b/hotspot/test/gc/arguments/TestAlignmentToUseLargePages.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test TestAlignmentToUseLargePages + * @summary All parallel GC variants may use large pages without the requirement that the + * heap alignment is large page aligned. Other collectors also need to start up with odd sized heaps. + * @bug 8024396 + * @key gc + * @key regression + * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:-UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseSerialGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseSerialGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseConcMarkSweepGC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseConcMarkSweepGC -XX:-UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseG1GC -XX:+UseLargePages TestAlignmentToUseLargePages + * @run main/othervm -Xms7M -Xmx9M -XX:+UseG1GC -XX:-UseLargePages TestAlignmentToUseLargePages + */ + +public class TestAlignmentToUseLargePages { + public static void main(String args[]) throws Exception { + // nothing to do + } +} diff --git a/hotspot/test/gc/arguments/TestCompressedClassFlags.java b/hotspot/test/gc/arguments/TestCompressedClassFlags.java new file mode 100644 index 00000000000..4135debd89c --- /dev/null +++ b/hotspot/test/gc/arguments/TestCompressedClassFlags.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.*; + +/* + * @test + * @bug 8015107 + * @summary Tests that VM prints a warning when -XX:CompressedClassSpaceSize + * is used together with -XX:-UseCompressedClassPointers + * @library /testlibrary + */ +public class TestCompressedClassFlags { + public static void main(String[] args) throws Exception { + if (Platform.is64bit()) { + OutputAnalyzer output = runJava("-XX:CompressedClassSpaceSize=1g", + "-XX:-UseCompressedClassPointers", + "-version"); + output.shouldContain("warning"); + output.shouldNotContain("error"); + output.shouldHaveExitValue(0); + } + } + + private static OutputAnalyzer runJava(String ... args) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args); + return new OutputAnalyzer(pb.start()); + } +} diff --git a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java new file mode 100644 index 00000000000..852076e768e --- /dev/null +++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +/* + * @test TestUseCompressedOopsErgo + * @key gc + * @bug 8010722 + * @summary Tests ergonomics for UseCompressedOops. + * @library /testlibrary /testlibrary/whitebox + * @build TestUseCompressedOopsErgo TestUseCompressedOopsErgoTools + * @run main ClassFileInstaller sun.hotspot.WhiteBox + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseG1GC + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseParallelGC -XX:-UseParallelOldGC + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseConcMarkSweepGC + * @run main/othervm TestUseCompressedOopsErgo -XX:+UseSerialGC + */ + +public class TestUseCompressedOopsErgo { + + public static void main(String args[]) throws Exception { + if (!TestUseCompressedOopsErgoTools.is64bitVM()) { + // this test is relevant for 64 bit VMs only + return; + } + final String[] gcFlags = args; + TestUseCompressedOopsErgoTools.checkCompressedOopsErgo(gcFlags); + } +} + diff --git a/hotspot/test/gc/arguments/TestUseCompressedOopsErgoTools.java b/hotspot/test/gc/arguments/TestUseCompressedOopsErgoTools.java new file mode 100644 index 00000000000..54c70672d04 --- /dev/null +++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgoTools.java @@ -0,0 +1,177 @@ +/* +* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +* +* This code is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 only, as +* published by the Free Software Foundation. +* +* This code is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +* version 2 for more details (a copy is included in the LICENSE file that +* accompanied this code). +* +* You should have received a copy of the GNU General Public License version +* 2 along with this work; if not, write to the Free Software Foundation, +* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +* +* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +* or visit www.oracle.com if you need additional information or have any +* questions. +*/ + +import sun.management.ManagementFactoryHelper; +import com.sun.management.HotSpotDiagnosticMXBean; +import com.sun.management.VMOption; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import java.util.ArrayList; +import java.util.Arrays; + +import com.oracle.java.testlibrary.*; +import sun.hotspot.WhiteBox; + +class DetermineMaxHeapForCompressedOops { + public static void main(String[] args) throws Exception { + WhiteBox wb = WhiteBox.getWhiteBox(); + System.out.print(wb.getCompressedOopsMaxHeapSize()); + } +} + +class TestUseCompressedOopsErgoTools { + + private static long getCompressedClassSpaceSize() { + HotSpotDiagnosticMXBean diagnostic = ManagementFactoryHelper.getDiagnosticMXBean(); + + VMOption option = diagnostic.getVMOption("CompressedClassSpaceSize"); + return Long.parseLong(option.getValue()); + } + + + public static long getMaxHeapForCompressedOops(String[] vmargs) throws Exception { + OutputAnalyzer output = runWhiteBoxTest(vmargs, DetermineMaxHeapForCompressedOops.class.getName(), new String[] {}, false); + return Long.parseLong(output.getStdout()); + } + + public static boolean is64bitVM() { + String val = System.getProperty("sun.arch.data.model"); + if (val == null) { + throw new RuntimeException("Could not read sun.arch.data.model"); + } + if (val.equals("64")) { + return true; + } else if (val.equals("32")) { + return false; + } + throw new RuntimeException("Unexpected value " + val + " of sun.arch.data.model"); + } + + /** + * Executes a new VM process with the given class and parameters. + * @param vmargs Arguments to the VM to run + * @param classname Name of the class to run + * @param arguments Arguments to the class + * @param useTestDotJavaDotOpts Use test.java.opts as part of the VM argument string + * @return The OutputAnalyzer with the results for the invocation. + */ + public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, String[] arguments, boolean useTestDotJavaDotOpts) throws Exception { + ArrayList finalargs = new ArrayList(); + + String[] whiteboxOpts = new String[] { + "-Xbootclasspath/a:.", + "-XX:+UnlockDiagnosticVMOptions", "-XX:+WhiteBoxAPI", + "-cp", System.getProperty("java.class.path"), + }; + + if (useTestDotJavaDotOpts) { + // System.getProperty("test.java.opts") is '' if no options is set, + // we need to skip such a result + String[] externalVMOpts = new String[0]; + if (System.getProperty("test.java.opts") != null && System.getProperty("test.java.opts").length() != 0) { + externalVMOpts = System.getProperty("test.java.opts").split(" "); + } + finalargs.addAll(Arrays.asList(externalVMOpts)); + } + + finalargs.addAll(Arrays.asList(vmargs)); + finalargs.addAll(Arrays.asList(whiteboxOpts)); + finalargs.add(classname); + finalargs.addAll(Arrays.asList(arguments)); + + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(finalargs.toArray(new String[0])); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + return output; + } + + private static String[] join(String[] part1, String part2) { + ArrayList result = new ArrayList(); + result.addAll(Arrays.asList(part1)); + result.add(part2); + return result.toArray(new String[0]); + } + + public static void checkCompressedOopsErgo(String[] gcflags) throws Exception { + long maxHeapForCompressedOops = getMaxHeapForCompressedOops(gcflags); + + checkUseCompressedOops(gcflags, maxHeapForCompressedOops, true); + checkUseCompressedOops(gcflags, maxHeapForCompressedOops - 1, true); + checkUseCompressedOops(gcflags, maxHeapForCompressedOops + 1, false); + + // the use of HeapBaseMinAddress should not change the outcome + checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops, true); + checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops - 1, true); + checkUseCompressedOops(join(gcflags, "-XX:HeapBaseMinAddress=32G"), maxHeapForCompressedOops + 1, false); + + // use a different object alignment + maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16")); + + checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops, true); + checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops - 1, true); + checkUseCompressedOops(join(gcflags, "-XX:ObjectAlignmentInBytes=16"), maxHeapForCompressedOops + 1, false); + + // use a different CompressedClassSpaceSize + String compressedClassSpaceSizeArg = "-XX:CompressedClassSpaceSize=" + 2 * getCompressedClassSpaceSize(); + maxHeapForCompressedOops = getMaxHeapForCompressedOops(join(gcflags, compressedClassSpaceSizeArg)); + + checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops, true); + checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops - 1, true); + checkUseCompressedOops(join(gcflags, compressedClassSpaceSizeArg), maxHeapForCompressedOops + 1, false); + } + + private static void checkUseCompressedOops(String[] args, long heapsize, boolean expectUseCompressedOops) throws Exception { + ArrayList finalargs = new ArrayList(); + finalargs.addAll(Arrays.asList(args)); + finalargs.add("-Xmx" + heapsize); + finalargs.add("-XX:+PrintFlagsFinal"); + finalargs.add("-version"); + + String output = expectValid(finalargs.toArray(new String[0])); + + boolean actualUseCompressedOops = getFlagBoolValue(" UseCompressedOops", output); + + Asserts.assertEQ(expectUseCompressedOops, actualUseCompressedOops); + } + + private static boolean getFlagBoolValue(String flag, String where) { + Matcher m = Pattern.compile(flag + "\\s+:?= (true|false)").matcher(where); + if (!m.find()) { + throw new RuntimeException("Could not find value for flag " + flag + " in output string"); + } + return m.group(1).equals("true"); + } + + private static String expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(flags); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(errorcode); + return output.getStdout(); + } + + private static String expectValid(String[] flags) throws Exception { + return expect(flags, false, false, 0); + } +} + diff --git a/hotspot/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java b/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java similarity index 83% rename from hotspot/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java rename to hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java index b3258466a2d..8152a9eb1ca 100644 --- a/hotspot/test/gc/metaspace/ClassMetaspaceSizeInJmapHeap.java +++ b/hotspot/test/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -22,11 +22,11 @@ */ /* - * @test ClassMetaspaceSizeInJmapHeap + * @test CompressedClassSpaceSizeInJmapHeap * @bug 8004924 - * @summary Checks that jmap -heap contains the flag ClassMetaspaceSize + * @summary Checks that jmap -heap contains the flag CompressedClassSpaceSize * @library /testlibrary - * @run main/othervm -XX:ClassMetaspaceSize=50m ClassMetaspaceSizeInJmapHeap + * @run main/othervm -XX:CompressedClassSpaceSize=50m CompressedClassSpaceSizeInJmapHeap */ import com.oracle.java.testlibrary.*; @@ -35,7 +35,7 @@ import java.io.File; import java.nio.charset.Charset; import java.util.List; -public class ClassMetaspaceSizeInJmapHeap { +public class CompressedClassSpaceSizeInJmapHeap { public static void main(String[] args) throws Exception { String pid = Integer.toString(ProcessTools.getProcessId()); @@ -44,16 +44,16 @@ public class ClassMetaspaceSizeInJmapHeap { .addToolArg(pid); ProcessBuilder pb = new ProcessBuilder(jmap.getCommand()); - File out = new File("ClassMetaspaceSizeInJmapHeap.stdout.txt"); + File out = new File("CompressedClassSpaceSizeInJmapHeap.stdout.txt"); pb.redirectOutput(out); - File err = new File("ClassMetaspaceSizeInJmapHeap.stderr.txt"); + File err = new File("CompressedClassSpaceSizeInJmapHeap.stderr.txt"); pb.redirectError(err); run(pb); OutputAnalyzer output = new OutputAnalyzer(read(out)); - output.shouldContain("ClassMetaspaceSize = 52428800 (50.0MB)"); + output.shouldContain("CompressedClassSpaceSize = 52428800 (50.0MB)"); out.delete(); } diff --git a/hotspot/test/gc/metaspace/TestMetaspaceMemoryPool.java b/hotspot/test/gc/metaspace/TestMetaspaceMemoryPool.java index 440f91cbd85..bf9e74c8ab0 100644 --- a/hotspot/test/gc/metaspace/TestMetaspaceMemoryPool.java +++ b/hotspot/test/gc/metaspace/TestMetaspaceMemoryPool.java @@ -22,55 +22,35 @@ */ import java.util.List; -import java.lang.management.ManagementFactory; -import java.lang.management.MemoryManagerMXBean; -import java.lang.management.MemoryPoolMXBean; -import java.lang.management.MemoryUsage; - -import java.lang.management.RuntimeMXBean; -import java.lang.management.ManagementFactory; +import java.lang.management.*; +import com.oracle.java.testlibrary.*; +import static com.oracle.java.testlibrary.Asserts.*; /* @test TestMetaspaceMemoryPool * @bug 8000754 * @summary Tests that a MemoryPoolMXBeans is created for metaspace and that a * MemoryManagerMXBean is created. + * @library /testlibrary * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops TestMetaspaceMemoryPool * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:MaxMetaspaceSize=60m TestMetaspaceMemoryPool - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers TestMetaspaceMemoryPool - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:ClassMetaspaceSize=60m TestMetaspaceMemoryPool + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers TestMetaspaceMemoryPool + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:CompressedClassSpaceSize=60m TestMetaspaceMemoryPool */ public class TestMetaspaceMemoryPool { public static void main(String[] args) { verifyThatMetaspaceMemoryManagerExists(); - verifyMemoryPool(getMemoryPool("Metaspace"), isFlagDefined("MaxMetaspaceSize")); - if (runsOn64bit()) { - if (usesCompressedOops()) { + boolean isMetaspaceMaxDefined = InputArguments.containsPrefix("-XX:MaxMetaspaceSize"); + verifyMemoryPool(getMemoryPool("Metaspace"), isMetaspaceMaxDefined); + + if (Platform.is64bit()) { + if (InputArguments.contains("-XX:+UseCompressedOops")) { MemoryPoolMXBean cksPool = getMemoryPool("Compressed Class Space"); verifyMemoryPool(cksPool, true); } } } - private static boolean runsOn64bit() { - return !System.getProperty("sun.arch.data.model").equals("32"); - } - - private static boolean usesCompressedOops() { - return isFlagDefined("+UseCompressedOops"); - } - - private static boolean isFlagDefined(String name) { - RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean(); - List args = runtimeMxBean.getInputArguments(); - for (String arg : args) { - if (arg.startsWith("-XX:" + name)) { - return true; - } - } - return false; - } - private static void verifyThatMetaspaceMemoryManagerExists() { List managers = ManagementFactory.getMemoryManagerMXBeans(); for (MemoryManagerMXBean manager : managers) { @@ -95,32 +75,19 @@ public class TestMetaspaceMemoryPool { private static void verifyMemoryPool(MemoryPoolMXBean pool, boolean isMaxDefined) { MemoryUsage mu = pool.getUsage(); - assertDefined(mu.getInit(), "init"); - assertDefined(mu.getUsed(), "used"); - assertDefined(mu.getCommitted(), "committed"); + long init = mu.getInit(); + long used = mu.getUsed(); + long committed = mu.getCommitted(); + long max = mu.getMax(); + + assertGTE(init, 0L); + assertGTE(used, init); + assertGTE(committed, used); if (isMaxDefined) { - assertDefined(mu.getMax(), "max"); + assertGTE(max, committed); } else { - assertUndefined(mu.getMax(), "max"); - } - } - - private static void assertDefined(long value, String name) { - assertTrue(value != -1, "Expected " + name + " to be defined"); - } - - private static void assertUndefined(long value, String name) { - assertEquals(value, -1, "Expected " + name + " to be undefined"); - } - - private static void assertEquals(long actual, long expected, String msg) { - assertTrue(actual == expected, msg); - } - - private static void assertTrue(boolean condition, String msg) { - if (!condition) { - throw new RuntimeException(msg); + assertEQ(max, -1L); } } } diff --git a/hotspot/test/gc/metaspace/TestMetaspacePerfCounters.java b/hotspot/test/gc/metaspace/TestMetaspacePerfCounters.java index 26934249a7c..974066cba56 100644 --- a/hotspot/test/gc/metaspace/TestMetaspacePerfCounters.java +++ b/hotspot/test/gc/metaspace/TestMetaspacePerfCounters.java @@ -33,13 +33,13 @@ import static com.oracle.java.testlibrary.Asserts.*; * @summary Tests that performance counters for metaspace and compressed class * space exists and works. * - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UsePerfData -XX:+UseSerialGC TestMetaspacePerfCounters - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC TestMetaspacePerfCounters - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UsePerfData -XX:+UseG1GC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC TestMetaspacePerfCounters * - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UsePerfData -XX:+UseSerialGC TestMetaspacePerfCounters - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC TestMetaspacePerfCounters - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UsePerfData -XX:+UseG1GC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseSerialGC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseParallelGC -XX:+UseParallelOldGC TestMetaspacePerfCounters + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedClassPointers -XX:+UsePerfData -XX:+UseG1GC TestMetaspacePerfCounters */ public class TestMetaspacePerfCounters { public static Class fooClass = null; @@ -61,10 +61,15 @@ public class TestMetaspacePerfCounters { } private static void checkPerfCounters(String ns) throws Exception { - for (PerfCounter counter : countersInNamespace(ns)) { - String msg = "Expected " + counter.getName() + " to be larger than 0"; - assertGT(counter.longValue(), 0L, msg); - } + long minCapacity = getMinCapacity(ns); + long maxCapacity = getMaxCapacity(ns); + long capacity = getCapacity(ns); + long used = getUsed(ns); + + assertGTE(minCapacity, 0L); + assertGTE(used, minCapacity); + assertGTE(capacity, used); + assertGTE(maxCapacity, capacity); } private static void checkEmptyPerfCounters(String ns) throws Exception { @@ -75,12 +80,10 @@ public class TestMetaspacePerfCounters { } private static void checkUsedIncreasesWhenLoadingClass(String ns) throws Exception { - PerfCounter used = PerfCounters.findByName(ns + ".used"); - - long before = used.longValue(); + long before = getUsed(ns); fooClass = compileAndLoad("Foo", "public class Foo { }"); System.gc(); - long after = used.longValue(); + long after = getUsed(ns); assertGT(after, before); } @@ -99,6 +102,22 @@ public class TestMetaspacePerfCounters { } private static boolean isUsingCompressedClassPointers() { - return Platform.is64bit() && InputArguments.contains("-XX:+UseCompressedKlassPointers"); + return Platform.is64bit() && InputArguments.contains("-XX:+UseCompressedClassPointers"); + } + + private static long getMinCapacity(String ns) throws Exception { + return PerfCounters.findByName(ns + ".minCapacity").longValue(); + } + + private static long getCapacity(String ns) throws Exception { + return PerfCounters.findByName(ns + ".capacity").longValue(); + } + + private static long getMaxCapacity(String ns) throws Exception { + return PerfCounters.findByName(ns + ".maxCapacity").longValue(); + } + + private static long getUsed(String ns) throws Exception { + return PerfCounters.findByName(ns + ".used").longValue(); } } diff --git a/hotspot/test/gc/metaspace/TestMetaspaceSizeFlags.java b/hotspot/test/gc/metaspace/TestMetaspaceSizeFlags.java new file mode 100644 index 00000000000..c67b8dc5ce9 --- /dev/null +++ b/hotspot/test/gc/metaspace/TestMetaspaceSizeFlags.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.oracle.java.testlibrary.Asserts; +import com.oracle.java.testlibrary.OutputAnalyzer; +import com.oracle.java.testlibrary.ProcessTools; + +/* + * @test TestMetaspaceSizeFlags + * @key gc + * @bug 8024650 + * @summary Test that metaspace size flags can be set correctly + * @library /testlibrary + */ +public class TestMetaspaceSizeFlags { + public static final long K = 1024L; + public static final long M = 1024L * K; + + // HotSpot uses a number of different values to align memory size flags. + // This is currently the largest alignment (unless huge large pages are used). + public static final long MAX_ALIGNMENT = 32 * M; + + public static void main(String [] args) throws Exception { + testMaxMetaspaceSizeEQMetaspaceSize(MAX_ALIGNMENT, MAX_ALIGNMENT); + // 8024650: MaxMetaspaceSize was adjusted instead of MetaspaceSize. + testMaxMetaspaceSizeLTMetaspaceSize(MAX_ALIGNMENT, MAX_ALIGNMENT * 2); + testMaxMetaspaceSizeGTMetaspaceSize(MAX_ALIGNMENT * 2, MAX_ALIGNMENT); + testTooSmallInitialMetaspace(0, 0); + testTooSmallInitialMetaspace(0, MAX_ALIGNMENT); + testTooSmallInitialMetaspace(MAX_ALIGNMENT, 0); + } + + private static void testMaxMetaspaceSizeEQMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception { + MetaspaceFlags mf = runAndGetValue(maxMetaspaceSize, metaspaceSize); + Asserts.assertEQ(maxMetaspaceSize, metaspaceSize); + Asserts.assertEQ(mf.maxMetaspaceSize, maxMetaspaceSize); + Asserts.assertEQ(mf.metaspaceSize, metaspaceSize); + } + + private static void testMaxMetaspaceSizeLTMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception { + MetaspaceFlags mf = runAndGetValue(maxMetaspaceSize, metaspaceSize); + Asserts.assertEQ(mf.maxMetaspaceSize, maxMetaspaceSize); + Asserts.assertEQ(mf.metaspaceSize, maxMetaspaceSize); + } + + private static void testMaxMetaspaceSizeGTMetaspaceSize(long maxMetaspaceSize, long metaspaceSize) throws Exception { + MetaspaceFlags mf = runAndGetValue(maxMetaspaceSize, metaspaceSize); + Asserts.assertGT(maxMetaspaceSize, metaspaceSize); + Asserts.assertGT(mf.maxMetaspaceSize, mf.metaspaceSize); + Asserts.assertEQ(mf.maxMetaspaceSize, maxMetaspaceSize); + Asserts.assertEQ(mf.metaspaceSize, metaspaceSize); + } + + private static void testTooSmallInitialMetaspace(long maxMetaspaceSize, long metaspaceSize) throws Exception { + OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize); + output.shouldContain("Too small initial Metaspace size"); + } + + private static MetaspaceFlags runAndGetValue(long maxMetaspaceSize, long metaspaceSize) throws Exception { + OutputAnalyzer output = run(maxMetaspaceSize, metaspaceSize); + output.shouldNotMatch("Error occurred during initialization of VM\n.*"); + + String stringMaxMetaspaceSize = output.firstMatch(".* MaxMetaspaceSize .* := (\\d+).*", 1); + String stringMetaspaceSize = output.firstMatch(".* MetaspaceSize .* := (\\d+).*", 1); + + return new MetaspaceFlags(Long.parseLong(stringMaxMetaspaceSize), + Long.parseLong(stringMetaspaceSize)); + } + + private static OutputAnalyzer run(long maxMetaspaceSize, long metaspaceSize) throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-XX:MaxMetaspaceSize=" + maxMetaspaceSize, + "-XX:MetaspaceSize=" + metaspaceSize, + "-XX:-UseLargePages", // Prevent us from using 2GB large pages on solaris + sparc. + "-XX:+PrintFlagsFinal", + "-version"); + return new OutputAnalyzer(pb.start()); + } + + private static class MetaspaceFlags { + public long maxMetaspaceSize; + public long metaspaceSize; + public MetaspaceFlags(long maxMetaspaceSize, long metaspaceSize) { + this.maxMetaspaceSize = maxMetaspaceSize; + this.metaspaceSize = metaspaceSize; + } + } +} diff --git a/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java b/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java new file mode 100644 index 00000000000..e26aa6eee57 --- /dev/null +++ b/hotspot/test/gc/metaspace/TestPerfCountersAndMemoryPools.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.List; +import java.lang.management.*; + +import com.oracle.java.testlibrary.*; +import static com.oracle.java.testlibrary.Asserts.*; + +/* @test TestPerfCountersAndMemoryPools + * @bug 8023476 + * @summary Tests that a MemoryPoolMXBeans and PerfCounters for metaspace + * report the same data. + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:-UseCompressedOops -XX:-UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCompressedOops -XX:+UseCompressedKlassPointers -XX:+UseSerialGC -XX:+UsePerfData TestPerfCountersAndMemoryPools + */ +public class TestPerfCountersAndMemoryPools { + public static void main(String[] args) throws Exception { + checkMemoryUsage("Metaspace", "sun.gc.metaspace"); + + if (InputArguments.contains("-XX:+UseCompressedKlassPointers") && Platform.is64bit()) { + checkMemoryUsage("Compressed Class Space", "sun.gc.compressedclassspace"); + } + } + + private static MemoryUsage getMemoryUsage(String memoryPoolName) { + List pools = ManagementFactory.getMemoryPoolMXBeans(); + for (MemoryPoolMXBean pool : pools) { + if (pool.getName().equals(memoryPoolName)) { + return pool.getUsage(); + } + } + + throw new RuntimeException("Excpted to find a memory pool with name " + + memoryPoolName); + } + + private static void checkMemoryUsage(String memoryPoolName, String perfNS) + throws Exception { + // Need to do a gc before each comparison to update the perf counters + + System.gc(); + MemoryUsage mu = getMemoryUsage(memoryPoolName); + assertEQ(getMinCapacity(perfNS), mu.getInit()); + + System.gc(); + mu = getMemoryUsage(memoryPoolName); + assertEQ(getUsed(perfNS), mu.getUsed()); + + System.gc(); + mu = getMemoryUsage(memoryPoolName); + assertEQ(getCapacity(perfNS), mu.getCommitted()); + } + + private static long getMinCapacity(String ns) throws Exception { + return PerfCounters.findByName(ns + ".minCapacity").longValue(); + } + + private static long getCapacity(String ns) throws Exception { + return PerfCounters.findByName(ns + ".capacity").longValue(); + } + + private static long getUsed(String ns) throws Exception { + return PerfCounters.findByName(ns + ".used").longValue(); + } +} diff --git a/hotspot/test/runtime/6878713/Test6878713.sh b/hotspot/test/runtime/6878713/Test6878713.sh deleted file mode 100644 index a2b5b2d2eb7..00000000000 --- a/hotspot/test/runtime/6878713/Test6878713.sh +++ /dev/null @@ -1,137 +0,0 @@ -#!/bin/sh - -# -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - - - -## -## @test -## @bug 6878713 -## @bug 7030610 -## @bug 7037122 -## @bug 7123945 -## @summary Verifier heap corruption, relating to backward jsrs -## @run shell Test6878713.sh -## -## some tests require path to find test source dir -if [ "${TESTSRC}" = "" ] -then - TESTSRC=${PWD} - echo "TESTSRC not set. Using "${TESTSRC}" as default" -fi -echo "TESTSRC=${TESTSRC}" -## Adding common setup Variables for running shell tests. -. ${TESTSRC}/../../test_env.sh - -TARGET_CLASS=OOMCrashClass1960_2 - -echo "INFO: extracting the target class." -${COMPILEJAVA}${FS}bin${FS}jar xvf \ - ${TESTSRC}${FS}testcase.jar ${TARGET_CLASS}.class - -# remove any hs_err_pid that might exist here -rm -f hs_err_pid*.log - -echo "INFO: checking for 32-bit versus 64-bit VM." -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -version 2>&1 \ - | grep "64-Bit [^ ][^ ]* VM" > /dev/null 2>&1 -status="$?" -if [ "$status" = 0 ]; then - echo "INFO: testing a 64-bit VM." - is_64_bit=true -else - echo "INFO: testing a 32-bit VM." -fi - -if [ "$is_64_bit" = true ]; then - # limit is 768MB in 8-byte words (1024 * 1024 * 768 / 8) == 100663296 - MALLOC_MAX=100663296 -else - # limit is 768MB in 4-byte words (1024 * 1024 * 768 / 4) == 201326592 - MALLOC_MAX=201326592 -fi -echo "INFO: MALLOC_MAX=$MALLOC_MAX" - -echo "INFO: executing the target class." -# -XX:+PrintCommandLineFlags for debugging purposes -# -XX:+IgnoreUnrecognizedVMOptions so test will run on a VM without -# the new -XX:MallocMaxTestWords option -# -XX:+UnlockDiagnosticVMOptions so we can use -XX:MallocMaxTestWords -# -XX:MallocMaxTestWords limits malloc to $MALLOC_MAX -${TESTJAVA}${FS}bin${FS}java \ - -XX:+PrintCommandLineFlags \ - -XX:+IgnoreUnrecognizedVMOptions \ - -XX:+UnlockDiagnosticVMOptions \ - -XX:MallocMaxTestWords=$MALLOC_MAX \ - ${TESTVMOPTS} ${TARGET_CLASS} > test.out 2>&1 - -echo "INFO: begin contents of test.out:" -cat test.out -echo "INFO: end contents of test.out." - -echo "INFO: checking for memory allocation error message." -# We are looking for this specific memory allocation failure mesg so -# we know we exercised the right allocation path with the test class: -MESG1="Native memory allocation (malloc) failed to allocate 25696531[0-9][0-9] bytes" -grep "$MESG1" test.out -status="$?" -if [ "$status" = 0 ]; then - echo "INFO: found expected memory allocation error message." -else - echo "INFO: did not find expected memory allocation error message." - - # If we didn't find MESG1 above, then there are several scenarios: - # 1) -XX:MallocMaxTestWords is not supported by the current VM and we - # didn't fail TARGET_CLASS's memory allocation attempt; instead - # we failed to find TARGET_CLASS's main() method. The TARGET_CLASS - # is designed to provoke a memory allocation failure during class - # loading; we actually don't care about running the class which is - # why it doesn't have a main() method. - # 2) we failed a memory allocation, but not the one we were looking - # so it might be that TARGET_CLASS no longer tickles the same - # memory allocation code path - # 3) TARGET_CLASS reproduces the failure mode (SIGSEGV) fixed by - # 6878713 because the test is running on a pre-fix VM. - echo "INFO: checking for no main() method message." - MESG2="Error: Main method not found in class" - grep "$MESG2" test.out - status="$?" - if [ "$status" = 0 ]; then - echo "INFO: found no main() method message." - else - echo "FAIL: did not find no main() method message." - # status is non-zero for exit below - - if [ -s hs_err_pid*.log ]; then - echo "INFO: begin contents of hs_err_pid file:" - cat hs_err_pid*.log - echo "INFO: end contents of hs_err_pid file." - fi - fi -fi - -if [ "$status" = 0 ]; then - echo "PASS: test found one of the expected messages." -fi -exit "$status" diff --git a/hotspot/test/runtime/7020373/Test7020373.sh b/hotspot/test/runtime/7020373/Test7020373.sh deleted file mode 100644 index 83b7028c82f..00000000000 --- a/hotspot/test/runtime/7020373/Test7020373.sh +++ /dev/null @@ -1,43 +0,0 @@ -#!/bin/sh - -## -## @test -## @bug 7020373 7055247 7053586 7185550 -## @key cte_test -## @summary JSR rewriting can overflow memory address size variables -## @ignore Ignore it as 7053586 test uses lots of memory. See bug report for detail. -## @run shell Test7020373.sh -## - -if [ "${TESTSRC}" = "" ] -then - TESTSRC=${PWD} - echo "TESTSRC not set. Using "${TESTSRC}" as default" -fi -echo "TESTSRC=${TESTSRC}" -## Adding common setup Variables for running shell tests. -. ${TESTSRC}/../../test_env.sh - -${COMPILEJAVA}${FS}bin${FS}jar xvf ${TESTSRC}${FS}testcase.jar - -${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} OOMCrashClass4000_1 > test.out 2>&1 - -cat test.out - -egrep "SIGSEGV|An unexpected error has been detected" test.out - -if [ $? = 0 ] -then - echo "Test Failed" - exit 1 -else - egrep "java.lang.LinkageError|java.lang.NoSuchMethodError|Main method not found in class OOMCrashClass4000_1|insufficient memory" test.out - if [ $? = 0 ] - then - echo "Test Passed" - exit 0 - else - echo "Test Failed" - exit 1 - fi -fi diff --git a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java index 4ce2e82c771..c32c05ebd27 100644 --- a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java +++ b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java @@ -24,7 +24,7 @@ /* * @test * @bug 8003424 - * @summary Testing UseCompressedKlassPointers with CDS + * @summary Testing UseCompressedClassPointers with CDS * @library /testlibrary * @run main CDSCompressedKPtrs */ @@ -36,7 +36,7 @@ public class CDSCompressedKPtrs { ProcessBuilder pb; if (Platform.is64bit()) { pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UseCompressedKlassPointers", "-XX:+UseCompressedOops", + "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); try { @@ -44,7 +44,7 @@ public class CDSCompressedKPtrs { output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UseCompressedKlassPointers", "-XX:+UseCompressedOops", + "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version"); output = new OutputAnalyzer(pb.start()); output.shouldContain("sharing"); diff --git a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrsError.java b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrsError.java index b2cb84ac988..05b4ac9af28 100644 --- a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrsError.java +++ b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrsError.java @@ -24,7 +24,7 @@ /* * @test * @bug 8003424 - * @summary Test that cannot use CDS if UseCompressedKlassPointers is turned off. + * @summary Test that cannot use CDS if UseCompressedClassPointers is turned off. * @library /testlibrary * @run main CDSCompressedKPtrsError */ @@ -36,7 +36,7 @@ public class CDSCompressedKPtrsError { ProcessBuilder pb; if (Platform.is64bit()) { pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UseCompressedOops", "-XX:+UseCompressedKlassPointers", "-XX:+UnlockDiagnosticVMOptions", + "-XX:+UseCompressedOops", "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); try { @@ -44,21 +44,21 @@ public class CDSCompressedKPtrsError { output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder( - "-XX:-UseCompressedKlassPointers", "-XX:-UseCompressedOops", + "-XX:-UseCompressedClassPointers", "-XX:-UseCompressedOops", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Unable to use shared archive"); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder( - "-XX:-UseCompressedKlassPointers", "-XX:+UseCompressedOops", + "-XX:-UseCompressedClassPointers", "-XX:+UseCompressedOops", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Unable to use shared archive"); output.shouldHaveExitValue(0); pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UseCompressedKlassPointers", "-XX:-UseCompressedOops", + "-XX:+UseCompressedClassPointers", "-XX:-UseCompressedOops", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:on", "-version"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Unable to use shared archive"); @@ -71,19 +71,19 @@ public class CDSCompressedKPtrsError { // Test bad options with -Xshare:dump. pb = ProcessTools.createJavaProcessBuilder( - "-XX:-UseCompressedOops", "-XX:+UseCompressedKlassPointers", "-XX:+UnlockDiagnosticVMOptions", + "-XX:-UseCompressedOops", "-XX:+UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Cannot dump shared archive"); pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UseCompressedOops", "-XX:-UseCompressedKlassPointers", "-XX:+UnlockDiagnosticVMOptions", + "-XX:+UseCompressedOops", "-XX:-UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Cannot dump shared archive"); pb = ProcessTools.createJavaProcessBuilder( - "-XX:-UseCompressedOops", "-XX:-UseCompressedKlassPointers", "-XX:+UnlockDiagnosticVMOptions", + "-XX:-UseCompressedOops", "-XX:-UseCompressedClassPointers", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); output = new OutputAnalyzer(pb.start()); output.shouldContain("Cannot dump shared archive"); diff --git a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java index 7f36977ec70..9bd68e11733 100644 --- a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java +++ b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java @@ -33,16 +33,9 @@ import com.oracle.java.testlibrary.*; public class XShareAuto { public static void main(String[] args) throws Exception { - if (!Platform.is64bit()) { - System.out.println("ObjectAlignmentInBytes for CDS is only " + - "supported on 64bit platforms; this plaform is " + - System.getProperty("sun.arch.data.model")); - System.out.println("Skipping the test"); - return; - } ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", - "-Xshare:dump"); + "-server", "-XX:+UnlockDiagnosticVMOptions", + "-XX:SharedArchiveFile=./sample.jsa", "-Xshare:dump"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("Loading classes to share"); output.shouldHaveExitValue(0); diff --git a/hotspot/test/runtime/ClassFile/JsrRewriting.java b/hotspot/test/runtime/ClassFile/JsrRewriting.java new file mode 100644 index 00000000000..856658f9bf3 --- /dev/null +++ b/hotspot/test/runtime/ClassFile/JsrRewriting.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + + +/* + * @test JsrRewriting + * @summary JSR (jump local subroutine) + * rewriting can overflow memory address size variables + * @bug 7020373 + * @bug 7055247 + * @bug 7053586 + * @bug 7185550 + * @bug 7149464 + * @key cte_test + * @library /testlibrary + * @run main JsrRewriting + */ + +import com.oracle.java.testlibrary.*; +import java.io.File; + +public class JsrRewriting { + + public static void main(String[] args) throws Exception { + + // ======= Configure the test + String jarFile = System.getProperty("test.src") + + File.separator + "JsrRewritingTestCase.jar"; + String className = "OOMCrashClass4000_1"; + + // limit is 768MB in native words + int mallocMaxTestWords = (1024 * 1024 * 768 / 4); + if (Platform.is64bit()) + mallocMaxTestWords = (mallocMaxTestWords / 2); + + // ======= extract the test class + ProcessBuilder pb = new ProcessBuilder(new String[] { + JDKToolFinder.getJDKTool("jar"), + "xvf", jarFile } ); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + // ======= execute the test + pb = ProcessTools.createJavaProcessBuilder( + "-cp", ".", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:MallocMaxTestWords=" + mallocMaxTestWords, + className); + + output = new OutputAnalyzer(pb.start()); + String[] expectedMsgs = { + "java.lang.LinkageError", + "java.lang.NoSuchMethodError", + "Main method not found in class " + className, + "insufficient memory" + }; + + MultipleOrMatch(output, expectedMsgs); + } + + private static void + MultipleOrMatch(OutputAnalyzer analyzer, String[] whatToMatch) { + String output = analyzer.getOutput(); + + for (String expected : whatToMatch) + if (output.contains(expected)) + return; + + String err = + " stdout: [" + analyzer.getOutput() + "];\n" + + " exitValue = " + analyzer.getExitValue() + "\n"; + System.err.println(err); + + StringBuilder msg = new StringBuilder("Output did not contain " + + "any of the following expected messages: \n"); + for (String expected : whatToMatch) + msg.append(expected).append(System.lineSeparator()); + throw new RuntimeException(msg.toString()); + } +} + diff --git a/hotspot/test/runtime/7020373/testcase.jar b/hotspot/test/runtime/ClassFile/JsrRewritingTestCase.jar similarity index 100% rename from hotspot/test/runtime/7020373/testcase.jar rename to hotspot/test/runtime/ClassFile/JsrRewritingTestCase.jar diff --git a/hotspot/test/runtime/ClassFile/OomWhileParsingRepeatedJsr.java b/hotspot/test/runtime/ClassFile/OomWhileParsingRepeatedJsr.java new file mode 100644 index 00000000000..ad08b183e59 --- /dev/null +++ b/hotspot/test/runtime/ClassFile/OomWhileParsingRepeatedJsr.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + + +/* + * @test OomWhileParsingRepeatedJsr + * @summary Testing class file parser; specifically parsing + * a file with repeated JSR (jump local subroutine) + * bytecode command. + * @bug 6878713 + * @bug 7030610 + * @bug 7037122 + * @bug 7123945 + * @bug 8016029 + * @library /testlibrary + * @run main OomWhileParsingRepeatedJsr + */ + +import com.oracle.java.testlibrary.*; + + +public class OomWhileParsingRepeatedJsr { + + public static void main(String[] args) throws Exception { + + // ======= Configure the test + String jarFile = System.getProperty("test.src") + "/testcase.jar"; + String className = "OOMCrashClass1960_2"; + + // limit is 768MB in native words + int mallocMaxTestWords = (1024 * 1024 * 768 / 4); + if (Platform.is64bit()) + mallocMaxTestWords = (mallocMaxTestWords / 2); + + // ======= extract the test class + ProcessBuilder pb = new ProcessBuilder(new String[] { + JDKToolFinder.getJDKTool("jar"), + "xvf", jarFile } ); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + // ======= execute the test + pb = ProcessTools.createJavaProcessBuilder( + "-cp", ".", + "-XX:+UnlockDiagnosticVMOptions", + "-XX:MallocMaxTestWords=" + mallocMaxTestWords, + className ); + + output = new OutputAnalyzer(pb.start()); + output.shouldContain("Cannot reserve enough memory"); + } +} + diff --git a/hotspot/test/runtime/6878713/testcase.jar b/hotspot/test/runtime/ClassFile/testcase.jar similarity index 100% rename from hotspot/test/runtime/6878713/testcase.jar rename to hotspot/test/runtime/ClassFile/testcase.jar diff --git a/hotspot/test/runtime/CompressedOops/CompressedKlassPointerAndOops.java b/hotspot/test/runtime/CompressedOops/CompressedKlassPointerAndOops.java index dd0c26d9f10..228d8cb6a7a 100644 --- a/hotspot/test/runtime/CompressedOops/CompressedKlassPointerAndOops.java +++ b/hotspot/test/runtime/CompressedOops/CompressedKlassPointerAndOops.java @@ -25,7 +25,7 @@ * @test * @bug 8000968 * @key regression - * @summary NPG: UseCompressedKlassPointers asserts with ObjectAlignmentInBytes=32 + * @summary NPG: UseCompressedClassPointers asserts with ObjectAlignmentInBytes=32 * @library /testlibrary */ @@ -52,7 +52,7 @@ public class CompressedKlassPointerAndOops { OutputAnalyzer output; pb = ProcessTools.createJavaProcessBuilder( - "-XX:+UseCompressedKlassPointers", + "-XX:+UseCompressedClassPointers", "-XX:+UseCompressedOops", "-XX:ObjectAlignmentInBytes=" + alignment, "-version"); diff --git a/hotspot/test/runtime/InitialThreadOverflow/testme.sh b/hotspot/test/runtime/InitialThreadOverflow/testme.sh index 015a6bd43b1..b7154dc2abd 100644 --- a/hotspot/test/runtime/InitialThreadOverflow/testme.sh +++ b/hotspot/test/runtime/InitialThreadOverflow/testme.sh @@ -43,9 +43,9 @@ then exit 0 fi -gcc_cmd=`which gcc` -if [ "x$gcc_cmd" == "x" ]; then - echo "WARNING: gcc not found. Cannot execute test." 2>&1 +gcc_cmd=`which g++` +if [ "x$gcc_cmd" = "x" ]; then + echo "WARNING: g++ not found. Cannot execute test." 2>&1 exit 0; fi diff --git a/hotspot/test/testlibrary/OutputAnalyzerTest.java b/hotspot/test/testlibrary/OutputAnalyzerTest.java index 6117e9000bd..2fd677783a8 100644 --- a/hotspot/test/testlibrary/OutputAnalyzerTest.java +++ b/hotspot/test/testlibrary/OutputAnalyzerTest.java @@ -172,5 +172,22 @@ public class OutputAnalyzerTest { } catch (RuntimeException e) { // expected } + + { + String aaaa = "aaaa"; + String result = output.firstMatch(aaaa); + if (!aaaa.equals(result)) { + throw new Exception("firstMatch(String) faild to match. Expected: " + aaaa + " got: " + result); + } + } + + { + String aa = "aa"; + String aa_grouped_aa = aa + "(" + aa + ")"; + String result = output.firstMatch(aa_grouped_aa, 1); + if (!aa.equals(result)) { + throw new Exception("firstMatch(String, int) failed to match. Expected: " + aa + " got: " + result); + } + } } } diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java index 650d6c23390..6f40b4050be 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/InputArguments.java @@ -41,6 +41,9 @@ public class InputArguments { /** * Returns true if {@code arg} is an input argument to the VM. * + * This is useful for checking boolean flags such as -XX:+UseSerialGC or + * -XX:-UsePerfData. + * * @param arg The name of the argument. * @return {@code true} if the given argument is an input argument, * otherwise {@code false}. @@ -48,4 +51,26 @@ public class InputArguments { public static boolean contains(String arg) { return args.contains(arg); } + + /** + * Returns true if {@code prefix} is the start of an input argument to the + * VM. + * + * This is useful for checking if flags describing a quantity, such as + * -XX:+MaxMetaspaceSize=100m, is set without having to know the quantity. + * To check if the flag -XX:MaxMetaspaceSize is set, use + * {@code InputArguments.containsPrefix("-XX:MaxMetaspaceSize")}. + * + * @param prefix The start of the argument. + * @return {@code true} if the given argument is the start of an input + * argument, otherwise {@code false}. + */ + public static boolean containsPrefix(String prefix) { + for (String arg : args) { + if (arg.startsWith(prefix)) { + return true; + } + } + return false; + } } diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java index 91ad6a8c8a9..6434135c108 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java @@ -23,28 +23,84 @@ package com.oracle.java.testlibrary; -import java.io.File; +import java.io.FileNotFoundException; +import java.nio.file.Path; +import java.nio.file.Paths; public final class JDKToolFinder { - private JDKToolFinder() { - } - - /** - * Returns the full path to an executable in jdk/bin based on System property - * test.jdk (set by jtreg test suite) - * - * @return Full path to an executable in jdk/bin - */ - public static String getJDKTool(String tool) { - String binPath = System.getProperty("test.jdk"); - if (binPath == 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'."); + private JDKToolFinder() { } - binPath += File.separatorChar + "bin" + File.separatorChar + tool; + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} or {@code compile.jdk} (both are set by the jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getJDKTool(String tool) { - return binPath; - } + // First try to find the executable in test.jdk + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + + } + + // Now see if it's available in compile.jdk + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException("Failed to find " + tool + + ", looked in test.jdk (" + System.getProperty("test.jdk") + + ") and compile.jdk (" + System.getProperty("compile.jdk") + ")"); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code compile.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getCompileJDKTool(String tool) { + try { + return getTool(tool, "compile.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the full path to an executable in jdk/bin based on System + * property {@code test.jdk} + * + * @return Full path to an executable in jdk/bin + */ + public static String getTestJDKTool(String tool) { + try { + return getTool(tool, "test.jdk"); + } catch (FileNotFoundException e) { + throw new RuntimeException(e); + } + } + + private static String getTool(String tool, String property) throws FileNotFoundException { + String jdkPath = System.getProperty(property); + + if (jdkPath == null) { + throw new RuntimeException( + "System property '" + property + "' not set. This property is normally set by jtreg. " + + "When running test separately, set this property using '-D" + property + "=/path/to/jdk'."); + } + + Path toolName = Paths.get("bin", tool + (Platform.isWindows() ? ".exe" : "")); + + Path jdkTool = Paths.get(jdkPath, toolName.toString()); + if (!jdkTool.toFile().exists()) { + throw new FileNotFoundException("Could not find file " + jdkTool.toAbsolutePath()); + } + + return jdkTool.toAbsolutePath().toString(); + } } diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java index b9e37128d23..73b65165e91 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/OutputAnalyzer.java @@ -211,13 +211,13 @@ public final class OutputAnalyzer { if (matcher.find()) { reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' found in stdout \n"); + + "' found in stdout: '" + matcher.group() + "' \n"); } matcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); if (matcher.find()) { reportDiagnosticSummary(); throw new RuntimeException("'" + pattern - + "' found in stderr \n"); + + "' found in stderr: '" + matcher.group() + "' \n"); } } @@ -253,6 +253,37 @@ public final class OutputAnalyzer { } } + /** + * Get the captured group of the first string matching the pattern. + * stderr is searched before stdout. + * + * @param pattern The multi-line pattern to match + * @param group The group to capture + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern, int group) { + Matcher stderrMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stderr); + Matcher stdoutMatcher = Pattern.compile(pattern, Pattern.MULTILINE).matcher(stdout); + if (stderrMatcher.find()) { + return stderrMatcher.group(group); + } + if (stdoutMatcher.find()) { + return stdoutMatcher.group(group); + } + return null; + } + + /** + * Get the first string matching the pattern. + * stderr is searched before stdout. + * + * @param pattern The multi-line pattern to match + * @return The matched string or null if no match was found + */ + public String firstMatch(String pattern) { + return firstMatch(pattern, 0); + } + /** * Verify the exit value of the process * diff --git a/hotspot/test/testlibrary/ctw/Makefile b/hotspot/test/testlibrary/ctw/Makefile new file mode 100644 index 00000000000..5bca7754c69 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/Makefile @@ -0,0 +1,73 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +ifneq "x$(ALT_BOOTDIR)" "x" + BOOTDIR := $(ALT_BOOTDIR) +endif + +ifeq "x$(BOOTDIR)" "x" + JDK_HOME := $(shell dirname $(shell which java))/.. +else + JDK_HOME := $(BOOTDIR) +endif + +SRC_DIR = src +BUILD_DIR = build +OUTPUT_DIR = $(BUILD_DIR)/classes +WHITEBOX_DIR = ../whitebox + +JAVAC = $(JDK_HOME)/bin/javac +JAR = $(JDK_HOME)/bin/jar + +SRC_FILES = $(shell find $(SRC_DIR) -name '*.java') + +MAIN_CLASS = sun.hotspot.tools.ctw.CompileTheWorld + +.PHONY: clean cleantmp + +all: ctw.jar cleantmp + +clean: cleantmp + @rm -rf ctw.jar wb.jar + +cleantmp: + @rm -rf filelist manifest.mf + @rm -rf $(BUILD_DIR) + +ctw.jar: filelist wb.jar manifest.mf + @mkdir -p $(OUTPUT_DIR) + $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp wb.jar @filelist + $(JAR) cfm ctw.jar manifest.mf -C $(OUTPUT_DIR) . + +wb.jar: + make -C ${WHITEBOX_DIR} wb.jar + cp ${WHITEBOX_DIR}/wb.jar ./ + make -C ${WHITEBOX_DIR} clean + +filelist: $(SRC_FILES) + @rm -f $@ + @echo $(SRC_FILES) > $@ + +manifest.mf: + @echo "Main-Class: ${MAIN_CLASS}" > manifest.mf diff --git a/hotspot/test/testlibrary/ctw/README b/hotspot/test/testlibrary/ctw/README new file mode 100644 index 00000000000..babb0816229 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/README @@ -0,0 +1,93 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +DESCRIPTION + +This is replacement for CompileTheWorld (CTW) written on java. Its purpose is +to make possible the use of CTW in product builds. + +DEPENDENCES + +The tool depends on Whitebox API. Assumed, that the sources of whitebox are +located in '../whitebox' directory. + +BUILDING + +Simple way to build, just type 'make'. + +Makefile uses environment variables 'ALT_BOOTDIR', 'BOOTDIR' as root-dir of jdk +that will be used for compilation and creating jar. + +On successful building 'ctw.jar' will be created. + +RUNNING + +Since the tool uses WhiteBox API, options 'UnlockDiagnosticVMOptions' and +'WhiteBoxAPI' should be specified, and 'wb.jar' should be added to +boot-classpath: + $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar + +Arguments can be paths to '.jar, '.zip', '.lst' files or directories with +classes, that define which classes will be compiled: + - '.jar', '.zip' files and directories are interpreted like in classpath +(including '

    /*' syntax) + - '.lst' files -- files with class names (in java notation) to compile. +CTW will try to find these classes with default class loader, so they should +be located in classpath. + +Without arguments it would work as old version of CTW: all classes in +boot-classpath will be compiled, excluding classes in 'rt.jar' if 'rt.jar' isn't +first in boot-classpath. + +Due CTW's flags also are not available in product builds, the tool uses +properties with the same names: + - 'CompileTheWorldPreloadClasses' -- type:boolean, default:true, description: +Preload all classes used by a class before start loading + - 'CompileTheWorldStartAt' -- type:long, default:1, description: First class +to consider + - 'CompileTheWorldStopAt' -- type:long, default:Long.MAX_VALUE, description: +Last class to consider + +Also it uses additional properties: + - 'sun.hotspot.tools.ctw.verbose' -- type:boolean, default:false, +description: Verbose output, adds additional information about compilation + - 'sun.hotspot.tools.ctw.logfile' -- type:string, default:null, +description: Path to logfile, if it's null, cout will be used. + +EXAMPLES + +compile classes from 'rt.jar': + $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ${JAVA_HOME}/jre/lib/rt.jar + +compile classes from all '.jar' in './testjars' directory: + $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./testjars/* + +compile classes from './build/classes' directory: + $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar ./build/classes + +compile only java.lang.String, java.lang.Object classes: + $ echo java.lang.String > classes.lst + $ echo java.lang.Object >> classes.lst + $ java -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:wb.jar -jar ctw.jar classes.lst + diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java new file mode 100644 index 00000000000..3ee3526568d --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathDirEntry.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Set; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.concurrent.Executor; + +import java.io.*; +import java.nio.file.*; +import java.nio.file.attribute.*; + +/** + * * Handler for dirs containing classes to compile. + * @author igor.ignatyev@oracle.com + */ +public class ClassPathDirEntry extends PathHandler { + + private final int rootLength = root.toString().length(); + + public ClassPathDirEntry(Path root, Executor executor) { + super(root, executor); + try { + URL url = root.toUri().toURL(); + setLoader(new URLClassLoader(new URL[]{url})); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + @Override + public void process() { + System.out.println("# dir: " + root); + if (!Files.exists(root)) { + return; + } + try { + Files.walkFileTree(root, EnumSet.of(FileVisitOption.FOLLOW_LINKS), + Integer.MAX_VALUE, new CompileFileVisitor()); + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + private void processFile(Path file) { + if (Utils.isClassFile(file.toString())) { + processClass(pathToClassName(file)); + } + } + + private String pathToClassName(Path file) { + String fileString; + if (root == file) { + fileString = file.normalize().toString(); + } else { + fileString = file.normalize().toString().substring(rootLength + 1); + } + return Utils.fileNameToClassName(fileString); + } + + private class CompileFileVisitor extends SimpleFileVisitor { + + private final Set ready = new HashSet<>(); + + @Override + public FileVisitResult preVisitDirectory(Path dir, + BasicFileAttributes attrs) throws IOException { + if (ready.contains(dir)) { + return FileVisitResult.SKIP_SUBTREE; + } + ready.add(dir); + return super.preVisitDirectory(dir, attrs); + } + + @Override + public FileVisitResult visitFile(Path file, + BasicFileAttributes attrs) throws IOException { + if (!ready.contains(file)) { + processFile(file); + } + return isFinished() ? FileVisitResult.TERMINATE + : FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFileFailed(Path file, + IOException exc) throws IOException { + return FileVisitResult.CONTINUE; + } + } +} + diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java new file mode 100644 index 00000000000..3d39f1b2573 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarEntry.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import java.util.jar.*; +import java.util.concurrent.Executor; + +import java.io.*; +import java.nio.file.*; + +/** + * Handler for jar-files containing classes to compile. + * @author igor.ignatyev@oracle.com + */ +public class ClassPathJarEntry extends PathHandler { + + public ClassPathJarEntry(Path root, Executor executor) { + super(root, executor); + try { + URL url = root.toUri().toURL(); + setLoader(new URLClassLoader(new URL[]{url})); + } catch (MalformedURLException e) { + e.printStackTrace(); + } + } + + @Override + public void process() { + System.out.println("# jar: " + root); + if (!Files.exists(root)) { + return; + } + try { + JarFile jarFile = new JarFile(root.toFile()); + JarEntry entry; + for (Enumeration e = jarFile.entries(); + e.hasMoreElements(); ) { + entry = e.nextElement(); + processJarEntry(entry); + if (isFinished()) { + return; + } + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } + + private void processJarEntry(JarEntry entry) { + String filename = entry.getName(); + if (Utils.isClassFile(filename)) { + processClass(Utils.fileNameToClassName(filename)); + } + } +} + diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java new file mode 100644 index 00000000000..328280a2d88 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassPathJarInDirEntry.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.Executor; + +/** + * Handler for dirs containing jar-files with classes to compile. + * + * @author igor.ignatyev@oracle.com + */ +public class ClassPathJarInDirEntry extends PathHandler { + + public ClassPathJarInDirEntry(Path root, Executor executor) { + super(root, executor); + } + + @Override + public void process() { + System.out.println("# jar_in_dir: " + root); + if (!Files.exists(root)) { + return; + } + try (DirectoryStream ds + = Files.newDirectoryStream(root, "*.jar")) { + for (Path p : ds) { + new ClassPathJarEntry(p, executor).process(); + if (isFinished()) { + return; + } + } + } catch (IOException ioe) { + ioe.printStackTrace(); + } + } +} + diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java new file mode 100644 index 00000000000..6f36d8b5c6d --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/ClassesListInFile.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.concurrent.Executor; + +/** + * Handler for files containing a list of classes to compile. + * + * @author igor.ignatyev@oracle.com + */ +public class ClassesListInFile extends PathHandler { + public ClassesListInFile(Path root, Executor executor) { + super(root, executor); + } + + @Override + public void process() { + System.out.println("# list: " + root); + if (!Files.exists(root)) { + return; + } + try { + try (BufferedReader reader = Files.newBufferedReader(root, + StandardCharsets.UTF_8)) { + String line; + while (!isFinished() && ((line = reader.readLine()) != null)) { + processClass(line); + } + } + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java new file mode 100644 index 00000000000..f1d46526d31 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/CompileTheWorld.java @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import sun.management.ManagementFactoryHelper; + +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Paths; + +import java.util.List; +import java.util.concurrent.*; + +/** + * @author igor.ignatyev@oracle.com + */ +public class CompileTheWorld { + /** + * Entry point. Compiles classes in {@code args}, or all classes in + * boot-classpath if args is empty + * + * @param args paths to jar/zip, dir contains classes, or to .lst file + * contains list of classes to compile + */ + public static void main(String[] args) { + String logfile = Utils.LOG_FILE; + PrintStream os = null; + if (logfile != null) { + try { + os = new PrintStream(Files.newOutputStream(Paths.get(logfile))); + } catch (IOException io) { + } + } + if (os != null) { + System.setOut(os); + } + + try { + try { + if (ManagementFactoryHelper.getCompilationMXBean() == null) { + throw new RuntimeException( + "CTW can not work in interpreted mode"); + } + } catch (java.lang.NoClassDefFoundError e) { + // compact1, compact2 support + } + String[] paths = args; + boolean skipRtJar = false; + if (args.length == 0) { + paths = getDefaultPaths(); + skipRtJar = true; + } + ExecutorService executor = createExecutor(); + long start = System.currentTimeMillis(); + try { + String path; + for (int i = 0, n = paths.length; i < n + && !PathHandler.isFinished(); ++i) { + path = paths[i]; + if (skipRtJar && i > 0 && isRtJar(path)) { + // rt.jar is not first, so skip it + continue; + } + PathHandler.create(path, executor).process(); + } + } finally { + await(executor); + } + System.out.printf("Done (%d classes, %d methods, %d ms)%n", + Compiler.getClassCount(), + Compiler.getMethodCount(), + System.currentTimeMillis() - start); + } finally { + if (os != null) { + os.close(); + } + } + } + + private static ExecutorService createExecutor() { + final int threadsCount = Math.min( + Runtime.getRuntime().availableProcessors(), + Utils.CI_COMPILER_COUNT); + ExecutorService result; + if (threadsCount > 1) { + result = new ThreadPoolExecutor(threadsCount, threadsCount, + /* keepAliveTime */ 0L, TimeUnit.MILLISECONDS, + new ArrayBlockingQueue<>(threadsCount), + new ThreadPoolExecutor.CallerRunsPolicy()); + } else { + result = new CurrentThreadExecutor(); + } + return result; + } + + private static String[] getDefaultPaths() { + String property = System.getProperty("sun.boot.class.path"); + System.out.println( + "# use 'sun.boot.class.path' as args: " + property); + return Utils.PATH_SEPARATOR.split(property); + } + + private static void await(ExecutorService executor) { + executor.shutdown(); + while (!executor.isTerminated()) { + try { + executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS); + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); + break; + } + } + } + + private static boolean isRtJar(String path) { + return Utils.endsWithIgnoreCase(path, File.separator + "rt.jar"); + } + + private static class CurrentThreadExecutor extends AbstractExecutorService { + private boolean isShutdown; + + @Override + public void shutdown() { + this.isShutdown = true; + } + + @Override + public List shutdownNow() { + return null; + } + + @Override + public boolean isShutdown() { + return isShutdown; + } + + @Override + public boolean isTerminated() { + return isShutdown; + } + + @Override + public boolean awaitTermination(long timeout, TimeUnit unit) + throws InterruptedException { + return isShutdown; + } + + @Override + public void execute(Runnable command) { + command.run(); + } + } +} + diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java new file mode 100644 index 00000000000..ccb2d3ae53a --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Compiler.java @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import sun.hotspot.WhiteBox; +import sun.misc.SharedSecrets; +import sun.reflect.ConstantPool; + +import java.lang.reflect.Executable; + +import java.util.Objects; +import java.util.concurrent.Executor; +import java.util.concurrent.atomic.AtomicLong; + +/** + * Provide method to compile whole class. + * Also contains compiled methods and classes counters. + * + * @author igor.ignatyev@oracle.com + */ +public class Compiler { + private Compiler() { } + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + private static final AtomicLong CLASS_COUNT = new AtomicLong(0L); + private static final AtomicLong METHOD_COUNT = new AtomicLong(0L); + private static volatile boolean CLASSES_LIMIT_REACHED = false; + + /** + * @return count of processed classes + */ + public static long getClassCount() { + return CLASS_COUNT.get(); + } + + /** + * @return count of processed methods + */ + public static long getMethodCount() { + return METHOD_COUNT.get(); + } + + /** + * @return {@code true} if classes limit is reached + */ + public static boolean isLimitReached() { + return CLASSES_LIMIT_REACHED; + } + + /** + * Compiles all methods and constructors. + * + * @param aClass class to compile + * @param executor executor used for compile task invocation + * @throws NullPointerException if {@code class} or {@code executor} + * is {@code null} + */ + public static void compileClass(Class aClass, Executor executor) { + Objects.requireNonNull(aClass); + Objects.requireNonNull(executor); + long id = CLASS_COUNT.incrementAndGet(); + if (id > Utils.COMPILE_THE_WORLD_STOP_AT) { + CLASS_COUNT.decrementAndGet(); + CLASSES_LIMIT_REACHED = true; + return; + } + + if (id >= Utils.COMPILE_THE_WORLD_START_AT) { + String name = aClass.getName(); + try { + System.out.printf("[%d]\t%s%n", id, name); + ConstantPool constantPool = SharedSecrets.getJavaLangAccess(). + getConstantPool(aClass); + if (Utils.COMPILE_THE_WORLD_PRELOAD_CLASSES) { + preloadClasses(name, id, constantPool); + } + long methodCount = 0; + for (Executable e : aClass.getDeclaredConstructors()) { + ++methodCount; + executor.execute(new CompileMethodCommand(id, name, e)); + } + for (Executable e : aClass.getDeclaredMethods()) { + ++methodCount; + executor.execute(new CompileMethodCommand(id, name, e)); + } + METHOD_COUNT.addAndGet(methodCount); + + if (Utils.DEOPTIMIZE_ALL_CLASSES_RATE > 0 + && (id % Utils.DEOPTIMIZE_ALL_CLASSES_RATE == 0)) { + WHITE_BOX.deoptimizeAll(); + } + } catch (Throwable t) { + System.out.printf("[%d]\t%s\tskipping %s%n", id, name, t); + t.printStackTrace(); + } + } + } + + private static void preloadClasses(String className, long id, + ConstantPool constantPool) { + try { + for (int i = 0, n = constantPool.getSize(); i < n; ++i) { + try { + constantPool.getClassAt(i); + } catch (IllegalArgumentException ignore) { + } + } + } catch (Throwable t) { + System.out.printf("[%d]\t%s\tpreloading failed : %s%n", id, + className, t); + } + } + + + + /** + * Compilation of method. + * Will compile method on all available comp levels. + */ + private static class CompileMethodCommand implements Runnable { + private final long classId; + private final String className; + private final Executable method; + + /** + * @param classId id of class + * @param className name of class + * @param method compiled for compilation + */ + public CompileMethodCommand(long classId, String className, + Executable method) { + this.classId = classId; + this.className = className; + this.method = method; + } + + @Override + public final void run() { + int compLevel = Utils.INITIAL_COMP_LEVEL; + if (Utils.TIERED_COMPILATION) { + for (int i = compLevel; i <= Utils.TIERED_STOP_AT_LEVEL; ++i) { + WHITE_BOX.deoptimizeMethod(method); + compileMethod(method, i); + } + } else { + compileMethod(method, compLevel); + } + } + + private void waitCompilation() { + if (!Utils.BACKGROUND_COMPILATION) { + return; + } + final Object obj = new Object(); + synchronized (obj) { + for (int i = 0; + i < 10 && WHITE_BOX.isMethodQueuedForCompilation(method); + ++i) { + try { + obj.wait(1000); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + } + } + } + + private void compileMethod(Executable method, int compLevel) { + if (WHITE_BOX.isMethodCompilable(method, compLevel)) { + try { + WHITE_BOX.enqueueMethodForCompilation(method, compLevel); + waitCompilation(); + int tmp = WHITE_BOX.getMethodCompilationLevel(method); + if (tmp != compLevel) { + logMethod(method, "compilation level = " + tmp + + ", but not " + compLevel); + } else if (Utils.IS_VERBOSE) { + logMethod(method, "compilation level = " + tmp + ". OK"); + } + } catch (Throwable t) { + logMethod(method, "error on compile at " + compLevel + + " level"); + t.printStackTrace(); + } + } else if (Utils.IS_VERBOSE) { + logMethod(method, "not compilable at " + compLevel); + } + } + + private void logMethod(Executable method, String message) { + StringBuilder builder = new StringBuilder("["); + builder.append(classId); + builder.append("]\t"); + builder.append(className); + builder.append("::"); + builder.append(method.getName()); + builder.append('('); + Class[] params = method.getParameterTypes(); + for (int i = 0, n = params.length - 1; i < n; ++i) { + builder.append(params[i].getName()); + builder.append(", "); + } + if (params.length != 0) { + builder.append(params[params.length - 1].getName()); + } + builder.append(')'); + if (message != null) { + builder.append('\t'); + builder.append(message); + } + System.err.println(builder); + } + } + +} diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java new file mode 100644 index 00000000000..5c284f896a8 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/PathHandler.java @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.io.File; + +import java.util.Objects; +import java.util.regex.Pattern; +import java.util.regex.Matcher; +import java.util.concurrent.Executor; + +/** + * Abstract handler for path. + *

    + * Concrete subclasses should implement method {@link #process()}. + * + * @author igor.ignatyev@oracle.com + */ +public abstract class PathHandler { + private static final Pattern JAR_IN_DIR_PATTERN + = Pattern.compile("^(.*[/\\\\])?\\*$"); + protected final Path root; + protected final Executor executor; + private ClassLoader loader; + + /** + * @param root root path to process + * @param executor executor used for process task invocation + * @throws NullPointerException if {@code root} or {@code executor} is + * {@code null} + */ + protected PathHandler(Path root, Executor executor) { + Objects.requireNonNull(root); + Objects.requireNonNull(executor); + this.root = root.normalize(); + this.executor = executor; + this.loader = ClassLoader.getSystemClassLoader(); + } + + /** + * Factory method. Construct concrete handler in depends from {@code path}. + * + * @param path the path to process + * @param executor executor used for compile task invocation + * @throws NullPointerException if {@code path} or {@code executor} is + * {@code null} + */ + public static PathHandler create(String path, Executor executor) { + Objects.requireNonNull(path); + Objects.requireNonNull(executor); + Matcher matcher = JAR_IN_DIR_PATTERN.matcher(path); + if (matcher.matches()) { + path = matcher.group(1); + path = path.isEmpty() ? "." : path; + return new ClassPathJarInDirEntry(Paths.get(path), executor); + } else { + path = path.isEmpty() ? "." : path; + Path p = Paths.get(path); + if (isJarFile(p)) { + return new ClassPathJarEntry(p, executor); + } else if (isListFile(p)) { + return new ClassesListInFile(p, executor); + } else { + return new ClassPathDirEntry(p, executor); + } + } + } + + private static boolean isJarFile(Path path) { + if (Files.isRegularFile(path)) { + String name = path.toString(); + return Utils.endsWithIgnoreCase(name, ".zip") + || Utils.endsWithIgnoreCase(name, ".jar"); + } + return false; + } + + private static boolean isListFile(Path path) { + if (Files.isRegularFile(path)) { + String name = path.toString(); + return Utils.endsWithIgnoreCase(name, ".lst"); + } + return false; + } + + /** + * Processes all classes in specified path. + */ + public abstract void process(); + + /** + * Sets class loader, that will be used to define class at + * {@link #processClass(String)}. + * + * @param loader class loader + * @throws NullPointerException if {@code loader} is {@code null} + */ + protected final void setLoader(ClassLoader loader) { + Objects.requireNonNull(loader); + this.loader = loader; + } + + /** + * Processes specificed class. + * @param name fully qualified name of class to process + */ + protected final void processClass(String name) { + try { + Class aClass = Class.forName(name, true, loader); + Compiler.compileClass(aClass, executor); + } catch (ClassNotFoundException | LinkageError e) { + System.out.printf("Class %s loading failed : %s%n", name, + e.getMessage()); + } + } + + /** + * @return {@code true} if processing should be stopped + */ + public static boolean isFinished() { + return Compiler.isLimitReached(); + } + +} + diff --git a/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java new file mode 100644 index 00000000000..5ffd06cee8b --- /dev/null +++ b/hotspot/test/testlibrary/ctw/src/sun/hotspot/tools/ctw/Utils.java @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.hotspot.tools.ctw; + +import com.sun.management.HotSpotDiagnosticMXBean; +import sun.management.ManagementFactoryHelper; + +import java.io.File; +import java.util.regex.Pattern; + +/** + * Auxiliary methods. + * + * @author igor.ignatyev@oracle.com + */ +public class Utils { + /** + * Value of {@code -XX:CompileThreshold} + */ + public static final boolean TIERED_COMPILATION + = Boolean.parseBoolean(getVMOption("TieredCompilation", "false")); + /** + * Value of {@code -XX:BackgroundCompilation} + */ + public static final boolean BACKGROUND_COMPILATION + = Boolean.parseBoolean(getVMOption("BackgroundCompilation", + "false")); + /** + * Value of {@code -XX:TieredStopAtLevel} + */ + public static final int TIERED_STOP_AT_LEVEL; + /** + * Value of {@code -XX:CICompilerCount} + */ + public static final Integer CI_COMPILER_COUNT + = Integer.valueOf(getVMOption("CICompilerCount", "1")); + /** + * Initial compilation level. + */ + public static final int INITIAL_COMP_LEVEL; + /** + * Compiled path-separator regexp. + */ + public static final Pattern PATH_SEPARATOR = Pattern.compile( + File.pathSeparator, Pattern.LITERAL); + /** + * Value of {@code -DDeoptimizeAllClassesRate}. Frequency of + * {@code WB.deoptimizeAll()} invocation If it less that {@code 0}, + * {@code WB.deoptimizeAll()} will not be invoked. + */ + public static final int DEOPTIMIZE_ALL_CLASSES_RATE + = Integer.getInteger("DeoptimizeAllClassesRate", -1); + /** + * Value of {@code -DCompileTheWorldStopAt}. Last class to consider. + */ + public static final long COMPILE_THE_WORLD_STOP_AT + = Long.getLong("CompileTheWorldStopAt", Long.MAX_VALUE); + /** + * Value of {@code -DCompileTheWorldStartAt}. First class to consider. + */ + public static final long COMPILE_THE_WORLD_START_AT + = Long.getLong("CompileTheWorldStartAt", 1); + /** + * Value of {@code -DCompileTheWorldPreloadClasses}. Preload all classes + * used by a class before start loading. + */ + public static final boolean COMPILE_THE_WORLD_PRELOAD_CLASSES; + /** + * Value of {@code -Dsun.hotspot.tools.ctw.verbose}. Verbose output, + * adds additional information about compilation. + */ + public static final boolean IS_VERBOSE + = Boolean.getBoolean("sun.hotspot.tools.ctw.verbose"); + /** + * Value of {@code -Dsun.hotspot.tools.ctw.logfile}.Path to logfile, if + * it's null, cout will be used. + */ + public static final String LOG_FILE + = System.getProperty("sun.hotspot.tools.ctw.logfile"); + static { + if (Utils.TIERED_COMPILATION) { + INITIAL_COMP_LEVEL = 1; + } else { + String vmName = System.getProperty("java.vm.name"); + if (Utils.endsWithIgnoreCase(vmName, " Server VM")) { + INITIAL_COMP_LEVEL = 4; + } else if (Utils.endsWithIgnoreCase(vmName, " Client VM") + || Utils.endsWithIgnoreCase(vmName, " Minimal VM")) { + INITIAL_COMP_LEVEL = 1; + } else { + throw new RuntimeException("Unknown VM: " + vmName); + } + } + + TIERED_STOP_AT_LEVEL = Integer.parseInt(getVMOption("TieredStopAtLevel", + String.valueOf(INITIAL_COMP_LEVEL))); + } + + static { + String tmp = System.getProperty("CompileTheWorldPreloadClasses"); + if (tmp == null) { + COMPILE_THE_WORLD_PRELOAD_CLASSES = true; + } else { + COMPILE_THE_WORLD_PRELOAD_CLASSES = Boolean.parseBoolean(tmp); + } + } + + public static final String CLASSFILE_EXT = ".class"; + + private Utils() { + } + + /** + * Tests if the string ends with the suffix, ignoring case + * considerations + * + * @param string the tested string + * @param suffix the suffix + * @return {@code true} if {@code string} ends with the {@code suffix} + * @see String#endsWith(String) + */ + public static boolean endsWithIgnoreCase(String string, String suffix) { + if (string == null || suffix == null) { + return false; + } + int length = suffix.length(); + int toffset = string.length() - length; + if (toffset < 0) { + return false; + } + return string.regionMatches(true, toffset, suffix, 0, length); + } + + /** + * Returns value of VM option. + * + * @param name option's name + * @return value of option or {@code null}, if option doesn't exist + * @throws NullPointerException if name is null + */ + public static String getVMOption(String name) { + String result; + HotSpotDiagnosticMXBean diagnostic + = ManagementFactoryHelper.getDiagnosticMXBean(); + result = diagnostic.getVMOption(name).getValue(); + return result; + } + + /** + * Returns value of VM option or default value. + * + * @param name option's name + * @param defaultValue default value + * @return value of option or {@code defaultValue}, if option doesn't exist + * @throws NullPointerException if name is null + * @see #getVMOption(String) + */ + public static String getVMOption(String name, String defaultValue) { + String result; + try { + result = getVMOption(name); + } catch (NoClassDefFoundError e) { + // compact1, compact2 support + result = defaultValue; + } + return result == null ? defaultValue : result; + } + + /** + * Tests if the filename is valid filename for class file. + * + * @param filename tested filename + */ + public static boolean isClassFile(String filename) { + // If the filename has a period after removing '.class', it's not valid class file + return endsWithIgnoreCase(filename, CLASSFILE_EXT) + && (filename.indexOf('.') + == (filename.length() - CLASSFILE_EXT.length())); + } + + /** + * Converts the filename to classname. + * + * @param filename filename to convert + * @return corresponding classname. + * @throws AssertionError if filename isn't valid filename for class file - + * {@link #isClassFile(String)} + */ + public static String fileNameToClassName(String filename) { + assert isClassFile(filename); + return filename.substring(0, filename.length() - CLASSFILE_EXT.length()) + .replace(File.separatorChar, '.'); + } +} diff --git a/hotspot/test/testlibrary/ctw/test/Bar.java b/hotspot/test/testlibrary/ctw/test/Bar.java new file mode 100644 index 00000000000..9b0324555f8 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/Bar.java @@ -0,0 +1,5 @@ +public class Bar { + private static void staticMethod() { } + public void method() { } + protected Bar() { } +} diff --git a/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java b/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java new file mode 100644 index 00000000000..ae5eaf0f2e4 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/ClassesDirTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test ClassesDirTest + * @bug 8012447 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesDirTest Foo Bar + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * @run main ClassesDirTest prepare + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes + * @run main ClassesDirTest check ctw.log + * @summary testing of CompileTheWorld :: classes in directory + * @author igor.ignatyev@oracle.com + */ + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +public class ClassesDirTest extends CtwTest { + private static final String[] SHOULD_CONTAIN + = {"# dir: classes", "Done (2 classes, 6 methods, "}; + + private ClassesDirTest() { + super(SHOULD_CONTAIN); + } + + public static void main(String[] args) throws Exception { + new ClassesDirTest().run(args); + } + + protected void prepare() throws Exception { + String path = "classes"; + Files.createDirectory(Paths.get(path)); + Files.move(Paths.get("Foo.class"), Paths.get(path, "Foo.class"), + StandardCopyOption.REPLACE_EXISTING); + Files.move(Paths.get("Bar.class"), Paths.get(path, "Bar.class"), + StandardCopyOption.REPLACE_EXISTING); + } +} diff --git a/hotspot/test/testlibrary/ctw/test/ClassesListTest.java b/hotspot/test/testlibrary/ctw/test/ClassesListTest.java new file mode 100644 index 00000000000..a98cd53a3f6 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/ClassesListTest.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test ClassesListTest + * @bug 8012447 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox ClassesListTest Foo Bar + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * @run main ClassesListTest prepare + * @run main/othervm/timeout=600 -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld classes.lst + * @run main ClassesListTest check ctw.log + * @summary testing of CompileTheWorld :: list of classes in file + * @author igor.ignatyev@oracle.com + */ + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; + +public class ClassesListTest extends CtwTest { + private static final String[] SHOULD_CONTAIN + = {"# list: classes.lst", "Done (4 classes, "}; + + private ClassesListTest() { + super(SHOULD_CONTAIN); + } + + public static void main(String[] args) throws Exception { + new ClassesListTest().run(args); + } + + protected void prepare() throws Exception { + String path = "classes.lst"; + Files.copy(Paths.get(System.getProperty("test.src"), path), + Paths.get(path), StandardCopyOption.REPLACE_EXISTING); + } +} diff --git a/hotspot/test/testlibrary/ctw/test/CtwTest.java b/hotspot/test/testlibrary/ctw/test/CtwTest.java new file mode 100644 index 00000000000..ecc9c59c13a --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/CtwTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.List; +import java.util.Collections; +import java.util.ArrayList; + +import java.io.File; +import java.io.Writer; +import java.io.FileWriter; +import java.io.IOException; +import java.io.BufferedReader; + +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.nio.charset.Charset; + +import com.oracle.java.testlibrary.JDKToolFinder; +import com.oracle.java.testlibrary.OutputAnalyzer; + +public abstract class CtwTest { + protected final String[] shouldContain; + protected CtwTest(String[] shouldContain) { + this.shouldContain = shouldContain; + } + + public void run(String[] args) throws Exception { + if (args.length == 0) { + throw new Error("args is empty"); + } + switch (args[0]) { + case "prepare": + prepare(); + break; + case "check": + check(args); + break; + default: + throw new Error("unregonized action -- " + args[0]); + } + } + + protected void prepare() throws Exception { } + + protected void check(String[] args) throws Exception { + if (args.length < 2) { + throw new Error("logfile isn't specified"); + } + String logfile = args[1]; + try (BufferedReader r = Files.newBufferedReader(Paths.get(logfile), + Charset.defaultCharset())) { + OutputAnalyzer output = readOutput(r); + for (String test : shouldContain) { + output.shouldContain(test); + } + } + } + + private static OutputAnalyzer readOutput(BufferedReader reader) + throws IOException { + StringBuilder builder = new StringBuilder(); + String eol = String.format("%n"); + String line; + + while ((line = reader.readLine()) != null) { + builder.append(line); + builder.append(eol); + } + return new OutputAnalyzer(builder.toString(), ""); + } + + protected void dump(OutputAnalyzer output, String name) { + try (Writer w = new FileWriter(name + ".out")) { + String s = output.getStdout(); + w.write(s, s.length(), 0); + } catch (IOException io) { + io.printStackTrace(); + } + try (Writer w = new FileWriter(name + ".err")) { + String s = output.getStderr(); + w.write(s, s.length(), 0); + } catch (IOException io) { + io.printStackTrace(); + } + } + + protected ProcessBuilder createJarProcessBuilder(String... command) + throws Exception { + String javapath = JDKToolFinder.getJDKTool("jar"); + + ArrayList args = new ArrayList<>(); + args.add(javapath); + Collections.addAll(args, command); + + return new ProcessBuilder(args.toArray(new String[args.size()])); + } +} diff --git a/hotspot/test/testlibrary/ctw/test/Foo.java b/hotspot/test/testlibrary/ctw/test/Foo.java new file mode 100644 index 00000000000..07d8f4643ce --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/Foo.java @@ -0,0 +1,5 @@ +public class Foo { + private static void staticMethod() { } + public void method() { } + protected Foo() { } +} diff --git a/hotspot/test/testlibrary/ctw/test/JarDirTest.java b/hotspot/test/testlibrary/ctw/test/JarDirTest.java new file mode 100644 index 00000000000..76f682fd755 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/JarDirTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test JarDirTest + * @bug 8012447 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarDirTest Foo Bar + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * @run main JarDirTest prepare + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld jars/* + * @run main JarDirTest check ctw.log + * @summary testing of CompileTheWorld :: jars in directory + * @author igor.ignatyev@oracle.com + */ + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class JarDirTest extends CtwTest { + private static final String[] SHOULD_CONTAIN + = {"# jar_in_dir: jars", + "# jar: jars" + File.separator +"foo.jar", + "# jar: jars" + File.separator +"bar.jar", + "Done (4 classes, 12 methods, "}; + + private JarDirTest() { + super(SHOULD_CONTAIN); + } + + public static void main(String[] args) throws Exception { + new JarDirTest().run(args); + } + + protected void prepare() throws Exception { + String path = "jars"; + Files.createDirectory(Paths.get(path)); + + ProcessBuilder pb = createJarProcessBuilder("cf", "jars/foo.jar", + "Foo.class", "Bar.class"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + dump(output, "ctw-foo.jar"); + output.shouldHaveExitValue(0); + + pb = createJarProcessBuilder("cf", "jars/bar.jar", "Foo.class", + "Bar.class"); + output = new OutputAnalyzer(pb.start()); + dump(output, "ctw-bar.jar"); + output.shouldHaveExitValue(0); + } + +} diff --git a/hotspot/test/testlibrary/ctw/test/JarsTest.java b/hotspot/test/testlibrary/ctw/test/JarsTest.java new file mode 100644 index 00000000000..04792729f4e --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/JarsTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test JarsTest + * @bug 8012447 + * @library /testlibrary /testlibrary/whitebox /testlibrary/ctw/src + * @build sun.hotspot.tools.ctw.CompileTheWorld sun.hotspot.WhiteBox JarsTest Foo Bar + * @run main ClassFileInstaller sun.hotspot.WhiteBox Foo Bar + * @run main JarsTest prepare + * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Dsun.hotspot.tools.ctw.logfile=ctw.log sun.hotspot.tools.ctw.CompileTheWorld foo.jar bar.jar + * @run main JarsTest check ctw.log + * @summary testing of CompileTheWorld :: jars + * @author igor.ignatyev@oracle.com + */ + +import com.oracle.java.testlibrary.OutputAnalyzer; + +public class JarsTest extends CtwTest { + private static final String[] SHOULD_CONTAIN + = {"# jar: foo.jar", "# jar: bar.jar", + "Done (4 classes, 12 methods, "}; + + private JarsTest() { + super(SHOULD_CONTAIN); + } + + public static void main(String[] args) throws Exception { + new JarsTest().run(args); + } + + protected void prepare() throws Exception { + ProcessBuilder pb = createJarProcessBuilder("cf", "foo.jar", + "Foo.class", "Bar.class"); + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + dump(output, "ctw-foo.jar"); + output.shouldHaveExitValue(0); + + pb = createJarProcessBuilder("cf", "bar.jar", "Foo.class", "Bar.class"); + output = new OutputAnalyzer(pb.start()); + dump(output, "ctw-bar.jar"); + output.shouldHaveExitValue(0); + } + +} diff --git a/hotspot/test/testlibrary/ctw/test/classes.lst b/hotspot/test/testlibrary/ctw/test/classes.lst new file mode 100644 index 00000000000..044c029e783 --- /dev/null +++ b/hotspot/test/testlibrary/ctw/test/classes.lst @@ -0,0 +1,4 @@ +java.lang.String +java.lang.Object +Foo +Bar diff --git a/hotspot/test/testlibrary/whitebox/Makefile b/hotspot/test/testlibrary/whitebox/Makefile new file mode 100644 index 00000000000..8a84a0a4492 --- /dev/null +++ b/hotspot/test/testlibrary/whitebox/Makefile @@ -0,0 +1,63 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +# + +ifneq "x$(ALT_BOOTDIR)" "x" + BOOTDIR := $(ALT_BOOTDIR) +endif + +ifeq "x$(BOOTDIR)" "x" + JDK_HOME := $(shell dirname $(shell which java))/.. +else + JDK_HOME := $(BOOTDIR) +endif + +SRC_DIR = ./ +BUILD_DIR = build +OUTPUT_DIR = $(BUILD_DIR)/classes + +JAVAC = $(JDK_HOME)/bin/javac +JAR = $(JDK_HOME)/bin/jar + +SRC_FILES = $(shell find $(SRC_DIR) -name '*.java') + +.PHONY: filelist clean cleantmp + +all: wb.jar cleantmp + +wb.jar: filelist + @mkdir -p $(OUTPUT_DIR) + $(JAVAC) -sourcepath $(SRC_DIR) -d $(OUTPUT_DIR) -cp $(OUTPUT_DIR) @filelist + $(JAR) cf wb.jar -C $(OUTPUT_DIR) . + @rm -rf $(OUTPUT_DIR) + +filelist: $(SRC_FILES) + @rm -f $@ + @echo $(SRC_FILES) > $@ + +clean: cleantmp + @rm -rf wb.jar + +cleantmp: + @rm -rf filelist + @rm -rf $(BUILD_DIR) diff --git a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java index c508b8f121a..091b5f7543b 100644 --- a/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java +++ b/hotspot/test/testlibrary/whitebox/sun/hotspot/WhiteBox.java @@ -61,6 +61,8 @@ public class WhiteBox { registerNatives(); } + // Get the maximum heap size supporting COOPs + public native long getCompressedOopsMaxHeapSize(); // Arguments public native void printHeapSizes(); diff --git a/jaxp/.hgtags b/jaxp/.hgtags index e21e3e57573..bb0b1c00ce9 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -228,3 +228,6 @@ b1ceab582fc6d795b20aaa8a3fde2eba34af9399 jdk8-b103 a22fe9bd01e6c7e7ddc7995dfc9471711692b8d1 jdk8-b104 09a46ec11f880154886c70be03aff5ab2ddf0ab7 jdk8-b105 d3be8e3b429df917e72c1c23e7920c651219b587 jdk8-b106 +d6a32e3831aab20a9a3bc78cdc0a60aaad725c6c jdk8-b107 +8ade3eed63da87067a7137c111f684a821e9e531 jdk8-b108 +02bfab2aa93899e0f02584f1e85537485a196553 jdk8-b109 diff --git a/jaxp/make/jprt.properties b/jaxp/make/jprt.properties index 360b6b22dba..b03c53ca656 100644 --- a/jaxp/make/jprt.properties +++ b/jaxp/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,8 @@ jprt.build.targets= \ solaris_x64_5.10-{product|fastdebug}, \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # Directories to be excluded from the source bundles jprt.bundle.exclude.src.dirs=build dist webrev diff --git a/jaxws/.hgtags b/jaxws/.hgtags index d213728514a..75a5d5b556a 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -228,3 +228,6 @@ b1fb4612a2caea52b5661b87509e560fa044b194 jdk8-b98 42211ab0ab1cca51a050d184634cf1db7ef81fbf jdk8-b104 88390df7ed2cf128298a02c5e6d978f0a603cd58 jdk8-b105 6908370afe834ff01739e8ec992d4246c74b7e6e jdk8-b106 +e3c9328f75638289a342ce15fbe532f05078946e jdk8-b107 +d1ea68556fd7925a3c7078dd9f77c6ca73d5aa9e jdk8-b108 +df5d4d01642572e77fd3c01e4c8703ed3f6eec87 jdk8-b109 diff --git a/jaxws/make/jprt.properties b/jaxws/make/jprt.properties index 91064331043..12ce773022a 100644 --- a/jaxws/make/jprt.properties +++ b/jaxws/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -40,8 +40,8 @@ jprt.build.targets= \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ macosx_x64_10.7-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # Directories to be excluded from the source bundles jprt.bundle.exclude.src.dirs=build dist webrev diff --git a/jdk/.hgtags b/jdk/.hgtags index 3e3a625970b..cdae1de11aa 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -229,3 +229,6 @@ f1d8d15bfcb5ada858a942f8a31f6598f23214d1 jdk8-b104 1fe211ae3d2b8cc2dfc4f58d9a6eb96418679672 jdk8-b105 c817276bd870dfe1dcc3a3dbbc092436b6907f75 jdk8-b106 eea685b9ccaa1980e0a7e07d6a3a84bcc7e9ab82 jdk8-b107 +006aaa5f069e7dd98fccdc696866c9f8582c087c jdk8-b108 +946f3fd5f8bf0ccd180c258d25e5837fa1bf004c jdk8-b109 +54e099776f08430d3a7f4feabd9f2ba886b55320 jdk8-b110 diff --git a/jdk/make/Makefile b/jdk/make/Makefile index c2db5a816a2..e82edd7271f 100644 --- a/jdk/make/Makefile +++ b/jdk/make/Makefile @@ -99,7 +99,6 @@ COMPILER_PATH.desc = Compiler install directory CACERTS_FILE.desc = Location of certificates file DEVTOOLS_PATH.desc = Directory containing zip and unzip CUPS_HEADERS_PATH.desc = Include directory location for CUPS header files -DXSDK_PATH.desc = Root directory of DirectX SDK # Make variables to print out (description and value) VARIABLE_PRINTVAL_LIST += \ @@ -128,17 +127,6 @@ VARIABLE_CHECKDIR_LIST += \ VARIABLE_CHECKFIL_LIST += \ CACERTS_FILE -# Some are windows specific -ifeq ($(PLATFORM), windows) - -VARIABLE_PRINTVAL_LIST += \ - DXSDK_PATH - -VARIABLE_CHECKDIR_LIST += \ - DXSDK_PATH - -endif - # For pattern rules below, so all are treated the same DO_PRINTVAL_LIST=$(VARIABLE_PRINTVAL_LIST:%=%.printval) DO_CHECKDIR_LIST=$(VARIABLE_CHECKDIR_LIST:%=%.checkdir) diff --git a/jdk/make/bridge/AccessBridgeJava/Makefile b/jdk/make/bridge/AccessBridgeJava/Makefile index c5bebd02cea..bbba630996b 100644 --- a/jdk/make/bridge/AccessBridgeJava/Makefile +++ b/jdk/make/bridge/AccessBridgeJava/Makefile @@ -1,5 +1,5 @@ # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -51,7 +51,7 @@ endif # # Java files to compile. # -FILES_java = com/sun/java/accessibility/AccessBridge.java +FILES_java = com/sun/java/accessibility/AccessBridgeLoader.java com/sun/java/accessibility/AccessBridge.java # # Location for the newly built classfiles. @@ -61,14 +61,13 @@ CLASSDESTDIR = $(TEMPDIR)/classes # # Rules # -CLASSDESTDIR = $(TEMPDIR)/classes FILES_class = $(FILES_java:%.java=$(CLASSDESTDIR)/%.class) build: prebuild prebuild: - $(CP) $(CLOSED_PLATFORM_SRC)/classes/com/sun/java/accessibility/$(ABPLATFORM)/AccessBridge.java \ + $(CP) $(CLOSED_PLATFORM_SRC)/classes/com/sun/java/accessibility/$(ABPLATFORM)/AccessBridgeLoader.java \ $(CLOSED_PLATFORM_SRC)/classes/com/sun/java/accessibility all : build $(JARFILE) diff --git a/jdk/make/common/Defs-macosx.gmk b/jdk/make/common/Defs-macosx.gmk index 1b7aaa8ae20..befd2cfed5b 100644 --- a/jdk/make/common/Defs-macosx.gmk +++ b/jdk/make/common/Defs-macosx.gmk @@ -397,12 +397,10 @@ else INCLUDE_SA = true endif -ifdef CROSS_COMPILE_ARCH - # X11 headers are not under /usr/include - OTHER_CFLAGS += -I$(OPENWIN_HOME)/include - OTHER_CXXFLAGS += -I$(OPENWIN_HOME)/include - OTHER_CPPFLAGS += -I$(OPENWIN_HOME)/include -endif +# X11 headers are not under /usr/include +OTHER_CFLAGS += -I$(OPENWIN_HOME)/include +OTHER_CXXFLAGS += -I$(OPENWIN_HOME)/include +OTHER_CPPFLAGS += -I$(OPENWIN_HOME)/include LIB_LOCATION ?= $(LIBDIR) diff --git a/jdk/make/common/Defs-windows.gmk b/jdk/make/common/Defs-windows.gmk index c5c15b3d387..ef2c4aeab6f 100644 --- a/jdk/make/common/Defs-windows.gmk +++ b/jdk/make/common/Defs-windows.gmk @@ -78,8 +78,6 @@ ifeq ($(COMPILER_VERSION), VS2010) MS_RUNTIME_LIBRARIES = $(MSVCRNN_DLL) endif -EXTRA_LFLAGS += -LIBPATH:$(DXSDK_LIB_PATH) - # Full Debug Symbols has been enabled on Windows since JDK1.4.1. # The Full Debug Symbols (FDS) default for VARIANT == OPT builds is # enabled with debug info files ZIP'ed to save space. For VARIANT != diff --git a/jdk/make/common/Sanity.gmk b/jdk/make/common/Sanity.gmk index 25f5fa7bfe8..233abeacabb 100644 --- a/jdk/make/common/Sanity.gmk +++ b/jdk/make/common/Sanity.gmk @@ -65,7 +65,6 @@ sanity-base: pre-sanity \ sane-libCrun \ sane-unixccs_path \ sane-msdevtools_path \ - sane-dxsdk \ sane-compiler \ sane-cacerts \ sane-ant_version \ diff --git a/jdk/make/common/shared/Defs-versions.gmk b/jdk/make/common/shared/Defs-versions.gmk index 8a60563c122..a3a53c5c048 100644 --- a/jdk/make/common/shared/Defs-versions.gmk +++ b/jdk/make/common/shared/Defs-versions.gmk @@ -74,9 +74,6 @@ endif # REQUIRED_CYGWIN_VER # Windows only: If CYGWIN is used, the minimum CYGWIN version. # -# REQUIRED_DXSDK_VER -# Windows only: The version of DirectX SDK expected. -# # REQUIRED_FREETYPE_VERSION # If we are using freetype, the freetype version expected. # @@ -193,7 +190,6 @@ ifeq ($(PLATFORM), windows) REQUIRED_OS_VARIANT_VERSION = $(REQUIRED_OS_VERSION) REQUIRED_CYGWIN_VER = 4.0 REQUIRED_MKS_VER = 6.1 - REQUIRED_DXSDK_VER = 0x0900 ifeq ($(CC_VERSION),msvc) REQUIRED_COMPILER_NAME = Visual Studio 10 REQUIRED_COMPILER_VERSION = VS2010 diff --git a/jdk/make/common/shared/Defs-windows.gmk b/jdk/make/common/shared/Defs-windows.gmk index 40415547d71..d46d884cc05 100644 --- a/jdk/make/common/shared/Defs-windows.gmk +++ b/jdk/make/common/shared/Defs-windows.gmk @@ -79,7 +79,7 @@ override INCREMENTAL_BUILD = false # The ALT values should never really have spaces or use \. # Suspect these environment variables to have spaces and/or \ characters: # SYSTEMROOT, SystemRoot, WINDIR, windir, PROGRAMFILES, ProgramFiles, -# DXSDK_DIR, MSTOOLS, Mstools, MSSDK, MSSdk, VCnnCOMNTOOLS, +# MSTOOLS, Mstools, MSSDK, MSSdk, VCnnCOMNTOOLS, # MSVCDIR, MSVCDir. # So use $(subst \,/,) on them first adding quotes and placing them in # their own variable assigned with :=, then use FullPath. @@ -255,18 +255,6 @@ ifneq ($(word 1,$(_program_files)),$(_program_files)) _program_files:= endif -# DirectX SDK -ifdef ALT_DXSDK_DRIVE - _dx_sdk_dir =$(ALT_DXSDK_DRIVE):/DXSDK -else - ifdef DXSDK_DIR - xDXSDK_DIR :="$(subst \,/,$(DXSDK_DIR))" - else - xDXSDK_DIR :="$(_system_drive)/DXSDK" - endif - _dx_sdk_dir :=$(call FullPath,$(xDXSDK_DIR)) -endif - # Use of the Visual Studio compilers requires certain env variables be set: # PATH should include the path to cl.exe # INCLUDE should be defined @@ -489,39 +477,6 @@ ifeq ($(_NEEDS_MSVCRNN), true) MSVCRNN_DLL_PATH:=$(call AltCheckValue,MSVCRNN_DLL_PATH) endif -# DXSDK_PATH: path to Microsoft DirectX SDK Include and Lib -ifdef ALT_DXSDK_PATH - xALT_DXSDK_PATH :="$(subst \,/,$(ALT_DXSDK_PATH))" - DXSDK_PATH :=$(call FullPath,$(xALT_DXSDK_PATH)) -else - _DXSDK_PATH1 :=$(_dx_sdk_dir) - _DXSDK_PATH2 :=$(JDK_DEVTOOLS_DIR)/windows/dxsdk - DXSDK_PATH :=$(call DirExists,$(_DXSDK_PATH1),$(_DXSDK_PATH2),$(_dx_sdk_dir)) -endif -DXSDK_PATH :=$(call AltCheckSpaces,DXSDK_PATH) -DXSDK_PATH:=$(call AltCheckValue,DXSDK_PATH) - -# DXSDK_INCLUDE_PATH: path to Microsoft DirectX SDK Include -ifdef ALT_DXSDK_INCLUDE_PATH - xALT_DXSDK_INCLUDE_PATH :="$(subst \,/,$(ALT_DXSDK_INCLUDE_PATH))" - DXSDK_INCLUDE_PATH :=$(call FullPath,$(xALT_DXSDK_INCLUDE_PATH)) -else - DXSDK_INCLUDE_PATH =$(subst //,/,$(DXSDK_PATH)/Include) -endif - -# DXSDK_LIB_PATH: path to Microsoft DirectX SDK Lib -ifdef ALT_DXSDK_LIB_PATH - xALT_DXSDK_LIB_PATH :="$(subst \,/,$(ALT_DXSDK_LIB_PATH))" - DXSDK_LIB_PATH :=$(call FullPath,$(xALT_DXSDK_LIB_PATH)) -else - ifeq ($(ARCH_DATA_MODEL), 64) - # 64bit libs are located in "Lib/x64" subdir - DXSDK_LIB_PATH =$(subst //,/,$(DXSDK_PATH)/Lib/x64) - else - DXSDK_LIB_PATH =$(subst //,/,$(DXSDK_PATH)/Lib) - endif -endif - # DEPLOY_MSSDK: Microsoft SDK for this platform (for deploy) ifdef ALT_DEPLOY_MSSDK xALT_DEPLOY_MSSDK :="$(subst \,/,$(ALT_DEPLOY_MSSDK))" diff --git a/jdk/make/common/shared/Sanity-Settings.gmk b/jdk/make/common/shared/Sanity-Settings.gmk index ea32eeadcaa..2ceef21e13e 100644 --- a/jdk/make/common/shared/Sanity-Settings.gmk +++ b/jdk/make/common/shared/Sanity-Settings.gmk @@ -234,10 +234,6 @@ endif ALL_SETTINGS+=$(call addAltSetting,HOTSPOT_SERVER_PATH) ifeq ($(PLATFORM),windows) ALL_SETTINGS+=$(call addAltSetting,HOTSPOT_LIB_PATH) - ALL_SETTINGS+=$(call addRequiredSetting,DXSDK_VER) - ALL_SETTINGS+=$(call addAltSetting,DXSDK_PATH) - ALL_SETTINGS+=$(call addAltSetting,DXSDK_INCLUDE_PATH) - ALL_SETTINGS+=$(call addAltSetting,DXSDK_LIB_PATH) ALL_SETTINGS+=$(call addAltSetting,WINDOWSSDKDIR) ALL_SETTINGS+=$(call addRequiredSetting,RC) ALL_SETTINGS+=$(call addRequiredSetting,REBASE) diff --git a/jdk/make/common/shared/Sanity.gmk b/jdk/make/common/shared/Sanity.gmk index c4a96d73c5f..a9f4692064a 100644 --- a/jdk/make/common/shared/Sanity.gmk +++ b/jdk/make/common/shared/Sanity.gmk @@ -143,8 +143,6 @@ ifeq ($(PLATFORM), windows) _CYGWIN_VER := $(SYSTEM_UNAME) CYGWIN_VER :=$(call GetVersion,$(_CYGWIN_VER)) endif - DXSDK_VER := $(shell $(EGREP) DIRECT3D_VERSION $(DXSDK_INCLUDE_PATH)/d3d9.h 2>&1 | \ - $(EGREP) "\#define" | $(NAWK) '{print $$3}') endif # Get the version numbers of what we are using @@ -1300,51 +1298,6 @@ sane-unzip_version: "" >> $(WARNING_FILE) ; \ fi -###################################################### -# Check for windows DirectX sdk directory -###################################################### -sane-dxsdk: -ifeq ($(PLATFORM), windows) - @if [ ! -r $(DXSDK_INCLUDE_PATH)/d3d9.h ]; then \ - $(ECHO) "ERROR: You do not have access to a valid DirectX SDK Include dir.\n" \ - " The value of DXSDK_INCLUDE_PATH must point a valid DX SDK dir.\n" \ - " Please check your access to \n" \ - " $(DXSDK_INCLUDE_PATH) \n" \ - " and/or check your value of ALT_DXSDK_PATH or ALT_DXSDK_INCLUDE_PATH.\n" \ - " Microsoft DirectX 9 SDK (Summer 2004 Update or newer) can be downloaded from the following location:\n" \ - " http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp\n" \ - " Or http://www.microsoft.com/directx\n" \ - "" >> $(ERROR_FILE) ; \ - else \ - if [ ! "$(DXSDK_VER)" = "$(REQUIRED_DXSDK_VER)" ]; then \ - $(ECHO) "ERROR: The DirectX SDK must be version $(REQUIRED_DXSDK_VER).\n" \ - " $(YOU_ARE_USING) DirectX SDK version: $(DXSDK_VER)\n" \ - " The DirectX SDK was obtained from the following location: \n" \ - " $(DXSDK_PATH) \n" \ - " Please change your DirectX SDK. \n" \ - " Microsoft DirectX 9 SDK (Summer 2004 Update or newer) can be downloaded from the following location:\n" \ - " http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp\n" \ - " Or http://www.microsoft.com/directx\n" \ - "" >> $(ERROR_FILE) ; \ - else \ - if [ -r $(DXSDK_INCLUDE_PATH)/basetsd.h ]; then \ - if [ `$(EGREP) -c __int3264 $(DXSDK_INCLUDE_PATH)/basetsd.h` -ne 0 ]; then \ - $(ECHO) "WARNING: The DirectX SDK Include directory contains a newer basetsd.h,\n" \ - " which may indicate that you're using an incorrect version of DirectX SDK.\n" \ - " This may result in a build failure.\n" \ - " The DirectX SDK Include dir was obtained from the following location:\n" \ - " $(DXSDK_INCLUDE_PATH) \n" \ - " Please change your DirectX SDK to version 9 (Summer 2004 Update or newer).\n" \ - " Microsoft DirectX 9 SDK can be downloaded from the following location:\n" \ - " http://msdn.microsoft.com/library/default.asp?url=/downloads/list/directx.asp\n" \ - " Or http://www.microsoft.com/directx\n" \ - "" >> $(WARNING_FILE) ; \ - fi \ - fi \ - fi \ - fi -endif - ###################################################### # Check the linker version(s) ###################################################### diff --git a/jdk/make/java/java/Makefile b/jdk/make/java/java/Makefile index 829cf933001..d2a663f9ae0 100644 --- a/jdk/make/java/java/Makefile +++ b/jdk/make/java/java/Makefile @@ -105,6 +105,7 @@ FILES_java += java/util/prefs/MacOSXPreferences.java \ java/util/prefs/MacOSXPreferencesFactory.java CFLAGS_$(VARIANT)/java_props_md.o = -Os -x objective-c +CFLAGS_$(VARIANT)/java_props_macosx.o = -Os -x objective-c endif # diff --git a/jdk/make/java/java/genlocales.gmk b/jdk/make/java/java/genlocales.gmk index 6d35b8e734d..0d52565c9c5 100644 --- a/jdk/make/java/java/genlocales.gmk +++ b/jdk/make/java/java/genlocales.gmk @@ -38,31 +38,31 @@ FILES_compiled_properties_orig := $(FILES_compiled_properties) # only FILES_java and FILES_compiled_properties variables will be picked up # # $(BUILDDIR)/java/util/FILES_java.gmk & $(BUILDDIR)/java/util/FILES_properties.gmk -# contain "sun.util.resources" for US language support +# contain "sun.util.resources" for EN language support include $(BUILDDIR)/java/util/FILES_java.gmk include $(BUILDDIR)/java/util/FILES_properties.gmk -US_Resources_java := $(FILES_java) -US_Resources_properties := $(FILES_compiled_properties) +EN_Resources_java := $(FILES_java) +EN_Resources_properties := $(FILES_compiled_properties) # $(BUILDDIR)/java/text/FILES_java.gmk contains the "sun.text.resources" for -# US language support +# EN language support include $(BUILDDIR)/java/text/base/FILES_java.gmk -US_Resources_java += $(FILES_java) +EN_Resources_java += $(FILES_java) FILES_compiled_properties= # $(BUILDDIR)/sun/text/FILES_java.gmk & $(BUILDDIR)/sun/text/FILES_properties.gmk -# contain both resources for Non-US language support +# contain both resources for Non-EN language support include $(BUILDDIR)/sun/text/FILES_java.gmk include $(BUILDDIR)/sun/text/FILES_properties.gmk -NonUS_Resources_java := $(FILES_java) -NonUS_Resources_properties := $(FILES_compiled_properties) +NonEN_Resources_java := $(FILES_java) +NonEN_Resources_properties := $(FILES_compiled_properties) # Restore the orignal FILES_java & FILES_compiled_properties variables FILES_java := $(FILES_java_orig) @@ -80,30 +80,30 @@ RESOURCE_NAMES="FormatData CollationData TimeZoneNames LocaleNames CurrencyNames ifeq ($(PLATFORM), macosx) $(LocaleDataMetaInfo_Dest):$(LocaleDataMetaInfo_Src) $(LOCALEGEN_SH) - @$(RM) $@.tmp.us $@.tmp.nonus; + @$(RM) $@.tmp.en $@.tmp.nonen; @$(prep-target) - @$(ECHO) $(US_Resources_properties) | $(NAWK) 'gsub(/.properties/,"\n") {print}' > $@.tmp.us; - @$(ECHO) $(US_Resources_java) | $(NAWK) 'gsub(/.java/,"\n") {print}' >> $@.tmp.us; - @$(ECHO) $(NonUS_Resources_properties) | $(NAWK) 'gsub(/.properties/,"\n") {print}' > $@.tmp.nonus; - @$(ECHO) $(NonUS_Resources_java) | $(NAWK) 'gsub(/.java/,"\n") {print}' >> $@.tmp.nonus; + @$(ECHO) $(EN_Resources_properties) | $(NAWK) 'gsub(/.properties/,"\n") {print}' > $@.tmp.en; + @$(ECHO) $(EN_Resources_java) | $(NAWK) 'gsub(/.java/,"\n") {print}' >> $@.tmp.en; + @$(ECHO) $(NonEN_Resources_properties) | $(NAWK) 'gsub(/.properties/,"\n") {print}' > $@.tmp.nonen; + @$(ECHO) $(NonEN_Resources_java) | $(NAWK) 'gsub(/.java/,"\n") {print}' >> $@.tmp.nonen; NAWK="$(NAWK)" SED="$(SED)" SORT="$(SORT)" \ - $(SH) $(LOCALEGEN_SH) $(RESOURCE_NAMES) $@.tmp.us \ - $@.tmp.nonus $< $@ - @$(RM) $@.tmp.us $@.tmp.nonus; + $(SH) $(LOCALEGEN_SH) $(RESOURCE_NAMES) $@.tmp.en \ + $@.tmp.nonen $< $@ + @$(RM) $@.tmp.en $@.tmp.nonen; else $(LocaleDataMetaInfo_Dest):$(LocaleDataMetaInfo_Src) $(LOCALEGEN_SH) - @$(RM) $@.tmp.us $@.tmp.nonus; + @$(RM) $@.tmp.en $@.tmp.nonen; @$(prep-target) - @$(ECHO) $(subst .properties,'\n',$(US_Resources_properties)) > $@.tmp.us; - @$(ECHO) $(subst .java,'\n',$(US_Resources_java)) >> $@.tmp.us; - @$(ECHO) $(subst .properties,'\n',$(NonUS_Resources_properties)) > $@.tmp.nonus; - @$(ECHO) $(subst .java,'\n',$(NonUS_Resources_java)) >> $@.tmp.nonus; + @$(ECHO) $(subst .properties,'\n',$(EN_Resources_properties)) > $@.tmp.en; + @$(ECHO) $(subst .java,'\n',$(EN_Resources_java)) >> $@.tmp.en; + @$(ECHO) $(subst .properties,'\n',$(NonEN_Resources_properties)) > $@.tmp.nonen; + @$(ECHO) $(subst .java,'\n',$(NonEN_Resources_java)) >> $@.tmp.nonen; NAWK="$(NAWK)" SED="$(SED)" SORT="$(SORT)" \ - $(SH) $(LOCALEGEN_SH) $(RESOURCE_NAMES) $@.tmp.us \ - $@.tmp.nonus $< $@ - @$(RM) $@.tmp.us $@.tmp.nonus; + $(SH) $(LOCALEGEN_SH) $(RESOURCE_NAMES) $@.tmp.en \ + $@.tmp.nonen $< $@ + @$(RM) $@.tmp.en $@.tmp.nonen; endif genlocales : $(LocaleDataMetaInfo_Dest) diff --git a/jdk/make/java/java/localegen.sh b/jdk/make/java/java/localegen.sh index 8fad25ef534..78493d31f95 100644 --- a/jdk/make/java/java/localegen.sh +++ b/jdk/make/java/java/localegen.sh @@ -35,11 +35,11 @@ # A list of resource base name list; RESOURCE_NAMES=$1 -# A list of US resources; -US_FILES_LIST=$2 +# A list of EN resources; +EN_FILES_LIST=$2 -# A list of non-US resources; -NONUS_FILES_LIST=$3 +# A list of non-EN resources; +NONEN_FILES_LIST=$3 INPUT_FILE=$4 OUTPUT_FILE=$5 @@ -53,23 +53,23 @@ getlocalelist() { sed_script="$SED -e \"s@^#warn .*@// -- This file was mechanically generated: Do not edit! -- //@\" " # ja-JP-JP and th-TH-TH need to be manually added, as they don't have any resource files. -nonusall=" ja-JP-JP th-TH-TH " +nonenall=" ja-JP-JP th-TH-TH " for FILE in $RESOURCE_NAMES do - getlocalelist $FILE $US_FILES_LIST - sed_script=$sed_script"-e \"s@#"$FILE"_USLocales#@$localelist@g\" " - usall=$usall" "$localelist - getlocalelist $FILE $NONUS_FILES_LIST - sed_script=$sed_script"-e \"s@#"$FILE"_NonUSLocales#@$localelist@g\" " - nonusall=$nonusall" "$localelist + getlocalelist $FILE $EN_FILES_LIST + sed_script=$sed_script"-e \"s@#"$FILE"_ENLocales#@$localelist@g\" " + enall=$enall" "$localelist + getlocalelist $FILE $NONEN_FILES_LIST + sed_script=$sed_script"-e \"s@#"$FILE"_NonENLocales#@$localelist@g\" " + nonenall=$nonenall" "$localelist done -usall=`(for LOC in $usall; do echo $LOC;done) |$SORT -u` -nonusall=`(for LOC in $nonusall; do echo $LOC;done) |$SORT -u` +enall=`(for LOC in $enall; do echo $LOC;done) |$SORT -u` +nonenall=`(for LOC in $nonenall; do echo $LOC;done) |$SORT -u` -sed_script=$sed_script"-e \"s@#AvailableLocales_USLocales#@$usall@g\" " -sed_script=$sed_script"-e \"s@#AvailableLocales_NonUSLocales#@$nonusall@g\" " +sed_script=$sed_script"-e \"s@#AvailableLocales_ENLocales#@$enall@g\" " +sed_script=$sed_script"-e \"s@#AvailableLocales_NonENLocales#@$nonenall@g\" " sed_script=$sed_script"$INPUT_FILE > $OUTPUT_FILE" eval $sed_script diff --git a/jdk/make/java/security/Makefile b/jdk/make/java/security/Makefile index bbb0ca4f757..05b6b8a5664 100644 --- a/jdk/make/java/security/Makefile +++ b/jdk/make/java/security/Makefile @@ -70,9 +70,13 @@ POLICY_BUILD = $(LIBDIR)/security/java.policy CACERTS_SRC = $(CACERTS_FILE) CACERTS_BUILD = $(LIBDIR)/security/cacerts +BLACKLISTED_CERTS_SRC = $(TOPDIR)/src/share/lib/security/blacklisted.certs +BLACKLISTED_CERTS_BUILD = $(LIBDIR)/security/blacklisted.certs + ifndef OPENJDK BLACKLIST_SRC = $(CLOSED_SHARE_SRC)/lib/security/blacklist BLACKLIST_BUILD = $(LIBDIR)/security/blacklist + BLACKLISTED_CERTS_SRC += $(wildcard $(CLOSED_SHARE_SRC)/lib/security/blacklisted.certs) TRUSTEDLIBS_SRC = $(CLOSED_SHARE_SRC)/lib/security/trusted.libraries TRUSTEDLIBS_BUILD = $(LIBDIR)/security/trusted.libraries endif @@ -85,9 +89,9 @@ FILES_class = $(FILES_java:%.java=$(CLASSBINDIR)/%.class) include $(BUILDDIR)/common/Rules.gmk ifdef OPENJDK -build: properties policy cacerts +build: properties policy cacerts blacklisted-certs else -build: properties policy cacerts blacklist trustedlibs +build: properties policy cacerts blacklist blacklisted-certs trustedlibs endif install: all @@ -100,6 +104,8 @@ cacerts: classes $(CACERTS_BUILD) blacklist: classes $(BLACKLIST_BUILD) +blacklisted-certs: classes $(BLACKLISTED_CERTS_BUILD) + trustedlibs: classes $(TRUSTEDLIBS_BUILD) $(PROPS_BUILD): $(PROPS_SRC) @@ -114,12 +120,25 @@ $(CACERTS_BUILD): $(CACERTS_SRC) $(BLACKLIST_BUILD): $(BLACKLIST_SRC) $(install-file) +$(BLACKLISTED_CERTS_BUILD): $(BLACKLISTED_CERTS_SRC) + $(MKDIR) -p $(@D) + $(CAT) $^ | $(SED) '/^$$/d' | $(SORT) | $(UNIQ) > $@.tmp + $(GREP) -i Algorithm $@.tmp > $@ + if [ `$(SED) -n -e "$$=" $@` != 1 ]; then \ + $(ECHO) "Different algorithms defined in $^"; \ + $(RM) $@ $@.tmp; \ + false; \ + fi + $(GREP) -iv Algorithm $@.tmp >> $@ + $(RM) $@.tmp + $(TRUSTEDLIBS_BUILD): $(TRUSTEDLIBS_SRC) $(install-file) clean clobber:: .delete.classlist $(RM) -r $(CLASSBINDIR)/java/security - $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD) $(TRUSTEDLIBS_BUILD) + $(RM) $(PROPS_BUILD) $(POLICY_BUILD) $(CACERTS_BUILD) $(BLACKLIST_BUILD) \ + $(BLACKLISTED_CERTS_BUILD) $(TRUSTEDLIBS_BUILD) # Additional Rule for building sun.security.util $(CLASSBINDIR)/%.class: $(SHARE_SRC)/sun/%.java diff --git a/jdk/make/java/text/base/FILES_java.gmk b/jdk/make/java/text/base/FILES_java.gmk index c2e0f479c6b..47abc6ff095 100644 --- a/jdk/make/java/text/base/FILES_java.gmk +++ b/jdk/make/java/text/base/FILES_java.gmk @@ -107,5 +107,17 @@ FILES_java = \ sun/text/resources/FormatData.java \ sun/text/resources/JavaTimeSupplementary.java \ sun/text/resources/en/FormatData_en.java \ + sun/text/resources/en/FormatData_en_AU.java \ + sun/text/resources/en/FormatData_en_CA.java \ + sun/text/resources/en/FormatData_en_GB.java \ + sun/text/resources/en/FormatData_en_IE.java \ + sun/text/resources/en/FormatData_en_IN.java \ + sun/text/resources/en/FormatData_en_MT.java \ + sun/text/resources/en/FormatData_en_NZ.java \ + sun/text/resources/en/FormatData_en_PH.java \ + sun/text/resources/en/FormatData_en_SG.java \ sun/text/resources/en/FormatData_en_US.java \ + sun/text/resources/en/FormatData_en_ZA.java \ sun/text/resources/en/JavaTimeSupplementary_en.java \ + sun/text/resources/en/JavaTimeSupplementary_en_GB.java \ + sun/text/resources/en/JavaTimeSupplementary_en_SG.java diff --git a/jdk/make/java/util/FILES_java.gmk b/jdk/make/java/util/FILES_java.gmk index 677a97c52cb..75bbe38031c 100644 --- a/jdk/make/java/util/FILES_java.gmk +++ b/jdk/make/java/util/FILES_java.gmk @@ -30,4 +30,7 @@ FILES_java = \ sun/util/resources/LocaleNamesBundle.java \ sun/util/resources/TimeZoneNamesBundle.java \ sun/util/resources/TimeZoneNames.java \ - sun/util/resources/en/TimeZoneNames_en.java + sun/util/resources/en/TimeZoneNames_en.java \ + sun/util/resources/en/TimeZoneNames_en_CA.java \ + sun/util/resources/en/TimeZoneNames_en_GB.java \ + sun/util/resources/en/TimeZoneNames_en_IE.java diff --git a/jdk/make/java/util/FILES_properties.gmk b/jdk/make/java/util/FILES_properties.gmk index 4b777c5f2d8..e2fc3cb118b 100644 --- a/jdk/make/java/util/FILES_properties.gmk +++ b/jdk/make/java/util/FILES_properties.gmk @@ -26,9 +26,25 @@ FILES_compiled_properties = \ sun/util/resources/LocaleNames.properties \ sun/util/resources/en/LocaleNames_en.properties \ + sun/util/resources/en/LocaleNames_en_MT.properties \ + sun/util/resources/en/LocaleNames_en_PH.properties \ + sun/util/resources/en/LocaleNames_en_SG.properties \ \ sun/util/resources/CalendarData.properties \ sun/util/resources/en/CalendarData_en.properties \ + sun/util/resources/en/CalendarData_en_GB.properties \ + sun/util/resources/en/CalendarData_en_IE.properties \ + sun/util/resources/en/CalendarData_en_MT.properties \ \ sun/util/resources/CurrencyNames.properties \ - sun/util/resources/en/CurrencyNames_en_US.properties + sun/util/resources/en/CurrencyNames_en_AU.properties \ + sun/util/resources/en/CurrencyNames_en_CA.properties \ + sun/util/resources/en/CurrencyNames_en_GB.properties \ + sun/util/resources/en/CurrencyNames_en_IE.properties \ + sun/util/resources/en/CurrencyNames_en_IN.properties \ + sun/util/resources/en/CurrencyNames_en_MT.properties \ + sun/util/resources/en/CurrencyNames_en_NZ.properties \ + sun/util/resources/en/CurrencyNames_en_PH.properties \ + sun/util/resources/en/CurrencyNames_en_SG.properties \ + sun/util/resources/en/CurrencyNames_en_US.properties \ + sun/util/resources/en/CurrencyNames_en_ZA.properties diff --git a/jdk/make/javax/sound/jsoundds/Makefile b/jdk/make/javax/sound/jsoundds/Makefile index f476b39811a..a747d699a0a 100644 --- a/jdk/make/javax/sound/jsoundds/Makefile +++ b/jdk/make/javax/sound/jsoundds/Makefile @@ -55,8 +55,7 @@ FILES_export = \ LDLIBS += dsound.lib winmm.lib user32.lib ole32.lib CPPFLAGS += \ -DUSE_DAUDIO=TRUE \ - -I$(SHARE_SRC)/native/com/sun/media/sound \ - -I$(DXSDK_INCLUDE_PATH) + -I$(SHARE_SRC)/native/com/sun/media/sound # # Add to the ambient VPATH. diff --git a/jdk/make/jdk_generic_profile.sh b/jdk/make/jdk_generic_profile.sh index 28705393a33..1103a56aa52 100644 --- a/jdk/make/jdk_generic_profile.sh +++ b/jdk/make/jdk_generic_profile.sh @@ -80,7 +80,6 @@ # ALT_BOOTDIR # Windows Only: # ALT_UNIXCOMMAND_PATH -# ALT_DXSDK_PATH # ALT_MSVCRNN_DLL_PATH # ############################################################################# diff --git a/jdk/make/jprt.properties b/jdk/make/jprt.properties index 8f7038e1f3b..eb6ff3ff2f0 100644 --- a/jdk/make/jprt.properties +++ b/jdk/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -40,8 +40,8 @@ jprt.build.targets= \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ macosx_x64_10.7-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # User can select the test set with jprt submit "-testset name" option jprt.my.test.set=${jprt.test.set} @@ -55,8 +55,8 @@ jprt.my.test.target.set= \ linux_i586_2.6-product-{c1|c2}-TESTNAME, \ linux_x64_2.6-product-c2-TESTNAME, \ macosx_x64_10.7-product-c2-TESTNAME, \ - windows_i586_5.1-product-c1-TESTNAME, \ - windows_x64_5.2-product-c2-TESTNAME + windows_i586_6.1-product-c1-TESTNAME, \ + windows_x64_6.1-product-c2-TESTNAME # Default vm test targets (testset=default) jprt.vm.default.test.targets= \ diff --git a/jdk/make/netbeans/awt2d/README b/jdk/make/netbeans/awt2d/README index 040c9e76919..4df566dd157 100644 --- a/jdk/make/netbeans/awt2d/README +++ b/jdk/make/netbeans/awt2d/README @@ -39,7 +39,6 @@ Here are the steps: (on Windows): #>env | grep ALT ALT_JDK_IMPORT_PATH=c:/devtools/java/jdk1.7.0 - ALT_DXSDK_PATH=c:/devtools/DirectX/DXSDK_Dec06 ALT_BOOTDIR=c:/DevTools/java/jdk1.6.0 If your build is a FASTDEBUG build, don't forget @@ -50,7 +49,6 @@ Here are the steps: accordingly: make.options=\ ALT_JDK_IMPORT_PATH=c:/devtools/java/jdk1.7.0 \ - ALT_DXSDK_PATH=c:/devtools/DirectX/DXSDK_Dec06 \ ALT_BOOTDIR=c:/DevTools/java/jdk1.6.0 \ FASTDEBUG=true make=c:/devtools/cygwin/bin/make @@ -175,7 +173,6 @@ Notes on using CND (C/C++ pack) with this project and NetBeans. ../../build/windows-i586/tmp/sun/sun.awt/splashscreen/CClassHeaders; ../../build/windows-i586/tmp/sun/sun.font/fontmanager/CClassHeaders; ../../build/windows-i586/tmp/sun/sun.font/t2k/CClassHeaders; - C:/DevTools/DirectX/DXSDK_Dec06/Include; C:/devtools/VS2003/SDK/v1.1/include; C:/devtools/VS2003/VC7/ATLMFC/INCLUDE; C:/devtools/VS2003/VC7/INCLUDE; @@ -188,7 +185,7 @@ Notes on using CND (C/C++ pack) with this project and NetBeans. Note that most paths are relative to the native project directory - this helps if you decide to relocate the workspace later. The ones that aren't relative are paths to external include directories, like those - of the Platform SDK, DirectX SDK. + of the Platform SDK. On Unix platforms these may be directories like /usr/include. The parser must know some defines to correctly parse the source files, diff --git a/jdk/make/sun/awt/Makefile b/jdk/make/sun/awt/Makefile index c45ecb9fe45..9f11638a69e 100644 --- a/jdk/make/sun/awt/Makefile +++ b/jdk/make/sun/awt/Makefile @@ -562,7 +562,6 @@ OTHER_INCLUDES += -I$(CLASSHDRDIR)/../../java/jvm \ -I$(OBJDIR) \ -I$(SHARE_SRC)/native/common \ -I$(WINAWT_native) \ - -I$(DXSDK_INCLUDE_PATH) \ -I$(SHARE_SRC)/native/sun/awt/image/cvutils \ -I$(SHARE_SRC)/native/sun/awt/image \ -I$(SHARE_SRC)/native/sun/java2d/loops \ diff --git a/jdk/make/sun/cmm/lcms/mapfile-vers b/jdk/make/sun/cmm/lcms/mapfile-vers index 3d9074f746d..949ff9b5787 100644 --- a/jdk/make/sun/cmm/lcms/mapfile-vers +++ b/jdk/make/sun/cmm/lcms/mapfile-vers @@ -28,9 +28,8 @@ SUNWprivate_1.1 { global: Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; - Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; - Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; - Java_sun_java2d_cmm_lcms_LCMS_getProfileData; + Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative; + Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative; Java_sun_java2d_cmm_lcms_LCMS_getTagNative; Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; diff --git a/jdk/make/sun/jawt/Makefile b/jdk/make/sun/jawt/Makefile index 718fb33c499..0520fc17bf1 100644 --- a/jdk/make/sun/jawt/Makefile +++ b/jdk/make/sun/jawt/Makefile @@ -69,7 +69,6 @@ OTHER_CXXFLAGS += $(GX_OPTION) -DUNICODE -D_UNICODE # Other extra flags needed for compiling. # CPPFLAGS += -I$(SHARE_SRC)/native/common \ - -I$(DXSDK_INCLUDE_PATH) \ -I$(PLATFORM_SRC)/native/sun/windows \ -I$(CLASSHDRDIR)/../../awt/CClassHeaders \ -I$(SHARE_SRC)/native/sun/awt/debug \ diff --git a/jdk/make/sun/lwawt/FILES_export_macosx.gmk b/jdk/make/sun/lwawt/FILES_export_macosx.gmk index 5799b32c954..7b32f911c21 100644 --- a/jdk/make/sun/lwawt/FILES_export_macosx.gmk +++ b/jdk/make/sun/lwawt/FILES_export_macosx.gmk @@ -110,7 +110,6 @@ FILES_export = \ sun/lwawt/LWWindowPeer.java \ sun/lwawt/PlatformWindow.java \ sun/lwawt/SecurityWarningWindow.java \ - sun/lwawt/SelectionClearListener.java \ sun/lwawt/macosx/CPrinterDevice.java \ sun/lwawt/macosx/CPrinterDialog.java \ sun/lwawt/macosx/CPrinterDialogPeer.java \ @@ -141,7 +140,6 @@ FILES_export = \ sun/lwawt/macosx/CMenuBar.java \ sun/lwawt/macosx/CMenuComponent.java \ sun/lwawt/macosx/CMenuItem.java \ - sun/lwawt/macosx/CMouseInfoPeer.java \ sun/lwawt/macosx/CPlatformView.java \ sun/lwawt/macosx/CPlatformWindow.java \ sun/lwawt/macosx/CWarningWindow.java \ diff --git a/jdk/make/sun/text/FILES_java.gmk b/jdk/make/sun/text/FILES_java.gmk index 2f15ec33612..dbb4856c673 100644 --- a/jdk/make/sun/text/FILES_java.gmk +++ b/jdk/make/sun/text/FILES_java.gmk @@ -96,16 +96,6 @@ FILES_java = \ sun/text/resources/el/FormatData_el.java \ sun/text/resources/el/FormatData_el_CY.java \ sun/text/resources/el/FormatData_el_GR.java \ - sun/text/resources/en/FormatData_en_AU.java \ - sun/text/resources/en/FormatData_en_CA.java \ - sun/text/resources/en/FormatData_en_GB.java \ - sun/text/resources/en/FormatData_en_IE.java \ - sun/text/resources/en/FormatData_en_IN.java \ - sun/text/resources/en/FormatData_en_MT.java \ - sun/text/resources/en/FormatData_en_NZ.java \ - sun/text/resources/en/FormatData_en_PH.java \ - sun/text/resources/en/FormatData_en_SG.java \ - sun/text/resources/en/FormatData_en_ZA.java \ sun/text/resources/es/FormatData_es.java \ sun/text/resources/es/FormatData_es_BO.java \ sun/text/resources/es/FormatData_es_AR.java \ @@ -214,9 +204,6 @@ FILES_java = \ sun/util/resources/zh/CurrencyNames_zh_SG.java \ sun/util/resources/zh/LocaleNames_zh_HK.java \ sun/util/resources/de/TimeZoneNames_de.java \ - sun/util/resources/en/TimeZoneNames_en_CA.java \ - sun/util/resources/en/TimeZoneNames_en_GB.java \ - sun/util/resources/en/TimeZoneNames_en_IE.java \ sun/util/resources/es/TimeZoneNames_es.java \ sun/util/resources/fr/TimeZoneNames_fr.java \ sun/util/resources/hi/TimeZoneNames_hi.java \ @@ -237,8 +224,6 @@ FILES_java = \ sun/text/resources/da/JavaTimeSupplementary_da.java \ sun/text/resources/de/JavaTimeSupplementary_de.java \ sun/text/resources/el/JavaTimeSupplementary_el.java \ - sun/text/resources/en/JavaTimeSupplementary_en_GB.java \ - sun/text/resources/en/JavaTimeSupplementary_en_SG.java \ sun/text/resources/es/JavaTimeSupplementary_es.java \ sun/text/resources/et/JavaTimeSupplementary_et.java \ sun/text/resources/fi/JavaTimeSupplementary_fi.java \ diff --git a/jdk/make/sun/text/FILES_properties.gmk b/jdk/make/sun/text/FILES_properties.gmk index a3a1321cfb9..494d6cc4b19 100644 --- a/jdk/make/sun/text/FILES_properties.gmk +++ b/jdk/make/sun/text/FILES_properties.gmk @@ -33,9 +33,6 @@ FILES_compiled_properties = \ sun/util/resources/de/LocaleNames_de.properties \ sun/util/resources/el/LocaleNames_el.properties \ sun/util/resources/el/LocaleNames_el_CY.properties \ - sun/util/resources/en/LocaleNames_en_MT.properties \ - sun/util/resources/en/LocaleNames_en_PH.properties \ - sun/util/resources/en/LocaleNames_en_SG.properties \ sun/util/resources/es/LocaleNames_es.properties \ sun/util/resources/es/LocaleNames_es_US.properties \ sun/util/resources/et/LocaleNames_et.properties \ @@ -88,9 +85,6 @@ FILES_compiled_properties = \ sun/util/resources/de/CalendarData_de.properties \ sun/util/resources/el/CalendarData_el.properties \ sun/util/resources/el/CalendarData_el_CY.properties \ - sun/util/resources/en/CalendarData_en_GB.properties \ - sun/util/resources/en/CalendarData_en_IE.properties \ - sun/util/resources/en/CalendarData_en_MT.properties \ sun/util/resources/es/CalendarData_es.properties \ sun/util/resources/es/CalendarData_es_ES.properties \ sun/util/resources/es/CalendarData_es_US.properties \ @@ -164,16 +158,6 @@ FILES_compiled_properties = \ sun/util/resources/de/CurrencyNames_de_LU.properties \ sun/util/resources/el/CurrencyNames_el_CY.properties \ sun/util/resources/el/CurrencyNames_el_GR.properties \ - sun/util/resources/en/CurrencyNames_en_AU.properties \ - sun/util/resources/en/CurrencyNames_en_CA.properties \ - sun/util/resources/en/CurrencyNames_en_GB.properties \ - sun/util/resources/en/CurrencyNames_en_IE.properties \ - sun/util/resources/en/CurrencyNames_en_IN.properties \ - sun/util/resources/en/CurrencyNames_en_MT.properties \ - sun/util/resources/en/CurrencyNames_en_NZ.properties \ - sun/util/resources/en/CurrencyNames_en_PH.properties \ - sun/util/resources/en/CurrencyNames_en_SG.properties \ - sun/util/resources/en/CurrencyNames_en_ZA.properties \ sun/util/resources/es/CurrencyNames_es.properties \ sun/util/resources/es/CurrencyNames_es_AR.properties \ sun/util/resources/es/CurrencyNames_es_BO.properties \ diff --git a/jdk/make/sun/xawt/mapfile-vers b/jdk/make/sun/xawt/mapfile-vers index 5455530cbed..e75f0c1914b 100644 --- a/jdk/make/sun/xawt/mapfile-vers +++ b/jdk/make/sun/xawt/mapfile-vers @@ -305,6 +305,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XlibWrapper_XkbGetUpdatedMap; Java_sun_awt_X11_XlibWrapper_XkbFreeKeyboard; Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode; + Java_sun_awt_X11_XlibWrapper_XkbSetDetectableAutoRepeat; Java_sun_awt_X11_XlibWrapper_XGetModifierMapping; Java_sun_awt_X11_XlibWrapper_XFreeModifiermap; Java_sun_awt_X11_XlibWrapper_XRefreshKeyboardMapping; diff --git a/jdk/make/tools/src/build/tools/generatecharacter/CharacterName.java b/jdk/make/tools/src/build/tools/generatecharacter/CharacterName.java index 0872100b7db..833a835c0ce 100644 --- a/jdk/make/tools/src/build/tools/generatecharacter/CharacterName.java +++ b/jdk/make/tools/src/build/tools/generatecharacter/CharacterName.java @@ -11,7 +11,7 @@ public class CharacterName { FileReader reader = null; try { if (args.length != 2) { - System.err.println("Usage: java CharacterName UniocdeData.txt uniName.dat"); + System.err.println("Usage: java CharacterName UnicodeData.txt uniName.dat"); System.exit(1); } diff --git a/jdk/makefiles/CompileDemos.gmk b/jdk/makefiles/CompileDemos.gmk index 0a093b586a9..6cd5dd4df0d 100644 --- a/jdk/makefiles/CompileDemos.gmk +++ b/jdk/makefiles/CompileDemos.gmk @@ -65,14 +65,10 @@ $(eval $(call SetupAppletDemo,DitherTest)) $(eval $(call SetupAppletDemo,DrawTest)) $(eval $(call SetupAppletDemo,Fractal)) $(eval $(call SetupAppletDemo,GraphicsTest)) -$(eval $(call SetupAppletDemo,MoleculeViewer)) $(eval $(call SetupAppletDemo,NervousText)) $(eval $(call SetupAppletDemo,SimpleGraph)) $(eval $(call SetupAppletDemo,SortDemo)) $(eval $(call SetupAppletDemo,SpreadSheet)) -# Build WireFrame without a server since it -# has a class Matrix3D that also exists in MoleculeViewer. -$(eval $(call SetupAppletDemo,WireFrame,true)) ifndef OPENJDK $(eval $(call SetupAppletDemo,Animator,,closed/)) @@ -83,7 +79,7 @@ endif ################################################################################################## -PATTERNS_TO_COPY=.html .txt .properties .js .gif .jpg .theme .data .opt README .c .h .png .ttf +PATTERNS_TO_COPY=.html .txt .properties .js .gif .jpg .theme .data .opt README .c .h .png .ttf .xyz .obj define SetupDemo # Param 1 = Name of the demo @@ -161,6 +157,8 @@ $(JDK_OUTPUTDIR)/demo/jfc/CodePointIM/_the.services : \ BUILD_DEMOS+=$(JDK_OUTPUTDIR)/demo/jfc/CodePointIM/_the.services +$(eval $(call SetupDemo,MoleculeViewer,applets,,XYZChemModel,,,example*.html XYZApp.java)) +$(eval $(call SetupDemo,WireFrame,applets,,ThreeD,,,example*.html ThreeD.java)) $(eval $(call SetupDemo,FileChooserDemo,jfc,,FileChooserDemo,,,README*)) $(eval $(call SetupDemo,Font2DTest,jfc,,Font2DTest,,,*.html *.txt)) $(eval $(call SetupDemo,Metalworks,jfc,,Metalworks,,,README*)) diff --git a/jdk/makefiles/CompileJavaClasses.gmk b/jdk/makefiles/CompileJavaClasses.gmk index 0b3e70dd914..a015846e39f 100644 --- a/jdk/makefiles/CompileJavaClasses.gmk +++ b/jdk/makefiles/CompileJavaClasses.gmk @@ -62,6 +62,7 @@ ifndef OPENJDK # AccessBridge is compiled separately below. EXFILES += AccessBridge.java \ + AccessBridgeLoader.java \ com/sun/java/accessibility/util/java/awt/ChoiceTranslator.java # This seems to never be built EXCLUDES += com/sun/java/accessibility/extensions diff --git a/jdk/makefiles/CompileLaunchers.gmk b/jdk/makefiles/CompileLaunchers.gmk index 5776629e837..d9489b7b606 100644 --- a/jdk/makefiles/CompileLaunchers.gmk +++ b/jdk/makefiles/CompileLaunchers.gmk @@ -23,7 +23,7 @@ # questions. # -defalt: all +default: all include $(SPEC) include MakeBase.gmk diff --git a/jdk/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index d5ffe0448c9..29289eaedcb 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -23,7 +23,7 @@ # questions. # -defalt: all +default: all include $(SPEC) include MakeBase.gmk @@ -211,6 +211,7 @@ ifneq ($(OPENJDK_TARGET_OS),macosx) LIBJAVA_EXCLUDE_FILES += java_props_macosx.c else BUILD_LIBJAVA_java_props_md.c_CFLAGS:=-x objective-c + BUILD_LIBJAVA_java_props_macosx.c_CFLAGS:=-x objective-c endif ifeq ($(OPENJDK_TARGET_OS),windows) @@ -252,6 +253,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA,\ LDFLAGS_SUFFIX_linux:=$(LIBDL) $(BUILD_LIBFDLIBM),\ LDFLAGS_SUFFIX_macosx:=-L$(JDK_OUTPUTDIR)/objs/ -lfdlibm \ -framework CoreFoundation \ + -framework Foundation \ -framework Security -framework SystemConfiguration, \ LDFLAGS_SUFFIX_windows:=-export:winFileHandleOpen -export:handleLseek \ jvm.lib $(BUILD_LIBFDLIBM) $(WIN_VERIFY_LIB) \ @@ -472,7 +474,6 @@ ifeq ($(OPENJDK_TARGET_OS),windows) $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/windows \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/d3d - LIBAWT_CFLAGS+=-I$(DXSDK_INCLUDE_PATH) else LIBAWT_DIRS+=\ $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/x11 @@ -1478,8 +1479,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) -I$(JDK_TOPDIR)/src/share/native/sun/awt/debug \ -I$(JDK_TOPDIR)/src/share/native/sun/java2d \ -I$(JDK_TOPDIR)/src/share/native/sun/awt/image/cvutils \ - -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows \ - -I$(DXSDK_INCLUDE_PATH), \ + -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/native/sun/java2d/windows, \ LDFLAGS:=$(LDFLAGS_JDKLIB) $(KERNEL32_LIB) $(LDFLAGS_CXX_JDK) \ advapi32.lib $(WIN_AWT_LIB),\ LDFLAGS_SUFFIX:=$(LDFLAGS_JDKLIB_SUFFIX),\ @@ -2957,8 +2957,7 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJSOUNDDS,\ OPTIMIZATION:=LOW, \ CFLAGS:=$(CFLAGS_JDKLIB) \ $(LIBJSOUND_CFLAGS) \ - -DUSE_DAUDIO=TRUE \ - -I$(DXSDK_INCLUDE_PATH), \ + -DUSE_DAUDIO=TRUE, \ LDFLAGS:=$(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ $(call SET_SHARED_LIBRARY_ORIGIN),\ LDFLAGS_SUFFIX:=$(LDFLAGS_JDKLIB_SUFFIX) dsound.lib winmm.lib user32.lib ole32.lib,\ diff --git a/jdk/makefiles/CopyFiles.gmk b/jdk/makefiles/CopyFiles.gmk index 2b3cbf2e200..abdf3546a18 100644 --- a/jdk/makefiles/CopyFiles.gmk +++ b/jdk/makefiles/CopyFiles.gmk @@ -382,11 +382,16 @@ COPY_FILES += $(CACERTS_DST) ########################################################################################## +BLACKLISTED_CERTS_SRC := $(JDK_TOPDIR)/src/share/lib/security/blacklisted.certs +BLACKLISTED_CERTS_DST := $(JDK_OUTPUTDIR)/lib/security/blacklisted.certs + ifndef OPENJDK BLACKLIST_SRC := $(JDK_TOPDIR)/src/closed/share/lib/security/blacklist BLACKLIST_DST := $(JDK_OUTPUTDIR)/lib/security/blacklist +BLACKLISTED_CERTS_SRC += $(wildcard $(JDK_TOPDIR)/src/closed/share/lib/security/blacklisted.certs) + TRUSTEDLIBS_SRC := $(JDK_TOPDIR)/src/closed/share/lib/security/trusted.libraries TRUSTEDLIBS_DST := $(JDK_OUTPUTDIR)/lib/security/trusted.libraries @@ -402,6 +407,20 @@ COPY_FILES += $(TRUSTEDLIBS_DST) endif +$(BLACKLISTED_CERTS_DST): $(BLACKLISTED_CERTS_SRC) + $(MKDIR) -p $(@D) + $(CAT) $^ | $(SED) '/^$$/d' | $(SORT) | $(UNIQ) > $@.tmp + $(GREP) -i Algorithm $@.tmp > $@ + if [ `$(SED) -n -e "$$=" $@` != 1 ]; then \ + $(ECHO) "Different algorithms defined in $^"; \ + $(RM) $@ $@.tmp; \ + false; \ + fi + $(GREP) -iv Algorithm $@.tmp >> $@ + $(RM) $@.tmp + +COPY_FILES += $(BLACKLISTED_CERTS_DST) + ########################################################################################## ifndef OPENJDK diff --git a/jdk/makefiles/CreateJars.gmk b/jdk/makefiles/CreateJars.gmk index 54531f19ef5..be721548d04 100644 --- a/jdk/makefiles/CreateJars.gmk +++ b/jdk/makefiles/CreateJars.gmk @@ -80,39 +80,6 @@ LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in LOCALEDATA_INCLUDES := $(addprefix sun/text/resources/,$(LOCALEDATA_INCLUDE_LOCALES)) \ $(addprefix sun/util/resources/,$(LOCALEDATA_INCLUDE_LOCALES)) -# For non-US English locale data - -LOCALEDATA_INCLUDES += \ - sun/text/resources/en/FormatData_en_AU.class \ - sun/text/resources/en/FormatData_en_CA.class \ - sun/text/resources/en/FormatData_en_GB.class \ - sun/text/resources/en/FormatData_en_IE.class \ - sun/text/resources/en/FormatData_en_IN.class \ - sun/text/resources/en/FormatData_en_MT.class \ - sun/text/resources/en/FormatData_en_NZ.class \ - sun/text/resources/en/FormatData_en_PH.class \ - sun/text/resources/en/FormatData_en_SG.class \ - sun/text/resources/en/FormatData_en_ZA.class \ - sun/util/resources/en/CalendarData_en_GB.class \ - sun/util/resources/en/CalendarData_en_IE.class \ - sun/util/resources/en/CalendarData_en_MT.class \ - sun/util/resources/en/CurrencyNames_en_AU.class \ - sun/util/resources/en/CurrencyNames_en_CA.class \ - sun/util/resources/en/CurrencyNames_en_GB.class \ - sun/util/resources/en/CurrencyNames_en_IE.class \ - sun/util/resources/en/CurrencyNames_en_IN.class \ - sun/util/resources/en/CurrencyNames_en_MT.class \ - sun/util/resources/en/CurrencyNames_en_NZ.class \ - sun/util/resources/en/CurrencyNames_en_PH.class \ - sun/util/resources/en/CurrencyNames_en_SG.class \ - sun/util/resources/en/CurrencyNames_en_ZA.class \ - sun/util/resources/en/LocaleNames_en_MT.class \ - sun/util/resources/en/LocaleNames_en_PH.class \ - sun/util/resources/en/LocaleNames_en_SG.class \ - sun/util/resources/en/TimeZoneNames_en_CA.class \ - sun/util/resources/en/TimeZoneNames_en_GB.class \ - sun/util/resources/en/TimeZoneNames_en_IE.class - $(eval $(call SetupArchive,BUILD_LOCALEDATA_JAR,,\ SRCS:=$(JDK_OUTPUTDIR)/classes,\ SUFFIXES:=.class _dict _th,\ @@ -986,13 +953,13 @@ ifeq ($(OPENJDK_TARGET_OS), windows) ifeq ($(OPENJDK_TARGET_CPU_BITS), 32) $(eval $(call SetupArchive,BUILD_ACCESSBRIDGE_32_JAR,,\ - SRCS:=$(JDK_OUTPUTDIR)/classes_ab/32bit $(JDK_OUTPUTDIR)/classes,\ + SRCS:=$(JDK_OUTPUTDIR)/classes_ab/32bit,\ INCLUDES:=com/sun/java/accessibility,\ JAR:=$(IMAGES_OUTPUTDIR)/lib/ext/access-bridge-32.jar,\ SKIP_METAINF:=true)) $(eval $(call SetupArchive,BUILD_ACCESSBRIDGE_LEGACY_JAR,,\ - SRCS:=$(JDK_OUTPUTDIR)/classes_ab/legacy $(JDK_OUTPUTDIR)/classes,\ + SRCS:=$(JDK_OUTPUTDIR)/classes_ab/legacy,\ INCLUDES:=com/sun/java/accessibility,\ JAR:=$(IMAGES_OUTPUTDIR)/lib/ext/access-bridge.jar,\ SKIP_METAINF:=true)) @@ -1001,9 +968,8 @@ ifeq ($(OPENJDK_TARGET_OS), windows) $(IMAGES_OUTPUTDIR)/lib/ext/access-bridge.jar else $(eval $(call SetupArchive,BUILD_ACCESSBRIDGE_64_JAR,,\ - SRCS:=$(JDK_OUTPUTDIR)/classes_ab/64bit $(JDK_OUTPUTDIR)/classes,\ + SRCS:=$(JDK_OUTPUTDIR)/classes_ab/64bit,\ INCLUDES:=com/sun/java/accessibility,\ - EXCLUDES:=com/sun/java/accessibility/util/java,\ JAR:=$(IMAGES_OUTPUTDIR)/lib/ext/access-bridge-64.jar,\ SKIP_METAINF:=true)) diff --git a/jdk/makefiles/GensrcLocaleDataMetaInfo.gmk b/jdk/makefiles/GensrcLocaleDataMetaInfo.gmk index 306276adf59..1577017b7f2 100644 --- a/jdk/makefiles/GensrcLocaleDataMetaInfo.gmk +++ b/jdk/makefiles/GensrcLocaleDataMetaInfo.gmk @@ -50,27 +50,27 @@ ifneq (,$(MISSING_RESOURCES)$(NEW_RESOURCES)) $(shell $(RM) $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java) endif -# The US locales -US_LOCALES:=en en-US +# The EN locales +EN_LOCALES:=en% # ja-JP-JP and th-TH-TH need to be manually added, as they don't have any resource files. -ALL_NON_US_LOCALES:=ja-JP-JP th-TH-TH +ALL_NON_EN_LOCALES:=ja-JP-JP th-TH-TH SED_ARGS:=-e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g' # This macro creates a sed expression that substitues for example: -# #FormatData_USLocales# with: en and/or en_US. +# #FormatData_ENLocales# with: en% locales. define CaptureLocale $1_LOCALES := $$(subst _,-,$$(filter-out $1,$$(subst $1_,,$$(filter $1_%,$(LOCALE_RESOURCES))))) - $1_US_LOCALES := $$(filter $(US_LOCALES),$$($1_LOCALES)) - $1_NON_US_LOCALES := $$(filter-out $(US_LOCALES),$$($1_LOCALES)) + $1_EN_LOCALES := $$(filter $(EN_LOCALES),$$($1_LOCALES)) + $1_NON_EN_LOCALES := $$(filter-out $(EN_LOCALES),$$($1_LOCALES)) - ALL_US_LOCALES += $$($1_US_LOCALES) - ALL_NON_US_LOCALES += $$($1_NON_US_LOCALES) + ALL_EN_LOCALES += $$($1_EN_LOCALES) + ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES) # Don't sed in a space if there are no locales. - SED_ARGS+= -e 's/$$(HASH)$1_USLocales$$(HASH)/$$(if $$($1_US_LOCALES),$$(SPACE)$$($1_US_LOCALES),)/g' - SED_ARGS+= -e 's/$$(HASH)$1_NonUSLocales$$(HASH)/$$(if $$($1_NON_US_LOCALES),$$(SPACE)$$($1_NON_US_LOCALES),)/g' + SED_ARGS+= -e 's/$$(HASH)$1_ENLocales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g' + SED_ARGS+= -e 's/$$(HASH)$1_NonENLocales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g' endef #sun.text.resources.FormatData @@ -91,8 +91,8 @@ $(eval $(call CaptureLocale,CurrencyNames)) #sun.util.resources.CalendarData $(eval $(call CaptureLocale,CalendarData)) -SED_ARGS+= -e 's/$(HASH)AvailableLocales_USLocales$(HASH)/$(sort $(ALL_US_LOCALES))/g' -SED_ARGS+= -e 's/$(HASH)AvailableLocales_NonUSLocales$(HASH)/$(sort $(ALL_NON_US_LOCALES))/g' +SED_ARGS+= -e 's/$(HASH)AvailableLocales_ENLocales$(HASH)/$(sort $(ALL_EN_LOCALES))/g' +SED_ARGS+= -e 's/$(HASH)AvailableLocales_NonENLocales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g' $(JDK_OUTPUTDIR)/gensrc/sun/util/locale/provider/LocaleDataMetaInfo.java: \ $(JDK_TOPDIR)/src/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template diff --git a/jdk/makefiles/GensrcMisc.gmk b/jdk/makefiles/GensrcMisc.gmk index 812b2cee6c7..d557499cc83 100644 --- a/jdk/makefiles/GensrcMisc.gmk +++ b/jdk/makefiles/GensrcMisc.gmk @@ -200,26 +200,42 @@ ifeq ($(OPENJDK_TARGET_OS), windows) AB_SRC_DIR := $(JDK_TOPDIR)/src/closed/windows/classes/com/sun/java/accessibility ifeq ($(OPENJDK_TARGET_CPU_BITS), 32) + $(AB_GENSRC_DIR)/32bit/com/sun/java/accessibility/AccessBridgeLoader.java: \ + $(AB_SRC_DIR)/32bit/AccessBridgeLoader.java + $(install-file) + $(AB_GENSRC_DIR)/32bit/com/sun/java/accessibility/AccessBridge.java: \ - $(AB_SRC_DIR)/32bit/AccessBridge.java + $(AB_SRC_DIR)/AccessBridge.java + $(install-file) + + $(AB_GENSRC_DIR)/legacy/com/sun/java/accessibility/AccessBridgeLoader.java: \ + $(AB_SRC_DIR)/legacy/AccessBridgeLoader.java $(install-file) $(AB_GENSRC_DIR)/legacy/com/sun/java/accessibility/AccessBridge.java: \ - $(AB_SRC_DIR)/legacy/AccessBridge.java + $(AB_SRC_DIR)/AccessBridge.java $(install-file) - GENSRC_MISC += $(AB_GENSRC_DIR)/32bit/com/sun/java/accessibility/AccessBridge.java \ - $(AB_GENSRC_DIR)/legacy/com/sun/java/accessibility/AccessBridge.java + GENSRC_MISC += $(AB_GENSRC_DIR)/32bit/com/sun/java/accessibility/AccessBridgeLoader.java \ + $(AB_GENSRC_DIR)/legacy/com/sun/java/accessibility/AccessBridgeLoader.java \ + $(AB_GENSRC_DIR)/32bit/com/sun/java/accessibility/AccessBridge.java \ + $(AB_GENSRC_DIR)/legacy/com/sun/java/accessibility/AccessBridge.java else - $(AB_GENSRC_DIR)/64bit/com/sun/java/accessibility/AccessBridge.java: \ - $(AB_SRC_DIR)/64bit/AccessBridge.java + $(AB_GENSRC_DIR)/64bit/com/sun/java/accessibility/AccessBridgeLoader.java: \ + $(AB_SRC_DIR)/64bit/AccessBridgeLoader.java $(install-file) - GENSRC_MISC += $(AB_GENSRC_DIR)/64bit/com/sun/java/accessibility/AccessBridge.java + $(AB_GENSRC_DIR)/64bit/com/sun/java/accessibility/AccessBridge.java: \ + $(AB_SRC_DIR)/AccessBridge.java + $(install-file) + + GENSRC_MISC += $(AB_GENSRC_DIR)/64bit/com/sun/java/accessibility/AccessBridgeLoader.java \ + $(AB_GENSRC_DIR)/64bit/com/sun/java/accessibility/AccessBridge.java endif + endif endif -########################################################################################## \ No newline at end of file +########################################################################################## diff --git a/jdk/makefiles/GensrcProperties.gmk b/jdk/makefiles/GensrcProperties.gmk index 3ef3a538475..1e29376f6ad 100644 --- a/jdk/makefiles/GensrcProperties.gmk +++ b/jdk/makefiles/GensrcProperties.gmk @@ -253,6 +253,13 @@ ifeq ($(OPENJDK_TARGET_OS),windows) $(call CacheFind,$(JDK_TOPDIR)/src/windows/classes/sun/awt/windows)),\ ListResourceBundle,%zh_TW,%zh_HK)) endif +# os x specific awt properties +ifeq ($(OPENJDK_TARGET_OS),macosx) +$(eval $(call add_properties_to_compile,SUN_AWT,\ + $(filter $(JDK_TOPDIR)/src/macosx/classes/sun/awt/resources/%.properties,\ + $(call CacheFind,$(JDK_TOPDIR)/src/macosx/classes/sun/awt/resources)),\ + ListResourceBundle)) +endif #sun/launcher/resources $(eval $(call add_properties_to_compile,SUN_LAUNCHER,\ diff --git a/jdk/makefiles/Images.gmk b/jdk/makefiles/Images.gmk index 492cf544ab5..d3c01e8a8f3 100644 --- a/jdk/makefiles/Images.gmk +++ b/jdk/makefiles/Images.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -190,6 +190,26 @@ $(foreach f,$(filter $(OVERLAY_FILTER),$(JDK_BIN_LIST)),\ $(foreach f,$(filter $(OVERLAY_FILTER),$(JDKJRE_BIN_LIST)),\ $(eval $(call AddFileToCopy,$(JDK_OUTPUTDIR),$(JDK_OVERLAY_IMAGE_DIR)/jre,$f,JDKJRE_BIN_TARGETS))) +ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_BITS),solaris-64) + define AddIsadirLink + # Param 1 - src file + # Param 2 - variable to add targets to + + $1_LINK := $$(dir $1)$(OPENJDK_TARGET_CPU_ISADIR)/$$(notdir $1) + + $$($1_LINK): + $(ECHO) $(LOG_INFO) Creating link $$(patsubst $(OUTPUT_ROOT)/%,%,$$@) + $(MKDIR) -p $$(@D) + $(LN) -s ../$$(@F) $$@ + + $2 += $$($1_LINK) + endef + + $(foreach f,$(JRE_BIN_TARGETS),$(eval $(call AddIsadirLink,$f,JRE_BIN_ISADIR_LINK_TARGETS))) + $(foreach f,$(JDK_BIN_TARGETS),$(eval $(call AddIsadirLink,$f,JDK_BIN_ISADIR_LINK_TARGETS))) + $(foreach f,$(JDKJRE_BIN_TARGETS),$(eval $(call AddIsadirLink,$f,JDKJRE_BIN_ISADIR_LINK_TARGETS))) +endif + ################################################################################ # /lib dir ifneq ($(OPENJDK_TARGET_OS), macosx) @@ -735,7 +755,8 @@ endif jre-image: $(JRE_BIN_TARGETS) $(JRE_LIB_TARGETS) $(JRE_IMAGE_DIR)/lib/applet \ $(JRE_IMAGE_DIR)/lib/meta-index $(JRE_IMAGE_DIR)/lib/ext/meta-index \ - $(JRE_MAN_PAGE_LIST) $(JRE_DOC_TARGETS) $(JRE_INFO_FILE) $(JRE_STRIP_LIST) + $(JRE_MAN_PAGE_LIST) $(JRE_DOC_TARGETS) $(JRE_INFO_FILE) $(JRE_STRIP_LIST) \ + $(JRE_BIN_ISADIR_LINK_TARGETS) jdk-image: $(JDK_BIN_TARGETS) $(JDKJRE_BIN_TARGETS) \ $(JDK_LIB_TARGETS) $(JDKJRE_LIB_TARGETS) \ @@ -746,7 +767,8 @@ jdk-image: $(JDK_BIN_TARGETS) $(JDKJRE_BIN_TARGETS) \ $(JDK_DB_TARGETS) $(JDK_INCLUDE_TARGETS) \ $(JDKJRE_DOC_TARGETS) $(JDK_DOC_TARGETS) \ $(JDK_INFO_FILE) $(JDKJRE_STRIP_LIST) $(JDK_BIN_STRIP_LIST) \ - $(JDK_IMAGE_DIR)/src.zip + $(JDK_IMAGE_DIR)/src.zip \ + $(JDK_BIN_ISADIR_LINK_TARGETS) $(JDKJRE_BIN_ISADIR_LINK_TARGETS) jre-overlay-image: $(JRE_OVERLAY_BIN_TARGETS) $(JRE_OVERLAY_LIB_TARGETS) \ $(JRE_OVERLAY_INFO_FILE) $(JRE_OVERLAY_STRIP_LIST) diff --git a/jdk/makefiles/Setup.gmk b/jdk/makefiles/Setup.gmk index 8012e547b55..4da575fed1a 100644 --- a/jdk/makefiles/Setup.gmk +++ b/jdk/makefiles/Setup.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,10 @@ DISABLE_WARNINGS:=-Xlint:all,-deprecation,-unchecked,-rawtypes,-cast,-serial,-dep-ann,-static,-fallthrough,-try,-varargs,-empty,-finally +# To build with all warnings enabled, do the following: +# make JAVAC_WARNINGS="-Xlint:all -Xmaxwarns 10000" +JAVAC_WARNINGS:=-Xlint:-unchecked,-deprecation,-overrides,classfile,dep-ann,divzero,varargs -Werror + # The generate old bytecode javac setup uses the new compiler to compile for the # boot jdk to generate tools that need to be run with the boot jdk. # Thus we force the target bytecode to 7. @@ -41,7 +45,7 @@ $(eval $(call SetupJavaCompiler,GENERATE_JDKBYTECODE,\ JVM:=$(JAVA),\ JAVAC:=$(NEW_JAVAC),\ FLAGS:=-bootclasspath $(JDK_OUTPUTDIR)/classes -source 8 -target 8 \ - -encoding ascii -XDignore.symbol.file=true $(DISABLE_WARNINGS) \ + -encoding ascii -XDignore.symbol.file=true $(JAVAC_WARNINGS) \ $(GENERATE_JDKBYTECODE_EXTRA_FLAGS),\ SERVER_DIR:=$(SJAVAC_SERVER_DIR),\ SERVER_JVM:=$(SJAVAC_SERVER_JAVA))) diff --git a/jdk/makefiles/jprt.properties b/jdk/makefiles/jprt.properties index a4a077226e8..1051bb34bb7 100644 --- a/jdk/makefiles/jprt.properties +++ b/jdk/makefiles/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -39,8 +39,8 @@ jprt.build.targets= \ solaris_x64_5.10-{product|fastdebug}, \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # User can select the test set with jprt submit "-testset name" option jprt.my.test.set=${jprt.test.set} @@ -53,8 +53,8 @@ jprt.vm.default.test.targets= \ solaris_x64_5.10-product-c2-jvm98, \ linux_i586_2.6-product-{c1|c2}-jvm98, \ linux_x64_2.6-product-c2-jvm98, \ - windows_i586_5.1-product-c1-jvm98, \ - windows_x64_5.2-product-c2-jvm98 + windows_i586_6.1-product-c1-jvm98, \ + windows_x64_6.1-product-c2-jvm98 # Select vm testlist to use (allow for testset to be empty too) jprt.vm.all.test.targets=${jprt.vm.default.test.targets} @@ -70,8 +70,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_beans1, \ linux_i586_2.6-product-{c1|c2}-jdk_beans1, \ linux_x64_2.6-product-c2-jdk_beans1, \ - windows_i586_5.1-product-c1-jdk_beans1, \ - windows_x64_5.2-product-c2-jdk_beans1, \ + windows_i586_6.1-product-c1-jdk_beans1, \ + windows_x64_6.1-product-c2-jdk_beans1, \ \ solaris_sparc_5.10-product-c1-jdk_io, \ solaris_sparcv9_5.10-product-c2-jdk_io, \ @@ -79,8 +79,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_io, \ linux_i586_2.6-product-{c1|c2}-jdk_io, \ linux_x64_2.6-product-c2-jdk_io, \ - windows_i586_5.1-product-c1-jdk_io, \ - windows_x64_5.2-product-c2-jdk_io, \ + windows_i586_6.1-product-c1-jdk_io, \ + windows_x64_6.1-product-c2-jdk_io, \ \ solaris_sparc_5.10-product-c1-jdk_lang, \ solaris_sparcv9_5.10-product-c2-jdk_lang, \ @@ -88,8 +88,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_lang, \ linux_i586_2.6-product-{c1|c2}-jdk_lang, \ linux_x64_2.6-product-c2-jdk_lang, \ - windows_i586_5.1-product-c1-jdk_lang, \ - windows_x64_5.2-product-c2-jdk_lang, \ + windows_i586_6.1-product-c1-jdk_lang, \ + windows_x64_6.1-product-c2-jdk_lang, \ \ solaris_sparc_5.10-product-c1-jdk_math, \ solaris_sparcv9_5.10-product-c2-jdk_math, \ @@ -97,8 +97,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_math, \ linux_i586_2.6-product-{c1|c2}-jdk_math, \ linux_x64_2.6-product-c2-jdk_math, \ - windows_i586_5.1-product-c1-jdk_math, \ - windows_x64_5.2-product-c2-jdk_math, \ + windows_i586_6.1-product-c1-jdk_math, \ + windows_x64_6.1-product-c2-jdk_math, \ \ solaris_sparc_5.10-product-c1-jdk_misc, \ solaris_sparcv9_5.10-product-c2-jdk_misc, \ @@ -106,8 +106,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_misc, \ linux_i586_2.6-product-{c1|c2}-jdk_misc, \ linux_x64_2.6-product-c2-jdk_misc, \ - windows_i586_5.1-product-c1-jdk_misc, \ - windows_x64_5.2-product-c2-jdk_misc, \ + windows_i586_6.1-product-c1-jdk_misc, \ + windows_x64_6.1-product-c2-jdk_misc, \ \ solaris_sparc_5.10-product-c1-jdk_net, \ solaris_sparcv9_5.10-product-c2-jdk_net, \ @@ -115,8 +115,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_net, \ linux_i586_2.6-product-{c1|c2}-jdk_net, \ linux_x64_2.6-product-c2-jdk_net, \ - windows_i586_5.1-product-c1-jdk_net, \ - windows_x64_5.2-product-c2-jdk_net, \ + windows_i586_6.1-product-c1-jdk_net, \ + windows_x64_6.1-product-c2-jdk_net, \ \ solaris_sparc_5.10-product-c1-jdk_nio1, \ solaris_sparcv9_5.10-product-c2-jdk_nio1, \ @@ -124,8 +124,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_nio1, \ linux_i586_2.6-product-{c1|c2}-jdk_nio1, \ linux_x64_2.6-product-c2-jdk_nio1, \ - windows_i586_5.1-product-c1-jdk_nio1, \ - windows_x64_5.2-product-c2-jdk_nio1, \ + windows_i586_6.1-product-c1-jdk_nio1, \ + windows_x64_6.1-product-c2-jdk_nio1, \ \ solaris_sparc_5.10-product-c1-jdk_nio2, \ solaris_sparcv9_5.10-product-c2-jdk_nio2, \ @@ -133,8 +133,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_nio2, \ linux_i586_2.6-product-{c1|c2}-jdk_nio2, \ linux_x64_2.6-product-c2-jdk_nio2, \ - windows_i586_5.1-product-c1-jdk_nio2, \ - windows_x64_5.2-product-c2-jdk_nio2, \ + windows_i586_6.1-product-c1-jdk_nio2, \ + windows_x64_6.1-product-c2-jdk_nio2, \ \ solaris_sparc_5.10-product-c1-jdk_nio3, \ solaris_sparcv9_5.10-product-c2-jdk_nio3, \ @@ -142,8 +142,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_nio3, \ linux_i586_2.6-product-{c1|c2}-jdk_nio3, \ linux_x64_2.6-product-c2-jdk_nio3, \ - windows_i586_5.1-product-c1-jdk_nio3, \ - windows_x64_5.2-product-c2-jdk_nio3, \ + windows_i586_6.1-product-c1-jdk_nio3, \ + windows_x64_6.1-product-c2-jdk_nio3, \ \ solaris_sparc_5.10-product-c1-jdk_security1, \ solaris_sparcv9_5.10-product-c2-jdk_security1, \ @@ -151,8 +151,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_security1, \ linux_i586_2.6-product-{c1|c2}-jdk_security1, \ linux_x64_2.6-product-c2-jdk_security1, \ - windows_i586_5.1-product-c1-jdk_security1, \ - windows_x64_5.2-product-c2-jdk_security1, \ + windows_i586_6.1-product-c1-jdk_security1, \ + windows_x64_6.1-product-c2-jdk_security1, \ \ solaris_sparc_5.10-product-c1-jdk_text, \ solaris_sparcv9_5.10-product-c2-jdk_text, \ @@ -160,8 +160,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_text, \ linux_i586_2.6-product-{c1|c2}-jdk_text, \ linux_x64_2.6-product-c2-jdk_text, \ - windows_i586_5.1-product-c1-jdk_text, \ - windows_x64_5.2-product-c2-jdk_text, \ + windows_i586_6.1-product-c1-jdk_text, \ + windows_x64_6.1-product-c2-jdk_text, \ \ solaris_sparc_5.10-product-c1-jdk_tools1, \ solaris_sparcv9_5.10-product-c2-jdk_tools1, \ @@ -169,8 +169,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_tools1, \ linux_i586_2.6-product-{c1|c2}-jdk_tools1, \ linux_x64_2.6-product-c2-jdk_tools1, \ - windows_i586_5.1-product-c1-jdk_tools1, \ - windows_x64_5.2-product-c2-jdk_tools1, \ + windows_i586_6.1-product-c1-jdk_tools1, \ + windows_x64_6.1-product-c2-jdk_tools1, \ \ solaris_sparc_5.10-product-c1-jdk_util, \ solaris_sparcv9_5.10-product-c2-jdk_util, \ @@ -178,8 +178,8 @@ jprt.make.rule.default.test.targets= \ solaris_x64_5.10-product-c2-jdk_util, \ linux_i586_2.6-product-{c1|c2}-jdk_util, \ linux_x64_2.6-product-c2-jdk_util, \ - windows_i586_5.1-product-c1-jdk_util, \ - windows_x64_5.2-product-c2-jdk_util + windows_i586_6.1-product-c1-jdk_util, \ + windows_x64_6.1-product-c2-jdk_util # All jdk test targets in test/Makefile (still no fastdebug & limited c2) jprt.make.rule.all.test.targets= \ @@ -192,8 +192,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_awt, \ linux_i586_2.6-product-{c1|c2}-jdk_awt, \ linux_x64_2.6-product-c2-jdk_awt, \ - windows_i586_5.1-product-c1-jdk_awt, \ - windows_x64_5.2-product-c2-jdk_awt, \ + windows_i586_6.1-product-c1-jdk_awt, \ + windows_x64_6.1-product-c2-jdk_awt, \ \ solaris_sparc_5.10-product-c1-jdk_beans2, \ solaris_sparcv9_5.10-product-c2-jdk_beans2, \ @@ -201,8 +201,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_beans2, \ linux_i586_2.6-product-{c1|c2}-jdk_beans2, \ linux_x64_2.6-product-c2-jdk_beans2, \ - windows_i586_5.1-product-c1-jdk_beans2, \ - windows_x64_5.2-product-c2-jdk_beans2, \ + windows_i586_6.1-product-c1-jdk_beans2, \ + windows_x64_6.1-product-c2-jdk_beans2, \ \ solaris_sparc_5.10-product-c1-jdk_beans3, \ solaris_sparcv9_5.10-product-c2-jdk_beans3, \ @@ -210,8 +210,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_beans3, \ linux_i586_2.6-product-{c1|c2}-jdk_beans3, \ linux_x64_2.6-product-c2-jdk_beans3, \ - windows_i586_5.1-product-c1-jdk_beans3, \ - windows_x64_5.2-product-c2-jdk_beans3, \ + windows_i586_6.1-product-c1-jdk_beans3, \ + windows_x64_6.1-product-c2-jdk_beans3, \ \ solaris_sparc_5.10-product-c1-jdk_management1, \ solaris_sparcv9_5.10-product-c2-jdk_management1, \ @@ -219,8 +219,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_management1, \ linux_i586_2.6-product-{c1|c2}-jdk_management1, \ linux_x64_2.6-product-c2-jdk_management1, \ - windows_i586_5.1-product-c1-jdk_management1, \ - windows_x64_5.2-product-c2-jdk_management1, \ + windows_i586_6.1-product-c1-jdk_management1, \ + windows_x64_6.1-product-c2-jdk_management1, \ \ solaris_sparc_5.10-product-c1-jdk_management2, \ solaris_sparcv9_5.10-product-c2-jdk_management2, \ @@ -228,8 +228,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_management2, \ linux_i586_2.6-product-{c1|c2}-jdk_management2, \ linux_x64_2.6-product-c2-jdk_management2, \ - windows_i586_5.1-product-c1-jdk_management2, \ - windows_x64_5.2-product-c2-jdk_management2, \ + windows_i586_6.1-product-c1-jdk_management2, \ + windows_x64_6.1-product-c2-jdk_management2, \ \ solaris_sparc_5.10-product-c1-jdk_rmi, \ solaris_sparcv9_5.10-product-c2-jdk_rmi, \ @@ -237,8 +237,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_rmi, \ linux_i586_2.6-product-{c1|c2}-jdk_rmi, \ linux_x64_2.6-product-c2-jdk_rmi, \ - windows_i586_5.1-product-c1-jdk_rmi, \ - windows_x64_5.2-product-c2-jdk_rmi, \ + windows_i586_6.1-product-c1-jdk_rmi, \ + windows_x64_6.1-product-c2-jdk_rmi, \ \ solaris_sparc_5.10-product-c1-jdk_security2, \ solaris_sparcv9_5.10-product-c2-jdk_security2, \ @@ -246,8 +246,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_security2, \ linux_i586_2.6-product-{c1|c2}-jdk_security2, \ linux_x64_2.6-product-c2-jdk_security2, \ - windows_i586_5.1-product-c1-jdk_security2, \ - windows_x64_5.2-product-c2-jdk_security2, \ + windows_i586_6.1-product-c1-jdk_security2, \ + windows_x64_6.1-product-c2-jdk_security2, \ \ solaris_sparc_5.10-product-c1-jdk_security3, \ solaris_sparcv9_5.10-product-c2-jdk_security3, \ @@ -255,8 +255,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_security3, \ linux_i586_2.6-product-{c1|c2}-jdk_security3, \ linux_x64_2.6-product-c2-jdk_security3, \ - windows_i586_5.1-product-c1-jdk_security3, \ - windows_x64_5.2-product-c2-jdk_security3, \ + windows_i586_6.1-product-c1-jdk_security3, \ + windows_x64_6.1-product-c2-jdk_security3, \ \ solaris_sparc_5.10-product-c1-jdk_sound, \ solaris_sparcv9_5.10-product-c2-jdk_sound, \ @@ -264,8 +264,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_sound, \ linux_i586_2.6-product-{c1|c2}-jdk_sound, \ linux_x64_2.6-product-c2-jdk_sound, \ - windows_i586_5.1-product-c1-jdk_sound, \ - windows_x64_5.2-product-c2-jdk_sound, \ + windows_i586_6.1-product-c1-jdk_sound, \ + windows_x64_6.1-product-c2-jdk_sound, \ \ solaris_sparc_5.10-product-c1-jdk_swing, \ solaris_sparcv9_5.10-product-c2-jdk_swing, \ @@ -273,8 +273,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_swing, \ linux_i586_2.6-product-{c1|c2}-jdk_swing, \ linux_x64_2.6-product-c2-jdk_swing, \ - windows_i586_5.1-product-c1-jdk_swing, \ - windows_x64_5.2-product-c2-jdk_swing, \ + windows_i586_6.1-product-c1-jdk_swing, \ + windows_x64_6.1-product-c2-jdk_swing, \ \ solaris_sparc_5.10-product-c1-jdk_tools2, \ solaris_sparcv9_5.10-product-c2-jdk_tools2, \ @@ -282,8 +282,8 @@ jprt.make.rule.all.test.targets= \ solaris_x64_5.10-product-c2-jdk_tools2, \ linux_i586_2.6-product-{c1|c2}-jdk_tools2, \ linux_x64_2.6-product-c2-jdk_tools2, \ - windows_i586_5.1-product-c1-jdk_tools2, \ - windows_x64_5.2-product-c2-jdk_tools2 + windows_i586_6.1-product-c1-jdk_tools2, \ + windows_x64_6.1-product-c2-jdk_tools2 # JCK test targets in test/Makefile (no fastdebug & limited c2, windows broken) jprt.my.jck.test.target.set= \ diff --git a/jdk/makefiles/mapfiles/libawt_xawt/mapfile-vers b/jdk/makefiles/mapfiles/libawt_xawt/mapfile-vers index 7a1a8117a3d..a2bb9bda97b 100644 --- a/jdk/makefiles/mapfiles/libawt_xawt/mapfile-vers +++ b/jdk/makefiles/mapfiles/libawt_xawt/mapfile-vers @@ -305,6 +305,7 @@ SUNWprivate_1.1 { Java_sun_awt_X11_XlibWrapper_XkbGetUpdatedMap; Java_sun_awt_X11_XlibWrapper_XkbFreeKeyboard; Java_sun_awt_X11_XlibWrapper_XkbTranslateKeyCode; + Java_sun_awt_X11_XlibWrapper_XkbSetDetectableAutoRepeat; Java_sun_awt_X11_XlibWrapper_XGetModifierMapping; Java_sun_awt_X11_XlibWrapper_XFreeModifiermap; Java_sun_awt_X11_XlibWrapper_XRefreshKeyboardMapping; diff --git a/jdk/makefiles/mapfiles/liblcms/mapfile-vers b/jdk/makefiles/mapfiles/liblcms/mapfile-vers index 024511423d3..2e63d68e5d4 100644 --- a/jdk/makefiles/mapfiles/liblcms/mapfile-vers +++ b/jdk/makefiles/mapfiles/liblcms/mapfile-vers @@ -28,9 +28,8 @@ SUNWprivate_1.1 { global: Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative; - Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative; - Java_sun_java2d_cmm_lcms_LCMS_getProfileSize; - Java_sun_java2d_cmm_lcms_LCMS_getProfileData; + Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative; + Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative; Java_sun_java2d_cmm_lcms_LCMS_getTagNative; Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative; Java_sun_java2d_cmm_lcms_LCMS_colorConvert; diff --git a/jdk/src/macosx/classes/apple/applescript/AppleScriptEngineFactory.java b/jdk/src/macosx/classes/apple/applescript/AppleScriptEngineFactory.java index 564dfe063f7..8c50b9d9301 100644 --- a/jdk/src/macosx/classes/apple/applescript/AppleScriptEngineFactory.java +++ b/jdk/src/macosx/classes/apple/applescript/AppleScriptEngineFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,14 +30,9 @@ import java.util.*; import javax.script.*; public class AppleScriptEngineFactory implements ScriptEngineFactory { - private static native void initNative(); + private static volatile boolean initialized = false; - static { - java.awt.Toolkit.getDefaultToolkit(); - System.loadLibrary("AppleScriptEngine"); - initNative(); - TRACE(""); - } + private static native void initNative(); static void TRACE(final String str) { // System.out.println(AppleScriptEngineFactory.class.getName() + "." + str); @@ -80,6 +75,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return full name of the ScriptEngine */ + @Override public String getEngineName() { TRACE("getEngineName()"); return ENGINE_NAME; @@ -90,6 +86,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return version of the ScriptEngine */ + @Override public String getEngineVersion() { TRACE("getEngineVersion()"); return ENGINE_VERSION; @@ -100,6 +97,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return name of the language supported by the ScriptEngine(Factory) */ + @Override public String getLanguageName() { TRACE("getLanguageName()"); return LANGUAGE; @@ -110,11 +108,12 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return language version supported by the ScriptEngine(Factory) */ + @Override public String getLanguageVersion() { TRACE("getLanguageVersion()"); return AccessController.doPrivileged(new PrivilegedAction() { public String run() { - final AppleScriptEngine engine = new AppleScriptEngine(AppleScriptEngineFactory.this); + final AppleScriptEngine engine = getScriptEngine(); return engine.getLanguageVersion(); } }); @@ -126,6 +125,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return ArrayList of file extensions AppleScript associates with */ + @Override public List getExtensions() { TRACE("getExtensions()"); return Arrays.asList("scpt", "applescript", "app"); @@ -137,6 +137,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return ArrayList of mimetypes that AppleScript associates with */ + @Override public List getMimeTypes() { TRACE("getMimeTypes()"); return Arrays.asList("application/x-applescript", "text/plain", "text/applescript"); @@ -148,6 +149,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return */ + @Override public List getNames() { TRACE("getNames()"); return Arrays.asList("AppleScriptEngine", "AppleScript", "OSA"); @@ -165,6 +167,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * arguments to the function * @return the AppleScript string calling the method */ + @Override public String getMethodCallSyntax(final String obj, final String fname, final String ... args) { // StringBuilder builder = new StringBuilder(); // builder.append("my " + fname + "("); @@ -181,6 +184,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * @param toDisplay * @return */ + @Override public String getOutputStatement(final String toDisplay) { // TODO -- this might even be good enough? XD return getMethodCallSyntax(null, "print", toDisplay); @@ -193,8 +197,9 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * the key to look up * @return the static preseeded value for the key in the ScriptEngine, if it exists, otherwise null */ + @Override public Object getParameter(final String key) { - final AppleScriptEngine engine = new AppleScriptEngine(this); + final AppleScriptEngine engine = getScriptEngine(); if (!engine.getBindings(ScriptContext.ENGINE_SCOPE).containsKey(key)) return null; return engine.getBindings(ScriptContext.ENGINE_SCOPE).get(key); } @@ -205,6 +210,7 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * @param statements * @return */ + @Override public String getProgram(final String ... statements) { final StringBuilder program = new StringBuilder(); for (final String statement : statements) { @@ -218,8 +224,21 @@ public class AppleScriptEngineFactory implements ScriptEngineFactory { * * @return new AppleScriptEngine with this factory as it's parent */ - public ScriptEngine getScriptEngine() { + @Override + public AppleScriptEngine getScriptEngine() { AppleScriptEngine.checkSecurity(); + ensureInitialized(); + return new AppleScriptEngine(this); } + + private static synchronized void ensureInitialized() { + if (!initialized) { + initialized = true; + + java.awt.Toolkit.getDefaultToolkit(); + System.loadLibrary("AppleScriptEngine"); + initNative(); + } + } } diff --git a/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java index b7598f99d6d..be4b5b72a32 100644 --- a/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java +++ b/jdk/src/macosx/classes/com/apple/laf/AquaFileChooserUI.java @@ -42,6 +42,7 @@ import javax.swing.filechooser.*; import javax.swing.plaf.*; import javax.swing.table.*; +import sun.swing.AbstractFilterComboBoxModel; import sun.swing.SwingUtilities2; public class AquaFileChooserUI extends FileChooserUI { @@ -1266,64 +1267,9 @@ public class AquaFileChooserUI extends FileChooserUI { /** * Data model for a type-face selection combo-box. */ - protected class FilterComboBoxModel extends DefaultListModel implements ComboBoxModel, PropertyChangeListener { - int selectedIndex = -1; - - protected FilterComboBoxModel() { - super(); - final FileFilter filters[] = getFileChooser().getChoosableFileFilters(); - for (int i = 0; i < filters.length; i++) { - this.add(i, filters[i]); - } - } - - public void propertyChange(final PropertyChangeEvent e) { - final String prop = e.getPropertyName(); - if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { - this.clear(); - final FileFilter filters[] = (FileFilter[])e.getNewValue(); - - for (int i = 0; i < filters.length; i++) { - this.add(i, filters[i]); - } - - fireContentsChanged(this, -1, -1); - } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { - final FileFilter currentFilter = (FileFilter)e.getNewValue(); - FileFilter filters[] = getFileChooser().getChoosableFileFilters(); - - boolean found = false; - if (currentFilter != null) { - for (final FileFilter element : filters) { - if (element == currentFilter) { - found = true; - } - } - if (found == false) { - getFileChooser().addChoosableFileFilter(currentFilter); - } - } - - filters = getFileChooser().getChoosableFileFilters(); - setSelectedItem(e.getNewValue()); - } - } - - public void setSelectedItem(final Object filter) { - if (filter != null) { - selectedIndex = this.indexOf(filter); - fireContentsChanged(this, -1, -1); - } - } - - public Object getSelectedItem() { - final Object returnValue = null; - - if (this.size() > 0) { - if ((selectedIndex != -1) && (selectedIndex < size())) { return this.get(selectedIndex); } - } - - return returnValue; + protected class FilterComboBoxModel extends AbstractFilterComboBoxModel { + protected JFileChooser getFileChooser() { + return AquaFileChooserUI.this.getFileChooser(); } } diff --git a/jdk/src/macosx/classes/com/apple/laf/resources/aqua_ko.properties b/jdk/src/macosx/classes/com/apple/laf/resources/aqua_ko.properties index 3fbfbe7e76e..82c4ce2f2dc 100644 --- a/jdk/src/macosx/classes/com/apple/laf/resources/aqua_ko.properties +++ b/jdk/src/macosx/classes/com/apple/laf/resources/aqua_ko.properties @@ -46,7 +46,7 @@ FileChooser.saveButton.textAndMnemonic=\uC800\uC7A5 FileChooser.openButton.textAndMnemonic=\uC5F4\uAE30 FileChooser.saveDialogTitle.textAndMnemonic=\uC800\uC7A5 FileChooser.openDialogTitle.textAndMnemonic=\uC5F4\uAE30 -FileChooser.updateButton.textAndMnemonic=\uAC31\uC2E0 +FileChooser.updateButton.textAndMnemonic=\uC5C5\uB370\uC774\uD2B8 FileChooser.helpButton.textAndMnemonic=\uB3C4\uC6C0\uB9D0 FileChooser.directoryOpenButton.textAndMnemonic=\uC5F4\uAE30 diff --git a/jdk/src/macosx/classes/sun/awt/resources/awtosx.properties b/jdk/src/macosx/classes/sun/awt/resources/awtosx.properties new file mode 100644 index 00000000000..bfc3bd01b3b --- /dev/null +++ b/jdk/src/macosx/classes/sun/awt/resources/awtosx.properties @@ -0,0 +1,71 @@ +# +# OS X specific AWT properties +# + +# Modifier names +AWT.shift=\u21e7 +AWT.control=\u2303 +AWT.alt=\u2325 +AWT.meta=\u2318 +AWT.altGraph=\u2325 + +# Key names +AWT.enter=\u23ce +AWT.backSpace=\u232b +AWT.tab=\u21e5 +AWT.cancel=\u238b +AWT.clear=\u2327 +AWT.capsLock=\u21ea +AWT.escape=\u238b +AWT.space=\u2423 +AWT.pgup=\u21de +AWT.pgdn=\u21df +AWT.end=\u2198 +AWT.home=\u2196 +AWT.left=\u2190 +AWT.up=\u2191 +AWT.right=\u2192 +AWT.down=\u2193 +AWT.comma=, +AWT.period=. +AWT.slash=/ +AWT.semicolon=; +AWT.equals=\u003d +AWT.openBracket=[ +AWT.backSlash=\\ +AWT.closeBracket=] +AWT.multiply=\u2328 * +AWT.add=\u2328 + +AWT.separator=\u2328 , +AWT.separater=\u2328 , +AWT.subtract=\u2328 - +AWT.decimal=\u2328 . +AWT.divide=\u2328 / +AWT.delete=\u2326 +AWT.printScreen=\u2399 +AWT.backQuote=` +AWT.quote=' +AWT.ampersand=& +AWT.asterisk=* +AWT.quoteDbl=" +AWT.Less=< +AWT.greater=> +AWT.braceLeft=[ +AWT.braceRight=] +AWT.at=@ +AWT.colon=: +AWT.circumflex=^ +AWT.dollar=$ +AWT.euro=\u20ac +AWT.exclamationMark=! +AWT.invertedExclamationMark=\u00a1 +AWT.leftParenthesis=( +AWT.numberSign=# +AWT.plus=+ +AWT.minus=- +AWT.rightParenthesis=) +AWT.underscore=_ + +# Numeric Keypad +AWT.numpad=\u2328 + diff --git a/jdk/src/macosx/classes/sun/lwawt/LWButtonPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWButtonPeer.java index e5f8838c8cd..f4b46c7639a 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWButtonPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWButtonPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,10 @@ import java.awt.peer.ButtonPeer; import javax.swing.JButton; +/** + * Lightweight implementation of {@link ButtonPeer}. Delegates most of the work + * to the {@link JButton}. + */ final class LWButtonPeer extends LWComponentPeer implements ButtonPeer, ActionListener { @@ -42,7 +46,7 @@ final class LWButtonPeer extends LWComponentPeer } @Override - protected JButton createDelegate() { + JButton createDelegate() { return new JButtonDelegate(); } @@ -74,6 +78,7 @@ final class LWButtonPeer extends LWComponentPeer return true; } + @SuppressWarnings("serial")// Safe: outer class is non-serializable. private final class JButtonDelegate extends JButton { // Empty non private constructor was added because access to this diff --git a/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java index 0c80ff0af0d..c7559c216c6 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWCanvasPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,10 @@ import java.awt.peer.CanvasPeer; import javax.swing.JComponent; +/** + * Lightweight implementation of {@link CanvasPeer}. This peer is empty, because + * all the components in lwawt use graphic object from the top level window. + */ class LWCanvasPeer extends LWComponentPeer implements CanvasPeer { diff --git a/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java index de1c378b860..c3b91a2fa86 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWCheckboxPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,11 @@ import javax.swing.JRadioButton; import javax.swing.JToggleButton; import javax.swing.SwingUtilities; +/** + * Lightweight implementation of {@link CheckboxPeer}. Delegates most of the + * work to the {@link JCheckBox} and {@link JRadioButton}, which are placed + * inside an empty {@link JComponent}. + */ final class LWCheckboxPeer extends LWComponentPeer implements CheckboxPeer, ItemListener { @@ -51,12 +56,12 @@ final class LWCheckboxPeer } @Override - protected CheckboxDelegate createDelegate() { + CheckboxDelegate createDelegate() { return new CheckboxDelegate(); } @Override - protected Component getDelegateFocusOwner() { + Component getDelegateFocusOwner() { return getDelegate().getCurrentButton(); } @@ -137,6 +142,7 @@ final class LWCheckboxPeer return true; } + @SuppressWarnings("serial")// Safe: outer class is non-serializable. final class CheckboxDelegate extends JComponent { private final JCheckBox cb; diff --git a/jdk/src/macosx/classes/sun/lwawt/LWChoicePeer.java b/jdk/src/macosx/classes/sun/lwawt/LWChoicePeer.java index dc781d3d682..5b78e74b6a2 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWChoicePeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWChoicePeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,14 +26,18 @@ package sun.lwawt; -import java.awt.Choice; -import java.awt.Point; +import java.awt.*; import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.peer.ChoicePeer; -import javax.swing.JComboBox; +import javax.accessibility.Accessible; +import javax.swing.*; +/** + * Lightweight implementation of {@link ChoicePeer}. Delegates most of the work + * to the {@link JComboBox}. + */ final class LWChoicePeer extends LWComponentPeer> implements ChoicePeer, ItemListener { @@ -50,7 +54,7 @@ final class LWChoicePeer extends LWComponentPeer> } @Override - protected JComboBox createDelegate() { + JComboBox createDelegate() { return new JComboBoxDelegate(); } @@ -128,6 +132,7 @@ final class LWChoicePeer extends LWComponentPeer> return true; } + @SuppressWarnings("serial")// Safe: outer class is non-serializable. private final class JComboBoxDelegate extends JComboBox { // Empty non private constructor was added because access to this @@ -159,5 +164,32 @@ final class LWChoicePeer extends LWComponentPeer> } super.setSelectedItem(anObject); } + + @Override + public void firePopupMenuWillBecomeVisible() { + super.firePopupMenuWillBecomeVisible(); + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + JPopupMenu popupMenu = getPopupMenu(); + if (popupMenu != null) { + if (popupMenu.getInvoker() != LWChoicePeer.this.getTarget()) { + popupMenu.setVisible(false); + popupMenu.show(LWChoicePeer.this.getTarget(), 0, 0); + } + } + } + }); + } + + private JPopupMenu getPopupMenu() { + for (int i = 0; i < getAccessibleContext().getAccessibleChildrenCount(); i++) { + Accessible child = getAccessibleContext().getAccessibleChild(i); + if (child instanceof JPopupMenu) { + return (JPopupMenu) child; + } + } + return null; + } } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java index 05d1d5d1fad..f6adcda7fde 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -72,19 +72,23 @@ public abstract class LWComponentPeer { private static final PlatformLogger focusLog = PlatformLogger.getLogger("sun.lwawt.focus.LWComponentPeer"); - // State lock is to be used for modifications to this - // peer's fields (e.g. bounds, background, font, etc.) - // It should be the last lock in the lock chain - private final Object stateLock = - new StringBuilder("LWComponentPeer.stateLock"); + /** + * State lock is to be used for modifications to this peer's fields (e.g. + * bounds, background, font, etc.) It should be the last lock in the lock + * chain + */ + private final Object stateLock = new Object(); - // The lock to operate with the peers hierarchy. AWT tree - // lock is not used as there are many peers related ops - // to be done on the toolkit thread, and we don't want to - // depend on a public lock on this thread - private static final Object peerTreeLock = - new StringBuilder("LWComponentPeer.peerTreeLock"); + /** + * The lock to operate with the peers hierarchy. AWT tree lock is not used + * as there are many peers related ops to be done on the toolkit thread, and + * we don't want to depend on a public lock on this thread + */ + private static final Object peerTreeLock = new Object(); + /** + * The associated AWT object. + */ private final T target; /** @@ -95,7 +99,7 @@ public abstract class LWComponentPeer * the hierarchy. The exception is LWWindowPeers: their containers are * always null */ - private final LWContainerPeer containerPeer; + private final LWContainerPeer containerPeer; /** * Handy reference to the top-level window peer. Window peer is borrowed @@ -147,11 +151,18 @@ public abstract class LWComponentPeer */ private Image backBuffer; + /** + * All Swing delegates use delegateContainer as a parent. This container + * intentionally do not use parent of the peer. + */ + @SuppressWarnings("serial")// Safe: outer class is non-serializable. private final class DelegateContainer extends Container { { enableEvents(0xFFFFFFFF); } + // Empty non private constructor was added because access to this + // class shouldn't be emulated by a synthetic accessor method. DelegateContainer() { super(); } @@ -182,7 +193,7 @@ public abstract class LWComponentPeer } } - public LWComponentPeer(T target, PlatformComponent platformComponent) { + LWComponentPeer(final T target, final PlatformComponent platformComponent) { targetPaintArea = new LWRepaintArea(); this.target = target; this.platformComponent = platformComponent; @@ -276,15 +287,18 @@ public abstract class LWComponentPeer * This method is called under getDelegateLock(). * Overridden in subclasses. */ - protected D createDelegate() { + D createDelegate() { return null; } - protected final D getDelegate() { + final D getDelegate() { return delegate; } - protected Component getDelegateFocusOwner() { + /** + * This method should be called under getDelegateLock(). + */ + Component getDelegateFocusOwner() { return getDelegate(); } @@ -356,7 +370,7 @@ public abstract class LWComponentPeer } // Just a helper method - protected final LWContainerPeer getContainerPeer() { + protected final LWContainerPeer getContainerPeer() { return containerPeer; } @@ -390,7 +404,7 @@ public abstract class LWComponentPeer protected void disposeImpl() { destroyBuffers(); - LWContainerPeer cp = getContainerPeer(); + LWContainerPeer cp = getContainerPeer(); if (cp != null) { cp.removeChildPeer(this); } @@ -462,12 +476,13 @@ public abstract class LWComponentPeer sg2d.constrain(size.x, size.y, size.width, size.height, getVisibleRegion()); } - public Region getVisibleRegion() { + Region getVisibleRegion() { return computeVisibleRect(this, getRegion()); } - static final Region computeVisibleRect(LWComponentPeer c, Region region) { - final LWContainerPeer p = c.getContainerPeer(); + static final Region computeVisibleRect(final LWComponentPeer c, + Region region) { + final LWContainerPeer p = c.getContainerPeer(); if (p != null) { final Rectangle r = c.getBounds(); region = region.getTranslatedRegion(r.x, r.y); @@ -612,7 +627,7 @@ public abstract class LWComponentPeer * @param p Point relative to the peer. * @return Cursor of the peer or null if default cursor should be used. */ - protected Cursor getCursor(final Point p) { + Cursor getCursor(final Point p) { return getTarget().getCursor(); } @@ -717,7 +732,7 @@ public abstract class LWComponentPeer @Override public void setEnabled(final boolean e) { boolean status = e; - final LWComponentPeer cp = getContainerPeer(); + final LWComponentPeer cp = getContainerPeer(); if (cp != null) { status &= cp.isEnabled(); } @@ -802,12 +817,12 @@ public abstract class LWComponentPeer } @Override - public void setZOrder(ComponentPeer above) { - LWContainerPeer cp = getContainerPeer(); + public void setZOrder(final ComponentPeer above) { + LWContainerPeer cp = getContainerPeer(); // Don't check containerPeer for null as it can only happen // for windows, but this method is overridden in // LWWindowPeer and doesn't call super() - cp.setChildPeerZOrder(this, (LWComponentPeer) above); + cp.setChildPeerZOrder(this, (LWComponentPeer) above); } @Override @@ -923,7 +938,9 @@ public abstract class LWComponentPeer LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget()); return false; } - LWWindowPeer parentPeer = (LWWindowPeer) parentWindow.getPeer(); + final LWWindowPeer parentPeer = + (LWWindowPeer) AWTAccessor.getComponentAccessor() + .getPeer(parentWindow); if (parentPeer == null) { focusLog.fine("request rejected, parentPeer is null"); LWKeyboardFocusManagerPeer.removeLastFocusRequest(getTarget()); @@ -1138,7 +1155,7 @@ public abstract class LWComponentPeer } protected final void repaintParent(final Rectangle oldB) { - final LWContainerPeer cp = getContainerPeer(); + final LWContainerPeer cp = getContainerPeer(); if (cp != null) { // Repaint unobscured part of the parent cp.repaintPeer(cp.getContentSize().intersection(oldB)); @@ -1254,6 +1271,8 @@ public abstract class LWComponentPeer KeyEvent ke = (KeyEvent) e; delegateEvent = new KeyEvent(getDelegateFocusOwner(), ke.getID(), ke.getWhen(), ke.getModifiers(), ke.getKeyCode(), ke.getKeyChar(), ke.getKeyLocation()); + AWTAccessor.getKeyEventAccessor().setExtendedKeyCode((KeyEvent) delegateEvent, + ke.getExtendedKeyCode()); } else if (e instanceof FocusEvent) { FocusEvent fe = (FocusEvent) e; delegateEvent = new FocusEvent(getDelegateFocusOwner(), fe.getID(), fe.isTemporary()); @@ -1273,7 +1292,7 @@ public abstract class LWComponentPeer /** * Handler for FocusEvents. */ - protected void handleJavaFocusEvent(FocusEvent e) { + void handleJavaFocusEvent(final FocusEvent e) { // Note that the peer receives all the FocusEvents from // its lightweight children as well KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); @@ -1309,7 +1328,7 @@ public abstract class LWComponentPeer * Finds a top-most visible component for the given point. The location is * specified relative to the peer's parent. */ - public LWComponentPeer findPeerAt(final int x, final int y) { + LWComponentPeer findPeerAt(final int x, final int y) { final Rectangle r = getBounds(); final Region sh = getRegion(); final boolean found = isVisible() && sh.contains(x - r.x, y - r.y); @@ -1326,7 +1345,7 @@ public abstract class LWComponentPeer } public Point windowToLocal(Point p, LWWindowPeer wp) { - LWComponentPeer cp = this; + LWComponentPeer cp = this; while (cp != wp) { Rectangle cpb = cp.getBounds(); p.x -= cpb.x; @@ -1347,7 +1366,7 @@ public abstract class LWComponentPeer } public Point localToWindow(Point p) { - LWComponentPeer cp = getContainerPeer(); + LWComponentPeer cp = getContainerPeer(); Rectangle r = getBounds(); while (cp != null) { p.x += r.x; @@ -1368,7 +1387,7 @@ public abstract class LWComponentPeer repaintPeer(getSize()); } - public void repaintPeer(final Rectangle r) { + void repaintPeer(final Rectangle r) { final Rectangle toPaint = getSize().intersection(r); if (!isShowing() || toPaint.isEmpty()) { return; @@ -1387,7 +1406,7 @@ public abstract class LWComponentPeer protected final boolean isShowing() { synchronized (getPeerTreeLock()) { if (isVisible()) { - final LWContainerPeer container = getContainerPeer(); + final LWContainerPeer container = getContainerPeer(); return (container == null) || container.isShowing(); } } @@ -1395,8 +1414,7 @@ public abstract class LWComponentPeer } /** - * Paints the peer. Overridden in subclasses to delegate the actual painting - * to Swing components. + * Paints the peer. Delegate the actual painting to Swing components. */ protected final void paintPeer(final Graphics g) { final D delegate = getDelegate(); diff --git a/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java index c213664b8ce..3069d3c2a3b 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWContainerPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,32 +41,25 @@ import java.util.List; import javax.swing.JComponent; abstract class LWContainerPeer - extends LWCanvasPeer - implements ContainerPeer -{ - // List of child peers sorted by z-order from bottom-most - // to top-most - private List childPeers = - new LinkedList(); + extends LWCanvasPeer implements ContainerPeer { - LWContainerPeer(T target, PlatformComponent platformComponent) { + /** + * List of child peers sorted by z-order from bottom-most to top-most. + */ + private final List> childPeers = new LinkedList<>(); + + LWContainerPeer(final T target, final PlatformComponent platformComponent) { super(target, platformComponent); } - void addChildPeer(LWComponentPeer child) { + final void addChildPeer(final LWComponentPeer child) { synchronized (getPeerTreeLock()) { - addChildPeer(child, childPeers.size()); + childPeers.add(childPeers.size(), child); + // TODO: repaint } } - void addChildPeer(LWComponentPeer child, int index) { - synchronized (getPeerTreeLock()) { - childPeers.add(index, child); - } - // TODO: repaint - } - - void removeChildPeer(LWComponentPeer child) { + final void removeChildPeer(final LWComponentPeer child) { synchronized (getPeerTreeLock()) { childPeers.remove(child); } @@ -74,7 +67,8 @@ abstract class LWContainerPeer } // Used by LWComponentPeer.setZOrder() - void setChildPeerZOrder(LWComponentPeer peer, LWComponentPeer above) { + final void setChildPeerZOrder(final LWComponentPeer peer, + final LWComponentPeer above) { synchronized (getPeerTreeLock()) { childPeers.remove(peer); int index = (above != null) ? childPeers.indexOf(above) : childPeers.size(); @@ -98,25 +92,27 @@ abstract class LWContainerPeer } @Override - public void beginValidate() { - // TODO: it seems that begin/endValidate() is only useful - // for heavyweight windows, when a batch movement for - // child windows occurs. That's why no-op - } - @Override - public void endValidate() { + public final void beginValidate() { // TODO: it seems that begin/endValidate() is only useful // for heavyweight windows, when a batch movement for // child windows occurs. That's why no-op } @Override - public void beginLayout() { + public final void endValidate() { + // TODO: it seems that begin/endValidate() is only useful + // for heavyweight windows, when a batch movement for + // child windows occurs. That's why no-op + } + + @Override + public final void beginLayout() { // Skip all painting till endLayout() setLayouting(true); } + @Override - public void endLayout() { + public final void endLayout() { setLayouting(false); // Post an empty event to flush all the pending target paints @@ -125,18 +121,19 @@ abstract class LWContainerPeer // ---- PEER NOTIFICATIONS ---- // - /* + /** * Returns a copy of the childPeer collection. */ - protected List getChildren() { + @SuppressWarnings("unchecked") + final List> getChildren() { synchronized (getPeerTreeLock()) { - Object copy = ((LinkedList)childPeers).clone(); - return (List)copy; + Object copy = ((LinkedList) childPeers).clone(); + return (List>) copy; } } @Override - public final Region getVisibleRegion() { + final Region getVisibleRegion() { return cutChildren(super.getVisibleRegion(), null); } @@ -144,9 +141,9 @@ abstract class LWContainerPeer * Removes bounds of children above specific child from the region. If above * is null removes all bounds of children. */ - protected final Region cutChildren(Region r, final LWComponentPeer above) { + final Region cutChildren(Region r, final LWComponentPeer above) { boolean aboveFound = above == null; - for (final LWComponentPeer child : getChildren()) { + for (final LWComponentPeer child : getChildren()) { if (!aboveFound && child == above) { aboveFound = true; continue; @@ -170,8 +167,8 @@ abstract class LWContainerPeer * specified relative to the peer's parent. */ @Override - public final LWComponentPeer findPeerAt(int x, int y) { - LWComponentPeer peer = super.findPeerAt(x, y); + final LWComponentPeer findPeerAt(int x, int y) { + LWComponentPeer peer = super.findPeerAt(x, y); final Rectangle r = getBounds(); // Translate to this container's coordinates to pass to children x -= r.x; @@ -179,7 +176,7 @@ abstract class LWContainerPeer if (peer != null && getContentSize().contains(x, y)) { synchronized (getPeerTreeLock()) { for (int i = childPeers.size() - 1; i >= 0; --i) { - LWComponentPeer p = childPeers.get(i).findPeerAt(x, y); + LWComponentPeer p = childPeers.get(i).findPeerAt(x, y); if (p != null) { peer = p; break; @@ -195,7 +192,7 @@ abstract class LWContainerPeer * peers should be repainted */ @Override - public final void repaintPeer(final Rectangle r) { + final void repaintPeer(final Rectangle r) { final Rectangle toPaint = getSize().intersection(r); if (!isShowing() || toPaint.isEmpty()) { return; @@ -208,13 +205,13 @@ abstract class LWContainerPeer repaintChildren(toPaint); } - /* - * Paints all the child peers in the straight z-order, so the - * bottom-most ones are painted first. - */ + /** + * Paints all the child peers in the straight z-order, so the + * bottom-most ones are painted first. + */ private void repaintChildren(final Rectangle r) { final Rectangle content = getContentSize(); - for (final LWComponentPeer child : getChildren()) { + for (final LWComponentPeer child : getChildren()) { final Rectangle childBounds = child.getBounds(); Rectangle toPaint = r.intersection(childBounds); toPaint = toPaint.intersection(content); @@ -223,21 +220,21 @@ abstract class LWContainerPeer } } - protected Rectangle getContentSize() { + Rectangle getContentSize() { return getSize(); } @Override public void setEnabled(final boolean e) { super.setEnabled(e); - for (final LWComponentPeer child : getChildren()) { + for (final LWComponentPeer child : getChildren()) { child.setEnabled(e && child.getTarget().isEnabled()); } } @Override public void setBackground(final Color c) { - for (final LWComponentPeer child : getChildren()) { + for (final LWComponentPeer child : getChildren()) { if (!child.getTarget().isBackgroundSet()) { child.setBackground(c); } @@ -247,7 +244,7 @@ abstract class LWContainerPeer @Override public void setForeground(final Color c) { - for (final LWComponentPeer child : getChildren()) { + for (final LWComponentPeer child : getChildren()) { if (!child.getTarget().isForegroundSet()) { child.setForeground(c); } @@ -257,7 +254,7 @@ abstract class LWContainerPeer @Override public void setFont(final Font f) { - for (final LWComponentPeer child : getChildren()) { + for (final LWComponentPeer child : getChildren()) { if (!child.getTarget().isFontSet()) { child.setFont(f); } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java b/jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java index de1b537856a..e17cced7021 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWCursorManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.awt.Point; import java.util.concurrent.atomic.AtomicBoolean; +import sun.awt.AWTAccessor; import sun.awt.SunToolkit; public abstract class LWCursorManager { @@ -105,11 +106,13 @@ public abstract class LWCursorManager { c = peer.getTarget(); if (c instanceof Container) { final Point p = peer.getLocationOnScreen(); - c = ((Container) c).findComponentAt(cursorPos.x - p.x, - cursorPos.y - p.y); + c = AWTAccessor.getContainerAccessor().findComponentAt( + (Container) c, cursorPos.x - p.x, cursorPos.y - p.y, false); + } while (c != null) { - if (c.isVisible() && c.isEnabled() && (c.getPeer() != null)) { + final Object p = AWTAccessor.getComponentAccessor().getPeer(c); + if (c.isVisible() && c.isEnabled() && p != null) { break; } c = c.getParent(); diff --git a/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java index 19743da74a3..68af14af333 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWLabelPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ final class LWLabelPeer extends LWComponentPeer } @Override - protected JLabel createDelegate() { + JLabel createDelegate() { return new JLabel(); } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java index 90e2e88c441..624be6bfc10 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -34,6 +34,8 @@ import java.awt.dnd.DropTarget; import sun.awt.CausedFocusEvent; import sun.awt.LightweightFrame; +import sun.swing.JLightweightFrame; +import sun.swing.SwingAccessor; public class LWLightweightFramePeer extends LWWindowPeer { @@ -90,11 +92,6 @@ public class LWLightweightFramePeer extends LWWindowPeer { setBounds(x, y, w, h, op, true, false); } - @Override - public void updateCursorImmediately() { - // TODO: tries to switch to the awt/fx toolkit thread and causes a deadlock on macosx - } - @Override public void addDropTarget(DropTarget dt) { } @@ -112,4 +109,9 @@ public class LWLightweightFramePeer extends LWWindowPeer { public void ungrab() { getLwTarget().ungrabFocus(); } + + @Override + public void updateCursorImmediately() { + SwingAccessor.getJLightweightFrameAccessor().updateCursor((JLightweightFrame)getLwTarget()); + } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java index 5edb8e16cd0..e6e1ec38c3d 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWListPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,8 @@ import java.awt.peer.ListPeer; import java.util.Arrays; /** - * Lightweight implementation of {@link ListPeer}. + * Lightweight implementation of {@link ListPeer}. Delegates most of the work to + * the {@link JList}, which is placed inside {@link JScrollPane}. */ final class LWListPeer extends LWComponentPeer implements ListPeer { @@ -56,7 +57,7 @@ final class LWListPeer extends LWComponentPeer } @Override - protected ScrollableJList createDelegate() { + ScrollableJList createDelegate() { return new ScrollableJList(); } @@ -78,7 +79,7 @@ final class LWListPeer extends LWComponentPeer } @Override - protected Component getDelegateFocusOwner() { + Component getDelegateFocusOwner() { return getDelegate().getView(); } @@ -193,6 +194,7 @@ final class LWListPeer extends LWComponentPeer } } + @SuppressWarnings("serial")// Safe: outer class is non-serializable. final class ScrollableJList extends JScrollPane implements ListSelectionListener { private boolean skipStateChangedEvent; @@ -234,9 +236,10 @@ final class LWListPeer extends LWComponentPeer } @Override + @SuppressWarnings("unchecked") public void valueChanged(final ListSelectionEvent e) { if (!e.getValueIsAdjusting() && !isSkipStateChangedEvent()) { - final JList source = (JList) e.getSource(); + final JList source = (JList) e.getSource(); for(int i = 0 ; i < source.getModel().getSize(); i++) { final boolean wasSelected = Arrays.binarySearch(oldSelectedIndices, i) >= 0; @@ -255,6 +258,7 @@ final class LWListPeer extends LWComponentPeer } } + @SuppressWarnings("unchecked") public JList getView() { return (JList) getViewport().getView(); } @@ -289,7 +293,7 @@ final class LWListPeer extends LWComponentPeer private final class JListDelegate extends JList { JListDelegate() { - super(ScrollableJList.this.model); + super(model); } @Override diff --git a/jdk/src/macosx/classes/sun/lwawt/LWMouseInfoPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWMouseInfoPeer.java index 2cce1b17269..1920a73d3b0 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWMouseInfoPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWMouseInfoPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,9 @@ import java.awt.Window; import java.awt.peer.MouseInfoPeer; -public class LWMouseInfoPeer implements MouseInfoPeer { +import sun.awt.AWTAccessor; - public LWMouseInfoPeer() { - } +public class LWMouseInfoPeer implements MouseInfoPeer { @Override public int fillPointWithCoords(Point point) { @@ -52,7 +51,7 @@ public class LWMouseInfoPeer implements MouseInfoPeer { return false; } - LWWindowPeer windowPeer = (LWWindowPeer)w.getPeer(); + final Object windowPeer = AWTAccessor.getComponentAccessor().getPeer(w); return LWWindowPeer.getWindowUnderCursor() == windowPeer; } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java index 6b1f48b08ad..ef1e93e8b11 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWPanelPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,10 @@ import java.awt.peer.PanelPeer; import javax.swing.JPanel; +/** + * Lightweight implementation of {@link PanelPeer}. Delegates most of the work + * to the {@link JPanel}. + */ final class LWPanelPeer extends LWContainerPeer implements PanelPeer { @@ -39,7 +43,7 @@ final class LWPanelPeer extends LWContainerPeer } @Override - public JPanel createDelegate() { + JPanel createDelegate() { return new JPanel(); } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java b/jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java index e67b2fa435e..7b7c7e8b67d 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWRepaintArea.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,39 +26,38 @@ package sun.lwawt; -import sun.awt.RepaintArea; - import java.awt.Component; import java.awt.Graphics; +import sun.awt.AWTAccessor; +import sun.awt.RepaintArea; + /** + * Emulates appearance of heavyweight components before call of the user code. + * * @author Sergey Bylokhov */ final class LWRepaintArea extends RepaintArea { @Override protected void updateComponent(final Component comp, final Graphics g) { + // We shouldn't paint native component as a result of UPDATE events, + // just flush onscreen back-buffer. if (comp != null) { super.updateComponent(comp, g); - flushBuffers((LWComponentPeer) comp.getPeer()); + LWComponentPeer.flushOnscreenGraphics(); } } @Override protected void paintComponent(final Component comp, final Graphics g) { if (comp != null) { - final LWComponentPeer peer = (LWComponentPeer) comp.getPeer(); + Object peer = AWTAccessor.getComponentAccessor().getPeer(comp); if (peer != null) { - peer.paintPeer(g); + ((LWComponentPeer) peer).paintPeer(g); } super.paintComponent(comp, g); - flushBuffers(peer); - } - } - - private static void flushBuffers(final LWComponentPeer peer) { - if (peer != null) { - peer.flushOnscreenGraphics(); + LWComponentPeer.flushOnscreenGraphics(); } } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java index f5cb0d576e6..6fce0d58461 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWScrollBarPeer.java @@ -34,10 +34,14 @@ import java.awt.peer.ScrollbarPeer; import javax.swing.JScrollBar; +/** + * Lightweight implementation of {@link ScrollbarPeer}. Delegates most of the + * work to the {@link JScrollBar}. + */ final class LWScrollBarPeer extends LWComponentPeer implements ScrollbarPeer, AdjustmentListener { - //JScrollBar fires two changes with firePropertyChange (one for old value + // JScrollBar fires two changes with firePropertyChange (one for old value // and one for new one. // We save the last value and don't fire event if not changed. private int currentValue; @@ -48,7 +52,7 @@ final class LWScrollBarPeer extends LWComponentPeer } @Override - protected JScrollBar createDelegate() { + JScrollBar createDelegate() { return new JScrollBar(); } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWScrollPanePeer.java b/jdk/src/macosx/classes/sun/lwawt/LWScrollPanePeer.java index 723a9dd8da7..4db7cac124a 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWScrollPanePeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWScrollPanePeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,10 @@ import java.awt.event.MouseWheelEvent; import java.awt.peer.ScrollPanePeer; import java.util.List; +/** + * Lightweight implementation of {@link ScrollPanePeer}. Delegates most of the + * work to the {@link JScrollPane}. + */ final class LWScrollPanePeer extends LWContainerPeer implements ScrollPanePeer, ChangeListener { @@ -41,7 +45,8 @@ final class LWScrollPanePeer extends LWContainerPeer super(target, platformComponent); } - protected JScrollPane createDelegate() { + @Override + JScrollPane createDelegate() { final JScrollPane sp = new JScrollPane(); final JPanel panel = new JPanel(); panel.setOpaque(false); @@ -72,7 +77,7 @@ final class LWScrollPanePeer extends LWContainerPeer SwingUtilities.invokeLater(new Runnable() { @Override public void run() { - final LWComponentPeer viewPeer = getViewPeer(); + final LWComponentPeer viewPeer = getViewPeer(); if (viewPeer != null) { final Rectangle r; synchronized (getDelegateLock()) { @@ -96,14 +101,13 @@ final class LWScrollPanePeer extends LWContainerPeer } } - LWComponentPeer getViewPeer() { - List peerList = getChildren(); + LWComponentPeer getViewPeer() { + final List> peerList = getChildren(); return peerList.isEmpty() ? null : peerList.get(0); } - @Override - protected Rectangle getContentSize() { + Rectangle getContentSize() { Rectangle viewRect = getDelegate().getViewport().getViewRect(); return new Rectangle(viewRect.width, viewRect.height); } @@ -112,7 +116,7 @@ final class LWScrollPanePeer extends LWContainerPeer public void layout() { super.layout(); synchronized (getDelegateLock()) { - LWComponentPeer viewPeer = getViewPeer(); + final LWComponentPeer viewPeer = getViewPeer(); if (viewPeer != null) { Component view = getDelegate().getViewport().getView(); view.setBounds(viewPeer.getBounds()); diff --git a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java index 98032e20c29..5db1b6ca296 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextAreaPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,7 +44,7 @@ import javax.swing.text.JTextComponent; /** * Lightweight implementation of {@link TextAreaPeer}. Delegates most of the - * work to the {@link JTextArea} inside JScrollPane. + * work to the {@link JTextArea} inside {@link JScrollPane}. */ final class LWTextAreaPeer extends LWTextComponentPeer @@ -66,7 +66,7 @@ final class LWTextAreaPeer } @Override - protected ScrollableJTextArea createDelegate() { + ScrollableJTextArea createDelegate() { return new ScrollableJTextArea(); } @@ -85,7 +85,7 @@ final class LWTextAreaPeer } @Override - protected Cursor getCursor(final Point p) { + Cursor getCursor(final Point p) { final boolean isContains; synchronized (getDelegateLock()) { isContains = getDelegate().getViewport().getBounds().contains(p); @@ -94,7 +94,7 @@ final class LWTextAreaPeer } @Override - protected Component getDelegateFocusOwner() { + Component getDelegateFocusOwner() { return getTextComponent(); } @@ -200,7 +200,7 @@ final class LWTextAreaPeer } } - @SuppressWarnings("serial") + @SuppressWarnings("serial")// Safe: outer class is non-serializable. final class ScrollableJTextArea extends JScrollPane { ScrollableJTextArea() { @@ -218,7 +218,6 @@ final class LWTextAreaPeer super.setEnabled(enabled); } - @SuppressWarnings("serial") private final class JTextAreaDelegate extends JTextArea { // Empty non private constructor was added because access to this diff --git a/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java index aab0baf43e0..860aa546610 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWTextComponentPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,11 +44,14 @@ import javax.swing.event.DocumentListener; import javax.swing.text.Document; import javax.swing.text.JTextComponent; +/** + * Lightweight implementation of {@link TextComponentPeer}. Provides useful + * methods for {@link LWTextAreaPeer} and {@link LWTextFieldPeer} + */ abstract class LWTextComponentPeer extends LWComponentPeer implements DocumentListener, TextComponentPeer, InputMethodListener { - private volatile boolean firstChangeSkipped; LWTextComponentPeer(final T target, @@ -218,14 +221,14 @@ abstract class LWTextComponentPeer implements TextFieldPeer, ActionListener { @@ -47,7 +51,7 @@ final class LWTextFieldPeer } @Override - protected JPasswordField createDelegate() { + JPasswordField createDelegate() { return new JPasswordFieldDelegate(); } @@ -107,7 +111,7 @@ final class LWTextFieldPeer * @param e the focus event */ @Override - protected void handleJavaFocusEvent(final FocusEvent e) { + void handleJavaFocusEvent(final FocusEvent e) { if (e.getID() == FocusEvent.FOCUS_LOST) { // In order to de-select the selection setCaretPosition(0); @@ -115,6 +119,7 @@ final class LWTextFieldPeer super.handleJavaFocusEvent(e); } + @SuppressWarnings("serial")// Safe: outer class is non-serializable. private final class JPasswordFieldDelegate extends JPasswordField { // Empty non private constructor was added because access to this diff --git a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java index fb7032f0b74..f98dffbf3f1 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWToolkit.java @@ -38,6 +38,7 @@ import java.util.*; import sun.awt.*; import sun.lwawt.macosx.*; import sun.print.*; +import sun.security.util.SecurityConstants; public abstract class LWToolkit extends SunToolkit implements Runnable { @@ -502,7 +503,7 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { public Clipboard getSystemClipboard() { SecurityManager security = System.getSecurityManager(); if (security != null) { - security.checkSystemClipboardAccess(); + security.checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION); } synchronized (this) { @@ -556,16 +557,18 @@ public abstract class LWToolkit extends SunToolkit implements Runnable { } @Override - public void grab(Window w) { - if (w.getPeer() != null) { - ((LWWindowPeer)w.getPeer()).grab(); + public void grab(final Window w) { + final Object peer = AWTAccessor.getComponentAccessor().getPeer(w); + if (peer != null) { + ((LWWindowPeer) peer).grab(); } } @Override - public void ungrab(Window w) { - if (w.getPeer() != null) { - ((LWWindowPeer)w.getPeer()).ungrab(false); + public void ungrab(final Window w) { + final Object peer = AWTAccessor.getComponentAccessor().getPeer(w); + if (peer != null) { + ((LWWindowPeer) peer).ungrab(false); } } diff --git a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java index 2be41cf3b0d..632fe844e7b 100644 --- a/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -43,7 +43,7 @@ public class LWWindowPeer extends LWContainerPeer implements FramePeer, DialogPeer, FullScreenCapable, DisplayChangedListener, PlatformEventNotifier { - public static enum PeerType { + public enum PeerType { SIMPLEWINDOW, FRAME, DIALOG, @@ -83,15 +83,15 @@ public class LWWindowPeer // A peer where the last mouse event came to. Used by cursor manager to // find the component under cursor - private static volatile LWComponentPeer lastCommonMouseEventPeer = null; + private static volatile LWComponentPeer lastCommonMouseEventPeer; // A peer where the last mouse event came to. Used to generate // MOUSE_ENTERED/EXITED notifications - private volatile LWComponentPeer lastMouseEventPeer; + private volatile LWComponentPeer lastMouseEventPeer; // Peers where all dragged/released events should come to, // depending on what mouse button is being dragged according to Cocoa - private static LWComponentPeer mouseDownTarget[] = new LWComponentPeer[3]; + private static final LWComponentPeer[] mouseDownTarget = new LWComponentPeer[3]; // A bitmask that indicates what mouse buttons produce MOUSE_CLICKED events // on MOUSE_RELEASE. Click events are only generated if there were no drag @@ -129,7 +129,8 @@ public class LWWindowPeer this.peerType = peerType; Window owner = target.getOwner(); - LWWindowPeer ownerPeer = (owner != null) ? (LWWindowPeer)owner.getPeer() : null; + LWWindowPeer ownerPeer = owner == null ? null : + (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(owner); PlatformWindow ownerDelegate = (ownerPeer != null) ? ownerPeer.getPlatformWindow() : null; // The delegate.initialize() needs a non-null GC on X11. @@ -163,10 +164,10 @@ public class LWWindowPeer // Init warning window(for applets) SecurityWarningWindow warn = null; - if (((Window)target).getWarningString() != null) { + if (target.getWarningString() != null) { // accessSystemTray permission allows to display TrayIcon, TrayIcon tooltip // and TrayIcon balloon windows without a warning window. - if (!AWTAccessor.getWindowAccessor().isTrayIconWindow((Window)target)) { + if (!AWTAccessor.getWindowAccessor().isTrayIconWindow(target)) { LWToolkit toolkit = (LWToolkit)Toolkit.getDefaultToolkit(); warn = toolkit.createSecurityWarning(target, this); } @@ -210,6 +211,7 @@ public class LWWindowPeer } // Just a helper method + @Override public PlatformWindow getPlatformWindow() { return platformWindow; } @@ -391,7 +393,8 @@ public class LWWindowPeer @Override public void setModalBlocked(Dialog blocker, boolean blocked) { synchronized (getPeerTreeLock()) { - this.blocker = blocked ? (LWWindowPeer)blocker.getPeer() : null; + this.blocker = !blocked ? null : + (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(blocker); } platformWindow.setModalBlocked(blocked); @@ -458,6 +461,7 @@ public class LWWindowPeer textured = isTextured; } + @Override public final boolean isTranslucent() { synchronized (getStateLock()) { /* @@ -537,7 +541,8 @@ public class LWWindowPeer public void blockWindows(List windows) { //TODO: LWX will probably need some collectJavaToplevels to speed this up for (Window w : windows) { - WindowPeer wp = (WindowPeer)w.getPeer(); + WindowPeer wp = + (WindowPeer) AWTAccessor.getComponentAccessor().getPeer(w); if (wp != null) { wp.setModalBlocked((Dialog)getTarget(), true); } @@ -694,7 +699,7 @@ public class LWWindowPeer // TODO: fill "bdata" member of AWTEvent Rectangle r = getBounds(); // findPeerAt() expects parent coordinates - LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y); + LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y); if (id == MouseEvent.MOUSE_EXITED) { isMouseOver = false; @@ -743,7 +748,7 @@ public class LWWindowPeer screenX, screenY, modifiers, clickCount, popupTrigger, targetPeer); } else { - LWComponentPeer topmostTargetPeer = + LWComponentPeer topmostTargetPeer = topmostWindowPeer != null ? topmostWindowPeer.findPeerAt(r.x + x, r.y + y) : null; topmostWindowPeer.generateMouseEnterExitEventsForComponents(when, button, x, y, screenX, screenY, modifiers, clickCount, popupTrigger, @@ -840,7 +845,7 @@ public class LWWindowPeer private void generateMouseEnterExitEventsForComponents(long when, int button, int x, int y, int screenX, int screenY, int modifiers, int clickCount, boolean popupTrigger, - LWComponentPeer targetPeer) { + final LWComponentPeer targetPeer) { if (!isMouseOver || targetPeer == lastMouseEventPeer) { return; @@ -899,7 +904,7 @@ public class LWWindowPeer // TODO: could we just use the last mouse event target here? Rectangle r = getBounds(); // findPeerAt() expects parent coordinates - final LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y); + final LWComponentPeer targetPeer = findPeerAt(r.x + x, r.y + y); if (targetPeer == null || !targetPeer.isEnabled()) { return; } @@ -933,7 +938,12 @@ public class LWWindowPeer focusOwner = this.getTarget(); } } - postEvent(new KeyEvent(focusOwner, id, when, modifiers, keyCode, keyChar, keyLocation)); + + KeyEvent keyEvent = new KeyEvent(focusOwner, id, when, modifiers, + keyCode, keyChar, keyLocation); + AWTAccessor.getKeyEventAccessor().setExtendedKeyCode(keyEvent, + ExtendedKeyCodes.getExtendedKeyCodeForChar(keyChar)); + postEvent(keyEvent); } // ---- UTILITY METHODS ---- // @@ -1152,8 +1162,9 @@ public class LWWindowPeer if (focusLog.isLoggable(PlatformLogger.Level.FINE)) { focusLog.fine("requesting native focus to the owner " + owner); } - LWWindowPeer currentActivePeer = (currentActive != null ? - (LWWindowPeer)currentActive.getPeer() : null); + LWWindowPeer currentActivePeer = currentActive == null ? null : + (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer( + currentActive); // Ensure the opposite is natively active and suppress sending events. if (currentActivePeer != null && currentActivePeer.platformWindow.isActive()) { @@ -1265,7 +1276,8 @@ public class LWWindowPeer while (owner != null && !(owner instanceof Frame || owner instanceof Dialog)) { owner = owner.getOwner(); } - return owner != null ? (LWWindowPeer)owner.getPeer() : null; + return owner == null ? null : + (LWWindowPeer) AWTAccessor.getComponentAccessor().getPeer(owner); } /** @@ -1284,11 +1296,13 @@ public class LWWindowPeer } } + @Override public void enterFullScreenMode() { platformWindow.enterFullScreenMode(); updateSecurityWarningVisibility(); } + @Override public void exitFullScreenMode() { platformWindow.exitFullScreenMode(); updateSecurityWarningVisibility(); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java index 56a7061325e..cad1b36aa9c 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenu.java @@ -26,9 +26,11 @@ package sun.lwawt.macosx; import java.awt.*; +import java.awt.peer.MenuItemPeer; import java.awt.peer.MenuPeer; public class CMenu extends CMenuItem implements MenuPeer { + public CMenu(Menu target) { super(target); } @@ -40,6 +42,20 @@ public class CMenu extends CMenuItem implements MenuPeer { setEnabled(target.isEnabled()); } + @Override + public final void setEnabled(final boolean b) { + super.setEnabled(b); + final Menu target = (Menu) getTarget(); + final int count = target.getItemCount(); + for (int i = 0; i < count; ++i) { + MenuItem item = target.getItem(i); + MenuItemPeer p = (MenuItemPeer) LWCToolkit.targetToPeer(item); + if (p != null) { + p.setEnabled(b && item.isEnabled()); + } + } + } + @Override protected long createModel() { CMenuComponent parent = (CMenuComponent) diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java index ac3bea392a1..b1492bd0a43 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CMenuItem.java @@ -28,17 +28,20 @@ package sun.lwawt.macosx; import sun.awt.SunToolkit; import sun.lwawt.LWToolkit; +import java.awt.MenuContainer; import java.awt.MenuItem; import java.awt.MenuShortcut; import java.awt.event.*; import java.awt.peer.MenuItemPeer; +import java.util.concurrent.atomic.AtomicBoolean; public class CMenuItem extends CMenuComponent implements MenuItemPeer { + private final AtomicBoolean enabled = new AtomicBoolean(true); + public CMenuItem(MenuItem target) { super(target); initialize(target); - } // This way we avoiding invocation of the setters twice @@ -124,9 +127,19 @@ public class CMenuItem extends CMenuComponent implements MenuItemPeer { setEnabled(false); } + public final boolean isEnabled() { + return enabled.get(); + } + @Override public void setEnabled(boolean b) { - nativeSetEnabled(getModel(), b); + final Object parent = LWToolkit.targetToPeer(getTarget().getParent()); + if (parent instanceof CMenuItem) { + b &= ((CMenuItem) parent).isEnabled(); + } + if (enabled.compareAndSet(!b, b)) { + nativeSetEnabled(getModel(), b); + } } private native long nativeCreate(long parentMenu, boolean isSeparator); diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java index d38946d4376..b85942002fb 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/CPlatformWindow.java @@ -820,6 +820,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo } nativeSetEnabled(getNSWindowPtr(), !blocked); + checkBlockingAndOrder(); } public final void invalidateShadow(){ @@ -984,7 +985,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo setStyleBits(SHOULD_BECOME_KEY | SHOULD_BECOME_MAIN, isFocusable); // set both bits at once } - private boolean checkBlocking() { + private boolean checkBlockingAndOrder() { LWWindowPeer blocker = (peer == null)? null : peer.getBlocker(); if (blocker == null) { return false; @@ -1040,7 +1041,7 @@ public class CPlatformWindow extends CFRetainedResource implements PlatformWindo private void windowDidBecomeMain() { assert CThreading.assertAppKit(); - if (checkBlocking()) return; + if (checkBlockingAndOrder()) return; // If it's not blocked, make sure it's above its siblings orderAboveSiblings(); } diff --git a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 943dbe2fe47..d698845e558 100644 --- a/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -44,6 +44,8 @@ import sun.lwawt.*; import sun.lwawt.LWWindowPeer.PeerType; import sun.security.action.GetBooleanAction; +import sun.util.CoreResourceBundleControl; + class NamedCursor extends Cursor { NamedCursor(String name) { super(name); @@ -67,13 +69,28 @@ public final class LWCToolkit extends LWToolkit { static { System.err.flush(); - java.security.AccessController.doPrivileged(new java.security.PrivilegedAction() { - public Object run() { + + ResourceBundle platformResources = java.security.AccessController.doPrivileged( + new java.security.PrivilegedAction() { + public ResourceBundle run() { + ResourceBundle platformResources = null; + try { + platformResources = + ResourceBundle.getBundle("sun.awt.resources.awtosx", + CoreResourceBundleControl.getRBControlInstance()); + } catch (MissingResourceException e) { + // No resource file; defaults will be used. + } + System.loadLibrary("awt"); System.loadLibrary("fontmanager"); - return null; + + return platformResources; } }); + + AWTAccessor.getToolkitAccessor().setPlatformResources(platformResources); + if (!GraphicsEnvironment.isHeadless()) { initIDs(); } @@ -207,9 +224,9 @@ public final class LWCToolkit extends LWToolkit { @Override public MenuBarPeer createMenuBar(MenuBar target) { - MenuBarPeer peer = new CMenuBar(target); - targetCreatedPeer(target, peer); - return peer; + MenuBarPeer peer = new CMenuBar(target); + targetCreatedPeer(target, peer); + return peer; } @Override @@ -302,11 +319,6 @@ public final class LWCToolkit extends LWToolkit { return new OSXPlatformFont(name, style); } - @Override - protected MouseInfoPeer createMouseInfoPeerImpl() { - return new CMouseInfoPeer(); - } - @Override protected int getScreenHeight() { return GraphicsEnvironment.getLocalGraphicsEnvironment() diff --git a/jdk/src/macosx/native/sun/awt/AWTEvent.m b/jdk/src/macosx/native/sun/awt/AWTEvent.m index b2d54f7e705..c6bda77d172 100644 --- a/jdk/src/macosx/native/sun/awt/AWTEvent.m +++ b/jdk/src/macosx/native/sun/awt/AWTEvent.m @@ -759,7 +759,7 @@ JNF_COCOA_EXIT(env); */ JNIEXPORT jint JNICALL Java_sun_lwawt_macosx_event_NSEvent_nsToJavaChar -(JNIEnv *env, jclass cls, char nsChar, jint modifierFlags) +(JNIEnv *env, jclass cls, jchar nsChar, jint modifierFlags) { jchar javaChar = 0; diff --git a/jdk/src/macosx/native/sun/awt/AWTView.m b/jdk/src/macosx/native/sun/awt/AWTView.m index 7e1f248c7ed..28bdb4b9077 100644 --- a/jdk/src/macosx/native/sun/awt/AWTView.m +++ b/jdk/src/macosx/native/sun/awt/AWTView.m @@ -126,7 +126,7 @@ AWT_ASSERT_APPKIT_THREAD; self.cglLayer = nil; - JNIEnv *env = [ThreadUtilities getJNIEnv]; + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; (*env)->DeleteGlobalRef(env, m_cPlatformView); m_cPlatformView = NULL; @@ -387,7 +387,7 @@ AWT_ASSERT_APPKIT_THREAD; [rolloverTrackingArea release]; } - int options = (NSTrackingActiveInActiveApp | NSTrackingMouseEnteredAndExited | + int options = (NSTrackingActiveAlways | NSTrackingMouseEnteredAndExited | NSTrackingMouseMoved | NSTrackingEnabledDuringMouseDrag); rolloverTrackingArea = [[NSTrackingArea alloc] initWithRect:[self visibleRect] diff --git a/jdk/src/macosx/native/sun/awt/AWTWindow.m b/jdk/src/macosx/native/sun/awt/AWTWindow.m index 5608b4ad98c..c933379f141 100644 --- a/jdk/src/macosx/native/sun/awt/AWTWindow.m +++ b/jdk/src/macosx/native/sun/awt/AWTWindow.m @@ -350,7 +350,7 @@ AWT_ASSERT_APPKIT_THREAD; - (void) dealloc { AWT_ASSERT_APPKIT_THREAD; - JNIEnv *env = [ThreadUtilities getJNIEnv]; + JNIEnv *env = [ThreadUtilities getJNIEnvUncached]; [self.javaPlatformWindow setJObject:nil withEnv:env]; self.nsWindow = nil; @@ -366,6 +366,22 @@ AWT_ASSERT_APPKIT_THREAD; - (BOOL) canBecomeMainWindow { AWT_ASSERT_APPKIT_THREAD; + if(!self.isEnabled){ + // Native system can bring up the NSWindow to + // the top even if the window is not main. + // We should bring up the modal dialog manually + [AWTToolkit eventCountPlusPlus]; + + JNIEnv *env = [ThreadUtilities getJNIEnv]; + jobject platformWindow = [self.javaPlatformWindow jObjectWithEnv:env]; + if (platformWindow != NULL) { + static JNF_MEMBER_CACHE(jm_checkBlockingAndOrder, jc_CPlatformWindow, + "checkBlockingAndOrder", "()Z"); + JNFCallVoidMethod(env, platformWindow, jm_checkBlockingAndOrder); + (*env)->DeleteLocalRef(env, platformWindow); + } + } + return self.isEnabled && IS(self.styleBits, SHOULD_BECOME_MAIN); } diff --git a/jdk/src/macosx/native/sun/awt/CTextPipe.m b/jdk/src/macosx/native/sun/awt/CTextPipe.m index d9bf48afd92..f6510f204ae 100644 --- a/jdk/src/macosx/native/sun/awt/CTextPipe.m +++ b/jdk/src/macosx/native/sun/awt/CTextPipe.m @@ -145,11 +145,6 @@ void JavaCT_DrawGlyphVector BOOL saved = false; - /* Save and restore of graphics context is done before the iteration. - This seems to work using our test case (see bug ID 7158350) so we are restoring it at - the end of the for loop. If we find out that save/restore outside the loop - doesn't work on all cases then we will move the Save/Restore inside the loop.*/ - CGContextSaveGState(cgRef); CGAffineTransform invTx = CGAffineTransformInvert(strike->fTx); NSUInteger i; @@ -226,7 +221,9 @@ void JavaCT_DrawGlyphVector } // reset the font on the context after striking a unicode with CoreText - CGContextRestoreGState(cgRef); + if (saved) { + CGContextRestoreGState(cgRef); + } } // Using the Quartz Surface Data context, draw a hot-substituted character run diff --git a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties index fe0f918d9bf..45148664672 100644 --- a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties +++ b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_de.properties @@ -102,7 +102,7 @@ horizontal=horizontal # # accessible actions # -toggleexpand=ein-/ausblenden +toggleexpand=einblenden umschalten # new relations, roles and states for J2SE 1.5.0 diff --git a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_es.properties b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_es.properties index c3f90416a30..ce185a10dd1 100644 --- a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_es.properties +++ b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_es.properties @@ -102,7 +102,7 @@ horizontal=horizontal # # accessible actions # -toggleexpand=activar/desactivar ampliaci\u00F3n +toggleexpand=conmutar ampliaci\u00F3n # new relations, roles and states for J2SE 1.5.0 diff --git a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_fr.properties b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_fr.properties index c399d9a0b32..88e8ae304b4 100644 --- a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_fr.properties +++ b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_fr.properties @@ -102,7 +102,7 @@ horizontal=horizontal # # accessible actions # -toggleexpand=basculer le d\u00E9veloppement +toggleexpand=activer/d\u00E9sactiver d\u00E9veloppement # new relations, roles and states for J2SE 1.5.0 diff --git a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_it.properties b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_it.properties index 94eefb0a2a3..a8af9705d19 100644 --- a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_it.properties +++ b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_it.properties @@ -102,7 +102,7 @@ horizontal=orizzontale # # accessible actions # -toggleexpand=abilita/disabilita espansione +toggleexpand=attiva/disattiva espansione # new relations, roles and states for J2SE 1.5.0 diff --git a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_pt_BR.properties b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_pt_BR.properties index f8aaf355040..638b46a7219 100644 --- a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_pt_BR.properties +++ b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_pt_BR.properties @@ -102,7 +102,7 @@ horizontal=horizontal # # accessible actions # -toggleexpand=alternar expans\u00E3o +toggleexpand=alternar expandir # new relations, roles and states for J2SE 1.5.0 diff --git a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_sv.properties b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_sv.properties index 962b9d35dc5..3261b2c9be3 100644 --- a/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_sv.properties +++ b/jdk/src/share/classes/com/sun/accessibility/internal/resources/accessibility_sv.properties @@ -102,7 +102,7 @@ horizontal=horisontell # # accessible actions # -toggleexpand=v\u00E4xla ut\u00F6ka +toggleexpand=v\u00E4xla expandering # new relations, roles and states for J2SE 1.5.0 diff --git a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java index 6036cb49870..c7b8fd3d0e5 100644 --- a/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java +++ b/jdk/src/share/classes/com/sun/imageio/plugins/jpeg/JPEGMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -278,10 +278,11 @@ public class JPEGMetadata extends IIOMetadata implements Cloneable { (JFIFMarkerSegment) findMarkerSegment (JFIFMarkerSegment.class, true); if (jfif == null) { - throw new IIOException - ("ICC APP2 encountered without prior JFIF!"); + newGuy = new MarkerSegment(buffer); + newGuy.loadData(buffer); + } else { + jfif.addICC(buffer); } - jfif.addICC(buffer); // newGuy remains null } else { newGuy = new MarkerSegment(buffer); diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index 0cff673711c..df2b7f7cc23 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -41,6 +41,7 @@ import javax.swing.plaf.basic.BasicDirectoryModel; import javax.swing.table.*; import javax.accessibility.*; +import sun.swing.AbstractFilterComboBoxModel; import sun.swing.SwingUtilities2; import sun.swing.plaf.synth.*; @@ -1328,71 +1329,9 @@ class GTKFileChooserUI extends SynthFileChooserUI { /** * Data model for filter combo-box. */ - protected class FilterComboBoxModel extends AbstractListModel - implements ComboBoxModel, PropertyChangeListener { - protected FileFilter[] filters; - - protected FilterComboBoxModel() { - super(); - filters = getFileChooser().getChoosableFileFilters(); - } - - public void propertyChange(PropertyChangeEvent e) { - String prop = e.getPropertyName(); - if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { - filters = (FileFilter[]) e.getNewValue(); - fireContentsChanged(this, -1, -1); - } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { - fireContentsChanged(this, -1, -1); - } - } - - public void setSelectedItem(Object filter) { - if (filter != null) { - getFileChooser().setFileFilter((FileFilter) filter); - fireContentsChanged(this, -1, -1); - } - } - - public Object getSelectedItem() { - // Ensure that the current filter is in the list. - // NOTE: we shouldnt' have to do this, since JFileChooser adds - // the filter to the choosable filters list when the filter - // is set. Lets be paranoid just in case someone overrides - // setFileFilter in JFileChooser. - FileFilter currentFilter = getFileChooser().getFileFilter(); - boolean found = false; - if (currentFilter != null) { - for (FileFilter filter : filters) { - if (filter == currentFilter) { - found = true; - } - } - if (found == false) { - getFileChooser().addChoosableFileFilter(currentFilter); - } - } - return getFileChooser().getFileFilter(); - } - - public int getSize() { - if (filters != null) { - return filters.length; - } else { - return 0; - } - } - - public Object getElementAt(int index) { - if (index > getSize() - 1) { - // This shouldn't happen. Try to recover gracefully. - return getFileChooser().getFileFilter(); - } - if (filters != null) { - return filters[index]; - } else { - return null; - } + protected class FilterComboBoxModel extends AbstractFilterComboBoxModel { + protected JFileChooser getFileChooser() { + return GTKFileChooserUI.this.getFileChooser(); } } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java index 048e76647c4..b821a56abc1 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/MotifFileChooserUI.java @@ -38,6 +38,7 @@ import java.io.File; import java.io.IOException; import java.util.*; import sun.awt.shell.ShellFolder; +import sun.swing.AbstractFilterComboBoxModel; import sun.swing.SwingUtilities2; /** @@ -777,70 +778,9 @@ public class MotifFileChooserUI extends BasicFileChooserUI { /** * Data model for a type-face selection combo-box. */ - protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, - PropertyChangeListener { - protected FileFilter[] filters; - protected FilterComboBoxModel() { - super(); - filters = getFileChooser().getChoosableFileFilters(); - } - - public void propertyChange(PropertyChangeEvent e) { - String prop = e.getPropertyName(); - if(prop.equals(JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY)) { - filters = (FileFilter[]) e.getNewValue(); - fireContentsChanged(this, -1, -1); - } else if (prop.equals(JFileChooser.FILE_FILTER_CHANGED_PROPERTY)) { - fireContentsChanged(this, -1, -1); - } - } - - public void setSelectedItem(Object filter) { - if(filter != null) { - getFileChooser().setFileFilter((FileFilter) filter); - fireContentsChanged(this, -1, -1); - } - } - - public Object getSelectedItem() { - // Ensure that the current filter is in the list. - // NOTE: we shouldnt' have to do this, since JFileChooser adds - // the filter to the choosable filters list when the filter - // is set. Lets be paranoid just in case someone overrides - // setFileFilter in JFileChooser. - FileFilter currentFilter = getFileChooser().getFileFilter(); - boolean found = false; - if(currentFilter != null) { - for (FileFilter filter : filters) { - if (filter == currentFilter) { - found = true; - } - } - if (!found) { - getFileChooser().addChoosableFileFilter(currentFilter); - } - } - return getFileChooser().getFileFilter(); - } - - public int getSize() { - if(filters != null) { - return filters.length; - } else { - return 0; - } - } - - public FileFilter getElementAt(int index) { - if(index > getSize() - 1) { - // This shouldn't happen. Try to recover gracefully. - return getFileChooser().getFileFilter(); - } - if(filters != null) { - return filters[index]; - } else { - return null; - } + protected class FilterComboBoxModel extends AbstractFilterComboBoxModel { + protected JFileChooser getFileChooser() { + return MotifFileChooserUI.this.getFileChooser(); } } diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties index 43ba5b6d32b..0c177f8b122 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_de.properties @@ -30,7 +30,7 @@ FileChooser.pathLabel.textAndMnemonic=&Pfad- oder Ordnername eingeben: FileChooser.filterLabel.textAndMnemonic=Filte&r FileChooser.foldersLabel.textAndMnemonic=Ord&ner FileChooser.filesLabel.textAndMnemonic=Date&ien -FileChooser.enterFileNameLabel.textAndMnemonic=Dateiname ei&ngeben: +FileChooser.enterFileNameLabel.textAndMnemonic=Dateina&me eingeben: FileChooser.enterFolderNameLabel.textAndMnemonic=Ordnernamen eingeben: FileChooser.cancelButtonToolTip.textAndMnemonic=Dialogfeld f\u00FCr Dateiauswahl schlie\u00DFen. diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties index f7e2625e9c9..7090ef5a7c4 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/motif/resources/motif_ko.properties @@ -24,7 +24,7 @@ FileChooser.saveButton.textAndMnemonic=\uC800\uC7A5 FileChooser.openButton.textAndMnemonic=\uD655\uC778 FileChooser.saveDialogTitle.textAndMnemonic=\uC800\uC7A5 FileChooser.openDialogTitle.textAndMnemonic=\uC5F4\uAE30 -FileChooser.updateButton.textAndMnemonic=\uAC31\uC2E0 +FileChooser.updateButton.textAndMnemonic=\uC5C5\uB370\uC774\uD2B8 FileChooser.helpButton.textAndMnemonic=\uB3C4\uC6C0\uB9D0 FileChooser.pathLabel.textAndMnemonic=\uACBD\uB85C \uB610\uB294 \uD3F4\uB354 \uC774\uB984 \uC785\uB825(&P): FileChooser.filterLabel.textAndMnemonic=\uD544\uD130(&R) @@ -36,5 +36,5 @@ FileChooser.enterFolderNameLabel.textAndMnemonic=\uD3F4\uB354 \uC774\uB984 \uC78 FileChooser.cancelButtonToolTip.textAndMnemonic=\uD30C\uC77C \uC120\uD0DD\uAE30 \uB300\uD654\uC0C1\uC790\uB97C \uC911\uB2E8\uD569\uB2C8\uB2E4. FileChooser.saveButtonToolTip.textAndMnemonic=\uC120\uD0DD\uB41C \uD30C\uC77C\uC744 \uC800\uC7A5\uD569\uB2C8\uB2E4. FileChooser.openButtonToolTip.textAndMnemonic=\uC120\uD0DD\uB41C \uD30C\uC77C\uC744 \uC5FD\uB2C8\uB2E4. -FileChooser.updateButtonToolTip.textAndMnemonic=\uB514\uB809\uD1A0\uB9AC \uBAA9\uB85D\uC744 \uAC31\uC2E0\uD569\uB2C8\uB2E4. +FileChooser.updateButtonToolTip.textAndMnemonic=\uB514\uB809\uD1A0\uB9AC \uBAA9\uB85D\uC744 \uC5C5\uB370\uC774\uD2B8\uD569\uB2C8\uB2E4. FileChooser.helpButtonToolTip.textAndMnemonic=FileChooser \uB3C4\uC6C0\uB9D0\uC785\uB2C8\uB2E4. diff --git a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java index 2e1168199c9..8d40da00013 100644 --- a/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java +++ b/jdk/src/share/classes/com/sun/java/swing/plaf/windows/WindowsFileChooserUI.java @@ -1193,70 +1193,9 @@ public class WindowsFileChooserUI extends BasicFileChooserUI { /** * Data model for a type-face selection combo-box. */ - protected class FilterComboBoxModel extends AbstractListModel implements ComboBoxModel, - PropertyChangeListener { - protected FileFilter[] filters; - protected FilterComboBoxModel() { - super(); - filters = getFileChooser().getChoosableFileFilters(); - } - - public void propertyChange(PropertyChangeEvent e) { - String prop = e.getPropertyName(); - if(prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { - filters = (FileFilter[]) e.getNewValue(); - fireContentsChanged(this, -1, -1); - } else if (prop == JFileChooser.FILE_FILTER_CHANGED_PROPERTY) { - fireContentsChanged(this, -1, -1); - } - } - - public void setSelectedItem(Object filter) { - if(filter != null) { - getFileChooser().setFileFilter((FileFilter) filter); - fireContentsChanged(this, -1, -1); - } - } - - public Object getSelectedItem() { - // Ensure that the current filter is in the list. - // NOTE: we shouldnt' have to do this, since JFileChooser adds - // the filter to the choosable filters list when the filter - // is set. Lets be paranoid just in case someone overrides - // setFileFilter in JFileChooser. - FileFilter currentFilter = getFileChooser().getFileFilter(); - boolean found = false; - if(currentFilter != null) { - for (FileFilter filter : filters) { - if (filter == currentFilter) { - found = true; - } - } - if(found == false) { - getFileChooser().addChoosableFileFilter(currentFilter); - } - } - return getFileChooser().getFileFilter(); - } - - public int getSize() { - if(filters != null) { - return filters.length; - } else { - return 0; - } - } - - public FileFilter getElementAt(int index) { - if(index > getSize() - 1) { - // This shouldn't happen. Try to recover gracefully. - return getFileChooser().getFileFilter(); - } - if(filters != null) { - return filters[index]; - } else { - return null; - } + protected class FilterComboBoxModel extends AbstractFilterComboBoxModel { + protected JFileChooser getFileChooser() { + return WindowsFileChooserUI.this.getFileChooser(); } } diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java new file mode 100644 index 00000000000..de35d5ac0eb --- /dev/null +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_ja.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.java.util.jar.pack; + +import java.util.ListResourceBundle; + +public class DriverResource_ja extends ListResourceBundle { + public static final String VERSION ="VERSION"; + public static final String BAD_ARGUMENT ="BAD_ARGUMENT"; + public static final String BAD_OPTION ="BAD_OPTION"; + public static final String BAD_REPACK_OUTPUT="BAD_REPACK_OUTPUT"; + public static final String DETECTED_ZIP_COMMENT="DETECTED_ZIP_COMMENT"; + public static final String SKIP_FOR_REPACKED ="SKIP_FOR_REPACKED"; + public static final String WRITE_PACK_FILE ="WRITE_PACK_FILE"; + public static final String WIRTE_PACKGZ_FILE="WIRTE_PACKGZ_FILE"; + public static final String SKIP_FOR_MOVE_FAILED="SKIP_FOR_MOVE_FAILED"; + public static final String PACK_HELP="PACK_HELP"; + public static final String UNPACK_HELP ="UNPACK_HELP"; + public static final String MORE_INFO = "MORE_INFO"; + public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION"; + public static final String BAD_SPEC = "BAD_SPEC"; + + //The following string is duplicate in PACK and UNPACK comment,which was draw out to ruduce translation work. + private static final String PARAMETER_V = " -v, --verbose increase program verbosity"; + private static final String PARAMETER_Q = " -q, --quiet set verbosity to lowest level"; + private static final String PARAMETER_LF = " -l{F}, --log-file={F} output to the given log file, or '-' for System.out"; + private static final String PARAMETER_H = " -?, -h, --help print this message"; + private static final String PARAMETER_VER = " -V, --version print program version"; + private static final String PARAMETER_J = " -J{X} pass option X to underlying Java VM"; + + + //The following are outputs of command 'pack200' and 'unpack200'. + //Don't translate command arguments ,words with a prefix of '-' or '--'. + // + private static final Object[][] resource= { + {VERSION,"{0}\u30D0\u30FC\u30B8\u30E7\u30F3{1}"},//parameter 0:class name;parameter 1: version value + {BAD_ARGUMENT,"\u7121\u52B9\u306A\u5F15\u6570: {0}"}, + {BAD_OPTION,"\u7121\u52B9\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0}={1}"},//parameter 0:option name;parameter 1:option value + {BAD_REPACK_OUTPUT,"\u7121\u52B9\u306A--repack\u51FA\u529B: {0}"},//parameter 0:filename + {DETECTED_ZIP_COMMENT,"\u691C\u51FA\u3055\u308C\u305FZIP\u30B3\u30E1\u30F3\u30C8: {0}"},//parameter 0:comment + {SKIP_FOR_REPACKED,"\u3059\u3067\u306B\u518D\u5727\u7E2E\u3055\u308C\u3066\u3044\u308B\u305F\u3081\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059: {0}"},//parameter 0:filename + {WRITE_PACK_FILE,"*.pack\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080\u306B\u306F\u3001--no-gzip\u3092\u6307\u5B9A\u3057\u307E\u3059: {0}"},//parameter 0:filename + {WIRTE_PACKGZ_FILE,"*.pack.gz\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080\u306B\u306F\u3001--gzip\u3092\u6307\u5B9A\u3057\u307E\u3059: {0}"},//parameter 0:filename + {SKIP_FOR_MOVE_FAILED,"\u79FB\u52D5\u304C\u5931\u6557\u3057\u305F\u305F\u3081\u89E3\u51CD\u3092\u30B9\u30AD\u30C3\u30D7\u3057\u3066\u3044\u307E\u3059: {0}"},//parameter 0:filename + {PACK_HELP,new String[]{ + "\u4F7F\u7528\u65B9\u6CD5: pack200 [-opt... | --option=value]... x.pack[.gz] y.jar", + "", + "\u5727\u7E2E\u30AA\u30D7\u30B7\u30E7\u30F3", + " -g\u3001--no-gzip \u30D7\u30EC\u30FC\u30F3\u306A*.pack\u30D5\u30A1\u30A4\u30EB\u3092\u5727\u7E2E\u305B\u305A\u306B\u51FA\u529B\u3057\u307E\u3059", + " --gzip (\u30C7\u30D5\u30A9\u30EB\u30C8)\u5727\u7E2E\u51FA\u529B\u3092gzip\u3067\u5F8C\u51E6\u7406\u3057\u307E\u3059", + " -G\u3001--strip-debug \u5727\u7E2E\u4E2D\u306B\u30C7\u30D0\u30C3\u30B0\u5C5E\u6027\u3092\u524A\u9664\u3057\u307E\u3059", + " -O\u3001--no-keep-file-order \u30D5\u30A1\u30A4\u30EB\u306E\u9806\u5E8F\u4ED8\u3051\u60C5\u5831\u3092\u8EE2\u9001\u3057\u307E\u305B\u3093", + " --keep-file-order (\u30C7\u30D5\u30A9\u30EB\u30C8)\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u9806\u5E8F\u4ED8\u3051\u3092\u4FDD\u6301\u3057\u307E\u3059", + " -S{N}\u3001--segment-limit={N} \u30BB\u30B0\u30E1\u30F3\u30C8\u5236\u9650\u3092\u51FA\u529B\u3057\u307E\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8N=1Mb)", + " -E{N}\u3001--effort={N} \u5727\u7E2E\u306E\u8A66\u884C(\u30C7\u30D5\u30A9\u30EB\u30C8N=5)", + " -H{h}\u3001--deflate-hint={h} \u30C7\u30D5\u30EC\u30FC\u30C8\u30FB\u30D2\u30F3\u30C8\u3092\u8EE2\u9001\u3057\u307E\u3059: true\u3001false\u307E\u305F\u306Fkeep(\u30C7\u30D5\u30A9\u30EB\u30C8)", + " -m{V}\u3001--modification-time={V} \u5909\u66F4\u6642\u9593\u3092\u8EE2\u9001\u3057\u307E\u3059: latest\u307E\u305F\u306Fkeep(\u30C7\u30D5\u30A9\u30EB\u30C8)", + " -P{F}\u3001--pass-file={F} \u6307\u5B9A\u3055\u308C\u305F\u5727\u7E2E\u3055\u308C\u3066\u3044\u306A\u3044\u5165\u529B\u8981\u7D20\u3092\u8EE2\u9001\u3057\u307E\u3059", + " -U{a}\u3001--unknown-attribute={a} \u4E0D\u660E\u306E\u5C5E\u6027\u30A2\u30AF\u30B7\u30E7\u30F3: error\u3001strip\u307E\u305F\u306Fpass(\u30C7\u30D5\u30A9\u30EB\u30C8)", + " -C{N}={L}\u3001--class-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", + " -F{N}={L}\u3001--field-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", + " -M{N}={L}\u3001--method-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", + " -D{N}={L}\u3001--code-attribute={N}={L} (\u30E6\u30FC\u30B6\u30FC\u5B9A\u7FA9\u5C5E\u6027)", + " -f{F}\u3001--config-file={F} Pack200.Packer\u30D7\u30ED\u30D1\u30C6\u30A3\u306B\u30D5\u30A1\u30A4\u30EBF\u3092\u8AAD\u307F\u8FBC\u307F\u307E\u3059", + PARAMETER_V , + PARAMETER_Q , + PARAMETER_LF , + PARAMETER_H , + PARAMETER_VER , + PARAMETER_J, + "", + "\u6CE8\u610F:", + " -P\u3001-C\u3001-F\u3001-M\u304A\u3088\u3073-D\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u7D2F\u7A4D\u3055\u308C\u307E\u3059\u3002", + " \u5C5E\u6027\u5B9A\u7FA9\u306E\u4F8B: -C SourceFile=RUH .", + " Config.\u30D5\u30A1\u30A4\u30EB\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306F\u3001Pack200 API\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002", + " -S\u3001-E\u3001-H\u3001-m\u3001-U\u306E\u5024\u306E\u610F\u5473\u306F\u3001Pack200 API\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002", + " \u30EC\u30A4\u30A2\u30A6\u30C8\u5B9A\u7FA9(RUH\u306A\u3069)\u306FJSR 200\u306B\u3088\u3063\u3066\u5B9A\u7FA9\u3055\u308C\u307E\u3059\u3002", + "", + "\u518D\u5727\u7E2E\u30E2\u30FC\u30C9\u3067\u306F\u3001JAR\u30D5\u30A1\u30A4\u30EB\u304C\u5727\u7E2E/\u89E3\u51CD\u30B5\u30A4\u30AF\u30EB\u3067\u66F4\u65B0\u3055\u308C\u307E\u3059:", + " pack200 [-r|--repack] [-opt | --option=value]... [repackedy.jar] y.jar\n" + } + }, + {UNPACK_HELP,new String[]{ + "\u4F7F\u7528\u65B9\u6CD5: unpack200 [-opt... | --option=value]... x.pack[.gz] y.jar\n", + "", + "\u89E3\u51CD\u30AA\u30D7\u30B7\u30E7\u30F3", + " -H{h}\u3001--deflate-hint={h} \u8EE2\u9001\u3055\u308C\u305F\u30C7\u30D5\u30EC\u30FC\u30C8\u30FB\u30D2\u30F3\u30C8\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u3059: true\u3001false\u307E\u305F\u306Fkeep(\u30C7\u30D5\u30A9\u30EB\u30C8)", + " -r\u3001--remove-pack-file \u89E3\u51CD\u5F8C\u306B\u5165\u529B\u30D5\u30A1\u30A4\u30EB\u3092\u524A\u9664\u3057\u307E\u3059", + PARAMETER_V , + PARAMETER_Q , + PARAMETER_LF , + PARAMETER_H , + PARAMETER_VER , + PARAMETER_J, + } + }, + + {MORE_INFO,"(\u8A73\u7D30\u306F\u3001{0} --help\u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002)"},//parameter 0:command name + {DUPLICATE_OPTION,"\u91CD\u8907\u30AA\u30D7\u30B7\u30E7\u30F3: {0}"},//parameter 0:option + {BAD_SPEC,"{0}\u306E\u7121\u52B9\u306A\u4ED5\u69D8: {1}"},//parameter 0:option;parameter 1:specifier + }; + + protected Object[][] getContents() { + return resource; + } + + +} diff --git a/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java b/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java new file mode 100644 index 00000000000..25cc710e61f --- /dev/null +++ b/jdk/src/share/classes/com/sun/java/util/jar/pack/DriverResource_zh_CN.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute 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.java.util.jar.pack; + +import java.util.ListResourceBundle; + +public class DriverResource_zh_CN extends ListResourceBundle { + public static final String VERSION ="VERSION"; + public static final String BAD_ARGUMENT ="BAD_ARGUMENT"; + public static final String BAD_OPTION ="BAD_OPTION"; + public static final String BAD_REPACK_OUTPUT="BAD_REPACK_OUTPUT"; + public static final String DETECTED_ZIP_COMMENT="DETECTED_ZIP_COMMENT"; + public static final String SKIP_FOR_REPACKED ="SKIP_FOR_REPACKED"; + public static final String WRITE_PACK_FILE ="WRITE_PACK_FILE"; + public static final String WIRTE_PACKGZ_FILE="WIRTE_PACKGZ_FILE"; + public static final String SKIP_FOR_MOVE_FAILED="SKIP_FOR_MOVE_FAILED"; + public static final String PACK_HELP="PACK_HELP"; + public static final String UNPACK_HELP ="UNPACK_HELP"; + public static final String MORE_INFO = "MORE_INFO"; + public static final String DUPLICATE_OPTION = "DUPLICATE_OPTION"; + public static final String BAD_SPEC = "BAD_SPEC"; + + //The following string is duplicate in PACK and UNPACK comment,which was draw out to ruduce translation work. + private static final String PARAMETER_V = " -v, --verbose increase program verbosity"; + private static final String PARAMETER_Q = " -q, --quiet set verbosity to lowest level"; + private static final String PARAMETER_LF = " -l{F}, --log-file={F} output to the given log file, or '-' for System.out"; + private static final String PARAMETER_H = " -?, -h, --help print this message"; + private static final String PARAMETER_VER = " -V, --version print program version"; + private static final String PARAMETER_J = " -J{X} pass option X to underlying Java VM"; + + + //The following are outputs of command 'pack200' and 'unpack200'. + //Don't translate command arguments ,words with a prefix of '-' or '--'. + // + private static final Object[][] resource= { + {VERSION,"{0}\u7248\u672C{1}"},//parameter 0:class name;parameter 1: version value + {BAD_ARGUMENT,"\u9519\u8BEF\u53C2\u6570: {0}"}, + {BAD_OPTION,"\u9519\u8BEF\u9009\u9879: {0}={1}"},//parameter 0:option name;parameter 1:option value + {BAD_REPACK_OUTPUT,"--repack \u8F93\u51FA\u9519\u8BEF: {0}"},//parameter 0:filename + {DETECTED_ZIP_COMMENT,"\u68C0\u6D4B\u5230 ZIP \u6CE8\u91CA: {0}"},//parameter 0:comment + {SKIP_FOR_REPACKED,"\u7531\u4E8E\u5DF2\u91CD\u65B0\u6253\u5305\u800C\u8DF3\u8FC7: {0}"},//parameter 0:filename + {WRITE_PACK_FILE,"\u8981\u5199\u5165 *.pack \u6587\u4EF6, \u8BF7\u6307\u5B9A --no-gzip: {0}"},//parameter 0:filename + {WIRTE_PACKGZ_FILE,"\u8981\u5199\u5165 *.pack.gz \u6587\u4EF6, \u8BF7\u6307\u5B9A --gzip: {0}"},//parameter 0:filename + {SKIP_FOR_MOVE_FAILED,"\u7531\u4E8E\u79FB\u52A8\u5931\u8D25\u800C\u8DF3\u8FC7\u91CD\u65B0\u6253\u5305: {0}"},//parameter 0:filename + {PACK_HELP,new String[]{ + "\u7528\u6CD5: pack200 [-opt... | --option=value]... x.pack[.gz] y.jar", + "", + "\u6253\u5305\u9009\u9879", + " -g, --no-gzip \u8F93\u51FA\u65E0\u683C\u5F0F\u7684 *.pack \u6587\u4EF6, \u4E0D\u538B\u7F29", + " --gzip (\u9ED8\u8BA4\u503C) \u4F7F\u7528 gzip \u5BF9\u6253\u5305\u8FDB\u884C\u540E\u5904\u7406", + " -G, --strip-debug \u6253\u5305\u65F6\u5220\u9664\u8C03\u8BD5\u5C5E\u6027", + " -O, --no-keep-file-order \u4E0D\u4F20\u8F93\u6587\u4EF6\u6392\u5E8F\u4FE1\u606F", + " --keep-file-order (\u9ED8\u8BA4\u503C) \u4FDD\u7559\u8F93\u5165\u6587\u4EF6\u6392\u5E8F", + " -S{N}, --segment-limit={N} \u8F93\u51FA\u6BB5\u9650\u5236 (\u9ED8\u8BA4\u503C N=1Mb)", + " -E{N}, --effort={N} \u6253\u5305\u6548\u679C (\u9ED8\u8BA4\u503C N=5)", + " -H{h}, --deflate-hint={h} \u4F20\u8F93\u538B\u7F29\u63D0\u793A: true, false \u6216 keep (\u9ED8\u8BA4\u503C)", + " -m{V}, --modification-time={V} \u4F20\u8F93 modtimes: latest \u6216 keep (\u9ED8\u8BA4\u503C)", + " -P{F}, --pass-file={F} \u4F20\u8F93\u672A\u89E3\u538B\u7F29\u7684\u7ED9\u5B9A\u8F93\u5165\u5143\u7D20", + " -U{a}, --unknown-attribute={a} \u672A\u77E5\u5C5E\u6027\u64CD\u4F5C: error, strip \u6216 pass (\u9ED8\u8BA4\u503C)", + " -C{N}={L}, --class-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", + " -F{N}={L}, --field-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", + " -M{N}={L}, --method-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", + " -D{N}={L}, --code-attribute={N}={L} (\u7528\u6237\u5B9A\u4E49\u7684\u5C5E\u6027)", + " -f{F}, --config-file={F} \u8BFB\u53D6\u6587\u4EF6 F \u7684 Pack200.Packer \u5C5E\u6027", + PARAMETER_V , + PARAMETER_Q , + PARAMETER_LF , + PARAMETER_H , + PARAMETER_VER , + PARAMETER_J, + "", + "\u6CE8:", + " -P, -C, -F, -M \u548C -D \u9009\u9879\u7D2F\u8BA1\u3002", + " \u793A\u4F8B\u5C5E\u6027\u5B9A\u4E49: -C SourceFile=RUH\u3002", + " Config. \u6587\u4EF6\u5C5E\u6027\u7531 Pack200 API \u5B9A\u4E49\u3002", + " \u6709\u5173 -S, -E, -H-, -m, -U \u503C\u7684\u542B\u4E49, \u8BF7\u53C2\u9605 Pack200 API\u3002", + " \u5E03\u5C40\u5B9A\u4E49 (\u4F8B\u5982 RUH) \u7531 JSR 200 \u5B9A\u4E49\u3002", + "", + "\u91CD\u65B0\u6253\u5305\u6A21\u5F0F\u901A\u8FC7\u6253\u5305/\u89E3\u5305\u5468\u671F\u66F4\u65B0 JAR \u6587\u4EF6:", + " pack200 [-r|--repack] [-opt | --option=value]... [repackedy.jar] y.jar\n" + } + }, + {UNPACK_HELP,new String[]{ + "\u7528\u6CD5: unpack200 [-opt... | --option=value]... x.pack[.gz] y.jar\n", + "", + "\u89E3\u5305\u9009\u9879", + " -H{h}, --deflate-hint={h} \u8986\u76D6\u5DF2\u4F20\u8F93\u7684\u538B\u7F29\u63D0\u793A: true, false \u6216 keep (\u9ED8\u8BA4\u503C)", + " -r, --remove-pack-file \u89E3\u5305\u4E4B\u540E\u5220\u9664\u8F93\u5165\u6587\u4EF6", + PARAMETER_V , + PARAMETER_Q , + PARAMETER_LF , + PARAMETER_H , + PARAMETER_VER , + PARAMETER_J, + } + }, + + {MORE_INFO,"(\u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u8FD0\u884C {0} --help\u3002)"},//parameter 0:command name + {DUPLICATE_OPTION,"\u91CD\u590D\u7684\u9009\u9879: {0}"},//parameter 0:option + {BAD_SPEC,"{0}\u7684\u89C4\u8303\u9519\u8BEF: {1}"},//parameter 0:option;parameter 1:specifier + }; + + protected Object[][] getContents() { + return resource; + } + + +} diff --git a/jdk/src/share/classes/com/sun/nio/sctp/Association.java b/jdk/src/share/classes/com/sun/nio/sctp/Association.java index b367412b83f..965feae3418 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/Association.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/Association.java @@ -58,6 +58,13 @@ public class Association { /** * Initializes a new instance of this class. + * + * @param associationID + * The association ID + * @param maxInStreams + * The maximum number of inbound streams + * @param maxOutStreams + * The maximum number of outbound streams */ protected Association(int associationID, int maxInStreams, diff --git a/jdk/src/share/classes/com/sun/nio/sctp/IllegalReceiveException.java b/jdk/src/share/classes/com/sun/nio/sctp/IllegalReceiveException.java index 0dc063bd55c..b5a4137054d 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/IllegalReceiveException.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/IllegalReceiveException.java @@ -41,6 +41,9 @@ public class IllegalReceiveException extends IllegalStateException { /** * Constructs an instance of this class with the specified message. + * + * @param msg + * The String that contains a detailed message */ public IllegalReceiveException(String msg) { super(msg); diff --git a/jdk/src/share/classes/com/sun/nio/sctp/IllegalUnbindException.java b/jdk/src/share/classes/com/sun/nio/sctp/IllegalUnbindException.java index b48ef56b1b5..4088df34687 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/IllegalUnbindException.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/IllegalUnbindException.java @@ -41,6 +41,9 @@ public class IllegalUnbindException extends IllegalStateException { /** * Constructs an instance of this class with the specified detailed message. + * + * @param msg + * The String that contains a detailed message */ public IllegalUnbindException(String msg) { super(msg); diff --git a/jdk/src/share/classes/com/sun/nio/sctp/InvalidStreamException.java b/jdk/src/share/classes/com/sun/nio/sctp/InvalidStreamException.java index 40a818fe5bd..abe49f24593 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/InvalidStreamException.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/InvalidStreamException.java @@ -40,6 +40,9 @@ public class InvalidStreamException extends IllegalArgumentException { /** * Constructs an instance of this class with the specified detailed message. + * + * @param msg + * The String that contains a detailed message */ public InvalidStreamException(String msg) { super(msg); diff --git a/jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java b/jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java index d7a2ee81563..997c6253834 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/MessageInfo.java @@ -48,7 +48,7 @@ import java.net.SocketAddress; * longer required to be sent after the time period expires. It is not a hard * timeout and may be influenced by whether the association supports the partial * reliability extension, RFC 3758 - * + * . * *

    {@code MessageInfo} instances are not safe for use by multiple concurrent * threads. If a MessageInfo is to be used by more than one thread then access diff --git a/jdk/src/share/classes/com/sun/nio/sctp/Notification.java b/jdk/src/share/classes/com/sun/nio/sctp/Notification.java index cc23b8f2e47..2436fae7ba7 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/Notification.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/Notification.java @@ -40,6 +40,8 @@ package com.sun.nio.sctp; public interface Notification { /** * Returns the association that this notification is applicable to. + * + * @return The association */ public Association association(); } diff --git a/jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java b/jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java index 0b351a4ca3f..22cf07650f4 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/SctpChannel.java @@ -59,7 +59,7 @@ import java.nio.channels.SelectionKey; * {@link #setOption(SctpSocketOption,Object) setOption} method. An SCTP * channel support the following options: *

    - * + *
    * * * @@ -636,6 +636,9 @@ public abstract class SctpChannel /** * Returns the value of a socket option. * + * @param + * The type of the socket option value + * * @param name * The socket option * @@ -659,6 +662,9 @@ public abstract class SctpChannel /** * Sets the value of a socket option. * + * @param + * The type of the socket option value + * * @param name * The socket option * @@ -752,6 +758,9 @@ public abstract class SctpChannel * the {@code receive} method of this channel, if it does an * {@link IllegalReceiveException} will be thrown. * + * @param + * The type of the attachment + * * @param dst * The buffer into which message bytes are to be transferred * @@ -831,7 +840,7 @@ public abstract class SctpChannel * there was insufficient room for the message in the underlying * output buffer * - * @throws InvalidStreamExcepton + * @throws InvalidStreamException * If {@code streamNumner} is negative or greater than or equal to * the maximum number of outgoing streams * diff --git a/jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java b/jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java index f8745dba41e..42e56591e43 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/SctpMultiChannel.java @@ -63,7 +63,7 @@ import java.nio.channels.SelectionKey; * {@link #setOption(SctpSocketOption,Object,Association) setOption} method. An * {@code SctpMultiChannel} supports the following options: *
    - *
    Option NameDescription
    + *
    * * * @@ -394,6 +394,9 @@ public abstract class SctpMultiChannel * Returns all of the remote addresses to which the given association on * this channel's socket is connected. * + * @param association + * The association + * * @return All of the remote addresses for the given association, or * an empty {@code Set} if the association has been shutdown * @@ -431,6 +434,9 @@ public abstract class SctpMultiChannel * ignored if given. However, if the option is association specific then the * association must be given. * + * @param + * The type of the socket option value + * * @param name * The socket option * @@ -464,6 +470,9 @@ public abstract class SctpMultiChannel * ignored if given. However, if the option is association specific then the * association must be given. * + * @param + * The type of the socket option value + * * @param name * The socket option * @@ -567,6 +576,9 @@ public abstract class SctpMultiChannel * the {@code receive} method of this channel, if it does an * {@link IllegalReceiveException} will be thrown. * + * @param + * The type of the attachment + * * @param buffer * The buffer into which bytes are to be transferred * @@ -673,7 +685,7 @@ public abstract class SctpMultiChannel * there was insufficient room for the message in the underlying * output buffer * - * @throws InvalidStreamExcepton + * @throws InvalidStreamException * If {@code streamNumber} is negative, or if an association already * exists and {@code streamNumber} is greater than the maximum number * of outgoing streams diff --git a/jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java b/jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java index 637df72d394..c96e516ca4d 100644 --- a/jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java +++ b/jdk/src/share/classes/com/sun/nio/sctp/SctpServerChannel.java @@ -47,7 +47,7 @@ import java.nio.channels.spi.AbstractSelectableChannel; * {@link #setOption(SctpSocketOption,Object) setOption} method. SCTP server socket * channels support the following options: *
    - *
    Option NameDescription
    + *
    * * * @@ -345,6 +345,9 @@ public abstract class SctpServerChannel /** * Returns the value of a socket option. * + * @param + * The type of the socket option value + * * @param name * The socket option * @@ -367,6 +370,9 @@ public abstract class SctpServerChannel /** * Sets the value of a socket option. * + * @param + * The type of the socket option value + * * @param name * The socket option * diff --git a/jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties b/jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties index 3dd9ee0d1b9..89bbf67ec53 100644 --- a/jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties +++ b/jdk/src/share/classes/com/sun/rowset/RowSetResourceBundle_ko.properties @@ -44,7 +44,7 @@ cachedrowsetimpl.doublefail = {1} \uC5F4\uC758 \uAC12({0})\uC5D0\uC11C getDouble cachedrowsetimpl.dtypemismt = \uB370\uC774\uD130 \uC720\uD615\uC774 \uC77C\uCE58\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. cachedrowsetimpl.datefail = {1} \uC5F4\uC758 \uAC12({0})\uC5D0\uC11C getDate\uB97C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uBCC0\uD658\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. cachedrowsetimpl.timefail = {1} \uC5F4\uC758 \uAC12({0})\uC5D0\uC11C getTime\uC744 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uBCC0\uD658\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. -cachedrowsetimpl.posupdate = \uC704\uCE58\uAC00 \uC9C0\uC815\uB41C \uAC31\uC2E0\uC774 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. +cachedrowsetimpl.posupdate = \uC704\uCE58\uAC00 \uC9C0\uC815\uB41C \uC5C5\uB370\uC774\uD2B8\uAC00 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. cachedrowsetimpl.unableins = \uC778\uC2A4\uD134\uC2A4\uD654\uD560 \uC218 \uC5C6\uC74C: {0} cachedrowsetimpl.beforefirst = beforeFirst: \uCEE4\uC11C \uC791\uC5C5\uC774 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. cachedrowsetimpl.first = \uCC98\uC74C: \uCEE4\uC11C \uC791\uC5C5\uC774 \uBD80\uC801\uD569\uD569\uB2C8\uB2E4. @@ -110,7 +110,7 @@ jdbcrowsetimpl.matchcols2 = \uC77C\uCE58 \uC5F4\uC740 \uB110 \uB610\uB294 \uBE48 jdbcrowsetimpl.unsetmatch = \uC124\uC815\uC744 \uD574\uC81C\uD558\uB824\uB294 \uC5F4\uC774 \uC124\uC815\uB41C \uC5F4\uACFC \uB2E4\uB985\uB2C8\uB2E4. jdbcrowsetimpl.usecolname = \uC5F4 \uC774\uB984\uC744 unsetMatchColumn\uC758 \uC778\uC218\uB85C \uC0AC\uC6A9\uD558\uC2ED\uC2DC\uC624. jdbcrowsetimpl.usecolid = \uC5F4 ID\uB97C unsetMatchColumn\uC758 \uC778\uC218\uB85C \uC0AC\uC6A9\uD558\uC2ED\uC2DC\uC624. -jdbcrowsetimpl.resnotupd = ResultSet\uB97C \uAC31\uC2E0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. +jdbcrowsetimpl.resnotupd = ResultSet\uB97C \uC5C5\uB370\uC774\uD2B8\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. jdbcrowsetimpl.opnotysupp = \uC791\uC5C5\uC774 \uC544\uC9C1 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. jdbcrowsetimpl.featnotsupp = \uAE30\uB2A5\uC774 \uC9C0\uC6D0\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4. @@ -157,7 +157,7 @@ xmlrch.errdel = \uD589\uC744 \uC0AD\uC81C\uD558\uB294 \uC911 \uC624\uB958 \uBC1C xmlrch.errinsert = insert \uD589\uC744 \uC0DD\uC131\uD558\uB294 \uC911 \uC624\uB958 \uBC1C\uC0DD: {0} xmlrch.errinsdel = insdel \uD589\uC744 \uC0DD\uC131\uD558\uB294 \uC911 \uC624\uB958 \uBC1C\uC0DD: {0} xmlrch.errupdate = update \uD589\uC744 \uC0DD\uC131\uD558\uB294 \uC911 \uC624\uB958 \uBC1C\uC0DD: {0} -xmlrch.errupdrow = \uD589\uC744 \uAC31\uC2E0\uD558\uB294 \uC911 \uC624\uB958 \uBC1C\uC0DD: {0} +xmlrch.errupdrow = \uD589\uC744 \uC5C5\uB370\uC774\uD2B8\uD558\uB294 \uC911 \uC624\uB958 \uBC1C\uC0DD: {0} xmlrch.chars = \uBB38\uC790: xmlrch.badvalue = \uC798\uBABB\uB41C \uAC12: \uB110\uC77C \uC218 \uC5C6\uB294 \uC18D\uC131\uC785\uB2C8\uB2E4. xmlrch.badvalue1 = \uC798\uBABB\uB41C \uAC12: \uB110\uC77C \uC218 \uC5C6\uB294 \uBA54\uD0C0 \uB370\uC774\uD130\uC785\uB2C8\uB2E4. diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties index 86f010204dc..a8504f7872c 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties @@ -46,7 +46,7 @@ FileChooser.saveButton.textAndMnemonic=\uC800\uC7A5(&S) FileChooser.openButton.textAndMnemonic=\uC5F4\uAE30(&O) FileChooser.saveDialogTitle.textAndMnemonic=\uC800\uC7A5 FileChooser.openDialogTitle.textAndMnemonic=\uC5F4\uAE30 -FileChooser.updateButton.textAndMnemonic=\uAC31\uC2E0(&U) +FileChooser.updateButton.textAndMnemonic=\uC5C5\uB370\uC774\uD2B8(&U) FileChooser.helpButton.textAndMnemonic=\uB3C4\uC6C0\uB9D0(&H) FileChooser.directoryOpenButton.textAndMnemonic=\uC5F4\uAE30(&O) @@ -66,7 +66,7 @@ FileChooser.other.newFolder.subsequent=NewFolder.{0} FileChooser.cancelButtonToolTip.textAndMnemonic=\uD30C\uC77C \uC120\uD0DD\uAE30 \uB300\uD654\uC0C1\uC790 \uC911\uB2E8 FileChooser.saveButtonToolTip.textAndMnemonic=\uC120\uD0DD\uB41C \uD30C\uC77C \uC800\uC7A5 FileChooser.openButtonToolTip.textAndMnemonic=\uC120\uD0DD\uB41C \uD30C\uC77C \uC5F4\uAE30 -FileChooser.updateButtonToolTip.textAndMnemonic=\uB514\uB809\uD1A0\uB9AC \uBAA9\uB85D \uAC31\uC2E0 +FileChooser.updateButtonToolTip.textAndMnemonic=\uB514\uB809\uD1A0\uB9AC \uBAA9\uB85D \uC5C5\uB370\uC774\uD2B8 FileChooser.helpButtonToolTip.textAndMnemonic=FileChooser \uB3C4\uC6C0\uB9D0 FileChooser.directoryOpenButtonToolTip.textAndMnemonic=\uC120\uD0DD\uB41C \uB514\uB809\uD1A0\uB9AC \uC5F4\uAE30 diff --git a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties index 3d799b58a80..1b9b7e217c7 100644 --- a/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties +++ b/jdk/src/share/classes/com/sun/swing/internal/plaf/metal/resources/metal_sv.properties @@ -20,8 +20,8 @@ FileChooser.lookInLabel.textAndMnemonic=Leta &i: FileChooser.saveInLabel.textAndMnemonic=Spara i: -FileChooser.fileNameLabel.textAndMnemonic=Fil&namn: -FileChooser.folderNameLabel.textAndMnemonic=Mapp&namn: +FileChooser.fileNameLabel.textAndMnemonic=&Fil: +FileChooser.folderNameLabel.textAndMnemonic=&Mapp: FileChooser.filesOfTypeLabel.textAndMnemonic=Mapp&namn: FileChooser.upFolderToolTip.textAndMnemonic=Upp en niv\u00E5 FileChooser.upFolderAccessibleName=Upp diff --git a/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java b/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java index 20be57c85c4..84a14557b30 100644 --- a/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java +++ b/jdk/src/share/classes/com/sun/tools/jdi/SunCommandLineLauncher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -196,19 +196,7 @@ public class SunCommandLineLauncher extends AbstractLauncher implements Launchin try { if (home.length() > 0) { - /* - * A wrinkle in the environment: - * 64-bit executables are stored under $JAVA_HOME/bin/os_arch - * 32-bit executables are stored under $JAVA_HOME/bin - */ - String os_arch = System.getProperty("os.arch"); - if ("SunOS".equals(System.getProperty("os.name")) && - ("sparcv9".equals(os_arch) || "amd64".equals(os_arch))) { - exePath = home + File.separator + "bin" + File.separator + - os_arch + File.separator + exe; - } else { - exePath = home + File.separator + "bin" + File.separator + exe; - } + exePath = home + File.separator + "bin" + File.separator + exe; } else { exePath = exe; } diff --git a/jdk/src/share/classes/java/awt/AWTKeyStroke.java b/jdk/src/share/classes/java/awt/AWTKeyStroke.java index 8966d753fb7..2cf7a332774 100644 --- a/jdk/src/share/classes/java/awt/AWTKeyStroke.java +++ b/jdk/src/share/classes/java/awt/AWTKeyStroke.java @@ -67,7 +67,7 @@ import java.lang.reflect.Field; public class AWTKeyStroke implements Serializable { static final long serialVersionUID = -6430539691155161871L; - private static Map modifierKeywords; + private static Map modifierKeywords; /** * Associates VK_XXX (as a String) with code (as Integer). This is * done to avoid the overhead of the reflective call to find the @@ -85,8 +85,8 @@ public class AWTKeyStroke implements Serializable { * AWTKeyStroke class. * Must be called under locked AWTKeyStro */ - private static Class getAWTKeyStrokeClass() { - Class clazz = (Class)AppContext.getAppContext().get(AWTKeyStroke.class); + private static Class getAWTKeyStrokeClass() { + Class clazz = (Class)AppContext.getAppContext().get(AWTKeyStroke.class); if (clazz == null) { clazz = AWTKeyStroke.class; AppContext.getAppContext().put(AWTKeyStroke.class, AWTKeyStroke.class); @@ -182,7 +182,7 @@ public class AWTKeyStroke implements Serializable { throw new IllegalArgumentException("subclass cannot be null"); } synchronized (AWTKeyStroke.class) { - Class keyStrokeClass = (Class)AppContext.getAppContext().get(AWTKeyStroke.class); + Class keyStrokeClass = (Class)AppContext.getAppContext().get(AWTKeyStroke.class); if (keyStrokeClass != null && keyStrokeClass.equals(subclass)){ // Already registered return; @@ -229,8 +229,8 @@ public class AWTKeyStroke implements Serializable { */ private static Constructor getCtor(final Class clazz) { - Object ctor = AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + Constructor ctor = AccessController.doPrivileged(new PrivilegedAction() { + public Constructor run() { try { Constructor ctor = clazz.getDeclaredConstructor((Class[]) null); if (ctor != null) { @@ -249,17 +249,17 @@ public class AWTKeyStroke implements Serializable { private static synchronized AWTKeyStroke getCachedStroke (char keyChar, int keyCode, int modifiers, boolean onKeyRelease) { - Map cache = (Map)AppContext.getAppContext().get(APP_CONTEXT_CACHE_KEY); + Map cache = (Map)AppContext.getAppContext().get(APP_CONTEXT_CACHE_KEY); AWTKeyStroke cacheKey = (AWTKeyStroke)AppContext.getAppContext().get(APP_CONTEXT_KEYSTROKE_KEY); if (cache == null) { - cache = new HashMap(); + cache = new HashMap<>(); AppContext.getAppContext().put(APP_CONTEXT_CACHE_KEY, cache); } if (cacheKey == null) { try { - Class clazz = getAWTKeyStrokeClass(); + Class clazz = getAWTKeyStrokeClass(); cacheKey = (AWTKeyStroke)getCtor(clazz).newInstance((Object[]) null); AppContext.getAppContext().put(APP_CONTEXT_KEYSTROKE_KEY, cacheKey); } catch (InstantiationException e) { @@ -485,11 +485,11 @@ public class AWTKeyStroke implements Serializable { * If typed, pressed or released is not specified, pressed is assumed. Here * are some examples: *
    -     *     "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
    -     *     "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
    -     *     "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
    -     *     "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
    -     *     "typed a" => getAWTKeyStroke('a');
    +     *     "INSERT" => getAWTKeyStroke(KeyEvent.VK_INSERT, 0);
    +     *     "control DELETE" => getAWTKeyStroke(KeyEvent.VK_DELETE, InputEvent.CTRL_MASK);
    +     *     "alt shift X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK);
    +     *     "alt shift released X" => getAWTKeyStroke(KeyEvent.VK_X, InputEvent.ALT_MASK | InputEvent.SHIFT_MASK, true);
    +     *     "typed a" => getAWTKeyStroke('a');
          * 
    * * @param s a String formatted as described above @@ -513,7 +513,7 @@ public class AWTKeyStroke implements Serializable { synchronized (AWTKeyStroke.class) { if (modifierKeywords == null) { - Map uninitializedMap = new HashMap(8, 1.0f); + Map uninitializedMap = new HashMap<>(8, 1.0f); uninitializedMap.put("shift", Integer.valueOf(InputEvent.SHIFT_DOWN_MASK |InputEvent.SHIFT_MASK)); @@ -861,12 +861,12 @@ public class AWTKeyStroke implements Serializable { } class VKCollection { - Map code2name; - Map name2code; + Map code2name; + Map name2code; public VKCollection() { - code2name = new HashMap(); - name2code = new HashMap(); + code2name = new HashMap<>(); + name2code = new HashMap<>(); } public synchronized void put(String name, Integer code) { diff --git a/jdk/src/share/classes/java/awt/CardLayout.java b/jdk/src/share/classes/java/awt/CardLayout.java index 32355efed60..35ee3379267 100644 --- a/jdk/src/share/classes/java/awt/CardLayout.java +++ b/jdk/src/share/classes/java/awt/CardLayout.java @@ -66,7 +66,7 @@ public class CardLayout implements LayoutManager2, * pairs of components and their names. * @see java.util.Vector */ - Vector vector = new Vector(); + Vector vector = new Vector<>(); /* * A pair of Component and String that represents its name. @@ -570,10 +570,10 @@ public class CardLayout implements LayoutManager2, if (f.defaulted("vector")) { // pre-1.4 stream - Hashtable tab = (Hashtable)f.get("tab", null); - vector = new Vector(); + Hashtable tab = (Hashtable)f.get("tab", null); + vector = new Vector<>(); if (tab != null && !tab.isEmpty()) { - for (Enumeration e = tab.keys() ; e.hasMoreElements() ; ) { + for (Enumeration e = tab.keys() ; e.hasMoreElements() ; ) { String key = (String)e.nextElement(); Component comp = (Component)tab.get(key); vector.add(new Card(key, comp)); @@ -594,7 +594,7 @@ public class CardLayout implements LayoutManager2, private void writeObject(ObjectOutputStream s) throws IOException { - Hashtable tab = new Hashtable(); + Hashtable tab = new Hashtable<>(); int ncomponents = vector.size(); for (int i = 0; i < ncomponents; i++) { Card card = (Card)vector.get(i); diff --git a/jdk/src/share/classes/java/awt/Component.java b/jdk/src/share/classes/java/awt/Component.java index c3307538f27..64a753844d7 100644 --- a/jdk/src/share/classes/java/awt/Component.java +++ b/jdk/src/share/classes/java/awt/Component.java @@ -972,6 +972,10 @@ public abstract class Component implements ImageObserver, MenuContainer, public AccessControlContext getAccessControlContext(Component comp) { return comp.getAccessControlContext(); } + + public void revalidateSynchronously(Component comp) { + comp.revalidateSynchronously(); + } }); } @@ -2022,7 +2026,7 @@ public abstract class Component implements ImageObserver, MenuContainer, * @return an instance of Point representing * the top-left corner of the component's bounds in the * coordinate space of the screen - * @throws IllegalComponentStateException if the + * @throws IllegalComponentStateException if the * component is not showing on the screen * @see #setLocation * @see #getLocation @@ -2977,6 +2981,13 @@ public abstract class Component implements ImageObserver, MenuContainer, * @since 1.7 */ public void revalidate() { + revalidateSynchronously(); + } + + /** + * Revalidates the component synchronously. + */ + final void revalidateSynchronously() { synchronized (getTreeLock()) { invalidate(); diff --git a/jdk/src/share/classes/java/awt/Container.java b/jdk/src/share/classes/java/awt/Container.java index 9029417b2ce..14bd55dae5c 100644 --- a/jdk/src/share/classes/java/awt/Container.java +++ b/jdk/src/share/classes/java/awt/Container.java @@ -258,6 +258,12 @@ public class Container extends Component { public void validateUnconditionally(Container cont) { cont.validateUnconditionally(); } + + @Override + public Component findComponentAt(Container cont, int x, int y, + boolean ignoreEnabled) { + return cont.findComponentAt(x, y, ignoreEnabled); + } }); } @@ -2651,7 +2657,6 @@ public class Container extends Component { * behavior. Setting 'ignoreEnabled' to 'false' bypasses disabled * Components during the search. This behavior is used by the * lightweight cursor support in sun.awt.GlobalCursorManager. - * The cursor code calls this function directly via native code. * * The addition of this feature is temporary, pending the * adoption of new, public API which exports this feature. diff --git a/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java b/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java index 7d36530ce2b..3f53698f7b5 100644 --- a/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java +++ b/jdk/src/share/classes/java/awt/ContainerOrderFocusTraversalPolicy.java @@ -85,7 +85,7 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy * list should be reused if possible. */ transient private Container cachedRoot; - transient private List cachedCycle; + transient private List cachedCycle; /* * We suppose to use getFocusTraversalCycle & getComponentIndex methods in order @@ -111,7 +111,7 @@ public class ContainerOrderFocusTraversalPolicy extends FocusTraversalPolicy return cycle.indexOf(aComponent); } - private void enumerateCycle(Container container, List cycle) { + private void enumerateCycle(Container container, List cycle) { if (!(container.isVisible() && container.isDisplayable())) { return; } diff --git a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java index 7c0c39d8ffa..4e07f16fa13 100644 --- a/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java +++ b/jdk/src/share/classes/java/awt/DefaultKeyboardFocusManager.java @@ -808,13 +808,13 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { } } boolean stopPostProcessing = false; - java.util.List processors = getKeyEventPostProcessors(); + java.util.List processors = getKeyEventPostProcessors(); if (processors != null) { - for (java.util.Iterator iter = processors.iterator(); + for (java.util.Iterator iter = processors.iterator(); !stopPostProcessing && iter.hasNext(); ) { - stopPostProcessing = (((KeyEventPostProcessor)(iter.next())). - postProcessKeyEvent(e)); + stopPostProcessing = iter.next(). + postProcessKeyEvent(e); } } if (!stopPostProcessing) { @@ -1059,12 +1059,12 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { return true; } - java.util.List dispatchers = getKeyEventDispatchers(); + java.util.List dispatchers = getKeyEventDispatchers(); if (dispatchers != null) { - for (java.util.Iterator iter = dispatchers.iterator(); + for (java.util.Iterator iter = dispatchers.iterator(); iter.hasNext(); ) { - if (((KeyEventDispatcher)(iter.next())). + if (iter.next(). dispatchKeyEvent(ke)) { return true; @@ -1131,7 +1131,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { oppStroke = AWTKeyStroke.getAWTKeyStroke(stroke.getKeyCode(), stroke.getModifiers(), !stroke.isOnKeyRelease()); - Set toTest; + Set toTest; boolean contains, containsOpp; toTest = focusedComponent.getFocusTraversalKeys( @@ -1246,7 +1246,7 @@ public class DefaultKeyboardFocusManager extends KeyboardFocusManager { * any) should be cancelled. * * @param after the timestamp specified in the call to - * enqueueKeyEvents, or any value < 0 + * enqueueKeyEvents, or any value < 0 * @param untilFocused the Component specified in the call to * enqueueKeyEvents * @see #enqueueKeyEvents diff --git a/jdk/src/share/classes/java/awt/Dialog.java b/jdk/src/share/classes/java/awt/Dialog.java index d27041fd322..a2248f033d7 100644 --- a/jdk/src/share/classes/java/awt/Dialog.java +++ b/jdk/src/share/classes/java/awt/Dialog.java @@ -61,7 +61,7 @@ import java.security.AccessControlException; *

    * The default layout for a dialog is BorderLayout. *

    - * A dialog may have its native decorations (i.e. Frame & Titlebar) turned off + * A dialog may have its native decorations (i.e. Frame & Titlebar) turned off * with setUndecorated. This can only be done while the dialog * is not {@link Component#isDisplayable() displayable}. *

    diff --git a/jdk/src/share/classes/java/awt/Event.java b/jdk/src/share/classes/java/awt/Event.java index fc119a0374e..2bc5c31b235 100644 --- a/jdk/src/share/classes/java/awt/Event.java +++ b/jdk/src/share/classes/java/awt/Event.java @@ -524,7 +524,7 @@ public class Event implements java.io.Serializable { * This field has been replaced by MouseEvent.getClickCount(). * * @serial - * @see java.awt.event.MouseEvent#getClickCount(). + * @see java.awt.event.MouseEvent#getClickCount() */ public int clickCount; diff --git a/jdk/src/share/classes/java/awt/EventQueue.java b/jdk/src/share/classes/java/awt/EventQueue.java index 76795eb5ed6..1a04dcb507a 100644 --- a/jdk/src/share/classes/java/awt/EventQueue.java +++ b/jdk/src/share/classes/java/awt/EventQueue.java @@ -690,7 +690,10 @@ public class EventQueue { final Object src = event.getSource(); final PrivilegedAction action = new PrivilegedAction() { public Void run() { - if (fwDispatcher == null) { + // In case fwDispatcher is installed and we're already on the + // dispatch thread (e.g. performing DefaultKeyboardFocusManager.sendMessage), + // dispatch the event straight away. + if (fwDispatcher == null || isDispatchThreadImpl()) { dispatchEventImpl(event, src); } else { fwDispatcher.scheduleDispatch(new Runnable() { diff --git a/jdk/src/share/classes/java/awt/Frame.java b/jdk/src/share/classes/java/awt/Frame.java index 2513ddb75ef..c7f5d4bcb80 100644 --- a/jdk/src/share/classes/java/awt/Frame.java +++ b/jdk/src/share/classes/java/awt/Frame.java @@ -265,12 +265,12 @@ public class Frame extends Window implements MenuContainer { * *

    Note that the correct test for frame being fully maximized is *

    -     *     (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH
    +     *     (state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH
          * 
    * *

    To test is frame is maximized in some direction use *

    -     *     (state & Frame.MAXIMIZED_BOTH) != 0
    +     *     (state & Frame.MAXIMIZED_BOTH) != 0
          * 
    * * @see #setExtendedState(int) diff --git a/jdk/src/share/classes/java/awt/GradientPaintContext.java b/jdk/src/share/classes/java/awt/GradientPaintContext.java index ac21d52da91..2536fa2cf04 100644 --- a/jdk/src/share/classes/java/awt/GradientPaintContext.java +++ b/jdk/src/share/classes/java/awt/GradientPaintContext.java @@ -41,7 +41,7 @@ class GradientPaintContext implements PaintContext { new DirectColorModel(24, 0x000000ff, 0x0000ff00, 0x00ff0000); static ColorModel cachedModel; - static WeakReference cached; + static WeakReference cached; static synchronized Raster getCachedRaster(ColorModel cm, int w, int h) { if (cm == cachedModel) { @@ -76,7 +76,7 @@ class GradientPaintContext implements PaintContext { } } cachedModel = cm; - cached = new WeakReference(ras); + cached = new WeakReference<>(ras); } double x1; diff --git a/jdk/src/share/classes/java/awt/GraphicsEnvironment.java b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java index f3d49b78243..9e1da05e35f 100644 --- a/jdk/src/share/classes/java/awt/GraphicsEnvironment.java +++ b/jdk/src/share/classes/java/awt/GraphicsEnvironment.java @@ -95,18 +95,18 @@ public abstract class GraphicsEnvironment { String nm = AccessController.doPrivileged(new GetPropertyAction("java.awt.graphicsenv", null)); try { // long t0 = System.currentTimeMillis(); - Class geCls; + Class geCls; try { // First we try if the bootclassloader finds the requested // class. This way we can avoid to run in a privileged block. - geCls = Class.forName(nm); + geCls = (Class)Class.forName(nm); } catch (ClassNotFoundException ex) { // If the bootclassloader fails, we try again with the // application classloader. ClassLoader cl = ClassLoader.getSystemClassLoader(); - geCls = Class.forName(nm, true, cl); + geCls = (Class)Class.forName(nm, true, cl); } - ge = (GraphicsEnvironment) geCls.newInstance(); + ge = geCls.newInstance(); // long t1 = System.currentTimeMillis(); // System.out.println("GE creation took " + (t1-t0)+ "ms."); if (isHeadless()) { @@ -161,7 +161,7 @@ public abstract class GraphicsEnvironment { private static boolean getHeadlessProperty() { if (headless == null) { java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { + new java.security.PrivilegedAction() { public Object run() { String nm = System.getProperty("java.awt.headless"); diff --git a/jdk/src/share/classes/java/awt/GridBagConstraints.java b/jdk/src/share/classes/java/awt/GridBagConstraints.java index c524efd0c63..3651b39be92 100644 --- a/jdk/src/share/classes/java/awt/GridBagConstraints.java +++ b/jdk/src/share/classes/java/awt/GridBagConstraints.java @@ -30,7 +30,7 @@ package java.awt; * GridBagLayout class. * * @author Doug Stein - * @author Bill Spitzak (orignial NeWS & OLIT implementation) + * @author Bill Spitzak (orignial NeWS & OLIT implementation) * @see java.awt.GridBagLayout * @since JDK1.0 */ diff --git a/jdk/src/share/classes/java/awt/GridBagLayout.java b/jdk/src/share/classes/java/awt/GridBagLayout.java index 22cb656ba60..fb306a8d3b4 100644 --- a/jdk/src/share/classes/java/awt/GridBagLayout.java +++ b/jdk/src/share/classes/java/awt/GridBagLayout.java @@ -120,9 +120,9 @@ import java.util.Arrays; * Orientation relative values are interpreted relative to the container's * ComponentOrientation property while absolute values * are not. Baseline relative values are calculated relative to the - * baseline. Valid values are: + * baseline. Valid values are: *

    - *

    Option NameDescription
    * * @@ -131,6 +131,7 @@ import java.util.Arrays; * * * * * * - *

    Absolute Values

    + *
      *
    • GridBagConstraints.NORTH
    • *
    • GridBagConstraints.SOUTH
    • *
    • GridBagConstraints.WEST
    • @@ -140,8 +141,10 @@ import java.util.Arrays; *
    • GridBagConstraints.SOUTHWEST
    • *
    • GridBagConstraints.SOUTHEAST
    • *
    • GridBagConstraints.CENTER (the default)
    • + *
    *
    + *
      *
    • GridBagConstraints.PAGE_START
    • *
    • GridBagConstraints.PAGE_END
    • *
    • GridBagConstraints.LINE_START
    • @@ -150,8 +153,10 @@ import java.util.Arrays; *
    • GridBagConstraints.FIRST_LINE_END
    • *
    • GridBagConstraints.LAST_LINE_START
    • *
    • GridBagConstraints.LAST_LINE_END
    • + *
    *
    + *
      *
    • GridBagConstraints.BASELINE
    • *
    • GridBagConstraints.BASELINE_LEADING
    • *
    • GridBagConstraints.BASELINE_TRAILING
    • @@ -161,9 +166,10 @@ import java.util.Arrays; *
    • GridBagConstraints.BELOW_BASELINE
    • *
    • GridBagConstraints.BELOW_BASELINE_LEADING
    • *
    • GridBagConstraints.BELOW_BASELINE_TRAILING
    • + *
    *

    + * *

    {@link GridBagConstraints#weightx}, * {@link GridBagConstraints#weighty} *
    Used to determine how to distribute space, which is @@ -246,7 +252,7 @@ import java.util.Arrays; * left-to-right container and Figure 3 shows the layout for a horizontal, * right-to-left container. *

    - *

    + *
    * *
    * The preceeding text describes this graphic (Figure 1). @@ -349,7 +355,7 @@ import java.util.Arrays; *
    *

    * @author Doug Stein - * @author Bill Spitzak (orignial NeWS & OLIT implementation) + * @author Bill Spitzak (orignial NeWS & OLIT implementation) * @see java.awt.GridBagConstraints * @see java.awt.GridBagLayoutInfo * @see java.awt.ComponentOrientation diff --git a/jdk/src/share/classes/java/awt/GridLayout.java b/jdk/src/share/classes/java/awt/GridLayout.java index 204995960d4..b08802e8e9d 100644 --- a/jdk/src/share/classes/java/awt/GridLayout.java +++ b/jdk/src/share/classes/java/awt/GridLayout.java @@ -55,7 +55,7 @@ package java.awt; * If the container's ComponentOrientation property is horizontal * and right-to-left, the example produces the output shown in Figure 2. *

    - *

    + *
    * * "}, + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + ""}, + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + "

    DEFAULT_NAME

    " + NL + "
    public static final java." +
    +            "lang.String DEFAULT_NAME
    "}, + {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", + "
  • Summary: 
  • " + NL + "
  • Field | 
  • "}, + {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", + "
  • Detail: 
  • " + NL + "
  • Field | 
  • "}, + }; private static final String[][] NEGATED_TEST = { {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", "
    " + NL + NL + "

    " + NL + NL + "

    " + diff --git a/langtools/test/com/sun/javadoc/testAnnotationTypes/pkg/AnnotationTypeField.java b/langtools/test/com/sun/javadoc/testAnnotationTypes/pkg/AnnotationTypeField.java new file mode 100644 index 00000000000..1dabafcc8db --- /dev/null +++ b/langtools/test/com/sun/javadoc/testAnnotationTypes/pkg/AnnotationTypeField.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg; + +import java.lang.annotation.*; + +/** + * This is just a test for annotation type fields. + */ +@Documented public @interface AnnotationTypeField { + String DEFAULT_NAME = "test"; + + String name() default DEFAULT_NAME; +} diff --git a/langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java b/langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java index c5dd3468443..1d1be4e5e02 100644 --- a/langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java +++ b/langtools/test/com/sun/javadoc/testDocFileDir/TestDocFileDir.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,7 @@ import java.io.File; /* * @test - * @bug 4258405 4973606 + * @bug 4258405 4973606 8024096 * @summary This test verifies that the doc-file directory does not * get overwritten when the sourcepath is equal to the destination * directory. @@ -47,25 +47,17 @@ public class TestDocFileDir extends JavadocTester { }; private static final String[][] NEGATED_TEST1 = NO_TEST; - private static final String[][] TEST2 = { - {BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-used1" + + private static final String[] FILE_TEST2 = { + BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-used1" + FS + "testfile.txt", - "passed" - }, - {BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-used2" + - FS + "testfile.txt", - "passed" - }, + BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-used2" + + FS + "testfile.txt" }; - private static final String[][] NEGATED_TEST2 = { - {BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-excluded1" + + private static final String[] FILE_NEGATED_TEST2 = { + BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-excluded1" + FS + "testfile.txt", - "passed" - }, - {BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-excluded2" + - FS + "testfile.txt", - "passed" - }, + BUG_ID + "-2" + FS + "pkg" + FS + "doc-files" + FS + "subdir-excluded2" + + FS + "testfile.txt" }; private static final String[][] TEST0 = { @@ -106,7 +98,7 @@ public class TestDocFileDir extends JavadocTester { run(tester, ARGS0, TEST0, NEGATED_TEST0); copyDir(SRC_DIR + FS + "pkg", BUG_ID + "-1"); run(tester, ARGS1, TEST1, NEGATED_TEST1); - run(tester, ARGS2, TEST2, NEGATED_TEST2); + run(tester, ARGS2, NO_TEST, NO_TEST, FILE_TEST2, FILE_NEGATED_TEST2); tester.printSummary(); } diff --git a/langtools/test/com/sun/javadoc/testEncoding/EncodeTest.java b/langtools/test/com/sun/javadoc/testEncoding/EncodeTest.java index 3fa762d5bf6..393ba8f5de2 100644 --- a/langtools/test/com/sun/javadoc/testEncoding/EncodeTest.java +++ b/langtools/test/com/sun/javadoc/testEncoding/EncodeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,9 @@ /** - * ±ñÉ¿í ¹©¢! + * Testing en\u00e7\u00f4ded string. + * In the encoded comment string, Unicode U+00E7 is "Latin small letter C with cedilla" + * and Unicode U+00F4 is "Latin small letter O with circumflex" */ public class EncodeTest { } diff --git a/langtools/test/com/sun/javadoc/testEncoding/TestEncoding.java b/langtools/test/com/sun/javadoc/testEncoding/TestEncoding.java index 0e9f1b6f101..db627b69156 100644 --- a/langtools/test/com/sun/javadoc/testEncoding/TestEncoding.java +++ b/langtools/test/com/sun/javadoc/testEncoding/TestEncoding.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4661481 + * @bug 4661481 8024096 * @summary This test determines if the value of the -encoding option is * properly passed from Javadoc to the source file parser. * @author jamieh @@ -40,12 +40,12 @@ public class TestEncoding extends JavadocTester { //If ??? is found in the output, the source file was not read with the correct encoding setting. private static final String[][] NEGATED_TEST = { - {BUG_ID + FS + "EncodeTest.html", "???"} + {BUG_ID + FS + "EncodeTest.html", "??"} }; private static final String[] ARGS = new String[] { "-d", BUG_ID, "-sourcepath", SRC_DIR, - "-encoding", "SJIS", SRC_DIR + FS + "EncodeTest.java" + "-encoding", "iso-8859-1", SRC_DIR + FS + "EncodeTest.java" }; /** diff --git a/langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java b/langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java index 162105edf8b..ec85bec863b 100644 --- a/langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java +++ b/langtools/test/com/sun/javadoc/testGeneratedBy/TestGeneratedBy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8000418 + * @bug 8000418 8024288 * @summary Verify that files use a common Generated By string * @library ../lib/ * @build JavadocTester TestGeneratedBy @@ -50,32 +50,44 @@ public class TestGeneratedBy extends JavadocTester { "index.html" }; - private static final String[] ARGS = + private static final String[] STD_ARGS = new String[] { "-d", OUTPUT_DIR, "-sourcepath", SRC_DIR, "pkg" }; - private static final String BUG_ID = "8000418"; - private static String[][] getTests() { + private static final String[] NO_TIMESTAMP_ARGS = + new String[] { + "-notimestamp", + "-d", OUTPUT_DIR, + "-sourcepath", SRC_DIR, + "pkg" + }; + + private static final String BUG_ID = "8000418-8024288"; + + private static String[][] getTests(boolean timestamp) { String version = System.getProperty("java.version"); String[][] tests = new String[FILES.length][]; for (int i = 0; i < FILES.length; i++) { + String genBy = "Generated by javadoc"; + if (timestamp) genBy += " (" + version + ") on "; tests[i] = new String[] { - OUTPUT_DIR + FS + FILES[i], - "Generated by javadoc (" + version + ") on " + OUTPUT_DIR + FS + FILES[i], genBy }; } return tests; } - private static String[][] getNegatedTests() { + private static String[][] getNegatedTests(boolean timestamp) { String[][] tests = new String[FILES.length][]; for (int i = 0; i < FILES.length; i++) { tests[i] = new String[] { OUTPUT_DIR + FS + FILES[i], - "Generated by javadoc (version", + (timestamp + ? "Generated by javadoc (version" + : "Generated by javadoc ("), "Generated by javadoc on" }; } @@ -88,9 +100,10 @@ public class TestGeneratedBy extends JavadocTester { */ public static void main(String[] args) { TestGeneratedBy tester = new TestGeneratedBy(); - int exitCode = run(tester, ARGS, getTests(), getNegatedTests()); + int ec1 = run(tester, STD_ARGS, getTests(true), getNegatedTests(true)); + int ec2 = run(tester, NO_TIMESTAMP_ARGS, getTests(false), getNegatedTests(false)); tester.printSummary(); - if (exitCode != 0) { + if (ec1 != 0 || ec2 != 0) { throw new Error("Error found while executing Javadoc"); } } diff --git a/langtools/test/com/sun/javadoc/testHref/TestHref.java b/langtools/test/com/sun/javadoc/testHref/TestHref.java index 297ddc69164..b8c4a24ca05 100644 --- a/langtools/test/com/sun/javadoc/testHref/TestHref.java +++ b/langtools/test/com/sun/javadoc/testHref/TestHref.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4663254 + * @bug 4663254 8016328 * @summary Verify that spaces do not appear in hrefs and anchors. * @author jamieh * @library ../lib/ @@ -46,11 +46,11 @@ public class TestHref extends JavadocTester { private static final String[][] TEST = { //External link. {BUG_ID + FS + "pkg" + FS + "C1.html", - "href=\"http://java.sun.com/j2se/1.4/docs/api/java/lang/Object.html?is-external=true#wait(long, int)\"" + "href=\"http://java.sun.com/j2se/1.4/docs/api/java/lang/Object.html?is-external=true#wait(long,%20int)\"" }, //Member summary table link. {BUG_ID + FS + "pkg" + FS + "C1.html", - "href=\"../pkg/C1.html#method(int, int, java.util.ArrayList)\"" + "href=\"../pkg/C1.html#method(int,%20int,%20java.util.ArrayList)\"" }, //Anchor test. {BUG_ID + FS + "pkg" + FS + "C1.html", @@ -66,11 +66,11 @@ public class TestHref extends JavadocTester { }, //{@link} test. {BUG_ID + FS + "pkg" + FS + "C2.html", - "Link: " + "Link: " }, //@see test. {BUG_ID + FS + "pkg" + FS + "C2.html", - "See Also:" + NL + "

    " + "See Also:" + NL + "
    " }, //Header does not link to the page itself. diff --git a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java index 763566a03ac..28602092110 100644 --- a/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java +++ b/langtools/test/com/sun/javadoc/testJavascript/TestJavascript.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4665566 4855876 7025314 8012375 8015997 + * @bug 4665566 4855876 7025314 8012375 8015997 8016328 * @summary Verify that the output has the right javascript. * @author jamieh * @library ../lib/ @@ -56,6 +56,12 @@ public class TestJavascript extends JavadocTester { " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))" + NL + " targetPage = \"undefined\";" + NL + " function validURL(url) {" + NL + + " try {" + NL + + " url = decodeURIComponent(url);" + NL + + " }" + NL + + " catch (error) {" + NL + + " return false;" + NL + + " }" + NL + " var pos = url.indexOf(\".html\");" + NL + " if (pos == -1 || pos != url.length - 5)" + NL + " return false;" + NL + @@ -67,7 +73,8 @@ public class TestJavascript extends JavadocTester { " if ('a' <= ch && ch <= 'z' ||" + NL + " 'A' <= ch && ch <= 'Z' ||" + NL + " ch == '$' ||" + NL + - " ch == '_') {" + NL + + " ch == '_' ||" + NL + + " ch.charCodeAt(0) > 127) {" + NL + " allowNumber = true;" + NL + " allowSep = true;" + NL + " } else if ('0' <= ch && ch <= '9'" + NL + diff --git a/langtools/test/com/sun/javadoc/testLambdaFeature/TestLambdaFeature.java b/langtools/test/com/sun/javadoc/testLambdaFeature/TestLambdaFeature.java index 7a157ffc17d..151549b57a2 100644 --- a/langtools/test/com/sun/javadoc/testLambdaFeature/TestLambdaFeature.java +++ b/langtools/test/com/sun/javadoc/testLambdaFeature/TestLambdaFeature.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8004893 + * @bug 8004893 8022738 * @summary Make sure that the lambda feature changes work fine in * javadoc. * @author bpatel @@ -35,11 +35,15 @@ public class TestLambdaFeature extends JavadocTester { //Test information. - private static final String BUG_ID = "8004893"; + private static final String BUG_ID = "8004893-8022738"; //Javadoc arguments. private static final String[] ARGS = new String[] { - "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg" + "-d", BUG_ID, "-sourcepath", SRC_DIR, "pkg", "pkg1" + }; + + private static final String[] ARGS_1 = new String[] { + "-d", BUG_ID + "-2", "-sourcepath", SRC_DIR, "-source", "1.5", "pkg1" }; //Input for string search tests. @@ -60,6 +64,11 @@ public class TestLambdaFeature extends JavadocTester { "Default Methods" + " "}, {BUG_ID + FS + "pkg" + FS + "A.html", + "
    " + NL + "
    Functional Interface:
    " + NL + + "
    This is a functional interface and can therefore be used as " + + "the assignment target for a lambda expression or method " + + "reference.
    " + NL + "
    "}, + {BUG_ID + FS + "pkg1" + FS + "FuncInf.html", "
    " + NL + "
    Functional Interface:
    " + NL + "
    This is a functional interface and can therefore be used as " + "the assignment target for a lambda expression or method " + @@ -75,6 +84,10 @@ public class TestLambdaFeature extends JavadocTester { {BUG_ID + FS + "pkg" + FS + "B.html", "
    " + NL + "
    Functional Interface:
    "} }; + private static final String[][] NEGATED_TEST_1 = { + {BUG_ID + "-2" + FS + "pkg1" + FS + "FuncInf.html", + "
    " + NL + "
    Functional Interface:
    "} + }; /** * The entry point of the test. @@ -83,6 +96,7 @@ public class TestLambdaFeature extends JavadocTester { public static void main(String[] args) { TestLambdaFeature tester = new TestLambdaFeature(); run(tester, ARGS, TEST, NEGATED_TEST); + run(tester, ARGS_1, NO_TEST, NEGATED_TEST_1); tester.printSummary(); } diff --git a/langtools/test/com/sun/javadoc/testLambdaFeature/pkg1/FuncInf.java b/langtools/test/com/sun/javadoc/testLambdaFeature/pkg1/FuncInf.java new file mode 100644 index 00000000000..566acf596ca --- /dev/null +++ b/langtools/test/com/sun/javadoc/testLambdaFeature/pkg1/FuncInf.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg1; + +public interface FuncInf { + + V call() throws Exception; +} diff --git a/langtools/test/com/sun/javadoc/testLegacyTaglet/C.java b/langtools/test/com/sun/javadoc/testLegacyTaglet/C.java index d5370c2dcd6..6de5ca31ef1 100644 --- a/langtools/test/com/sun/javadoc/testLegacyTaglet/C.java +++ b/langtools/test/com/sun/javadoc/testLegacyTaglet/C.java @@ -25,5 +25,13 @@ /** * This is an {@underline underline}. * @todo Finish this class. + * @check Check this. */ -public class C {} +public class C { + + /** + * @todo Tag in Method. + */ + public void mtd() { + } +} diff --git a/langtools/test/com/sun/javadoc/testLegacyTaglet/Check.java b/langtools/test/com/sun/javadoc/testLegacyTaglet/Check.java new file mode 100644 index 00000000000..a294603b99a --- /dev/null +++ b/langtools/test/com/sun/javadoc/testLegacyTaglet/Check.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.tools.doclets.Taglet; +import com.sun.javadoc.*; +import java.util.Map; + +public class Check implements Taglet { + + private static final String TAG_NAME = "check"; + private static final String TAG_HEADER = "Check:"; + + /** + * Return true since the tag can be used in package documentation. + * + * @return true since the tag can be used in package documentation. + */ + public boolean inPackage() { + return true; + } + + /** + * Return true since the tag can be used in overview documentation. + * + * @return true since the tag can be used in overview documentation. + */ + public boolean inOverview() { + return true; + } + + /** + * Return true since the tag can be used in type (class/interface) + * documentation. + * + * @return true since the tag can be used in type (class/interface) + * documentation. + */ + public boolean inType() { + return true; + } + + /** + * Return true since the tag can be used in constructor documentation. + * + * @return true since the tag can be used in constructor documentation. + */ + public boolean inConstructor() { + return true; + } + + /** + * Return true since the tag can be used in field documentation. + * + * @return true since the tag can be used in field documentation. + */ + public boolean inField() { + return true; + } + + /** + * Return true since the tag can be used in method documentation. + * + * @return true since the tag can be used in method documentation. + */ + public boolean inMethod() { + return true; + } + + /** + * Return false since the tag is not an inline tag. + * + * @return false since the tag is not an inline tag. + */ + public boolean isInlineTag() { + return false; + } + + /** + * Register this taglet. + * + * @param tagletMap the map to register this tag to. + */ + @SuppressWarnings("unchecked") + public static void register(Map tagletMap) { + Check tag = new Check(); + Taglet t = (Taglet) tagletMap.get(tag.getName()); + if (t != null) { + tagletMap.remove(tag.getName()); + } + tagletMap.put(tag.getName(), tag); + } + + /** + * Return the name of this custom tag. + * + * @return the name of this tag. + */ + public String getName() { + return TAG_NAME; + } + + /** + * Given the tag representation of this custom tag, return its string + * representation. + * + * @param tag the tag representation of this custom tag. + */ + public String toString(Tag tag) { + return "
    " + TAG_HEADER + ":
    " + tag.text() + + "
    \n"; + } + + /** + * Given an array of tags representing this custom tag, return its string + * representation. + * + * @param tags the array of tags representing of this custom tag. + * @return null to test if the javadoc throws an exception or not. + */ + public String toString(Tag[] tags) { + return null; + } +} diff --git a/langtools/test/com/sun/javadoc/testLegacyTaglet/TestLegacyTaglet.java b/langtools/test/com/sun/javadoc/testLegacyTaglet/TestLegacyTaglet.java index 8e1790de54a..f86c998e809 100644 --- a/langtools/test/com/sun/javadoc/testLegacyTaglet/TestLegacyTaglet.java +++ b/langtools/test/com/sun/javadoc/testLegacyTaglet/TestLegacyTaglet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,32 +23,33 @@ /* * @test - * @bug 4638723 + * @bug 4638723 8015882 * @summary Test to ensure that the refactored version of the standard * doclet still works with Taglets that implement the 1.4.0 interface. * @author jamieh * @library ../lib/ - * @compile ../lib/JavadocTester.java - * @compile TestLegacyTaglet.java - * @compile ToDoTaglet.java - * @compile UnderlineTaglet.java + * @compile ../lib/JavadocTester.java TestLegacyTaglet.java ToDoTaglet.java UnderlineTaglet.java Check.java * @run main TestLegacyTaglet */ public class TestLegacyTaglet extends JavadocTester { - private static final String BUG_ID = "4638723"; + private static final String BUG_ID = "4638723-8015882"; private static final String[] ARGS = new String[] {"-d", BUG_ID, "-sourcepath", SRC_DIR, - "-tagletpath", SRC_DIR, "-taglet", "ToDoTaglet", + "-tagletpath", SRC_DIR, "-taglet", "ToDoTaglet", "-taglet", "Check", "-taglet", "UnderlineTaglet", SRC_DIR + FS + "C.java"}; private static final String[][] TEST = new String[][] { {BUG_ID + FS + "C.html", "This is an underline"}, {BUG_ID + FS + "C.html", "
    To Do:
    Shows 6 buttons in rows of 2. Row 1 shows buttons 1 then 2.
diff --git a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java
index 51507696cff..72c3fdb4956 100644
--- a/jdk/src/share/classes/java/awt/KeyboardFocusManager.java
+++ b/jdk/src/share/classes/java/awt/KeyboardFocusManager.java
@@ -348,7 +348,7 @@ public abstract class KeyboardFocusManager
      * Component of those Windows that has no such array of its own explicitly
      * set.
      */
-    private Set[] defaultFocusTraversalKeys = new Set[4];
+    private Set<AWTKeyStroke>[] defaultFocusTraversalKeys = new Set[4];
 
     /**
      * The current focus cycle root. If the focus owner is itself a focus cycle
@@ -376,7 +376,7 @@ public abstract class KeyboardFocusManager
      * KeyEventDispatchers are registered, this field may be null or refer to
      * a List of length 0.
      */
-    private java.util.LinkedList keyEventDispatchers;
+    private java.util.LinkedList<KeyEventDispatcher> keyEventDispatchers;
 
     /**
      * This KeyboardFocusManager's KeyEventPostProcessor chain. The List does
@@ -385,12 +385,12 @@ public abstract class KeyboardFocusManager
      * If no other KeyEventPostProcessors are registered, this field may be
      * null or refer to a List of length 0.
      */
-    private java.util.LinkedList keyEventPostProcessors;
+    private java.util.LinkedList<KeyEventPostProcessor> keyEventPostProcessors;
 
     /**
      * Maps Windows to those Windows' most recent focus owners.
      */
-    private static java.util.Map mostRecentFocusOwners = new WeakHashMap();
+    private static java.util.Map<Window, WeakReference<Component>> mostRecentFocusOwners = new WeakHashMap<>();
 
     /**
      * We cache the permission used to verify that the calling thread is
@@ -431,7 +431,7 @@ public abstract class KeyboardFocusManager
      */
     public KeyboardFocusManager() {
         for (int i = 0; i < TRAVERSAL_KEY_LENGTH; i++) {
-            Set work_set = new HashSet();
+            Set<AWTKeyStroke> work_set = new HashSet<>();
             for (int j = 0; j < defaultFocusTraversalKeyStrokes[i].length; j++) {
                 work_set.add(defaultFocusTraversalKeyStrokes[i][j]);
             }
@@ -1125,7 +1125,7 @@ public abstract class KeyboardFocusManager
             throw new IllegalArgumentException( oldKeys; synchronized (this) { for (AWTKeyStroke keystroke : keystrokes) { @@ -1153,7 +1153,7 @@ public abstract class KeyboardFocusManager oldKeys = defaultFocusTraversalKeys[id]; defaultFocusTraversalKeys[id] = - Collections.unmodifiableSet(new HashSet(keystrokes)); + Collections.unmodifiableSet(new HashSet<>(keystrokes)); } firePropertyChange(defaultFocusTraversalKeyPropertyNames[id], @@ -1699,7 +1699,7 @@ public abstract class KeyboardFocusManager if (dispatcher != null) { synchronized (this) { if (keyEventDispatchers == null) { - keyEventDispatchers = new java.util.LinkedList(); + keyEventDispatchers = new java.util.LinkedList<>(); } keyEventDispatchers.add(dispatcher); } @@ -1787,7 +1787,7 @@ public abstract class KeyboardFocusManager if (processor != null) { synchronized (this) { if (keyEventPostProcessors == null) { - keyEventPostProcessors = new java.util.LinkedList(); + keyEventPostProcessors = new java.util.LinkedList<>(); } keyEventPostProcessors.add(processor); } @@ -1865,9 +1865,9 @@ public abstract class KeyboardFocusManager // of Component.parent fields. Since WeakHasMap refers to its // values strongly, we need to break the strong link from the // value (component) back to its key (window). - WeakReference weakValue = null; + WeakReference weakValue = null; if (component != null) { - weakValue = new WeakReference(component); + weakValue = new WeakReference<>(component); } mostRecentFocusOwners.put(window, weakValue); } @@ -1906,7 +1906,7 @@ public abstract class KeyboardFocusManager * javax.swing.JComponent.runInputVerifier() using reflection. */ static synchronized Component getMostRecentFocusOwner(Window window) { - WeakReference weakValue = + WeakReference weakValue = (WeakReference)mostRecentFocusOwners.get(window); return weakValue == null ? null : (Component)weakValue.get(); } @@ -2034,7 +2034,7 @@ public abstract class KeyboardFocusManager * oldest timestamp (if any) should be cancelled. * * @param after the timestamp specified in the call to - * enqueueKeyEvents, or any value < 0 + * enqueueKeyEvents, or any value < 0 * @param untilFocused the Component specified in the call to * enqueueKeyEvents * @see #enqueueKeyEvents @@ -2649,11 +2649,11 @@ public abstract class KeyboardFocusManager Component lastFocusOwner = null; Component currentFocusOwner = null; - for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) { + for (Iterator iter = localLightweightRequests.iterator(); iter.hasNext(); ) { currentFocusOwner = manager.getGlobalFocusOwner(); LightweightFocusRequest lwFocusRequest = - (LightweightFocusRequest)iter.next(); + iter.next(); /* * WARNING: This is based on DKFM's logic solely! @@ -2978,12 +2978,12 @@ public abstract class KeyboardFocusManager if (hwFocusRequest != null) { heavyweightRequests.removeFirst(); if (hwFocusRequest.lightweightRequests != null) { - for (Iterator lwIter = hwFocusRequest.lightweightRequests. + for (Iterator lwIter = hwFocusRequest.lightweightRequests. iterator(); lwIter.hasNext(); ) { manager.dequeueKeyEvents - (-1, ((LightweightFocusRequest)lwIter.next()). + (-1, lwIter.next(). component); } } @@ -3063,8 +3063,8 @@ public abstract class KeyboardFocusManager // Accessor to private field isProxyActive of KeyEvent private static boolean isProxyActiveImpl(KeyEvent e) { if (proxyActive == null) { - proxyActive = (Field) AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + proxyActive = AccessController.doPrivileged(new PrivilegedAction() { + public Field run() { Field field = null; try { field = KeyEvent.class.getDeclaredField("isProxyActive"); diff --git a/jdk/src/share/classes/java/awt/MenuBar.java b/jdk/src/share/classes/java/awt/MenuBar.java index bd0a7d890c0..feae49a4db5 100644 --- a/jdk/src/share/classes/java/awt/MenuBar.java +++ b/jdk/src/share/classes/java/awt/MenuBar.java @@ -43,7 +43,7 @@ import javax.accessibility.*; * This is what a menu bar might look like: *

    * *

    diff --git a/jdk/src/share/classes/java/awt/ScrollPane.java b/jdk/src/share/classes/java/awt/ScrollPane.java index bb27de0ce98..a2e2fc7ee0a 100644 --- a/jdk/src/share/classes/java/awt/ScrollPane.java +++ b/jdk/src/share/classes/java/awt/ScrollPane.java @@ -247,7 +247,7 @@ public class ScrollPane extends Container implements Accessible { * component is removed and the new one is added. * @param comp the component to be added * @param constraints not applicable - * @param index position of child component (must be <= 0) + * @param index position of child component (must be <= 0) */ protected final void addImpl(Component comp, Object constraints, int index) { synchronized (getTreeLock()) { diff --git a/jdk/src/share/classes/java/awt/ScrollPaneAdjustable.java b/jdk/src/share/classes/java/awt/ScrollPaneAdjustable.java index f9c08b39fbf..d51a84250c8 100644 --- a/jdk/src/share/classes/java/awt/ScrollPaneAdjustable.java +++ b/jdk/src/share/classes/java/awt/ScrollPaneAdjustable.java @@ -220,7 +220,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { * This method is public for this class to properly implement * Adjustable interface. * - * @throws AWTError Always throws an error when called. + * @throws AWTError Always throws an error when called. */ public void setMinimum(int min) { throw new AWTError(SCROLLPANE_ONLY); @@ -237,7 +237,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { * This method is public for this class to properly implement * Adjustable interface. * - * @throws AWTError Always throws an error when called. + * @throws AWTError Always throws an error when called. */ public void setMaximum(int max) { throw new AWTError(SCROLLPANE_ONLY); @@ -274,7 +274,7 @@ public class ScrollPaneAdjustable implements Adjustable, Serializable { * This method is public for this class to properly implement * Adjustable interface. * - * @throws AWTError Always throws an error when called. + * @throws AWTError Always throws an error when called. */ public void setVisibleAmount(int v) { throw new AWTError(SCROLLPANE_ONLY); diff --git a/jdk/src/share/classes/java/awt/Scrollbar.java b/jdk/src/share/classes/java/awt/Scrollbar.java index b6a581d96a8..8ecf5783057 100644 --- a/jdk/src/share/classes/java/awt/Scrollbar.java +++ b/jdk/src/share/classes/java/awt/Scrollbar.java @@ -715,6 +715,9 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * The unit increment must be greater than zero. * Attepts to set the unit increment to a value lower than 1 * will result in a value of 1 being set. + *

    + * In some operating systems, this property + * can be ignored by the underlying controls. * * @param v the amount by which to increment or decrement * the scroll bar's value @@ -752,6 +755,9 @@ public class Scrollbar extends Component implements Adjustable, Accessible { * scroll bar, generally through a mouse or keyboard gesture * that the scroll bar receives as an adjustment event. * The unit increment must be greater than zero. + *

    + * In some operating systems, this property + * can be ignored by the underlying controls. * * @return the unit increment of this scroll bar * @see java.awt.Scrollbar#setUnitIncrement diff --git a/jdk/src/share/classes/java/awt/SequencedEvent.java b/jdk/src/share/classes/java/awt/SequencedEvent.java index b57cde2683f..0ae8dad64db 100644 --- a/jdk/src/share/classes/java/awt/SequencedEvent.java +++ b/jdk/src/share/classes/java/awt/SequencedEvent.java @@ -49,7 +49,7 @@ class SequencedEvent extends AWTEvent implements ActiveEvent { private static final int ID = java.awt.event.FocusEvent.FOCUS_LAST + 1; - private static final LinkedList list = new LinkedList(); + private static final LinkedList list = new LinkedList<>(); private final AWTEvent nested; private AppContext appContext; diff --git a/jdk/src/share/classes/java/awt/SystemTray.java b/jdk/src/share/classes/java/awt/SystemTray.java index 444f85fa320..84e89265c78 100644 --- a/jdk/src/share/classes/java/awt/SystemTray.java +++ b/jdk/src/share/classes/java/awt/SystemTray.java @@ -63,8 +63,8 @@ import sun.awt.AWTAccessor; * *

    The following code snippet demonstrates how to access * and customize the system tray: - * *

    + * 
      *     {@link TrayIcon} trayIcon = null;
      *     if (SystemTray.isSupported()) {
      *         // get the SystemTray instance
    @@ -109,8 +109,8 @@ import sun.awt.AWTAccessor;
      *         trayIcon.{@link TrayIcon#setImage(java.awt.Image) setImage}(updatedImage);
      *     }
      *     // ...
    - * 
    * + * * * @since 1.6 * @see TrayIcon diff --git a/jdk/src/share/classes/java/awt/TextComponent.java b/jdk/src/share/classes/java/awt/TextComponent.java index 7a6cd26bbf3..2065db6a2cd 100644 --- a/jdk/src/share/classes/java/awt/TextComponent.java +++ b/jdk/src/share/classes/java/awt/TextComponent.java @@ -35,6 +35,7 @@ import java.text.BreakIterator; import javax.swing.text.AttributeSet; import javax.accessibility.*; import java.awt.im.InputMethodRequests; +import sun.security.util.SecurityConstants; /** * The TextComponent class is the superclass of @@ -728,7 +729,7 @@ public class TextComponent extends Component implements Accessible { SecurityManager sm = System.getSecurityManager(); if (sm == null) return true; try { - sm.checkSystemClipboardAccess(); + sm.checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION); return true; } catch (SecurityException e) {} return false; @@ -971,7 +972,7 @@ public class TextComponent extends Component implements Accessible { * coordinates. If the index is invalid a null rectangle * is returned. * - * @param i the index into the String >= 0 + * @param i the index into the String >= 0 * @return the screen coordinates of the character's bounding box */ public Rectangle getCharacterBounds(int i) { @@ -981,7 +982,7 @@ public class TextComponent extends Component implements Accessible { /** * Returns the number of characters (valid indicies) * - * @return the number of characters >= 0 + * @return the number of characters >= 0 */ public int getCharCount() { return TextComponent.this.getText().length(); @@ -1017,7 +1018,7 @@ public class TextComponent extends Component implements Accessible { * Return 0 if the text is empty, or the caret position * if no selection. * - * @return the index into the text of the start of the selection >= 0 + * @return the index into the text of the start of the selection >= 0 */ public int getSelectionStart() { return TextComponent.this.getSelectionStart(); @@ -1030,7 +1031,7 @@ public class TextComponent extends Component implements Accessible { * Return 0 if the text is empty, or the caret position * if no selection. * - * @return the index into teh text of the end of the selection >= 0 + * @return the index into teh text of the end of the selection >= 0 */ public int getSelectionEnd() { return TextComponent.this.getSelectionEnd(); @@ -1055,7 +1056,7 @@ public class TextComponent extends Component implements Accessible { * * @param part the AccessibleText.CHARACTER, AccessibleText.WORD, * or AccessibleText.SENTENCE to retrieve - * @param index an index within the text >= 0 + * @param index an index within the text >= 0 * @return the letter, word, or sentence, * null for an invalid index or part */ @@ -1121,7 +1122,7 @@ public class TextComponent extends Component implements Accessible { * * @param part the AccessibleText.CHARACTER, AccessibleText.WORD, * or AccessibleText.SENTENCE to retrieve - * @param index an index within the text >= 0 + * @param index an index within the text >= 0 * @return the letter, word, or sentence, null for an invalid * index or part */ @@ -1174,7 +1175,7 @@ public class TextComponent extends Component implements Accessible { * * @param part the AccessibleText.CHARACTER, AccessibleText.WORD, * or AccessibleText.SENTENCE to retrieve - * @param index an index within the text >= 0 + * @param index an index within the text >= 0 * @return the letter, word, or sentence, null for an invalid index * or part */ diff --git a/jdk/src/share/classes/java/awt/TextField.java b/jdk/src/share/classes/java/awt/TextField.java index 7c0e528f5f7..cbaf649f100 100644 --- a/jdk/src/share/classes/java/awt/TextField.java +++ b/jdk/src/share/classes/java/awt/TextField.java @@ -503,7 +503,7 @@ public class TextField extends TextComponent { * * @see #addActionListener * @see #removeActionListener - * @see java.awt.event#ActionListener + * @see java.awt.event.ActionListener * @since 1.4 */ public synchronized ActionListener[] getActionListeners() { diff --git a/jdk/src/share/classes/java/awt/TexturePaintContext.java b/jdk/src/share/classes/java/awt/TexturePaintContext.java index a6d2e04615d..359071e1015 100644 --- a/jdk/src/share/classes/java/awt/TexturePaintContext.java +++ b/jdk/src/share/classes/java/awt/TexturePaintContext.java @@ -73,11 +73,11 @@ abstract class TexturePaintContext implements PaintContext { WritableRaster raster = bufImg.getRaster(); ColorModel cm = bufImg.getColorModel(); int maxw = devBounds.width; - Object val = hints.get(hints.KEY_INTERPOLATION); + Object val = hints.get(RenderingHints.KEY_INTERPOLATION); boolean filter = (val == null - ? (hints.get(hints.KEY_RENDERING) == hints.VALUE_RENDER_QUALITY) - : (val != hints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)); + ? (hints.get(RenderingHints.KEY_RENDERING) == RenderingHints.VALUE_RENDER_QUALITY) + : (val != RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR)); if (raster instanceof IntegerInterleavedRaster && (!filter || isFilterableDCM(cm))) { @@ -234,8 +234,8 @@ abstract class TexturePaintContext implements PaintContext { return outRas; } - private static WeakReference xrgbRasRef; - private static WeakReference argbRasRef; + private static WeakReference xrgbRasRef; + private static WeakReference argbRasRef; synchronized static WritableRaster makeRaster(ColorModel cm, Raster srcRas, @@ -278,13 +278,13 @@ abstract class TexturePaintContext implements PaintContext { return; } if (xrgbmodel == cm) { - xrgbRasRef = new WeakReference(outRas); + xrgbRasRef = new WeakReference<>(outRas); } else if (argbmodel == cm) { - argbRasRef = new WeakReference(outRas); + argbRasRef = new WeakReference<>(outRas); } } - private static WeakReference byteRasRef; + private static WeakReference byteRasRef; synchronized static WritableRaster makeByteRaster(Raster srcRas, int w, int h) @@ -307,7 +307,7 @@ abstract class TexturePaintContext implements PaintContext { if (outRas == null) { return; } - byteRasRef = new WeakReference(outRas); + byteRasRef = new WeakReference<>(outRas); } public abstract WritableRaster makeRaster(int w, int h); diff --git a/jdk/src/share/classes/java/awt/Toolkit.java b/jdk/src/share/classes/java/awt/Toolkit.java index 92bedb7580b..de14eef1fea 100644 --- a/jdk/src/share/classes/java/awt/Toolkit.java +++ b/jdk/src/share/classes/java/awt/Toolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,6 +56,7 @@ import sun.awt.HeadlessToolkit; import sun.awt.NullComponentPeer; import sun.awt.PeerEvent; import sun.awt.SunToolkit; +import sun.awt.AWTAccessor; import sun.security.util.SecurityConstants; import sun.util.CoreResourceBundleControl; @@ -467,7 +468,7 @@ public abstract class Toolkit { GraphicsEnvironment.checkHeadless(); } -/** + /** * Controls whether the layout of Containers is validated dynamically * during resizing, or statically, after resizing is complete. * Use {@code isDynamicLayoutActive()} to detect if this feature enabled @@ -497,9 +498,12 @@ public abstract class Toolkit { * @see java.awt.GraphicsEnvironment#isHeadless * @since 1.4 */ - public void setDynamicLayout(boolean dynamic) + public void setDynamicLayout(final boolean dynamic) throws HeadlessException { GraphicsEnvironment.checkHeadless(); + if (this != getDefaultToolkit()) { + getDefaultToolkit().setDynamicLayout(dynamic); + } } /** @@ -1239,7 +1243,8 @@ public abstract class Toolkit { } /** - * Emits an audio beep. + * Emits an audio beep depending on native system settings and hardware + * capabilities. * @since JDK1.1 */ public abstract void beep(); @@ -1270,12 +1275,8 @@ public abstract class Toolkit { *

    * Each actual implementation of this method should first check if there * is a security manager installed. If there is, the method should call - * the security manager's checkSystemClipboardAccess method - * to ensure it's ok to to access the system clipboard. If the default - * implementation of checkSystemClipboardAccess is used (that - * is, that method is not overriden), then this results in a call to the - * security manager's checkPermission method with an - * AWTPermission("accessClipboard") permission. + * the security manager's {@link SecurityManager#checkPermission + * checkPermission} method to check {@code AWTPermission("accessClipboard")}. * * @return the system Clipboard * @exception HeadlessException if GraphicsEnvironment.isHeadless() @@ -1318,14 +1319,9 @@ public abstract class Toolkit { * system selection Clipboard as described above. *

    * Each actual implementation of this method should first check if there - * is a SecurityManager installed. If there is, the method - * should call the SecurityManager's - * checkSystemClipboardAccess method to ensure that client - * code has access the system selection. If the default implementation of - * checkSystemClipboardAccess is used (that is, if the method - * is not overridden), then this results in a call to the - * SecurityManager's checkPermission method with - * an AWTPermission("accessClipboard") permission. + * is a security manager installed. If there is, the method should call + * the security manager's {@link SecurityManager#checkPermission + * checkPermission} method to check {@code AWTPermission("accessClipboard")}. * * @return the system selection as a Clipboard, or * null if the native platform does not support a @@ -1607,6 +1603,12 @@ public abstract class Toolkit { * here, so that only one copy is maintained. */ private static ResourceBundle resources; + private static ResourceBundle platformResources; + + // called by platform toolkit + private static void setPlatformResources(ResourceBundle bundle) { + platformResources = bundle; + } /** * Initialize JNI field and method ids @@ -1655,6 +1657,14 @@ public abstract class Toolkit { } static { + AWTAccessor.setToolkitAccessor( + new AWTAccessor.ToolkitAccessor() { + @Override + public void setPlatformResources(ResourceBundle bundle) { + Toolkit.setPlatformResources(bundle); + } + }); + java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { @@ -1682,6 +1692,15 @@ public abstract class Toolkit { * This method returns defaultValue if the property is not found. */ public static String getProperty(String key, String defaultValue) { + // first try platform specific bundle + if (platformResources != null) { + try { + return platformResources.getString(key); + } + catch (MissingResourceException e) {} + } + + // then shared one if (resources != null) { try { return resources.getString(key); @@ -1699,25 +1718,20 @@ public abstract class Toolkit { * therefore not assume that the EventQueue instance returned * by this method will be shared by other applets or the system. * - *

    First, if there is a security manager, its - * checkAwtEventQueueAccess - * method is called. - * If the default implementation of checkAwtEventQueueAccess - * is used (that is, that method is not overriden), then this results in - * a call to the security manager's checkPermission method - * with an AWTPermission("accessEventQueue") permission. + *

    If there is a security manager then its + * {@link SecurityManager#checkPermission checkPermission} method + * is called to check {@code AWTPermission("accessEventQueue")}. * * @return the EventQueue object * @throws SecurityException - * if a security manager exists and its {@link - * java.lang.SecurityManager#checkAwtEventQueueAccess} - * method denies access to the EventQueue + * if a security manager is set and it denies access to + * the {@code EventQueue} * @see java.awt.AWTPermission */ public final EventQueue getSystemEventQueue() { SecurityManager security = System.getSecurityManager(); if (security != null) { - security.checkAwtEventQueueAccess(); + security.checkPermission(SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION); } return getSystemEventQueueImpl(); } diff --git a/jdk/src/share/classes/java/awt/WaitDispatchSupport.java b/jdk/src/share/classes/java/awt/WaitDispatchSupport.java index 1cfd24a1416..c9a671838a9 100644 --- a/jdk/src/share/classes/java/awt/WaitDispatchSupport.java +++ b/jdk/src/share/classes/java/awt/WaitDispatchSupport.java @@ -224,8 +224,8 @@ class WaitDispatchSupport implements SecondaryLoop { // starts. Thus, the enter() method will not hang. // // Event pump should be privileged. See 6300270. - AccessController.doPrivileged(new PrivilegedAction() { - public Object run() { + AccessController.doPrivileged(new PrivilegedAction() { + public Void run() { run.run(); return null; } diff --git a/jdk/src/share/classes/java/awt/Window.java b/jdk/src/share/classes/java/awt/Window.java index 4076939c7f0..7471683749e 100644 --- a/jdk/src/share/classes/java/awt/Window.java +++ b/jdk/src/share/classes/java/awt/Window.java @@ -195,10 +195,9 @@ public class Window extends Container implements Accessible { /** * This represents the warning message that is * to be displayed in a non secure window. ie : - * a window that has a security manager installed for - * which calling SecurityManager.checkTopLevelWindow() - * is false. This message can be displayed anywhere in - * the window. + * a window that has a security manager installed that denies + * {@code AWTPermission("showWindowWithoutWarningBanner")}. + * This message can be displayed anywhere in the window. * * @serial * @see #getWarningString @@ -417,11 +416,10 @@ public class Window extends Container implements Accessible { * Constructs a new, initially invisible window in default size with the * specified {@code GraphicsConfiguration}. *

    - * If there is a security manager, this method first calls - * the security manager's {@code checkTopLevelWindow} - * method with {@code this} - * as its argument to determine whether or not the window - * must be displayed with a warning banner. + * If there is a security manager, then it is invoked to check + * {@code AWTPermission("showWindowWithoutWarningBanner")} + * to determine whether or not the window must be displayed with + * a warning banner. * * @param gc the {@code GraphicsConfiguration} of the target screen * device. If {@code gc} is {@code null}, the system default @@ -432,7 +430,6 @@ public class Window extends Container implements Accessible { * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless - * @see java.lang.SecurityManager#checkTopLevelWindow */ Window(GraphicsConfiguration gc) { init(gc); @@ -511,25 +508,16 @@ public class Window extends Container implements Accessible { /** * Constructs a new, initially invisible window in the default size. - * - *

    First, if there is a security manager, its - * {@code checkTopLevelWindow} - * method is called with {@code this} - * as its argument - * to see if it's ok to display the window without a warning banner. - * If the default implementation of {@code checkTopLevelWindow} - * is used (that is, that method is not overriden), then this results in - * a call to the security manager's {@code checkPermission} method - * with an {@code AWTPermission("showWindowWithoutWarningBanner")} - * permission. It that method raises a SecurityException, - * {@code checkTopLevelWindow} returns false, otherwise it - * returns true. If it returns false, a warning banner is created. + *

    + * If there is a security manager set, it is invoked to check + * {@code AWTPermission("showWindowWithoutWarningBanner")}. + * If that check fails with a {@code SecurityException} then a warning + * banner is created. * * @exception HeadlessException when * {@code GraphicsEnvironment.isHeadless()} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless - * @see java.lang.SecurityManager#checkTopLevelWindow */ Window() throws HeadlessException { GraphicsEnvironment.checkHeadless(); @@ -541,11 +529,10 @@ public class Window extends Container implements Accessible { * {@code Frame} as its owner. The window will not be focusable * unless its owner is showing on the screen. *

    - * If there is a security manager, this method first calls - * the security manager's {@code checkTopLevelWindow} - * method with {@code this} - * as its argument to determine whether or not the window - * must be displayed with a warning banner. + * If there is a security manager set, it is invoked to check + * {@code AWTPermission("showWindowWithoutWarningBanner")}. + * If that check fails with a {@code SecurityException} then a warning + * banner is created. * * @param owner the {@code Frame} to act as owner or {@code null} * if this window has no owner @@ -555,7 +542,6 @@ public class Window extends Container implements Accessible { * {@code GraphicsEnvironment.isHeadless} returns {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless - * @see java.lang.SecurityManager#checkTopLevelWindow * @see #isShowing */ public Window(Frame owner) { @@ -570,11 +556,10 @@ public class Window extends Container implements Accessible { * unless its nearest owning {@code Frame} or {@code Dialog} * is showing on the screen. *

    - * If there is a security manager, this method first calls - * the security manager's {@code checkTopLevelWindow} - * method with {@code this} - * as its argument to determine whether or not the window - * must be displayed with a warning banner. + * If there is a security manager set, it is invoked to check + * {@code AWTPermission("showWindowWithoutWarningBanner")}. + * If that check fails with a {@code SecurityException} then a + * warning banner is created. * * @param owner the {@code Window} to act as owner or * {@code null} if this window has no owner @@ -585,7 +570,6 @@ public class Window extends Container implements Accessible { * {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless - * @see java.lang.SecurityManager#checkTopLevelWindow * @see #isShowing * * @since 1.2 @@ -603,11 +587,10 @@ public class Window extends Container implements Accessible { * its nearest owning {@code Frame} or {@code Dialog} * is showing on the screen. *

    - * If there is a security manager, this method first calls - * the security manager's {@code checkTopLevelWindow} - * method with {@code this} - * as its argument to determine whether or not the window - * must be displayed with a warning banner. + * If there is a security manager set, it is invoked to check + * {@code AWTPermission("showWindowWithoutWarningBanner")}. If that + * check fails with a {@code SecurityException} then a warning banner + * is created. * * @param owner the window to act as owner or {@code null} * if this window has no owner @@ -621,7 +604,6 @@ public class Window extends Container implements Accessible { * {@code true} * * @see java.awt.GraphicsEnvironment#isHeadless - * @see java.lang.SecurityManager#checkTopLevelWindow * @see GraphicsConfiguration#getBounds * @see #isShowing * @since 1.3 @@ -1093,7 +1075,6 @@ public class Window extends Container implements Accessible { * Hide this Window, its subcomponents, and all of its owned children. * The Window and its subcomponents can be made visible again * with a call to {@code show}. - *

    * @see #show * @see #dispose * @deprecated As of JDK version 1.5, replaced by @@ -1362,10 +1343,9 @@ public class Window extends Container implements Accessible { * Gets the warning string that is displayed with this window. * If this window is insecure, the warning string is displayed * somewhere in the visible area of the window. A window is - * insecure if there is a security manager, and the security - * manager's {@code checkTopLevelWindow} method returns - * {@code false} when this window is passed to it as an - * argument. + * insecure if there is a security manager and the security + * manager denies + * {@code AWTPermission("showWindowWithoutWarningBanner")}. *

    * If the window is secure, then {@code getWarningString} * returns {@code null}. If the window is insecure, this @@ -1373,7 +1353,6 @@ public class Window extends Container implements Accessible { * {@code awt.appletWarning} * and returns the string value of that property. * @return the warning string for this window. - * @see java.lang.SecurityManager#checkTopLevelWindow(java.lang.Object) */ public final String getWarningString() { return warningString; @@ -1383,10 +1362,12 @@ public class Window extends Container implements Accessible { warningString = null; SecurityManager sm = System.getSecurityManager(); if (sm != null) { - if (!sm.checkTopLevelWindow(this)) { + try { + sm.checkPermission(SecurityConstants.AWT.TOPLEVEL_WINDOW_PERMISSION); + } catch (SecurityException se) { // make sure the privileged action is only // for getting the property! We don't want the - // above checkTopLevelWindow call to always succeed! + // above checkPermission call to always succeed! warningString = AccessController.doPrivileged( new GetPropertyAction("awt.appletWarning", "Java Applet Window")); @@ -3391,27 +3372,27 @@ public class Window extends Container implements Accessible { * this property of the Window. *

    * For example, after the following code is executed: - *

    + *
          * setLocationByPlatform(true);
          * setVisible(true);
          * boolean flag = isLocationByPlatform();
    -     * 
    + * * The window will be shown at platform's default location and * {@code flag} will be {@code false}. *

    * In the following sample: - *

    + *
          * setLocationByPlatform(true);
          * setLocation(10, 10);
          * boolean flag = isLocationByPlatform();
          * setVisible(true);
    -     * 
    + * * The window will be shown at (10, 10) and {@code flag} will be * {@code false}. * * @param locationByPlatform {@code true} if this Window should appear * at the default location, {@code false} if at the current location - * @throws {@code IllegalComponentStateException} if the window + * @throws IllegalComponentStateException if the window * is showing on screen and locationByPlatform is {@code true}. * @see #setLocation * @see #isShowing diff --git a/jdk/src/share/classes/java/awt/color/ICC_Profile.java b/jdk/src/share/classes/java/awt/color/ICC_Profile.java index c1534249f39..7e44947477d 100644 --- a/jdk/src/share/classes/java/awt/color/ICC_Profile.java +++ b/jdk/src/share/classes/java/awt/color/ICC_Profile.java @@ -37,6 +37,7 @@ package java.awt.color; import sun.java2d.cmm.PCMM; import sun.java2d.cmm.CMSManager; +import sun.java2d.cmm.Profile; import sun.java2d.cmm.ProfileDataVerifier; import sun.java2d.cmm.ProfileDeferralMgr; import sun.java2d.cmm.ProfileDeferralInfo; @@ -94,7 +95,7 @@ public class ICC_Profile implements Serializable { private static final long serialVersionUID = -3938515861990936766L; - transient long ID; + private transient Profile cmmProfile; private transient ProfileDeferralInfo deferralInfo; private transient ProfileActivator profileActivator; @@ -727,8 +728,8 @@ public class ICC_Profile implements Serializable { /** * Constructs an ICC_Profile object with a given ID. */ - ICC_Profile(long ID) { - this.ID = ID; + ICC_Profile(Profile p) { + this.cmmProfile = p; } @@ -751,8 +752,8 @@ public class ICC_Profile implements Serializable { * Frees the resources associated with an ICC_Profile object. */ protected void finalize () { - if (ID != 0) { - CMSManager.getModule().freeProfile(ID); + if (cmmProfile != null) { + CMSManager.getModule().freeProfile(cmmProfile); } else if (profileActivator != null) { ProfileDeferralMgr.unregisterDeferral(profileActivator); } @@ -770,7 +771,7 @@ public class ICC_Profile implements Serializable { public static ICC_Profile getInstance(byte[] data) { ICC_Profile thisProfile; - long theID; + Profile p = null; if (ProfileDeferralMgr.deferring) { ProfileDeferralMgr.activateProfiles(); @@ -779,32 +780,32 @@ public class ICC_Profile implements Serializable { ProfileDataVerifier.verify(data); try { - theID = CMSManager.getModule().loadProfile(data); + p = CMSManager.getModule().loadProfile(data); } catch (CMMException c) { throw new IllegalArgumentException("Invalid ICC Profile Data"); } try { - if ((getColorSpaceType (theID) == ColorSpace.TYPE_GRAY) && - (getData (theID, icSigMediaWhitePointTag) != null) && - (getData (theID, icSigGrayTRCTag) != null)) { - thisProfile = new ICC_ProfileGray (theID); + if ((getColorSpaceType (p) == ColorSpace.TYPE_GRAY) && + (getData (p, icSigMediaWhitePointTag) != null) && + (getData (p, icSigGrayTRCTag) != null)) { + thisProfile = new ICC_ProfileGray (p); } - else if ((getColorSpaceType (theID) == ColorSpace.TYPE_RGB) && - (getData (theID, icSigMediaWhitePointTag) != null) && - (getData (theID, icSigRedColorantTag) != null) && - (getData (theID, icSigGreenColorantTag) != null) && - (getData (theID, icSigBlueColorantTag) != null) && - (getData (theID, icSigRedTRCTag) != null) && - (getData (theID, icSigGreenTRCTag) != null) && - (getData (theID, icSigBlueTRCTag) != null)) { - thisProfile = new ICC_ProfileRGB (theID); + else if ((getColorSpaceType (p) == ColorSpace.TYPE_RGB) && + (getData (p, icSigMediaWhitePointTag) != null) && + (getData (p, icSigRedColorantTag) != null) && + (getData (p, icSigGreenColorantTag) != null) && + (getData (p, icSigBlueColorantTag) != null) && + (getData (p, icSigRedTRCTag) != null) && + (getData (p, icSigGreenTRCTag) != null) && + (getData (p, icSigBlueTRCTag) != null)) { + thisProfile = new ICC_ProfileRGB (p); } else { - thisProfile = new ICC_Profile (theID); + thisProfile = new ICC_Profile (p); } } catch (CMMException c) { - thisProfile = new ICC_Profile (theID); + thisProfile = new ICC_Profile (p); } return thisProfile; } @@ -1119,7 +1120,7 @@ public class ICC_Profile implements Serializable { fileName); } try { - ID = CMSManager.getModule().loadProfile(profileData); + cmmProfile = CMSManager.getModule().loadProfile(profileData); } catch (CMMException c) { ProfileDataException pde = new ProfileDataException("Invalid ICC Profile Data" + fileName); @@ -1229,14 +1230,14 @@ public class ICC_Profile implements Serializable { causing a deferred profile to be loaded */ } - return getColorSpaceType(ID); + return getColorSpaceType(cmmProfile); } - static int getColorSpaceType(long profileID) { + static int getColorSpaceType(Profile p) { byte[] theHeader; int theColorSpaceSig, theColorSpace; - theHeader = getData(profileID, icSigHead); + theHeader = getData(p, icSigHead); theColorSpaceSig = intFromBigEndian(theHeader, icHdrColorSpace); theColorSpace = iccCStoJCS (theColorSpaceSig); return theColorSpace; @@ -1258,15 +1259,15 @@ public class ICC_Profile implements Serializable { if (ProfileDeferralMgr.deferring) { ProfileDeferralMgr.activateProfiles(); } - return getPCSType(ID); + return getPCSType(cmmProfile); } - static int getPCSType(long profileID) { + static int getPCSType(Profile p) { byte[] theHeader; int thePCSSig, thePCS; - theHeader = getData(profileID, icSigHead); + theHeader = getData(p, icSigHead); thePCSSig = intFromBigEndian(theHeader, icHdrPcs); thePCS = iccCStoJCS(thePCSSig); return thePCS; @@ -1326,12 +1327,12 @@ public class ICC_Profile implements Serializable { PCMM mdl = CMSManager.getModule(); /* get the number of bytes needed for this profile */ - profileSize = mdl.getProfileSize(ID); + profileSize = mdl.getProfileSize(cmmProfile); profileData = new byte [profileSize]; /* get the data for the profile */ - mdl.getProfileData(ID, profileData); + mdl.getProfileData(cmmProfile, profileData); return profileData; } @@ -1358,11 +1359,11 @@ public class ICC_Profile implements Serializable { ProfileDeferralMgr.activateProfiles(); } - return getData(ID, tagSignature); + return getData(cmmProfile, tagSignature); } - static byte[] getData(long profileID, int tagSignature) { + static byte[] getData(Profile p, int tagSignature) { int tagSize; byte[] tagData; @@ -1370,12 +1371,12 @@ public class ICC_Profile implements Serializable { PCMM mdl = CMSManager.getModule(); /* get the number of bytes needed for this tag */ - tagSize = mdl.getTagSize(profileID, tagSignature); + tagSize = mdl.getTagSize(p, tagSignature); tagData = new byte[tagSize]; /* get an array for the tag */ /* get the tag's data */ - mdl.getTagData(profileID, tagSignature, tagData); + mdl.getTagData(p, tagSignature, tagData); } catch(CMMException c) { tagData = null; } @@ -1406,7 +1407,7 @@ public class ICC_Profile implements Serializable { ProfileDeferralMgr.activateProfiles(); } - CMSManager.getModule().setTagData(ID, tagSignature, tagData); + CMSManager.getModule().setTagData(cmmProfile, tagSignature, tagData); } /** diff --git a/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java b/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java index d9042266663..a868a6f50fc 100644 --- a/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java +++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileGray.java @@ -35,7 +35,7 @@ package java.awt.color; -import java.awt.image.LookupTable; +import sun.java2d.cmm.Profile; import sun.java2d.cmm.ProfileDeferralInfo; /** @@ -76,8 +76,8 @@ extends ICC_Profile { /** * Constructs a new ICC_ProfileGray from a CMM ID. */ - ICC_ProfileGray(long ID) { - super(ID); + ICC_ProfileGray(Profile p) { + super(p); } /** diff --git a/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java b/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java index b0bad4d9a91..dcf65828650 100644 --- a/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java +++ b/jdk/src/share/classes/java/awt/color/ICC_ProfileRGB.java @@ -35,7 +35,7 @@ package java.awt.color; -import java.awt.image.LookupTable; +import sun.java2d.cmm.Profile; import sun.java2d.cmm.ProfileDeferralInfo; /** @@ -114,8 +114,8 @@ extends ICC_Profile { * @param ID The CMM ID for the profile. * */ - ICC_ProfileRGB(long ID) { - super(ID); + ICC_ProfileRGB(Profile p) { + super(p); } /** diff --git a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java index 400553dd854..bb6c632cdff 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java +++ b/jdk/src/share/classes/java/awt/datatransfer/DataFlavor.java @@ -463,7 +463,7 @@ public class DataFlavor implements Externalizable, Cloneable { /** * Constructs a DataFlavor from a mimeType string. - * The string can specify a "class=" + * The string can specify a "class=<fully specified Java class name>" * parameter to create a DataFlavor with the desired * representation class. If the string does not contain "class=" parameter, * java.io.InputStream is used as default. diff --git a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java index fe69767dd33..ef154acdc2e 100644 --- a/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java +++ b/jdk/src/share/classes/java/awt/datatransfer/SystemFlavorMap.java @@ -70,7 +70,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { /** * System singleton which maps a thread's ClassLoader to a SystemFlavorMap. */ - private static final WeakHashMap flavorMaps = new WeakHashMap(); + private static final WeakHashMap flavorMaps = new WeakHashMap<>(); /** * Copied from java.util.Properties. @@ -139,7 +139,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * native Strings. * Do not use the field directly, use getFlavorToNative() instead. */ - private final Map flavorToNative = new HashMap(); + private final Map> flavorToNative = new HashMap<>(); /** * Accessor to flavorToNative map. Since we use lazy initialization we must @@ -148,7 +148,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * * @return flavorToNative */ - private synchronized Map getFlavorToNative() { + private synchronized Map> getFlavorToNative() { if (!isMapInitialized) { initSystemFlavorMap(); } @@ -164,13 +164,13 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * Caches the result of getNativesForFlavor(). Maps DataFlavors to * SoftReferences which reference Lists of String natives. */ - private Map getNativesForFlavorCache = new HashMap(); + private Map>> getNativesForFlavorCache = new HashMap<>(); /** * Caches the result getFlavorsForNative(). Maps String natives to * SoftReferences which reference Lists of DataFlavors. */ - private Map getFlavorsForNativeCache = new HashMap(); + private Map>> getFlavorsForNativeCache = new HashMap<>(); /** * Dynamic mapping generation used for text mappings should not be applied @@ -193,7 +193,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { FlavorMap fm; synchronized(flavorMaps) { - fm = (FlavorMap)flavorMaps.get(contextClassLoader); + fm = flavorMaps.get(contextClassLoader); if (fm == null) { fm = new SystemFlavorMap(); flavorMaps.put(contextClassLoader, fm); @@ -520,10 +520,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * the appropriate Map location, but rather will be appended to a List * stored in that location. */ - private void store(Object hashed, Object listed, Map map) { - List list = (List)map.get(hashed); + private void store(H hashed, L listed, Map> map) { + List list = map.get(hashed); if (list == null) { - list = new ArrayList(1); + list = new ArrayList<>(1); map.put(hashed, list); } if (!list.contains(listed)) { @@ -537,17 +537,17 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * case, a new DataFlavor is synthesized, stored, and returned, if and * only if the specified native is encoded as a Java MIME type. */ - private List nativeToFlavorLookup(String nat) { + private List nativeToFlavorLookup(String nat) { List flavors = getNativeToFlavor().get(nat); if (nat != null && !disabledMappingGenerationKeys.contains(nat)) { DataTransferer transferer = DataTransferer.getInstance(); if (transferer != null) { - List platformFlavors = + List platformFlavors = transferer.getPlatformMappingsForNative(nat); if (!platformFlavors.isEmpty()) { if (flavors != null) { - platformFlavors.removeAll(new HashSet(flavors)); + platformFlavors.removeAll(new HashSet<>(flavors)); // Prepending the platform-specific mappings ensures // that the flavors added with // addFlavorForUnencodedNative() are at the end of @@ -573,15 +573,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } if (flavor != null) { - flavors = new ArrayList(1); + flavors = new ArrayList<>(1); getNativeToFlavor().put(nat, flavors); flavors.add(flavor); getFlavorsForNativeCache.remove(nat); getFlavorsForNativeCache.remove(null); - List natives = (List)getFlavorToNative().get(flavor); + List natives = getFlavorToNative().get(flavor); if (natives == null) { - natives = new ArrayList(1); + natives = new ArrayList<>(1); getFlavorToNative().put(flavor, natives); } natives.add(nat); @@ -590,7 +590,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } } - return (flavors != null) ? flavors : new ArrayList(0); + return (flavors != null) ? flavors : new ArrayList<>(0); } /** @@ -601,18 +601,18 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * encoding the DataFlavor's MIME type. Otherwise an empty List is returned * and 'flavorToNative' remains unaffected. */ - private List flavorToNativeLookup(final DataFlavor flav, - final boolean synthesize) { - List natives = (List)getFlavorToNative().get(flav); + private List flavorToNativeLookup(final DataFlavor flav, + final boolean synthesize) { + List natives = getFlavorToNative().get(flav); if (flav != null && !disabledMappingGenerationKeys.contains(flav)) { DataTransferer transferer = DataTransferer.getInstance(); if (transferer != null) { - List platformNatives = + List platformNatives = transferer.getPlatformMappingsForFlavor(flav); if (!platformNatives.isEmpty()) { if (natives != null) { - platformNatives.removeAll(new HashSet(natives)); + platformNatives.removeAll(new HashSet<>(natives)); // Prepend the platform-specific mappings to ensure // that the natives added with // addUnencodedNativeForFlavor() are at the end of @@ -627,7 +627,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { if (natives == null) { if (synthesize) { String encoded = encodeDataFlavor(flav); - natives = new ArrayList(1); + natives = new ArrayList<>(1); getFlavorToNative().put(flav, natives); natives.add(encoded); getNativesForFlavorCache.remove(flav); @@ -635,14 +635,14 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { List flavors = getNativeToFlavor().get(encoded); if (flavors == null) { - flavors = new ArrayList(1); + flavors = new ArrayList<>(1); getNativeToFlavor().put(encoded, flavors); } flavors.add(flav); getFlavorsForNativeCache.remove(encoded); getFlavorsForNativeCache.remove(null); } else { - natives = new ArrayList(0); + natives = new ArrayList<>(0); } } @@ -675,21 +675,21 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { * @since 1.4 */ public synchronized List getNativesForFlavor(DataFlavor flav) { - List retval = null; + List retval = null; // Check cache, even for null flav - SoftReference ref = (SoftReference)getNativesForFlavorCache.get(flav); + SoftReference> ref = getNativesForFlavorCache.get(flav); if (ref != null) { - retval = (List)ref.get(); + retval = ref.get(); if (retval != null) { // Create a copy, because client code can modify the returned // list. - return new ArrayList(retval); + return new ArrayList<>(retval); } } if (flav == null) { - retval = new ArrayList(getNativeToFlavor().keySet()); + retval = new ArrayList<>(getNativeToFlavor().keySet()); } else if (disabledMappingGenerationKeys.contains(flav)) { // In this case we shouldn't synthesize a native for this flavor, // since its mappings were explicitly specified. @@ -699,7 +699,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { // For text/* flavors, flavor-to-native mappings specified in // flavormap.properties are stored per flavor's base type. if ("text".equals(flav.getPrimaryType())) { - retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType()); + retval = getAllNativesForType(flav.mimeType.getBaseType()); if (retval != null) { // To prevent the List stored in the map from modification. retval = new ArrayList(retval); @@ -707,15 +707,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } // Also include text/plain natives, but don't duplicate Strings - List textPlainList = (List)getFlavorToNative().get(TEXT_PLAIN_BASE_TYPE); + List textPlainList = getAllNativesForType(TEXT_PLAIN_BASE_TYPE); if (textPlainList != null && !textPlainList.isEmpty()) { // To prevent the List stored in the map from modification. // This also guarantees that removeAll() is supported. - textPlainList = new ArrayList(textPlainList); + textPlainList = new ArrayList<>(textPlainList); if (retval != null && !retval.isEmpty()) { // Use HashSet to get constant-time performance for search. - textPlainList.removeAll(new HashSet(retval)); + textPlainList.removeAll(new HashSet<>(retval)); retval.addAll(textPlainList); } else { retval = textPlainList; @@ -728,7 +728,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { // In this branch it is guaranteed that natives explicitly // listed for flav's MIME type were added with // addUnencodedNativeForFlavor(), so they have lower priority. - List explicitList = + List explicitList = flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND); // flavorToNativeLookup() never returns null. @@ -736,14 +736,14 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { if (!explicitList.isEmpty()) { // To prevent the List stored in the map from modification. // This also guarantees that removeAll() is supported. - explicitList = new ArrayList(explicitList); + explicitList = new ArrayList<>(explicitList); // Use HashSet to get constant-time performance for search. - explicitList.removeAll(new HashSet(retval)); + explicitList.removeAll(new HashSet<>(retval)); retval.addAll(explicitList); } } } else if (DataTransferer.isFlavorNoncharsetTextType(flav)) { - retval = (List)getFlavorToNative().get(flav.mimeType.getBaseType()); + retval = getAllNativesForType(flav.mimeType.getBaseType()); if (retval == null || retval.isEmpty()) { retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND); @@ -751,7 +751,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { // In this branch it is guaranteed that natives explicitly // listed for flav's MIME type were added with // addUnencodedNativeForFlavor(), so they have lower priority. - List explicitList = + List explicitList = flavorToNativeLookup(flav, !SYNTHESIZE_IF_NOT_FOUND); // flavorToNativeLookup() never returns null. @@ -759,10 +759,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { if (!explicitList.isEmpty()) { // To prevent the List stored in the map from modification. // This also guarantees that add/removeAll() are supported. - retval = new ArrayList(retval); - explicitList = new ArrayList(explicitList); + retval = new ArrayList<>(retval); + explicitList = new ArrayList<>(explicitList); // Use HashSet to get constant-time performance for search. - explicitList.removeAll(new HashSet(retval)); + explicitList.removeAll(new HashSet<>(retval)); retval.addAll(explicitList); } } @@ -770,9 +770,9 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { retval = flavorToNativeLookup(flav, SYNTHESIZE_IF_NOT_FOUND); } - getNativesForFlavorCache.put(flav, new SoftReference(retval)); + getNativesForFlavorCache.put(flav, new SoftReference<>(retval)); // Create a copy, because client code can modify the returned list. - return new ArrayList(retval); + return new ArrayList<>(retval); } /** @@ -809,11 +809,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { public synchronized List getFlavorsForNative(String nat) { // Check cache, even for null nat - SoftReference ref = (SoftReference)getFlavorsForNativeCache.get(nat); + SoftReference> ref = getFlavorsForNativeCache.get(nat); if (ref != null) { - ArrayList retval = (ArrayList)ref.get(); + List retval = ref.get(); if (retval != null) { - return (List)retval.clone(); + return new ArrayList<>(retval); } } @@ -859,16 +859,15 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } - final ArrayList arrayList = new ArrayList(returnValue); - getFlavorsForNativeCache.put(nat, new SoftReference(arrayList)); - return (List)arrayList.clone(); + final List arrayList = new ArrayList<>(returnValue); + getFlavorsForNativeCache.put(nat, new SoftReference<>(arrayList)); + return new ArrayList<>(arrayList); } - private static LinkedHashSet convertMimeTypeToDataFlavors( + private static Set convertMimeTypeToDataFlavors( final String baseType) { - final LinkedHashSet returnValue = - new LinkedHashSet(); + final Set returnValue = new LinkedHashSet<>(); String subType = null; @@ -1009,11 +1008,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { flavor_list.toArray(flavors); } - HashMap retval = new HashMap(flavors.length, 1.0f); - for (int i = 0; i < flavors.length; i++) { - List natives = getNativesForFlavor(flavors[i]); - String nat = (natives.isEmpty()) ? null : (String)natives.get(0); - retval.put(flavors[i], nat); + Map retval = new HashMap<>(flavors.length, 1.0f); + for (DataFlavor flavor : flavors) { + List natives = getNativesForFlavor(flavor); + String nat = (natives.isEmpty()) ? null : natives.get(0); + retval.put(flavor, nat); } return retval; @@ -1054,12 +1053,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { native_list.toArray(natives); } - HashMap retval = new HashMap(natives.length, 1.0f); - for (int i = 0; i < natives.length; i++) { - List flavors = getFlavorsForNative(natives[i]); - DataFlavor flav = (flavors.isEmpty()) - ? null : (DataFlavor)flavors.get(0); - retval.put(natives[i], flav); + Map retval = new HashMap<>(natives.length, 1.0f); + for (String aNative : natives) { + List flavors = getFlavorsForNative(aNative); + DataFlavor flav = (flavors.isEmpty())? null : flavors.get(0); + retval.put(aNative, flav); } return retval; @@ -1091,9 +1089,9 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { throw new NullPointerException("null arguments not permitted"); } - List natives = (List)getFlavorToNative().get(flav); + List natives = getFlavorToNative().get(flav); if (natives == null) { - natives = new ArrayList(1); + natives = new ArrayList<>(1); getFlavorToNative().put(flav, natives); } else if (natives.contains(nat)) { return; @@ -1138,8 +1136,8 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } getFlavorToNative().remove(flav); - for (int i = 0; i < natives.length; i++) { - addUnencodedNativeForFlavor(flav, natives[i]); + for (String aNative : natives) { + addUnencodedNativeForFlavor(flav, aNative); } disabledMappingGenerationKeys.add(flav); // Clear the cache to handle the case of empty natives. @@ -1171,9 +1169,9 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { throw new NullPointerException("null arguments not permitted"); } - List flavors = (List)getNativeToFlavor().get(nat); + List flavors = getNativeToFlavor().get(nat); if (flavors == null) { - flavors = new ArrayList(1); + flavors = new ArrayList<>(1); getNativeToFlavor().put(nat, flavors); } else if (flavors.contains(flav)) { return; @@ -1217,8 +1215,8 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } getNativeToFlavor().remove(nat); - for (int i = 0; i < flavors.length; i++) { - addFlavorForUnencodedNative(nat, flavors[i]); + for (DataFlavor flavor : flavors) { + addFlavorForUnencodedNative(nat, flavor); } disabledMappingGenerationKeys.add(nat); // Clear the cache to handle the case of empty flavors. @@ -1321,4 +1319,18 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { ? new DataFlavor(retval_str) : null; } + + private List getAllNativesForType(String type) { + List retval = null; + for (DataFlavor dataFlavor : convertMimeTypeToDataFlavors(type)) { + List natives = getFlavorToNative().get(dataFlavor); + if (!natives.isEmpty()) { + if (retval == null) { + retval = new ArrayList<>(); + } + retval.addAll(natives); + } + } + return retval; + } } diff --git a/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java b/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java index 1f1b9a3f488..60c1876fddf 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java +++ b/jdk/src/share/classes/java/awt/dnd/DragGestureRecognizer.java @@ -114,7 +114,7 @@ public abstract class DragGestureRecognizer implements Serializable { * @param dgl the DragGestureRecognizer * to notify when a drag gesture is detected *

    - * @throws IllegalArgumentException + * @throws IllegalArgumentException * if ds is null. */ @@ -157,7 +157,7 @@ public abstract class DragGestureRecognizer implements Serializable { * @param sa the set (logical OR) of the DnDConstants * that this Drag and Drop operation will support *

    - * @throws IllegalArgumentException + * @throws IllegalArgumentException * if ds is null. */ @@ -185,7 +185,7 @@ public abstract class DragGestureRecognizer implements Serializable { * the DragGestureRecognizer * is not associated with any Component. *

    - * @throws IllegalArgumentException + * @throws IllegalArgumentException * if ds is null. */ @@ -202,7 +202,7 @@ public abstract class DragGestureRecognizer implements Serializable { * DragGestureRecognizer will * use to process the Drag and Drop operation *

    - * @throws IllegalArgumentException + * @throws IllegalArgumentException * if ds is null. */ @@ -332,7 +332,7 @@ public abstract class DragGestureRecognizer implements Serializable { * @param dgl the DragGestureListener to unregister * from this DragGestureRecognizer *

    - * @throws IllegalArgumentException if + * @throws IllegalArgumentException if * dgl is not (equal to) the currently registered DragGestureListener. */ diff --git a/jdk/src/share/classes/java/awt/dnd/DragSource.java b/jdk/src/share/classes/java/awt/dnd/DragSource.java index bceedda646b..d44733b71d8 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSource.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSource.java @@ -676,7 +676,7 @@ public class DragSource implements Serializable { * FooListeners on this * DragSource, or an empty array if no such listeners * have been added - * @exception ClassCastException if listenerType + * @exception ClassCastException if listenerType * doesn't specify a class or interface that implements * java.util.EventListener * diff --git a/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java b/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java index 77fc0e49c43..9655689a237 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSourceContext.java @@ -63,7 +63,7 @@ import java.util.TooManyListenersException; * itself between the platform and the * listeners provided by the initiator of the drag operation. *

    - * + * * By default, {@code DragSourceContext} sets the cursor as appropriate * for the current state of the drag and drop operation. For example, if * the user has chosen {@linkplain DnDConstants#ACTION_MOVE the move action}, diff --git a/jdk/src/share/classes/java/awt/dnd/DragSourceDragEvent.java b/jdk/src/share/classes/java/awt/dnd/DragSourceDragEvent.java index 4ca92d86c07..315fa3c680d 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSourceDragEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSourceDragEvent.java @@ -47,9 +47,9 @@ import java.awt.event.InputEvent; * source and the drop action selected by the user. The user can select a drop * action by pressing modifier keys during the drag operation: *

    - *   Ctrl + Shift -> ACTION_LINK
    - *   Ctrl         -> ACTION_COPY
    - *   Shift        -> ACTION_MOVE
    + *   Ctrl + Shift -> ACTION_LINK
    + *   Ctrl         -> ACTION_COPY
    + *   Shift        -> ACTION_MOVE
      * 
    * If the user selects a drop action, the user drop action is one of * DnDConstants that represents the selected drop action if this @@ -103,7 +103,7 @@ public class DragSourceDragEvent extends DragSourceEvent { * in one event. Use of the extended modifiers is * preferred. * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @see java.awt.event.InputEvent * @see DragSourceEvent#getLocation @@ -154,7 +154,7 @@ public class DragSourceDragEvent extends DragSourceEvent { * @param x the horizontal coordinate for the cursor location * @param y the vertical coordinate for the cursor location * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @see java.awt.event.InputEvent * @since 1.4 diff --git a/jdk/src/share/classes/java/awt/dnd/DragSourceDropEvent.java b/jdk/src/share/classes/java/awt/dnd/DragSourceDropEvent.java index 25a7051f0a2..e1116bc68d5 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSourceDropEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSourceDropEvent.java @@ -63,7 +63,7 @@ public class DragSourceDropEvent extends DragSourceEvent { * @param action the drop action * @param success a boolean indicating if the drop was successful * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @see DragSourceEvent#getLocation */ @@ -91,7 +91,7 @@ public class DragSourceDropEvent extends DragSourceEvent { * @param x the horizontal coordinate for the cursor location * @param y the vertical coordinate for the cursor location * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @since 1.4 */ @@ -112,7 +112,7 @@ public class DragSourceDropEvent extends DragSourceEvent { * * @param dsc the DragSourceContext * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @see DragSourceEvent#getLocation */ diff --git a/jdk/src/share/classes/java/awt/dnd/DragSourceEvent.java b/jdk/src/share/classes/java/awt/dnd/DragSourceEvent.java index f2616b06a3a..62ab7fcb27a 100644 --- a/jdk/src/share/classes/java/awt/dnd/DragSourceEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DragSourceEvent.java @@ -96,7 +96,7 @@ public class DragSourceEvent extends EventObject { * * @param dsc the DragSourceContext * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @see #getLocation */ @@ -117,7 +117,7 @@ public class DragSourceEvent extends EventObject { * @param x the horizontal coordinate for the cursor location * @param y the vertical coordinate for the cursor location * - * @throws IllegalArgumentException if dsc is null. + * @throws IllegalArgumentException if dsc is null. * * @since 1.4 */ diff --git a/jdk/src/share/classes/java/awt/dnd/DropTarget.java b/jdk/src/share/classes/java/awt/dnd/DropTarget.java index b167b8e63d8..4006f728c9b 100644 --- a/jdk/src/share/classes/java/awt/dnd/DropTarget.java +++ b/jdk/src/share/classes/java/awt/dnd/DropTarget.java @@ -305,7 +305,7 @@ public class DropTarget implements DropTargetListener, Serializable { *

    * @param dtl The new DropTargetListener *

    - * @throws TooManyListenersException if a + * @throws TooManyListenersException if a * DropTargetListener is already added to this * DropTarget. */ @@ -351,6 +351,8 @@ public class DropTarget implements DropTargetListener, Serializable { * @see #isActive */ public synchronized void dragEnter(DropTargetDragEvent dtde) { + isDraggingInside = true; + if (!active) return; if (dtListener != null) { @@ -421,6 +423,8 @@ public class DropTarget implements DropTargetListener, Serializable { * @see #isActive */ public synchronized void dragExit(DropTargetEvent dte) { + isDraggingInside = false; + if (!active) return; if (dtListener != null && active) dtListener.dragExit(dte); @@ -444,6 +448,8 @@ public class DropTarget implements DropTargetListener, Serializable { * @see #isActive */ public synchronized void drop(DropTargetDropEvent dtde) { + isDraggingInside = false; + clearAutoscroll(); if (dtListener != null && active) @@ -533,6 +539,12 @@ public class DropTarget implements DropTargetListener, Serializable { ((DropTargetPeer)nativePeer).removeDropTarget(this); componentPeer = nativePeer = null; + + synchronized (this) { + if (isDraggingInside) { + dragExit(new DropTargetEvent(getDropTargetContext())); + } + } } /** @@ -832,7 +844,7 @@ public class DropTarget implements DropTargetListener, Serializable { int actions = DnDConstants.ACTION_COPY_OR_MOVE; /** - * true if the DropTarget is accepting Drag & Drop operations. + * true if the DropTarget is accepting Drag & Drop operations. * * @serial */ @@ -855,4 +867,9 @@ public class DropTarget implements DropTargetListener, Serializable { */ private transient FlavorMap flavorMap; + + /* + * If the dragging is currently inside this drop target + */ + private transient boolean isDraggingInside; } diff --git a/jdk/src/share/classes/java/awt/dnd/DropTargetDragEvent.java b/jdk/src/share/classes/java/awt/dnd/DropTargetDragEvent.java index a315a6d5463..f74d0410664 100644 --- a/jdk/src/share/classes/java/awt/dnd/DropTargetDragEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DropTargetDragEvent.java @@ -49,9 +49,9 @@ import java.util.List; * source and the drop action selected by the user. The user can select a drop * action by pressing modifier keys during the drag operation: *

    - *   Ctrl + Shift -> ACTION_LINK
    - *   Ctrl         -> ACTION_COPY
    - *   Shift        -> ACTION_MOVE
    + *   Ctrl + Shift -> ACTION_LINK
    + *   Ctrl         -> ACTION_COPY
    + *   Shift        -> ACTION_MOVE
      * 
    * If the user selects a drop action, the user drop action is one of * DnDConstants that represents the selected drop action if this @@ -88,11 +88,11 @@ public class DropTargetDragEvent extends DropTargetEvent { * @param srcActions The source drop actions * * @throws NullPointerException if cursorLocn is null - * @throws IllegalArgumentException if dropAction is not one of + * @throws IllegalArgumentException if dropAction is not one of * DnDConstants. - * @throws IllegalArgumentException if srcActions is not + * @throws IllegalArgumentException if srcActions is not * a bitwise mask of DnDConstants. - * @throws IllegalArgumentException if dtc is null. + * @throws IllegalArgumentException if dtc is null. */ public DropTargetDragEvent(DropTargetContext dtc, Point cursorLocn, int dropAction, int srcActions) { diff --git a/jdk/src/share/classes/java/awt/dnd/DropTargetDropEvent.java b/jdk/src/share/classes/java/awt/dnd/DropTargetDropEvent.java index 2b36069d8ea..cb6ff209255 100644 --- a/jdk/src/share/classes/java/awt/dnd/DropTargetDropEvent.java +++ b/jdk/src/share/classes/java/awt/dnd/DropTargetDropEvent.java @@ -48,9 +48,9 @@ import java.util.List; * source and the drop action selected by the user. The user can select a drop * action by pressing modifier keys during the drag operation: *
    - *   Ctrl + Shift -> ACTION_LINK
    - *   Ctrl         -> ACTION_COPY
    - *   Shift        -> ACTION_MOVE
    + *   Ctrl + Shift -> ACTION_LINK
    + *   Ctrl         -> ACTION_COPY
    + *   Shift        -> ACTION_MOVE
      * 
    * If the user selects a drop action, the user drop action is one of * DnDConstants that represents the selected drop action if this @@ -92,13 +92,13 @@ public class DropTargetDropEvent extends DropTargetEvent { * @param dropAction the user drop action. * @param srcActions the source drop actions. * - * @throws NullPointerException + * @throws NullPointerException * if cursorLocn is null - * @throws IllegalArgumentException if dropAction is not one of - * DnDConstants. - * @throws IllegalArgumentException if srcActions is not - * a bitwise mask of DnDConstants. - * @throws IllegalArgumentException if dtc is null. + * @throws IllegalArgumentException + * if dropAction is not one of DnDConstants. + * @throws IllegalArgumentException + * if srcActions is not a bitwise mask of DnDConstants. + * @throws IllegalArgumentException if dtc is null. */ public DropTargetDropEvent(DropTargetContext dtc, Point cursorLocn, int dropAction, int srcActions) { @@ -136,13 +136,12 @@ public class DropTargetDropEvent extends DropTargetEvent { * @param srcActions the source drop actions. * @param isLocal True if the source is in the same JVM as the target * - * @throws NullPointerException if cursorLocn is - * null - * @throws IllegalArgumentException if dropAction is not one of - * DnDConstants. - * @throws IllegalArgumentException if srcActions is not - * a bitwise mask of DnDConstants. - * @throws IllegalArgumentException if dtc is null. + * @throws NullPointerException + * if cursorLocn is null + * @throws IllegalArgumentException + * if dropAction is not one of DnDConstants. + * @throws IllegalArgumentException if srcActions is not a bitwise mask of DnDConstants. + * @throws IllegalArgumentException if dtc is null. */ public DropTargetDropEvent(DropTargetContext dtc, Point cursorLocn, int dropAction, int srcActions, boolean isLocal) { diff --git a/jdk/src/share/classes/java/awt/event/InputEvent.java b/jdk/src/share/classes/java/awt/event/InputEvent.java index 078b1a16d6a..24965d20caf 100644 --- a/jdk/src/share/classes/java/awt/event/InputEvent.java +++ b/jdk/src/share/classes/java/awt/event/InputEvent.java @@ -33,6 +33,7 @@ import java.util.Arrays; import sun.awt.AWTAccessor; import sun.util.logging.PlatformLogger; +import sun.security.util.SecurityConstants; /** * The root event class for all component-level input events. @@ -350,7 +351,7 @@ public abstract class InputEvent extends ComponentEvent { SecurityManager sm = System.getSecurityManager(); if (sm != null) { try { - sm.checkSystemClipboardAccess(); + sm.checkPermission(SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION); b = true; } catch (SecurityException se) { if (logger.isLoggable(PlatformLogger.Level.FINE)) { diff --git a/jdk/src/share/classes/java/awt/event/MouseMotionListener.java b/jdk/src/share/classes/java/awt/event/MouseMotionListener.java index e9cb4ef5a70..4b8ff0899cb 100644 --- a/jdk/src/share/classes/java/awt/event/MouseMotionListener.java +++ b/jdk/src/share/classes/java/awt/event/MouseMotionListener.java @@ -60,9 +60,9 @@ public interface MouseMotionListener extends EventListener { * mouse button is released (regardless of whether the mouse position * is within the bounds of the component). *

    - * Due to platform-dependent Drag&Drop implementations, + * Due to platform-dependent Drag&Drop implementations, * MOUSE_DRAGGED events may not be delivered during a native - * Drag&Drop operation. + * Drag&Drop operation. */ public void mouseDragged(MouseEvent e); diff --git a/jdk/src/share/classes/java/awt/font/TransformAttribute.java b/jdk/src/share/classes/java/awt/font/TransformAttribute.java index f66da12041d..6156b4df7f3 100644 --- a/jdk/src/share/classes/java/awt/font/TransformAttribute.java +++ b/jdk/src/share/classes/java/awt/font/TransformAttribute.java @@ -141,14 +141,16 @@ public final class TransformAttribute implements Serializable { * @since 1.6 */ public boolean equals(Object rhs) { - try { - TransformAttribute that = (TransformAttribute)rhs; - if (transform == null) { - return that.transform == null; + if (rhs != null) { + try { + TransformAttribute that = (TransformAttribute)rhs; + if (transform == null) { + return that.transform == null; + } + return transform.equals(that.transform); + } + catch (ClassCastException e) { } - return transform.equals(that.transform); - } - catch (ClassCastException e) { } return false; } diff --git a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java index 6d667c56f2d..d4ec31a29e1 100644 --- a/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java +++ b/jdk/src/share/classes/java/beans/DefaultPersistenceDelegate.java @@ -149,6 +149,7 @@ public class DefaultPersistenceDelegate extends PersistenceDelegate { * @return An expression whose value is oldInstance. * * @throws NullPointerException if {@code out} is {@code null} + * and this value is used in the method * * @see #DefaultPersistenceDelegate(String[]) */ diff --git a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java index 1d59f7afddb..866d35ba56c 100644 --- a/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/IndexedPropertyDescriptor.java @@ -41,8 +41,8 @@ import java.lang.reflect.Method; public class IndexedPropertyDescriptor extends PropertyDescriptor { private Reference> indexedPropertyTypeRef; - private Reference indexedReadMethodRef; - private Reference indexedWriteMethodRef; + private final MethodRef indexedReadMethodRef = new MethodRef(); + private final MethodRef indexedWriteMethodRef = new MethodRef(); private String indexedReadMethodName; private String indexedWriteMethodName; @@ -173,11 +173,11 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { * May return null if the property isn't indexed or is write-only. */ public synchronized Method getIndexedReadMethod() { - Method indexedReadMethod = getIndexedReadMethod0(); + Method indexedReadMethod = this.indexedReadMethodRef.get(); if (indexedReadMethod == null) { Class cls = getClass0(); if (cls == null || - (indexedReadMethodName == null && indexedReadMethodRef == null)) { + (indexedReadMethodName == null && !this.indexedReadMethodRef.isSet())) { // the Indexed readMethod was explicitly set to null. return null; } @@ -215,20 +215,19 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { // the indexed property type is set by the reader. setIndexedPropertyType(findIndexedPropertyType(readMethod, - getIndexedWriteMethod0())); + this.indexedWriteMethodRef.get())); setIndexedReadMethod0(readMethod); } private void setIndexedReadMethod0(Method readMethod) { + this.indexedReadMethodRef.set(readMethod); if (readMethod == null) { indexedReadMethodName = null; - indexedReadMethodRef = null; return; } setClass0(readMethod.getDeclaringClass()); indexedReadMethodName = readMethod.getName(); - this.indexedReadMethodRef = getSoftReference(readMethod); setTransient(readMethod.getAnnotation(Transient.class)); } @@ -241,11 +240,11 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { * May return null if the property isn't indexed or is read-only. */ public synchronized Method getIndexedWriteMethod() { - Method indexedWriteMethod = getIndexedWriteMethod0(); + Method indexedWriteMethod = this.indexedWriteMethodRef.get(); if (indexedWriteMethod == null) { Class cls = getClass0(); if (cls == null || - (indexedWriteMethodName == null && indexedWriteMethodRef == null)) { + (indexedWriteMethodName == null && !this.indexedWriteMethodRef.isSet())) { // the Indexed writeMethod was explicitly set to null. return null; } @@ -301,15 +300,14 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { } private void setIndexedWriteMethod0(Method writeMethod) { + this.indexedWriteMethodRef.set(writeMethod); if (writeMethod == null) { indexedWriteMethodName = null; - indexedWriteMethodRef = null; return; } setClass0(writeMethod.getDeclaringClass()); indexedWriteMethodName = writeMethod.getName(); - this.indexedWriteMethodRef = getSoftReference(writeMethod); setTransient(writeMethod.getAnnotation(Transient.class)); } @@ -349,18 +347,6 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { : null; } - private Method getIndexedReadMethod0() { - return (this.indexedReadMethodRef != null) - ? this.indexedReadMethodRef.get() - : null; - } - - private Method getIndexedWriteMethod0() { - return (this.indexedWriteMethodRef != null) - ? this.indexedWriteMethodRef.get() - : null; - } - private Class findIndexedPropertyType(Method indexedReadMethod, Method indexedWriteMethod) throws IntrospectionException { @@ -492,8 +478,8 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { */ IndexedPropertyDescriptor(IndexedPropertyDescriptor old) { super(old); - indexedReadMethodRef = old.indexedReadMethodRef; - indexedWriteMethodRef = old.indexedWriteMethodRef; + this.indexedReadMethodRef.set(old.indexedReadMethodRef.get()); + this.indexedWriteMethodRef.set(old.indexedWriteMethodRef.get()); indexedPropertyTypeRef = old.indexedPropertyTypeRef; indexedWriteMethodName = old.indexedWriteMethodName; indexedReadMethodName = old.indexedReadMethodName; @@ -502,7 +488,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { void updateGenericsFor(Class type) { super.updateGenericsFor(type); try { - setIndexedPropertyType(findIndexedPropertyType(getIndexedReadMethod0(), getIndexedWriteMethod0())); + setIndexedPropertyType(findIndexedPropertyType(this.indexedReadMethodRef.get(), this.indexedWriteMethodRef.get())); } catch (IntrospectionException exception) { setIndexedPropertyType(null); @@ -532,7 +518,7 @@ public class IndexedPropertyDescriptor extends PropertyDescriptor { void appendTo(StringBuilder sb) { super.appendTo(sb); appendTo(sb, "indexedPropertyType", this.indexedPropertyTypeRef); - appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef); - appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef); + appendTo(sb, "indexedReadMethod", this.indexedReadMethodRef.get()); + appendTo(sb, "indexedWriteMethod", this.indexedWriteMethodRef.get()); } } diff --git a/jdk/src/share/classes/java/beans/MethodDescriptor.java b/jdk/src/share/classes/java/beans/MethodDescriptor.java index db760c0e20a..f8cd73d3897 100644 --- a/jdk/src/share/classes/java/beans/MethodDescriptor.java +++ b/jdk/src/share/classes/java/beans/MethodDescriptor.java @@ -38,7 +38,7 @@ import java.util.ArrayList; public class MethodDescriptor extends FeatureDescriptor { - private Reference methodRef; + private final MethodRef methodRef = new MethodRef(); private String[] paramNames; @@ -81,7 +81,7 @@ public class MethodDescriptor extends FeatureDescriptor { * @return The low-level description of the method */ public synchronized Method getMethod() { - Method method = getMethod0(); + Method method = this.methodRef.get(); if (method == null) { Class cls = getClass0(); String name = getName(); @@ -114,13 +114,7 @@ public class MethodDescriptor extends FeatureDescriptor { setClass0(method.getDeclaringClass()); } setParams(getParameterTypes(getClass0(), method)); - this.methodRef = getSoftReference(method); - } - - private Method getMethod0() { - return (this.methodRef != null) - ? this.methodRef.get() - : null; + this.methodRef.set(method); } private synchronized void setParams(Class[] param) { @@ -177,12 +171,10 @@ public class MethodDescriptor extends FeatureDescriptor { */ MethodDescriptor(MethodDescriptor x, MethodDescriptor y) { - super(x,y); + super(x, y); - methodRef = x.methodRef; - if (y.methodRef != null) { - methodRef = y.methodRef; - } + Method method = y.methodRef.get(); + this.methodRef.set(null != method ? method : x.methodRef.get()); params = x.params; if (y.params != null) { params = y.params; @@ -205,7 +197,7 @@ public class MethodDescriptor extends FeatureDescriptor { MethodDescriptor(MethodDescriptor old) { super(old); - methodRef = old.methodRef; + this.methodRef.set(old.getMethod()); params = old.params; paramNames = old.paramNames; @@ -219,7 +211,7 @@ public class MethodDescriptor extends FeatureDescriptor { } void appendTo(StringBuilder sb) { - appendTo(sb, "method", this.methodRef); + appendTo(sb, "method", this.methodRef.get()); if (this.parameterDescriptors != null) { sb.append("; parameterDescriptors={"); for (ParameterDescriptor pd : this.parameterDescriptors) { diff --git a/jdk/src/share/classes/java/beans/MethodRef.java b/jdk/src/share/classes/java/beans/MethodRef.java new file mode 100644 index 00000000000..59b2690b4fa --- /dev/null +++ b/jdk/src/share/classes/java/beans/MethodRef.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.beans; + +import java.lang.ref.SoftReference; +import java.lang.ref.WeakReference; +import java.lang.reflect.Method; + +import static sun.reflect.misc.ReflectUtil.isPackageAccessible; + +final class MethodRef { + private String signature; + private SoftReference methodRef; + private WeakReference> typeRef; + + void set(Method method) { + if (method == null) { + this.signature = null; + this.methodRef = null; + this.typeRef = null; + } + else { + this.signature = method.toGenericString(); + this.methodRef = new SoftReference<>(method); + this.typeRef = new WeakReference>(method.getDeclaringClass()); + } + } + + boolean isSet() { + return this.methodRef != null; + } + + Method get() { + if (this.methodRef == null) { + return null; + } + Method method = this.methodRef.get(); + if (method == null) { + method = find(this.typeRef.get(), this.signature); + if (method == null) { + this.signature = null; + this.methodRef = null; + this.typeRef = null; + } + else { + this.methodRef = new SoftReference<>(method); + } + } + return isPackageAccessible(method.getDeclaringClass()) ? method : null; + } + + private static Method find(Class type, String signature) { + if (type != null) { + for (Method method : type.getMethods()) { + if (type.equals(method.getDeclaringClass())) { + if (method.toGenericString().equals(signature)) { + return method; + } + } + } + } + return null; + } +} diff --git a/jdk/src/share/classes/java/beans/PersistenceDelegate.java b/jdk/src/share/classes/java/beans/PersistenceDelegate.java index bbdcdbf060c..4124d2ff935 100644 --- a/jdk/src/share/classes/java/beans/PersistenceDelegate.java +++ b/jdk/src/share/classes/java/beans/PersistenceDelegate.java @@ -162,6 +162,7 @@ public abstract class PersistenceDelegate { * @return An expression whose value is oldInstance. * * @throws NullPointerException if {@code out} is {@code null} + * and this value is used in the method */ protected abstract Expression instantiate(Object oldInstance, Encoder out); diff --git a/jdk/src/share/classes/java/beans/PropertyDescriptor.java b/jdk/src/share/classes/java/beans/PropertyDescriptor.java index c519b504d58..aed5ec57a4d 100644 --- a/jdk/src/share/classes/java/beans/PropertyDescriptor.java +++ b/jdk/src/share/classes/java/beans/PropertyDescriptor.java @@ -36,8 +36,8 @@ import java.lang.reflect.Constructor; public class PropertyDescriptor extends FeatureDescriptor { private Reference> propertyTypeRef; - private Reference readMethodRef; - private Reference writeMethodRef; + private final MethodRef readMethodRef = new MethodRef(); + private final MethodRef writeMethodRef = new MethodRef(); private Reference> propertyEditorClassRef; private boolean bound; @@ -68,8 +68,8 @@ public class PropertyDescriptor extends FeatureDescriptor { public PropertyDescriptor(String propertyName, Class beanClass) throws IntrospectionException { this(propertyName, beanClass, - Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName), - Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName)); + Introspector.IS_PREFIX + NameGenerator.capitalize(propertyName), + Introspector.SET_PREFIX + NameGenerator.capitalize(propertyName)); } /** @@ -203,10 +203,10 @@ public class PropertyDescriptor extends FeatureDescriptor { * May return null if the property can't be read. */ public synchronized Method getReadMethod() { - Method readMethod = getReadMethod0(); + Method readMethod = this.readMethodRef.get(); if (readMethod == null) { Class cls = getClass0(); - if (cls == null || (readMethodName == null && readMethodRef == null)) { + if (cls == null || (readMethodName == null && !this.readMethodRef.isSet())) { // The read method was explicitly set to null. return null; } @@ -247,17 +247,16 @@ public class PropertyDescriptor extends FeatureDescriptor { */ public synchronized void setReadMethod(Method readMethod) throws IntrospectionException { + this.readMethodRef.set(readMethod); if (readMethod == null) { readMethodName = null; - readMethodRef = null; return; } // The property type is determined by the read method. - setPropertyType(findPropertyType(readMethod, getWriteMethod0())); + setPropertyType(findPropertyType(readMethod, this.writeMethodRef.get())); setClass0(readMethod.getDeclaringClass()); readMethodName = readMethod.getName(); - this.readMethodRef = getSoftReference(readMethod); setTransient(readMethod.getAnnotation(Transient.class)); } @@ -268,10 +267,10 @@ public class PropertyDescriptor extends FeatureDescriptor { * May return null if the property can't be written. */ public synchronized Method getWriteMethod() { - Method writeMethod = getWriteMethod0(); + Method writeMethod = this.writeMethodRef.get(); if (writeMethod == null) { Class cls = getClass0(); - if (cls == null || (writeMethodName == null && writeMethodRef == null)) { + if (cls == null || (writeMethodName == null && !this.writeMethodRef.isSet())) { // The write method was explicitly set to null. return null; } @@ -318,9 +317,9 @@ public class PropertyDescriptor extends FeatureDescriptor { */ public synchronized void setWriteMethod(Method writeMethod) throws IntrospectionException { + this.writeMethodRef.set(writeMethod); if (writeMethod == null) { writeMethodName = null; - writeMethodRef = null; return; } // Set the property type - which validates the method @@ -328,22 +327,9 @@ public class PropertyDescriptor extends FeatureDescriptor { setClass0(writeMethod.getDeclaringClass()); writeMethodName = writeMethod.getName(); - this.writeMethodRef = getSoftReference(writeMethod); setTransient(writeMethod.getAnnotation(Transient.class)); } - private Method getReadMethod0() { - return (this.readMethodRef != null) - ? this.readMethodRef.get() - : null; - } - - private Method getWriteMethod0() { - return (this.writeMethodRef != null) - ? this.writeMethodRef.get() - : null; - } - /** * Overridden to ensure that a super class doesn't take precedent */ @@ -617,8 +603,8 @@ public class PropertyDescriptor extends FeatureDescriptor { PropertyDescriptor(PropertyDescriptor old) { super(old); propertyTypeRef = old.propertyTypeRef; - readMethodRef = old.readMethodRef; - writeMethodRef = old.writeMethodRef; + this.readMethodRef.set(old.readMethodRef.get()); + this.writeMethodRef.set(old.writeMethodRef.get()); propertyEditorClassRef = old.propertyEditorClassRef; writeMethodName = old.writeMethodName; @@ -632,7 +618,7 @@ public class PropertyDescriptor extends FeatureDescriptor { void updateGenericsFor(Class type) { setClass0(type); try { - setPropertyType(findPropertyType(getReadMethod0(), getWriteMethod0())); + setPropertyType(findPropertyType(this.readMethodRef.get(), this.writeMethodRef.get())); } catch (IntrospectionException exception) { setPropertyType(null); @@ -723,8 +709,8 @@ public class PropertyDescriptor extends FeatureDescriptor { appendTo(sb, "constrained", this.constrained); appendTo(sb, "propertyEditorClass", this.propertyEditorClassRef); appendTo(sb, "propertyType", this.propertyTypeRef); - appendTo(sb, "readMethod", this.readMethodRef); - appendTo(sb, "writeMethod", this.writeMethodRef); + appendTo(sb, "readMethod", this.readMethodRef.get()); + appendTo(sb, "writeMethod", this.writeMethodRef.get()); } private boolean isAssignable(Method m1, Method m2) { diff --git a/jdk/src/share/classes/java/beans/ThreadGroupContext.java b/jdk/src/share/classes/java/beans/ThreadGroupContext.java index 6236ec2b38c..d93f1a87217 100644 --- a/jdk/src/share/classes/java/beans/ThreadGroupContext.java +++ b/jdk/src/share/classes/java/beans/ThreadGroupContext.java @@ -41,24 +41,20 @@ import java.util.WeakHashMap; */ final class ThreadGroupContext { - private static final WeakIdentityMap contexts = new WeakIdentityMap<>(); + private static final WeakIdentityMap contexts = new WeakIdentityMap() { + protected ThreadGroupContext create(Object key) { + return new ThreadGroupContext(); + } + }; /** - * Returns the appropriate {@code AppContext} for the caller, + * Returns the appropriate {@code ThreadGroupContext} for the caller, * as determined by its {@code ThreadGroup}. * * @return the application-dependent context */ static ThreadGroupContext getContext() { - ThreadGroup group = Thread.currentThread().getThreadGroup(); - synchronized (contexts) { - ThreadGroupContext context = contexts.get(group); - if (context == null) { - context = new ThreadGroupContext(); - contexts.put(group, context); - } - return context; - } + return contexts.get(Thread.currentThread().getThreadGroup()); } private volatile boolean isDesignTime; diff --git a/jdk/src/share/classes/java/beans/WeakIdentityMap.java b/jdk/src/share/classes/java/beans/WeakIdentityMap.java index 42ac821a392..83d8bfb1b50 100644 --- a/jdk/src/share/classes/java/beans/WeakIdentityMap.java +++ b/jdk/src/share/classes/java/beans/WeakIdentityMap.java @@ -33,18 +33,22 @@ import java.lang.ref.WeakReference; * and reference-equality in place of object-equality to compare them. * An entry will automatically be removed when its key is no longer * in ordinary use. Both null values and the null key are supported. + * This class does not require additional synchronization. + * A thread-safety is provided by a fragile combination + * of synchronized blocks and volatile fields. + * Be very careful during editing! * * @see java.util.IdentityHashMap * @see java.util.WeakHashMap */ -final class WeakIdentityMap { +abstract class WeakIdentityMap { private static final int MAXIMUM_CAPACITY = 1 << 30; // it MUST be a power of two private static final Object NULL = new Object(); // special object for null key private final ReferenceQueue queue = new ReferenceQueue(); - private Entry[] table = newTable(1<<3); // table's length MUST be a power of two + private volatile Entry[] table = newTable(1<<3); // table's length MUST be a power of two private int threshold = 6; // the next size value at which to resize private int size = 0; // the number of key-value mappings @@ -54,78 +58,83 @@ final class WeakIdentityMap { key = NULL; } int hash = key.hashCode(); - int index = getIndex(this.table, hash); - for (Entry entry = this.table[index]; entry != null; entry = entry.next) { + Entry[] table = this.table; + // unsynchronized search improves performance + // the null value does not mean that there are no needed entry + int index = getIndex(table, hash); + for (Entry entry = table[index]; entry != null; entry = entry.next) { if (entry.isMatched(key, hash)) { return entry.value; } } - return null; - } - - public T put(Object key, T value) { - removeStaleEntries(); - if (key == null) { - key = NULL; - } - int hash = key.hashCode(); - int index = getIndex(this.table, hash); - for (Entry entry = this.table[index]; entry != null; entry = entry.next) { - if (entry.isMatched(key, hash)) { - T oldValue = entry.value; - entry.value = value; - return oldValue; + synchronized (NULL) { + // synchronized search improves stability + // we must create and add new value if there are no needed entry + index = getIndex(this.table, hash); + for (Entry entry = this.table[index]; entry != null; entry = entry.next) { + if (entry.isMatched(key, hash)) { + return entry.value; + } } - } - this.table[index] = new Entry(key, hash, value, this.queue, this.table[index]); - if (++this.size >= this.threshold) { - if (this.table.length == MAXIMUM_CAPACITY) { - this.threshold = Integer.MAX_VALUE; - } - else { - removeStaleEntries(); - Entry[] table = newTable(this.table.length * 2); - transfer(this.table, table); - - // If ignoring null elements and processing ref queue caused massive - // shrinkage, then restore old table. This should be rare, but avoids - // unbounded expansion of garbage-filled tables. - if (this.size >= this.threshold / 2) { - this.table = table; - this.threshold *= 2; + T value = create(key); + this.table[index] = new Entry(key, hash, value, this.queue, this.table[index]); + if (++this.size >= this.threshold) { + if (this.table.length == MAXIMUM_CAPACITY) { + this.threshold = Integer.MAX_VALUE; } else { - transfer(table, this.table); - } - } - } - return null; - } - - private void removeStaleEntries() { - for (Object ref = this.queue.poll(); ref != null; ref = this.queue.poll()) { - @SuppressWarnings("unchecked") - Entry entry = (Entry) ref; - int index = getIndex(this.table, entry.hash); - - Entry prev = this.table[index]; - Entry current = prev; - while (current != null) { - Entry next = current.next; - if (current == entry) { - if (prev == entry) { - this.table[index] = next; + removeStaleEntries(); + table = newTable(this.table.length * 2); + transfer(this.table, table); + // If ignoring null elements and processing ref queue caused massive + // shrinkage, then restore old table. This should be rare, but avoids + // unbounded expansion of garbage-filled tables. + if (this.size >= this.threshold / 2) { + this.table = table; + this.threshold *= 2; } else { - prev.next = next; + transfer(table, this.table); } - entry.value = null; // Help GC - entry.next = null; // Help GC - this.size--; - break; } - prev = current; - current = next; + } + return value; + } + } + + protected abstract T create(Object key); + + private void removeStaleEntries() { + Object ref = this.queue.poll(); + if (ref != null) { + synchronized (NULL) { + do { + @SuppressWarnings("unchecked") + Entry entry = (Entry) ref; + int index = getIndex(this.table, entry.hash); + + Entry prev = this.table[index]; + Entry current = prev; + while (current != null) { + Entry next = current.next; + if (current == entry) { + if (prev == entry) { + this.table[index] = next; + } + else { + prev.next = next; + } + entry.value = null; // Help GC + entry.next = null; // Help GC + this.size--; + break; + } + prev = current; + current = next; + } + ref = this.queue.poll(); + } + while (ref != null); } } } @@ -164,8 +173,8 @@ final class WeakIdentityMap { private static class Entry extends WeakReference { private final int hash; - private T value; - private Entry next; + private volatile T value; + private volatile Entry next; Entry(Object key, int hash, T value, ReferenceQueue queue, Entry next) { super(key, queue); diff --git a/jdk/src/share/classes/java/io/Console.java b/jdk/src/share/classes/java/io/Console.java index c100f8a0ccd..292e42eec7c 100644 --- a/jdk/src/share/classes/java/io/Console.java +++ b/jdk/src/share/classes/java/io/Console.java @@ -124,9 +124,11 @@ public final class Console implements Flushable * {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)} * on the returned object will not read in characters beyond the line * bound for each invocation, even if the destination buffer has space for - * more characters. A line bound is considered to be any one of a line feed - * ('\n'), a carriage return ('\r'), a carriage return - * followed immediately by a linefeed, or an end of stream. + * more characters. The {@code Reader}'s {@code read} methods may block if a + * line bound has not been entered or reached on the console's input device. + * A line bound is considered to be any one of a line feed ('\n'), + * a carriage return ('\r'), a carriage return followed immediately + * by a linefeed, or an end of stream. * * @return The reader associated with this console */ diff --git a/jdk/src/share/classes/java/lang/AutoCloseable.java b/jdk/src/share/classes/java/lang/AutoCloseable.java index ce0fffe5939..be47cd0835f 100644 --- a/jdk/src/share/classes/java/lang/AutoCloseable.java +++ b/jdk/src/share/classes/java/lang/AutoCloseable.java @@ -26,7 +26,24 @@ package java.lang; /** - * A resource that must be closed when it is no longer needed. + * An object that may hold resources (such as file or socket handles) + * until it is closed. The {@link #close()} method of an {@code AutoCloseable} + * object is called automatically when exiting a {@code + * try}-with-resources block for which the object has been declared in + * the resource specification header. This construction ensures prompt + * release, avoiding resource exhaustion exceptions and errors that + * may otherwise occur. + * + * @apiNote + *

    It is possible, and in fact common, for a base class to + * implement AutoCloseable even though not all of its subclasses or + * instances will hold releasable resources. For code that must operate + * in complete generality, or when it is known that the {@code AutoCloseable} + * instance requires resource release, it is recommended to use {@code + * try}-with-resources constructions. However, when using facilities such as + * {@link java.util.stream.Stream} that support both I/O-based and + * non-I/O-based forms, {@code try}-with-resources blocks are in + * general unnecessary when using non-I/O-based forms. * * @author Josh Bloch * @since 1.7 diff --git a/jdk/src/share/classes/java/lang/CharSequence.java b/jdk/src/share/classes/java/lang/CharSequence.java index ac80b22f066..a74a9d0d424 100644 --- a/jdk/src/share/classes/java/lang/CharSequence.java +++ b/jdk/src/share/classes/java/lang/CharSequence.java @@ -228,7 +228,7 @@ public interface CharSequence { Spliterators.spliteratorUnknownSize( new CodePointIterator(), Spliterator.ORDERED), - Spliterator.SUBSIZED | Spliterator.SIZED | Spliterator.ORDERED, + Spliterator.ORDERED, false); } } diff --git a/jdk/src/share/classes/java/lang/Class.java b/jdk/src/share/classes/java/lang/Class.java index 7895c62b3cc..d0c0f455f7f 100644 --- a/jdk/src/share/classes/java/lang/Class.java +++ b/jdk/src/share/classes/java/lang/Class.java @@ -48,6 +48,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Set; import java.util.Map; @@ -821,6 +822,10 @@ public final class Class implements java.io.Serializable, *

    If this object represents a primitive type or void, the method * returns an array of length 0. * + *

    If this {@code Class} object represents an array type, the + * interfaces {@code Cloneable} and {@code java.io.Serializable} are + * returned in that order. + * * @return an array of interfaces implemented by this class. */ public Class[] getInterfaces() { @@ -1500,22 +1505,24 @@ public final class Class implements java.io.Serializable, /** * Returns an array containing {@code Field} objects reflecting all * the accessible public fields of the class or interface represented by - * this {@code Class} object. The elements in the array returned are - * not sorted and are not in any particular order. This method returns an - * array of length 0 if the class or interface has no accessible public - * fields, or if it represents an array class, a primitive type, or void. + * this {@code Class} object. * - *

    Specifically, if this {@code Class} object represents a class, - * this method returns the public fields of this class and of all its - * superclasses. If this {@code Class} object represents an - * interface, this method returns the fields of this interface and of all - * its superinterfaces. + *

    If this {@code Class} object represents a class or interface with no + * no accessible public fields, then this method returns an array of length + * 0. * - *

    The implicit length field for array class is not reflected by this - * method. User code should use the methods of class {@code Array} to - * manipulate arrays. + *

    If this {@code Class} object represents a class, then this method + * returns the public fields of the class and of all its superclasses. * - *

    See The Java Language Specification, sections 8.2 and 8.3. + *

    If this {@code Class} object represents an interface, then this + * method returns the fields of the interface and of all its + * superinterfaces. + * + *

    If this {@code Class} object represents an array type, a primitive + * type, or void, then this method returns an array of length 0. + * + *

    The elements in the returned array are not sorted and are not in any + * particular order. * * @return the array of {@code Field} objects representing the * public fields @@ -1528,6 +1535,8 @@ public final class Class implements java.io.Serializable, * of this class. * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field[] getFields() throws SecurityException { @@ -1537,23 +1546,33 @@ public final class Class implements java.io.Serializable, /** - * Returns an array containing {@code Method} objects reflecting all - * the public member methods of the class or interface represented - * by this {@code Class} object, including those declared by the class - * or interface and those inherited from superclasses and - * superinterfaces. Array classes return all the (public) member methods - * inherited from the {@code Object} class. The elements in the array - * returned are not sorted and are not in any particular order. This - * method returns an array of length 0 if this {@code Class} object - * represents a class or interface that has no public member methods, or if - * this {@code Class} object represents a primitive type or void. + * Returns an array containing {@code Method} objects reflecting all the + * public methods of the class or interface represented by this {@code + * Class} object, including those declared by the class or interface and + * those inherited from superclasses and superinterfaces. * - *

    The class initialization method {@code } is not - * included in the returned array. If the class declares multiple public - * member methods with the same parameter types, they are all included in - * the returned array. + *

    If this {@code Class} object represents a type that has multiple + * public methods with the same name and parameter types, but different + * return types, then the returned array has a {@code Method} object for + * each such method. * - *

    See The Java Language Specification, sections 8.2 and 8.4. + *

    If this {@code Class} object represents a type with a class + * initialization method {@code }, then the returned array does + * not have a corresponding {@code Method} object. + * + *

    If this {@code Class} object represents an array type, then the + * returned array has a {@code Method} object for each of the public + * methods inherited by the array type from {@code Object}. It does not + * contain a {@code Method} object for {@code clone()}. + * + *

    If this {@code Class} object represents a class or interface with no + * public methods, then the returned array has length 0. + * + *

    If this {@code Class} object represents a primitive type or void, + * then the returned array has length 0. + * + *

    The elements in the returned array are not sorted and are not in any + * particular order. * * @return the array of {@code Method} objects representing the * public methods of this class @@ -1565,6 +1584,8 @@ public final class Class implements java.io.Serializable, * s.checkPackageAccess()} denies access to the package * of this class. * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive @@ -1611,13 +1632,14 @@ public final class Class implements java.io.Serializable, /** - * Returns a {@code Field} object that reflects the specified public - * member field of the class or interface represented by this - * {@code Class} object. The {@code name} parameter is a - * {@code String} specifying the simple name of the desired field. + * Returns a {@code Field} object that reflects the specified public member + * field of the class or interface represented by this {@code Class} + * object. The {@code name} parameter is a {@code String} specifying the + * simple name of the desired field. * *

    The field to be reflected is determined by the algorithm that - * follows. Let C be the class represented by this object: + * follows. Let C be the class or interface represented by this object: + * *

      *
    1. If C declares a public field with the name specified, that is the * field to be reflected.
    2. @@ -1630,7 +1652,8 @@ public final class Class implements java.io.Serializable, * is thrown. *
    * - *

    See The Java Language Specification, sections 8.2 and 8.3. + *

    If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. * * @param name the field name * @return the {@code Field} object of this class specified by @@ -1647,6 +1670,8 @@ public final class Class implements java.io.Serializable, * of this class. * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field getField(String name) @@ -1701,7 +1726,8 @@ public final class Class implements java.io.Serializable, * method and the method being overridden would have the same * signature but different return types. * - *

    See The Java Language Specification, sections 8.2 and 8.4. + *

    If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. * * @param name the name of the method * @param parameterTypes the list of parameters @@ -1718,6 +1744,8 @@ public final class Class implements java.io.Serializable, * s.checkPackageAccess()} denies access to the package * of this class. * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive @@ -1816,12 +1844,15 @@ public final class Class implements java.io.Serializable, * declared by the class or interface represented by this * {@code Class} object. This includes public, protected, default * (package) access, and private fields, but excludes inherited fields. - * The elements in the array returned are not sorted and are not in any - * particular order. This method returns an array of length 0 if the class - * or interface declares no fields, or if this {@code Class} object - * represents a primitive type, an array class, or void. * - *

    See The Java Language Specification, sections 8.2 and 8.3. + *

    If this {@code Class} object represents a class or interface with no + * declared fields, then this method returns an array of length 0. + * + *

    If this {@code Class} object represents an array type, a primitive + * type, or void, then this method returns an array of length 0. + * + *

    The elements in the returned array are not sorted and are not in any + * particular order. * * @return the array of {@code Field} objects representing all the * declared fields of this class @@ -1847,6 +1878,8 @@ public final class Class implements java.io.Serializable, * * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field[] getDeclaredFields() throws SecurityException { @@ -1856,20 +1889,29 @@ public final class Class implements java.io.Serializable, /** - * Returns an array of {@code Method} objects reflecting all the - * methods declared by the class or interface represented by this - * {@code Class} object. This includes public, protected, default - * (package) access, and private methods, but excludes inherited methods. - * The elements in the array returned are not sorted and are not in any - * particular order. This method returns an array of length 0 if the class - * or interface declares no methods, or if this {@code Class} object - * represents a primitive type, an array class, or void. The class - * initialization method {@code } is not included in the - * returned array. If the class declares multiple public member methods - * with the same parameter types, they are all included in the returned - * array. * - *

    See The Java Language Specification, section 8.2. + * Returns an array containing {@code Method} objects reflecting all the + * declared methods of the class or interface represented by this {@code + * Class} object, including public, protected, default (package) + * access, and private methods, but excluding inherited methods. + * + *

    If this {@code Class} object represents a type that has multiple + * declared methods with the same name and parameter types, but different + * return types, then the returned array has a {@code Method} object for + * each such method. + * + *

    If this {@code Class} object represents a type that has a class + * initialization method {@code }, then the returned array does + * not have a corresponding {@code Method} object. + * + *

    If this {@code Class} object represents a class or interface with no + * declared methods, then the returned array has length 0. + * + *

    If this {@code Class} object represents an array type, a primitive + * type, or void, then the returned array has length 0. + * + *

    The elements in the returned array are not sorted and are not in any + * particular order. * * @return the array of {@code Method} objects representing all the * declared methods of this class @@ -1894,6 +1936,8 @@ public final class Class implements java.io.Serializable, * * * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive @@ -1951,9 +1995,11 @@ public final class Class implements java.io.Serializable, /** * Returns a {@code Field} object that reflects the specified declared * field of the class or interface represented by this {@code Class} - * object. The {@code name} parameter is a {@code String} that - * specifies the simple name of the desired field. Note that this method - * will not reflect the {@code length} field of an array class. + * object. The {@code name} parameter is a {@code String} that specifies + * the simple name of the desired field. + * + *

    If this {@code Class} object represents an array type, then this + * method does not find the {@code length} field of the array type. * * @param name the name of the field * @return the {@code Field} object for the specified field in this @@ -1983,6 +2029,8 @@ public final class Class implements java.io.Serializable, * * * @since JDK1.1 + * @jls 8.2 Class Members + * @jls 8.3 Field Declarations */ @CallerSensitive public Field getDeclaredField(String name) @@ -2010,6 +2058,9 @@ public final class Class implements java.io.Serializable, * name is "<init>"or "<clinit>" a {@code NoSuchMethodException} * is raised. * + *

    If this {@code Class} object represents an array type, then this + * method does not find the {@code clone()} method. + * * @param name the name of the method * @param parameterTypes the parameter array * @return the {@code Method} object for the method of this class @@ -2037,6 +2088,8 @@ public final class Class implements java.io.Serializable, * * * + * @jls 8.2 Class Members + * @jls 8.4 Method Declarations * @since JDK1.1 */ @CallerSensitive @@ -2334,11 +2387,14 @@ public final class Class implements java.io.Serializable, private static final long reflectionDataOffset; // offset of Class.annotationType instance field private static final long annotationTypeOffset; + // offset of Class.annotationData instance field + private static final long annotationDataOffset; static { Field[] fields = Class.class.getDeclaredFields0(false); // bypass caches reflectionDataOffset = objectFieldOffset(fields, "reflectionData"); annotationTypeOffset = objectFieldOffset(fields, "annotationType"); + annotationDataOffset = objectFieldOffset(fields, "annotationData"); } private static long objectFieldOffset(Field[] fields, String fieldName) { @@ -2360,6 +2416,12 @@ public final class Class implements java.io.Serializable, AnnotationType newType) { return unsafe.compareAndSwapObject(clazz, annotationTypeOffset, oldType, newType); } + + static boolean casAnnotationData(Class clazz, + AnnotationData oldData, + AnnotationData newData) { + return unsafe.compareAndSwapObject(clazz, annotationDataOffset, oldData, newData); + } } /** @@ -2370,7 +2432,7 @@ public final class Class implements java.io.Serializable, private static boolean useCaches = true; // reflection data that might get invalidated when JVM TI RedefineClasses() is called - static class ReflectionData { + private static class ReflectionData { volatile Field[] declaredFields; volatile Field[] publicFields; volatile Method[] declaredMethods; @@ -3217,8 +3279,7 @@ public final class Class implements java.io.Serializable, public A getAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - initAnnotationsIfNecessary(); - return (A) annotations.get(annotationClass); + return (A) annotationData().annotations.get(annotationClass); } /** @@ -3239,16 +3300,14 @@ public final class Class implements java.io.Serializable, public A[] getAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - initAnnotationsIfNecessary(); - return AnnotationSupport.getMultipleAnnotations(annotations, annotationClass); + return AnnotationSupport.getMultipleAnnotations(annotationData().annotations, annotationClass); } /** * @since 1.5 */ public Annotation[] getAnnotations() { - initAnnotationsIfNecessary(); - return AnnotationParser.toArray(annotations); + return AnnotationParser.toArray(annotationData().annotations); } /** @@ -3260,8 +3319,7 @@ public final class Class implements java.io.Serializable, public A getDeclaredAnnotation(Class annotationClass) { Objects.requireNonNull(annotationClass); - initAnnotationsIfNecessary(); - return (A) declaredAnnotations.get(annotationClass); + return (A) annotationData().declaredAnnotations.get(annotationClass); } /** @@ -3272,52 +3330,85 @@ public final class Class implements java.io.Serializable, public A[] getDeclaredAnnotationsByType(Class annotationClass) { Objects.requireNonNull(annotationClass); - initAnnotationsIfNecessary(); - return AnnotationSupport.getMultipleAnnotations(declaredAnnotations, annotationClass); + return AnnotationSupport.getMultipleAnnotations(annotationData().declaredAnnotations, annotationClass); } /** * @since 1.5 */ public Annotation[] getDeclaredAnnotations() { - initAnnotationsIfNecessary(); - return AnnotationParser.toArray(declaredAnnotations); + return AnnotationParser.toArray(annotationData().declaredAnnotations); + } + + // annotation data that might get invalidated when JVM TI RedefineClasses() is called + private static class AnnotationData { + final Map, Annotation> annotations; + final Map, Annotation> declaredAnnotations; + + // Value of classRedefinedCount when we created this AnnotationData instance + final int redefinedCount; + + AnnotationData(Map, Annotation> annotations, + Map, Annotation> declaredAnnotations, + int redefinedCount) { + this.annotations = annotations; + this.declaredAnnotations = declaredAnnotations; + this.redefinedCount = redefinedCount; + } } // Annotations cache - private transient Map, Annotation> annotations; - private transient Map, Annotation> declaredAnnotations; - // Value of classRedefinedCount when we last cleared the cached annotations and declaredAnnotations fields - private transient int lastAnnotationsRedefinedCount = 0; + @SuppressWarnings("UnusedDeclaration") + private volatile transient AnnotationData annotationData; - // Clears cached values that might possibly have been obsoleted by - // a class redefinition. - private void clearAnnotationCachesOnClassRedefinition() { - if (lastAnnotationsRedefinedCount != classRedefinedCount) { - annotations = declaredAnnotations = null; - lastAnnotationsRedefinedCount = classRedefinedCount; + private AnnotationData annotationData() { + while (true) { // retry loop + AnnotationData annotationData = this.annotationData; + int classRedefinedCount = this.classRedefinedCount; + if (annotationData != null && + annotationData.redefinedCount == classRedefinedCount) { + return annotationData; + } + // null or stale annotationData -> optimistically create new instance + AnnotationData newAnnotationData = createAnnotationData(classRedefinedCount); + // try to install it + if (Atomic.casAnnotationData(this, annotationData, newAnnotationData)) { + // successfully installed new AnnotationData + return newAnnotationData; + } } } - private synchronized void initAnnotationsIfNecessary() { - clearAnnotationCachesOnClassRedefinition(); - if (annotations != null) - return; - declaredAnnotations = AnnotationParser.parseAnnotations( - getRawAnnotations(), getConstantPool(), this); + private AnnotationData createAnnotationData(int classRedefinedCount) { + Map, Annotation> declaredAnnotations = + AnnotationParser.parseAnnotations(getRawAnnotations(), getConstantPool(), this); Class superClass = getSuperclass(); - if (superClass == null) { + Map, Annotation> annotations = null; + if (superClass != null) { + Map, Annotation> superAnnotations = + superClass.annotationData().annotations; + for (Map.Entry, Annotation> e : superAnnotations.entrySet()) { + Class annotationClass = e.getKey(); + if (AnnotationType.getInstance(annotationClass).isInherited()) { + if (annotations == null) { // lazy construction + annotations = new LinkedHashMap<>((Math.max( + declaredAnnotations.size(), + Math.min(12, declaredAnnotations.size() + superAnnotations.size()) + ) * 4 + 2) / 3 + ); + } + annotations.put(annotationClass, e.getValue()); + } + } + } + if (annotations == null) { + // no inherited annotations -> share the Map with declaredAnnotations annotations = declaredAnnotations; } else { - annotations = new HashMap<>(); - superClass.initAnnotationsIfNecessary(); - for (Map.Entry, Annotation> e : superClass.annotations.entrySet()) { - Class annotationClass = e.getKey(); - if (AnnotationType.getInstance(annotationClass).isInherited()) - annotations.put(annotationClass, e.getValue()); - } + // at least one inherited annotation -> declared may override inherited annotations.putAll(declaredAnnotations); } + return new AnnotationData(annotations, declaredAnnotations, classRedefinedCount); } // Annotation types cache their internal (AnnotationType) form diff --git a/jdk/src/share/classes/java/lang/Math.java b/jdk/src/share/classes/java/lang/Math.java index ae83e4265ad..98e901ac942 100644 --- a/jdk/src/share/classes/java/lang/Math.java +++ b/jdk/src/share/classes/java/lang/Math.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -646,7 +646,7 @@ public final class Math { /** * Returns the closest {@code int} to the argument, with ties - * rounding up. + * rounding to positive infinity. * *

    * Special cases: @@ -665,15 +665,37 @@ public final class Math { * @see java.lang.Integer#MIN_VALUE */ public static int round(float a) { - if (a != 0x1.fffffep-2f) // greatest float value less than 0.5 - return (int)floor(a + 0.5f); - else - return 0; + int intBits = Float.floatToRawIntBits(a); + int biasedExp = (intBits & FloatConsts.EXP_BIT_MASK) + >> (FloatConsts.SIGNIFICAND_WIDTH - 1); + int shift = (FloatConsts.SIGNIFICAND_WIDTH - 2 + + FloatConsts.EXP_BIAS) - biasedExp; + if ((shift & -32) == 0) { // shift >= 0 && shift < 32 + // a is a finite number such that pow(2,-32) <= ulp(a) < 1 + int r = ((intBits & FloatConsts.SIGNIF_BIT_MASK) + | (FloatConsts.SIGNIF_BIT_MASK + 1)); + if (intBits < 0) { + r = -r; + } + // In the comments below each Java expression evaluates to the value + // the corresponding mathematical expression: + // (r) evaluates to a / ulp(a) + // (r >> shift) evaluates to floor(a * 2) + // ((r >> shift) + 1) evaluates to floor((a + 1/2) * 2) + // (((r >> shift) + 1) >> 1) evaluates to floor(a + 1/2) + return ((r >> shift) + 1) >> 1; + } else { + // a is either + // - a finite number with abs(a) < exp(2,FloatConsts.SIGNIFICAND_WIDTH-32) < 1/2 + // - a finite number with ulp(a) >= 1 and hence a is a mathematical integer + // - an infinity or NaN + return (int) a; + } } /** * Returns the closest {@code long} to the argument, with ties - * rounding up. + * rounding to positive infinity. * *

    Special cases: *

    • If the argument is NaN, the result is 0. @@ -692,10 +714,32 @@ public final class Math { * @see java.lang.Long#MIN_VALUE */ public static long round(double a) { - if (a != 0x1.fffffffffffffp-2) // greatest double value less than 0.5 - return (long)floor(a + 0.5d); - else - return 0; + long longBits = Double.doubleToRawLongBits(a); + long biasedExp = (longBits & DoubleConsts.EXP_BIT_MASK) + >> (DoubleConsts.SIGNIFICAND_WIDTH - 1); + long shift = (DoubleConsts.SIGNIFICAND_WIDTH - 2 + + DoubleConsts.EXP_BIAS) - biasedExp; + if ((shift & -64) == 0) { // shift >= 0 && shift < 64 + // a is a finite number such that pow(2,-64) <= ulp(a) < 1 + long r = ((longBits & DoubleConsts.SIGNIF_BIT_MASK) + | (DoubleConsts.SIGNIF_BIT_MASK + 1)); + if (longBits < 0) { + r = -r; + } + // In the comments below each Java expression evaluates to the value + // the corresponding mathematical expression: + // (r) evaluates to a / ulp(a) + // (r >> shift) evaluates to floor(a * 2) + // ((r >> shift) + 1) evaluates to floor((a + 1/2) * 2) + // (((r >> shift) + 1) >> 1) evaluates to floor(a + 1/2) + return ((r >> shift) + 1) >> 1; + } else { + // a is either + // - a finite number with abs(a) < exp(2,DoubleConsts.SIGNIFICAND_WIDTH-64) < 1/2 + // - a finite number with ulp(a) >= 1 and hence a is a mathematical integer + // - an infinity or NaN + return (long) a; + } } private static final class RandomNumberGeneratorHolder { diff --git a/jdk/src/share/classes/java/lang/SecurityManager.java b/jdk/src/share/classes/java/lang/SecurityManager.java index 34be905bd02..3565082033c 100644 --- a/jdk/src/share/classes/java/lang/SecurityManager.java +++ b/jdk/src/share/classes/java/lang/SecurityManager.java @@ -1336,9 +1336,16 @@ class SecurityManager { * top-level windows; false otherwise. * @exception NullPointerException if the window argument is * null. + * @deprecated The dependency on {@code AWTPermission} creates an + * impediment to future modularization of the Java platform. + * Users of this method should instead invoke + * {@link #checkPermission} directly. + * This method will be changed in a future release to check + * the permission {@code java.security.AllPermission}. * @see java.awt.Window * @see #checkPermission(java.security.Permission) checkPermission */ + @Deprecated public boolean checkTopLevelWindow(Object window) { if (window == null) { throw new NullPointerException("window can't be null"); @@ -1398,8 +1405,15 @@ class SecurityManager { * @since JDK1.1 * @exception SecurityException if the calling thread does not have * permission to access the system clipboard. + * @deprecated The dependency on {@code AWTPermission} creates an + * impediment to future modularization of the Java platform. + * Users of this method should instead invoke + * {@link #checkPermission} directly. + * This method will be changed in a future release to check + * the permission {@code java.security.AllPermission}. * @see #checkPermission(java.security.Permission) checkPermission */ + @Deprecated public void checkSystemClipboardAccess() { Permission perm = SecurityConstants.AWT.ACCESS_CLIPBOARD_PERMISSION; if (perm == null) { @@ -1427,8 +1441,15 @@ class SecurityManager { * @since JDK1.1 * @exception SecurityException if the calling thread does not have * permission to access the AWT event queue. + * @deprecated The dependency on {@code AWTPermission} creates an + * impediment to future modularization of the Java platform. + * Users of this method should instead invoke + * {@link #checkPermission} directly. + * This method will be changed in a future release to check + * the permission {@code java.security.AllPermission}. * @see #checkPermission(java.security.Permission) checkPermission */ + @Deprecated public void checkAwtEventQueueAccess() { Permission perm = SecurityConstants.AWT.CHECK_AWT_EVENTQUEUE_PERMISSION; if (perm == null) { diff --git a/jdk/src/share/classes/java/lang/StrictMath.java b/jdk/src/share/classes/java/lang/StrictMath.java index 52336484e75..ae4af2bcac8 100644 --- a/jdk/src/share/classes/java/lang/StrictMath.java +++ b/jdk/src/share/classes/java/lang/StrictMath.java @@ -633,7 +633,7 @@ public final class StrictMath { /** * Returns the closest {@code int} to the argument, with ties - * rounding up. + * rounding to positive infinity. * *

      Special cases: *

      • If the argument is NaN, the result is 0. @@ -656,7 +656,7 @@ public final class StrictMath { /** * Returns the closest {@code long} to the argument, with ties - * rounding up. + * rounding to positive infinity. * *

        Special cases: *

        *

        * @author John Rose, JSR 292 EG + * @since 1.7 */ public class MethodHandles { @@ -96,6 +95,38 @@ public class MethodHandles { return Lookup.PUBLIC_LOOKUP; } + /** + * Performs an unchecked "crack" of a direct method handle. + * The result is as if the user had obtained a lookup object capable enough + * to crack the target method handle, called + * {@link java.lang.invoke.MethodHandles.Lookup#revealDirect Lookup.revealDirect} + * on the target to obtain its symbolic reference, and then called + * {@link java.lang.invoke.MethodHandleInfo#reflectAs MethodHandleInfo.reflectAs} + * to resolve the symbolic reference to a member. + *

        + * If there is a security manager, its {@code checkPermission} method + * is called with a {@code ReflectPermission("suppressAccessChecks")} permission. + * @param the desired type of the result, either {@link Member} or a subtype + * @param target a direct method handle to crack into symbolic reference components + * @param expected a class object representing the desired result type {@code T} + * @return a reference to the method, constructor, or field object + * @exception SecurityException if the caller is not privileged to call {@code setAccessible} + * @exception NullPointerException if either argument is {@code null} + * @exception IllegalArgumentException if the target is not a direct method handle + * @exception ClassCastException if the member is not of the expected type + * @since 1.8 + */ + public static T + reflectAs(Class expected, MethodHandle target) { + SecurityManager smgr = System.getSecurityManager(); + if (smgr != null) smgr.checkPermission(ACCESS_PERMISSION); + Lookup lookup = Lookup.IMPL_LOOKUP; // use maximally privileged lookup + return lookup.revealDirect(target).reflectAs(expected, lookup); + } + // Copied from AccessibleObject, as used by Method.setAccessible, etc.: + static final private java.security.Permission ACCESS_PERMISSION = + new ReflectPermission("suppressAccessChecks"); + /** * A lookup object is a factory for creating method handles, * when the creation requires access checking. @@ -656,6 +687,7 @@ public class MethodHandles { return invoker(type); if ("invokeExact".equals(name)) return exactInvoker(type); + assert(!MemberName.isMethodHandleInvokeName(name)); return null; } @@ -901,6 +933,10 @@ return mh1; * @throws NullPointerException if the argument is null */ public MethodHandle unreflect(Method m) throws IllegalAccessException { + if (m.getDeclaringClass() == MethodHandle.class) { + MethodHandle mh = unreflectForMH(m); + if (mh != null) return mh; + } MemberName method = new MemberName(m); byte refKind = method.getReferenceKind(); if (refKind == REF_invokeSpecial) @@ -909,6 +945,12 @@ return mh1; Lookup lookup = m.isAccessible() ? IMPL_LOOKUP : this; return lookup.getDirectMethod(refKind, method.getDeclaringClass(), method, findBoundCallerClass(method)); } + private MethodHandle unreflectForMH(Method m) { + // these names require special lookups because they throw UnsupportedOperationException + if (MemberName.isMethodHandleInvokeName(m.getName())) + return MethodHandleImpl.fakeMethodHandleInvoke(new MemberName(m)); + return null; + } /** * Produces a method handle for a reflected method. @@ -1013,6 +1055,46 @@ return mh1; return unreflectField(f, true); } + /** + * Cracks a direct method handle created by this lookup object or a similar one. + * Security and access checks are performed to ensure that this lookup object + * is capable of reproducing the target method handle. + * This means that the cracking may fail if target is a direct method handle + * but was created by an unrelated lookup object. + * @param target a direct method handle to crack into symbolic reference components + * @return a symbolic reference which can be used to reconstruct this method handle from this lookup object + * @exception SecurityException if a security manager is present and it + * refuses access + * @throws IllegalArgumentException if the target is not a direct method handle or if access checking fails + * @exception NullPointerException if the target is {@code null} + * @since 1.8 + */ + public MethodHandleInfo revealDirect(MethodHandle target) { + MemberName member = target.internalMemberName(); + if (member == null || (!member.isResolved() && !member.isMethodHandleInvoke())) + throw newIllegalArgumentException("not a direct method handle"); + Class defc = member.getDeclaringClass(); + byte refKind = member.getReferenceKind(); + assert(MethodHandleNatives.refKindIsValid(refKind)); + if (refKind == REF_invokeSpecial && !target.isInvokeSpecial()) + // Devirtualized method invocation is usually formally virtual. + // To avoid creating extra MemberName objects for this common case, + // we encode this extra degree of freedom using MH.isInvokeSpecial. + refKind = REF_invokeVirtual; + if (refKind == REF_invokeVirtual && defc.isInterface()) + // Symbolic reference is through interface but resolves to Object method (toString, etc.) + refKind = REF_invokeInterface; + // Check SM permissions and member access before cracking. + try { + checkSecurityManager(defc, member); + checkAccess(refKind, defc, member); + } catch (IllegalAccessException ex) { + throw new IllegalArgumentException(ex); + } + // Produce the handle to the results. + return new InfoFromMemberName(this, member, refKind); + } + /// Helper methods, all package-private. MemberName resolveOrFail(byte refKind, Class refc, String name, Class type) throws NoSuchFieldException, IllegalAccessException { @@ -1210,12 +1292,12 @@ return mh1; private MethodHandle getDirectMethodCommon(byte refKind, Class refc, MemberName method, boolean doRestrict, Class callerClass) throws IllegalAccessException { checkMethod(refKind, refc, method); - if (method.isMethodHandleInvoke()) - return fakeMethodHandleInvoke(method); + assert(!method.isMethodHandleInvoke()); Class refcAsSuper; if (refKind == REF_invokeSpecial && refc != lookupClass() && + !refc.isInterface() && refc != (refcAsSuper = lookupClass().getSuperclass()) && refc.isAssignableFrom(lookupClass())) { assert(!method.getName().equals("")); // not this code path @@ -1243,9 +1325,6 @@ return mh1; mh = restrictReceiver(method, mh, lookupClass()); return mh; } - private MethodHandle fakeMethodHandleInvoke(MemberName method) { - return throwException(method.getReturnType(), UnsupportedOperationException.class); - } private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh, Class callerClass) throws IllegalAccessException { diff --git a/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java b/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java index a775fc43e34..9be96ff685b 100644 --- a/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java +++ b/jdk/src/share/classes/java/lang/invoke/SerializedLambda.java @@ -225,7 +225,7 @@ public final class SerializedLambda implements Serializable { @Override public String toString() { - String implKind=MethodHandleInfo.getReferenceKindString(implMethodKind); + String implKind=MethodHandleInfo.referenceKindToString(implMethodKind); return String.format("SerializedLambda[%s=%s, %s=%s.%s:%s, " + "%s=%s %s.%s:%s, %s=%s, %s=%d]", "capturingClass", capturingClass, diff --git a/jdk/src/share/classes/java/lang/reflect/Executable.java b/jdk/src/share/classes/java/lang/reflect/Executable.java index aa8820fd2d7..9d41a0217db 100644 --- a/jdk/src/share/classes/java/lang/reflect/Executable.java +++ b/jdk/src/share/classes/java/lang/reflect/Executable.java @@ -428,20 +428,32 @@ public abstract class Executable extends AccessibleObject } /** - * Returns an array of arrays that represent the annotations on - * the formal parameters, in declaration order, of the executable - * represented by this object. (Returns an array of length zero if - * the underlying executable is parameterless. If the executable has - * one or more parameters, a nested array of length zero is - * returned for each parameter with no annotations.) The - * annotation objects contained in the returned arrays are - * serializable. The caller of this method is free to modify the - * returned arrays; it will have no effect on the arrays returned - * to other callers. + * Returns an array of arrays of {@code Annotation}s that + * represent the annotations on the formal parameters, in + * declaration order, of the {@code Executable} represented by + * this object. Synthetic and mandated parameters (see + * explanation below), such as the outer "this" parameter to an + * inner class constructor will be represented in the returned + * array. If the executable has no parameters (meaning no formal, + * no synthetic, and no mandated parameters), a zero-length array + * will be returned. If the {@code Executable} has one or more + * parameters, a nested array of length zero is returned for each + * parameter with no annotations. The annotation objects contained + * in the returned arrays are serializable. The caller of this + * method is free to modify the returned arrays; it will have no + * effect on the arrays returned to other callers. * - * @return an array of arrays that represent the annotations on the formal - * parameters, in declaration order, of the executable represented by this - * object + * A compiler may add extra parameters that are implicitly + * declared in source ("mandated"), as well as parameters that + * are neither implicitly nor explicitly declared in source + * ("synthetic") to the parameter list for a method. See {@link + * java.lang.reflect.Parameter} for more information. + * + * @see java.lang.reflect.Parameter + * @see java.lang.reflect.Parameter#getAnnotations + * @return an array of arrays that represent the annotations on + * the formal and implicit parameters, in declaration order, of + * the executable represented by this object */ public abstract Annotation[][] getParameterAnnotations(); diff --git a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java index be9ac509731..446b4248a8e 100644 --- a/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java +++ b/jdk/src/share/classes/java/net/AbstractPlainSocketImpl.java @@ -719,7 +719,3 @@ abstract class AbstractPlainSocketImpl extends SocketImpl public final static int SHUT_RD = 0; public final static int SHUT_WR = 1; } - -class InetAddressContainer { - InetAddress addr; -} diff --git a/jdk/src/share/classes/java/net/IDN.java b/jdk/src/share/classes/java/net/IDN.java index ed2f3a38159..34642b9824c 100644 --- a/jdk/src/share/classes/java/net/IDN.java +++ b/jdk/src/share/classes/java/net/IDN.java @@ -292,13 +292,17 @@ public final class IDN { if (useSTD3ASCIIRules) { for (int i = 0; i < dest.length(); i++) { int c = dest.charAt(i); - if (!isLDHChar(c)) { - throw new IllegalArgumentException("Contains non-LDH characters"); + if (isNonLDHAsciiCodePoint(c)) { + throw new IllegalArgumentException( + "Contains non-LDH ASCII characters"); } } - if (dest.charAt(0) == '-' || dest.charAt(dest.length() - 1) == '-') { - throw new IllegalArgumentException("Has leading or trailing hyphen"); + if (dest.charAt(0) == '-' || + dest.charAt(dest.length() - 1) == '-') { + + throw new IllegalArgumentException( + "Has leading or trailing hyphen"); } } @@ -401,26 +405,20 @@ public final class IDN { // // LDH stands for "letter/digit/hyphen", with characters restricted to the // 26-letter Latin alphabet , the digits <0-9>, and the hyphen - // <-> - // non-LDH = 0..0x2C, 0x2E..0x2F, 0x3A..0x40, 0x56..0x60, 0x7B..0x7F + // <->. + // Non LDH refers to characters in the ASCII range, but which are not + // letters, digits or the hypen. // - private static boolean isLDHChar(int ch){ - // high runner case - if(ch > 0x007A){ - return false; - } - //['-' '0'..'9' 'A'..'Z' 'a'..'z'] - if((ch == 0x002D) || - (0x0030 <= ch && ch <= 0x0039) || - (0x0041 <= ch && ch <= 0x005A) || - (0x0061 <= ch && ch <= 0x007A) - ){ - return true; - } - return false; + // non-LDH = 0..0x2C, 0x2E..0x2F, 0x3A..0x40, 0x5B..0x60, 0x7B..0x7F + // + private static boolean isNonLDHAsciiCodePoint(int ch){ + return (0x0000 <= ch && ch <= 0x002C) || + (0x002E <= ch && ch <= 0x002F) || + (0x003A <= ch && ch <= 0x0040) || + (0x005B <= ch && ch <= 0x0060) || + (0x007B <= ch && ch <= 0x007F); } - // // search dots in a string and return the index of that character; // or if there is no dots, return the length of input string diff --git a/jdk/src/macosx/classes/sun/lwawt/SelectionClearListener.java b/jdk/src/share/classes/java/net/InetAddressContainer.java similarity index 80% rename from jdk/src/macosx/classes/sun/lwawt/SelectionClearListener.java rename to jdk/src/share/classes/java/net/InetAddressContainer.java index 4b378484240..28b64022fc7 100644 --- a/jdk/src/macosx/classes/sun/lwawt/SelectionClearListener.java +++ b/jdk/src/share/classes/java/net/InetAddressContainer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,12 +23,8 @@ * questions. */ -package sun.lwawt; +package java.net; -/* - * Every time the TextField (or TextArea) change selection, every other text components - * must immediately clear their selections. - */ -interface SelectionClearListener { - void clearSelection(); +class InetAddressContainer { + InetAddress addr; } diff --git a/jdk/src/share/classes/java/nio/file/Files.java b/jdk/src/share/classes/java/nio/file/Files.java index 721184c1533..f084040c179 100644 --- a/jdk/src/share/classes/java/nio/file/Files.java +++ b/jdk/src/share/classes/java/nio/file/Files.java @@ -25,34 +25,56 @@ package java.nio.file; -import java.nio.file.attribute.*; -import java.nio.file.spi.FileSystemProvider; -import java.nio.file.spi.FileTypeDetector; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.Closeable; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.io.Writer; import java.nio.channels.Channels; import java.nio.channels.FileChannel; import java.nio.channels.SeekableByteChannel; -import java.io.Closeable; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.Reader; -import java.io.Writer; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.IOException; -import java.io.UncheckedIOException; -import java.util.*; -import java.util.function.BiPredicate; -import java.util.stream.CloseableStream; -import java.util.stream.DelegatingStream; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.nio.charset.Charset; import java.nio.charset.CharsetDecoder; import java.nio.charset.CharsetEncoder; +import java.nio.file.attribute.BasicFileAttributeView; +import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.DosFileAttributes; +import java.nio.file.attribute.FileAttribute; +import java.nio.file.attribute.FileAttributeView; +import java.nio.file.attribute.FileOwnerAttributeView; +import java.nio.file.attribute.FileStoreAttributeView; +import java.nio.file.attribute.FileTime; +import java.nio.file.attribute.PosixFileAttributeView; +import java.nio.file.attribute.PosixFileAttributes; +import java.nio.file.attribute.PosixFilePermission; +import java.nio.file.attribute.UserPrincipal; +import java.nio.file.spi.FileSystemProvider; +import java.nio.file.spi.FileTypeDetector; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.EnumSet; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.function.BiPredicate; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; /** * This class consists exclusively of static methods that operate on files, @@ -74,6 +96,21 @@ public final class Files { return path.getFileSystem().provider(); } + /** + * Convert a Closeable to a Runnable by converting checked IOException + * to UncheckedIOException + */ + private static Runnable asUncheckedRunnable(Closeable c) { + return () -> { + try { + c.close(); + } + catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + } + // -- File contents -- /** @@ -3228,29 +3265,7 @@ public final class Files { // -- Stream APIs -- /** - * Implementation of CloseableStream - */ - private static class DelegatingCloseableStream extends DelegatingStream - implements CloseableStream - { - private final Closeable closeable; - - DelegatingCloseableStream(Closeable c, Stream delegate) { - super(delegate); - this.closeable = c; - } - - public void close() { - try { - closeable.close(); - } catch (IOException ex) { - throw new UncheckedIOException(ex); - } - } - } - - /** - * Return a lazily populated {@code CloseableStream}, the elements of + * Return a lazily populated {@code Stream}, the elements of * which are the entries in the directory. The listing is not recursive. * *

        The elements of the stream are {@link Path} objects that are @@ -3264,10 +3279,13 @@ public final class Files { * reflect updates to the directory that occur after returning from this * method. * - *

        When not using the try-with-resources construct, then the stream's - * {@link CloseableStream#close close} method should be invoked after the - * operation is completed so as to free any resources held for the open - * directory. Operating on a closed stream behaves as if the end of stream + *

        The returned stream encapsulates a {@link DirectoryStream}. + * If timely disposal of file system resources is required, the + * {@code try}-with-resources construct should be used to ensure that the + * stream's {@link Stream#close close} method is invoked after the stream + * operations are completed. + * + *

        Operating on a closed stream behaves as if the end of stream * has been reached. Due to read-ahead, one or more elements may be * returned after the stream has been closed. * @@ -3278,7 +3296,7 @@ public final class Files { * * @param dir The path to the directory * - * @return The {@code CloseableStream} describing the content of the + * @return The {@code Stream} describing the content of the * directory * * @throws NotDirectoryException @@ -3294,43 +3312,54 @@ public final class Files { * @see #newDirectoryStream(Path) * @since 1.8 */ - public static CloseableStream list(Path dir) throws IOException { + public static Stream list(Path dir) throws IOException { DirectoryStream ds = Files.newDirectoryStream(dir); - final Iterator delegate = ds.iterator(); + try { + final Iterator delegate = ds.iterator(); - // Re-wrap DirectoryIteratorException to UncheckedIOException - Iterator it = new Iterator() { - public boolean hasNext() { - try { - return delegate.hasNext(); - } catch (DirectoryIteratorException e) { - throw new UncheckedIOException(e.getCause()); + // Re-wrap DirectoryIteratorException to UncheckedIOException + Iterator it = new Iterator() { + @Override + public boolean hasNext() { + try { + return delegate.hasNext(); + } catch (DirectoryIteratorException e) { + throw new UncheckedIOException(e.getCause()); + } } - } - public Path next() { - try { - return delegate.next(); - } catch (DirectoryIteratorException e) { - throw new UncheckedIOException(e.getCause()); + @Override + public Path next() { + try { + return delegate.next(); + } catch (DirectoryIteratorException e) { + throw new UncheckedIOException(e.getCause()); + } } - } - }; + }; - Stream s = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), - false); - return new DelegatingCloseableStream<>(ds, s); + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false) + .onClose(asUncheckedRunnable(ds)); + } catch (Error|RuntimeException e) { + try { + ds.close(); + } catch (IOException ex) { + try { + e.addSuppressed(ex); + } catch (Throwable ignore) {} + } + throw e; + } } /** - * Return a {@code CloseableStream} that is lazily populated with {@code + * Return a {@code Stream} that is lazily populated with {@code * Path} by walking the file tree rooted at a given starting file. The * file tree is traversed depth-first, the elements in the stream * are {@link Path} objects that are obtained as if by {@link * Path#resolve(Path) resolving} the relative path against {@code start}. * *

        The {@code stream} walks the file tree as elements are consumed. - * The {@code CloseableStream} returned is guaranteed to have at least one + * The {@code Stream} returned is guaranteed to have at least one * element, the starting file itself. For each file visited, the stream * attempts to read its {@link BasicFileAttributes}. If the file is a * directory and can be opened successfully, entries in the directory, and @@ -3370,10 +3399,11 @@ public final class Files { *

        When a security manager is installed and it denies access to a file * (or directory), then it is ignored and not included in the stream. * - *

        When not using the try-with-resources construct, then the stream's - * {@link CloseableStream#close close} method should be invoked after the - * operation is completed so as to free any resources held for the open - * directory. Operate the stream after it is closed will throw an + *

        The returned stream encapsulates one or more {@link DirectoryStream}s. + * If timely disposal of file system resources is required, the + * {@code try}-with-resources construct should be used to ensure that the + * stream's {@link Stream#close close} method is invoked after the stream + * operations are completed. Operating on a closed stream will result in an * {@link java.lang.IllegalStateException}. * *

        If an {@link IOException} is thrown when accessing the directory @@ -3388,7 +3418,7 @@ public final class Files { * @param options * options to configure the traversal * - * @return the {@link CloseableStream} of {@link Path} + * @return the {@link Stream} of {@link Path} * * @throws IllegalArgumentException * if the {@code maxDepth} parameter is negative @@ -3401,21 +3431,22 @@ public final class Files { * if an I/O error is thrown when accessing the starting file. * @since 1.8 */ - public static CloseableStream walk(Path start, int maxDepth, - FileVisitOption... options) - throws IOException - { + public static Stream walk(Path start, int maxDepth, + FileVisitOption... options) + throws IOException { FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options); - - Stream s = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), - false). - map(entry -> entry.file()); - return new DelegatingCloseableStream<>(iterator, s); + try { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false) + .onClose(iterator::close) + .map(entry -> entry.file()); + } catch (Error|RuntimeException e) { + iterator.close(); + throw e; + } } /** - * Return a {@code CloseableStream} that is lazily populated with {@code + * Return a {@code Stream} that is lazily populated with {@code * Path} by walking the file tree rooted at a given starting file. The * file tree is traversed depth-first, the elements in the stream * are {@link Path} objects that are obtained as if by {@link @@ -3428,12 +3459,19 @@ public final class Files { * * In other words, it visits all levels of the file tree. * + *

        The returned stream encapsulates one or more {@link DirectoryStream}s. + * If timely disposal of file system resources is required, the + * {@code try}-with-resources construct should be used to ensure that the + * stream's {@link Stream#close close} method is invoked after the stream + * operations are completed. Operating on a closed stream will result in an + * {@link java.lang.IllegalStateException}. + * * @param start * the starting file * @param options * options to configure the traversal * - * @return the {@link CloseableStream} of {@link Path} + * @return the {@link Stream} of {@link Path} * * @throws SecurityException * If the security manager denies access to the starting file. @@ -3446,15 +3484,14 @@ public final class Files { * @see #walk(Path, int, FileVisitOption...) * @since 1.8 */ - public static CloseableStream walk(Path start, - FileVisitOption... options) - throws IOException - { + public static Stream walk(Path start, + FileVisitOption... options) + throws IOException { return walk(start, Integer.MAX_VALUE, options); } /** - * Return a {@code CloseableStream} that is lazily populated with {@code + * Return a {@code Stream} that is lazily populated with {@code * Path} by searching for files in a file tree rooted at a given starting * file. * @@ -3463,12 +3500,19 @@ public final class Files { * {@link BiPredicate} is invoked with its {@link Path} and {@link * BasicFileAttributes}. The {@code Path} object is obtained as if by * {@link Path#resolve(Path) resolving} the relative path against {@code - * start} and is only included in the returned {@link CloseableStream} if + * start} and is only included in the returned {@link Stream} if * the {@code BiPredicate} returns true. Compare to calling {@link * java.util.stream.Stream#filter filter} on the {@code Stream} * returned by {@code walk} method, this method may be more efficient by * avoiding redundant retrieval of the {@code BasicFileAttributes}. * + *

        The returned stream encapsulates one or more {@link DirectoryStream}s. + * If timely disposal of file system resources is required, the + * {@code try}-with-resources construct should be used to ensure that the + * stream's {@link Stream#close close} method is invoked after the stream + * operations are completed. Operating on a closed stream will result in an + * {@link java.lang.IllegalStateException}. + * *

        If an {@link IOException} is thrown when accessing the directory * after returned from this method, it is wrapped in an {@link * UncheckedIOException} which will be thrown from the method that caused @@ -3484,7 +3528,7 @@ public final class Files { * @param options * options to configure the traversal * - * @return the {@link CloseableStream} of {@link Path} + * @return the {@link Stream} of {@link Path} * * @throws IllegalArgumentException * if the {@code maxDepth} parameter is negative @@ -3499,24 +3543,25 @@ public final class Files { * @see #walk(Path, int, FileVisitOption...) * @since 1.8 */ - public static CloseableStream find(Path start, - int maxDepth, - BiPredicate matcher, - FileVisitOption... options) - throws IOException - { + public static Stream find(Path start, + int maxDepth, + BiPredicate matcher, + FileVisitOption... options) + throws IOException { FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options); - - Stream s = StreamSupport.stream( - Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), - false). - filter(entry -> matcher.test(entry.file(), entry.attributes())). - map(entry -> entry.file()); - return new DelegatingCloseableStream<>(iterator, s); + try { + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false) + .onClose(iterator::close) + .filter(entry -> matcher.test(entry.file(), entry.attributes())) + .map(entry -> entry.file()); + } catch (Error|RuntimeException e) { + iterator.close(); + throw e; + } } /** - * Read all lines from a file as a {@code CloseableStream}. Unlike {@link + * Read all lines from a file as a {@code Stream}. Unlike {@link * #readAllLines(Path, Charset) readAllLines}, this method does not read * all lines into a {@code List}, but instead populates lazily as the stream * is consumed. @@ -3528,22 +3573,24 @@ public final class Files { *

        After this method returns, then any subsequent I/O exception that * occurs while reading from the file or when a malformed or unmappable byte * sequence is read, is wrapped in an {@link UncheckedIOException} that will - * be thrown form the + * be thrown from the * {@link java.util.stream.Stream} method that caused the read to take * place. In case an {@code IOException} is thrown when closing the file, * it is also wrapped as an {@code UncheckedIOException}. * - *

        When not using the try-with-resources construct, then stream's - * {@link CloseableStream#close close} method should be invoked after - * operation is completed so as to free any resources held for the open - * file. + *

        The returned stream encapsulates a {@link Reader}. If timely + * disposal of file system resources is required, the try-with-resources + * construct should be used to ensure that the stream's + * {@link Stream#close close} method is invoked after the stream operations + * are completed. + * * * @param path * the path to the file * @param cs * the charset to use for decoding * - * @return the lines from the file as a {@code CloseableStream} + * @return the lines from the file as a {@code Stream} * * @throws IOException * if an I/O error occurs opening the file @@ -3557,10 +3604,19 @@ public final class Files { * @see java.io.BufferedReader#lines() * @since 1.8 */ - public static CloseableStream lines(Path path, Charset cs) - throws IOException - { + public static Stream lines(Path path, Charset cs) throws IOException { BufferedReader br = Files.newBufferedReader(path, cs); - return new DelegatingCloseableStream<>(br, br.lines()); + try { + return br.lines().onClose(asUncheckedRunnable(br)); + } catch (Error|RuntimeException e) { + try { + br.close(); + } catch (IOException ex) { + try { + e.addSuppressed(ex); + } catch (Throwable ignore) {} + } + throw e; + } } } diff --git a/jdk/src/share/classes/java/rmi/activation/Activatable.java b/jdk/src/share/classes/java/rmi/activation/Activatable.java index 7b43c27bd22..6ab4ba22481 100644 --- a/jdk/src/share/classes/java/rmi/activation/Activatable.java +++ b/jdk/src/share/classes/java/rmi/activation/Activatable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -93,6 +93,8 @@ public abstract class Activatable extends RemoteServer { * @exception RemoteException if either of the following fails: * a) registering the object with the activation system or b) exporting * the object to the RMI runtime. + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation. * @since 1.2 **/ protected Activatable(String location, @@ -143,6 +145,8 @@ public abstract class Activatable extends RemoteServer { * @exception RemoteException if either of the following fails: * a) registering the object with the activation system or b) exporting * the object to the RMI runtime. + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation. * @since 1.2 **/ protected Activatable(String location, @@ -175,6 +179,8 @@ public abstract class Activatable extends RemoteServer { * @param port the port number on which the object is exported * @exception RemoteException if exporting the object to the RMI * runtime fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ protected Activatable(ActivationID id, int port) @@ -206,6 +212,8 @@ public abstract class Activatable extends RemoteServer { * @param ssf the server-side socket factory for receiving remote calls * @exception RemoteException if exporting the object to the RMI * runtime fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ protected Activatable(ActivationID id, int port, @@ -239,6 +247,8 @@ public abstract class Activatable extends RemoteServer { * is not registered with the activation system * @exception ActivationException if activation system is not running * @exception RemoteException if remote call fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public static Remote register(ActivationDesc desc) @@ -273,6 +283,8 @@ public abstract class Activatable extends RemoteServer { * already be inactive) * @exception ActivationException if group is not active * @exception RemoteException if call informing monitor fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public static boolean inactive(ActivationID id) @@ -290,6 +302,8 @@ public abstract class Activatable extends RemoteServer { * @exception UnknownObjectException if object (id) is unknown * @exception ActivationException if activation system is not running * @exception RemoteException if remote call to activation system fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public static void unregister(ActivationID id) @@ -334,6 +348,8 @@ public abstract class Activatable extends RemoteServer { * the wrong group * @exception ActivationException if activation group is not active * @exception RemoteException if object registration or export fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 **/ public static ActivationID exportObject(Remote obj, @@ -407,6 +423,8 @@ public abstract class Activatable extends RemoteServer { * descriptor with the activation system * @exception ActivationException if activation group is not active * @exception RemoteException if object registration or export fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 **/ public static ActivationID exportObject(Remote obj, @@ -473,6 +491,8 @@ public abstract class Activatable extends RemoteServer { * @param port the port on which the object is exported (an anonymous * port is used if port=0) * @exception RemoteException if object export fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public static Remote exportObject(Remote obj, @@ -503,6 +523,8 @@ public abstract class Activatable extends RemoteServer { * remote object * @param ssf the server-side socket factory for receiving remote calls * @exception RemoteException if object export fails + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public static Remote exportObject(Remote obj, @@ -531,6 +553,8 @@ public abstract class Activatable extends RemoteServer { * @return true if operation is successful, false otherwise * @exception NoSuchObjectException if the remote object is not * currently exported + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public static boolean unexportObject(Remote obj, boolean force) diff --git a/jdk/src/share/classes/java/rmi/activation/ActivationDesc.java b/jdk/src/share/classes/java/rmi/activation/ActivationDesc.java index d206337f70f..e9170294d05 100644 --- a/jdk/src/share/classes/java/rmi/activation/ActivationDesc.java +++ b/jdk/src/share/classes/java/rmi/activation/ActivationDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,8 @@ public final class ActivationDesc implements Serializable { * @param data the object's initialization (activation) data contained * in marshalled form. * @exception ActivationException if the current group is nonexistent + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public ActivationDesc(String className, @@ -142,6 +144,8 @@ public final class ActivationDesc implements Serializable { * true does not force an initial immediate activation of * a newly registered object; initial activation is lazy. * @exception ActivationException if the current group is nonexistent + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public ActivationDesc(String className, @@ -176,6 +180,8 @@ public final class ActivationDesc implements Serializable { * @param data the object's initialization (activation) data contained * in marshalled form. * @exception IllegalArgumentException if groupID is null + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public ActivationDesc(ActivationGroupID groupID, @@ -208,6 +214,8 @@ public final class ActivationDesc implements Serializable { * true does not force an initial immediate activation of * a newly registered object; initial activation is lazy. * @exception IllegalArgumentException if groupID is null + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public ActivationDesc(ActivationGroupID groupID, diff --git a/jdk/src/share/classes/java/rmi/activation/ActivationGroup.java b/jdk/src/share/classes/java/rmi/activation/ActivationGroup.java index 28d41c25b3f..49dffd18e0e 100644 --- a/jdk/src/share/classes/java/rmi/activation/ActivationGroup.java +++ b/jdk/src/share/classes/java/rmi/activation/ActivationGroup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -133,6 +133,8 @@ public abstract class ActivationGroup * * @param groupID the group's identifier * @throws RemoteException if this group could not be exported + * @throws UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ protected ActivationGroup(ActivationGroupID groupID) @@ -267,6 +269,8 @@ public abstract class ActivationGroup * (Note: The default implementation of the security manager * checkSetFactory * method requires the RuntimePermission "setFactory") + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @see SecurityManager#checkSetFactory * @since 1.2 */ @@ -345,6 +349,8 @@ public abstract class ActivationGroup /** * Returns the current activation group's identifier. Returns null * if no group is currently active for this VM. + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @return the activation group's identifier * @since 1.2 */ @@ -394,6 +400,8 @@ public abstract class ActivationGroup * (Note: The default implementation of the security manager * checkSetFactory * method requires the RuntimePermission "setFactory") + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @see #getSystem * @see SecurityManager#checkSetFactory * @since 1.2 @@ -428,6 +436,8 @@ public abstract class ActivationGroup * @exception ActivationException if activation system cannot be * obtained or is not bound * (means that it is not running) + * @exception UnsupportedOperationException if and only if activation is + * not supported by this implementation * @see #setSystem * @since 1.2 */ diff --git a/jdk/src/share/classes/java/rmi/activation/ActivationGroupID.java b/jdk/src/share/classes/java/rmi/activation/ActivationGroupID.java index 85c1f0f5906..bbd816fd73e 100644 --- a/jdk/src/share/classes/java/rmi/activation/ActivationGroupID.java +++ b/jdk/src/share/classes/java/rmi/activation/ActivationGroupID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -63,6 +63,8 @@ public class ActivationGroupID implements java.io.Serializable { * Constructs a unique group id. * * @param system the group's activation system + * @throws UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public ActivationGroupID(ActivationSystem system) { diff --git a/jdk/src/share/classes/java/rmi/activation/ActivationID.java b/jdk/src/share/classes/java/rmi/activation/ActivationID.java index 1a5b33ff43c..02511b848b8 100644 --- a/jdk/src/share/classes/java/rmi/activation/ActivationID.java +++ b/jdk/src/share/classes/java/rmi/activation/ActivationID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -90,6 +90,8 @@ public class ActivationID implements Serializable { * * @param activator reference to the activator responsible for * activating the object + * @throws UnsupportedOperationException if and only if activation is + * not supported by this implementation * @since 1.2 */ public ActivationID(Activator activator) { diff --git a/jdk/src/share/classes/java/rmi/activation/package.html b/jdk/src/share/classes/java/rmi/activation/package.html index ceb26788d1f..ed4bb79bffe 100644 --- a/jdk/src/share/classes/java/rmi/activation/package.html +++ b/jdk/src/share/classes/java/rmi/activation/package.html @@ -1,5 +1,5 @@ + + + + CursorOverlappedPanelsTest, bug ID 8007155 + + + +

        See the dialog box (usually in upper left corner) for instructions

        + + diff --git a/jdk/test/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java b/jdk/test/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java new file mode 100644 index 00000000000..40f1ae6c499 --- /dev/null +++ b/jdk/test/java/awt/Cursor/CursorOverlappedPanelsTest/CursorOverlappedPanelsTest.java @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +//import java.applet.Applet; +import javax.swing.BorderFactory; +import javax.swing.JApplet; +import javax.swing.JFrame; +import javax.swing.JLayeredPane; +import javax.swing.JPanel; + +/** + * @test + * @bug 8007155 + * @summary [macosx] Disabled panel takes mouse input in JLayeredPane + * @author Alexander Scherbatiy: area=java.awt.Cursor + * @run applet/manual=yesno CursorOverlappedPanelsTest.html + */ +public class CursorOverlappedPanelsTest extends JApplet { + //Declare things used in the test, like buttons and labels here + + public void init() { + //Create instructions for the user here, as well as set up + // the environment -- set the layout manager, add buttons, + // etc. + this.setLayout(new BorderLayout()); + + String[] instructions = { + "Verify that the Crosshair cursor from enabled panel" + + " is displayed on the panels intersection", + "1) Move the mosue cursor on the Enabled and Disabled panels" + + " intersection", + "2) Check that the Crosshair cursor is displayed ", + "If so, press PASS, else press FAIL." + }; + Sysout.createDialogWithInstructions(instructions); + + }//End init() + + public void start() { + //Get things going. Request focus, set size, et cetera + setSize(200, 200); + setVisible(true); + validate(); + try { + EventQueue.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + } catch (Exception e) { + throw new RuntimeException(e); + } + }// start() + + //The rest of this class is the actions which perform the test... + //Use Sysout.println to communicate with the user NOT System.out!! + //Sysout.println ("Something Happened!"); + private static JPanel createPanel(Point location, boolean enabled) { + final JPanel panel = new JPanel(); + panel.setOpaque(false); + panel.setEnabled(enabled); + panel.setSize(new Dimension(200, 200)); + panel.setLocation(location); + panel.setBorder(BorderFactory.createTitledBorder( + enabled ? "Enabled" : "Disabled")); + panel.setCursor(Cursor.getPredefinedCursor( + enabled ? Cursor.CROSSHAIR_CURSOR : Cursor.DEFAULT_CURSOR)); + System.out.println("cursor: " + Cursor.getPredefinedCursor(enabled ? Cursor.CROSSHAIR_CURSOR : Cursor.DEFAULT_CURSOR)); + return panel; + } + + private static void createAndShowGUI() { + final JFrame frame = new JFrame("Test"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + JLayeredPane layeredPane = new JLayeredPane(); + layeredPane.setPreferredSize(new Dimension(400, 400)); + JPanel enabledPanel = createPanel(new Point(10, 10), true); + JPanel disabledPanel = createPanel(new Point(100, 100), false); + layeredPane.add(disabledPanel, JLayeredPane.PALETTE_LAYER); + layeredPane.add(enabledPanel, JLayeredPane.DEFAULT_LAYER); + + frame.getContentPane().add(layeredPane); + frame.pack(); + frame.setVisible(true); + } +}// class BlockedWindowTest + +/* Place other classes related to the test after this line */ +/** + * ************************************************** + * Standard Test Machinery DO NOT modify anything below -- it's a standard chunk + * of code whose purpose is to make user interaction uniform, and thereby make + * it simpler to read and understand someone else's test. + * ************************************************** + */ +/** + * This is part of the standard test machinery. It creates a dialog (with the + * instructions), and is the interface for sending text messages to the user. To + * print the instructions, send an array of strings to Sysout.createDialog + * WithInstructions method. Put one line of instructions per array entry. To + * display a message for the tester to see, simply call Sysout.println with the + * string to be displayed. This mimics System.out.println but works within the + * test harness as well as standalone. + */ +class Sysout { + + private static TestDialog dialog; + + public static void createDialogWithInstructions(String[] instructions) { + dialog = new TestDialog(new Frame(), "Instructions"); + dialog.printInstructions(instructions); + dialog.setVisible(true); + println("Any messages for the tester will display here."); + } + + public static void createDialog() { + dialog = new TestDialog(new Frame(), "Instructions"); + String[] defInstr = {"Instructions will appear here. ", ""}; + dialog.printInstructions(defInstr); + dialog.setVisible(true); + println("Any messages for the tester will display here."); + } + + public static void printInstructions(String[] instructions) { + dialog.printInstructions(instructions); + } + + public static void println(String messageIn) { + dialog.displayMessage(messageIn); + } +}// Sysout class + +/** + * This is part of the standard test machinery. It provides a place for the test + * instructions to be displayed, and a place for interactive messages to the + * user to be displayed. To have the test instructions displayed, see Sysout. To + * have a message to the user be displayed, see Sysout. Do not call anything in + * this dialog directly. + */ +class TestDialog extends Dialog { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog(Frame frame, String name) { + super(frame, name); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); + add("North", instructionsText); + + messageText = new TextArea("", 5, maxStringLength, scrollBoth); + add("Center", messageText); + + pack(); + + setVisible(true); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions(String[] instructions) { + //Clear out any current instructions + instructionsText.setText(""); + + //Go down array of instruction strings + + String printStr, remainingStr; + for (int i = 0; i < instructions.length; i++) { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i]; + while (remainingStr.length() > 0) { + //if longer than max then chop off first max chars to print + if (remainingStr.length() >= maxStringLength) { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf(' ', maxStringLength - 1); + + if (posOfSpace <= 0) { + posOfSpace = maxStringLength - 1; + } + + printStr = remainingStr.substring(0, posOfSpace + 1); + remainingStr = remainingStr.substring(posOfSpace + 1); + } //else just print + else { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append(printStr + "\n"); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage(String messageIn) { + messageText.append(messageIn + "\n"); + System.out.println(messageIn); + } +}// TestDialog class diff --git a/jdk/test/java/awt/Focus/KeyEventForBadFocusOwnerTest/KeyEventForBadFocusOwnerTest.java b/jdk/test/java/awt/Focus/KeyEventForBadFocusOwnerTest/KeyEventForBadFocusOwnerTest.java new file mode 100644 index 00000000000..d0280374879 --- /dev/null +++ b/jdk/test/java/awt/Focus/KeyEventForBadFocusOwnerTest/KeyEventForBadFocusOwnerTest.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + @test + @bug 4476629 + @library ../../../../javax/swing/regtesthelpers + @build Util + @summary KeyEvents dispatched to old focus owner that is no longer showing + @author son@sparc.spb.su: area=awt.focus + @run main KeyEventForBadFocusOwnerTest +*/ + +/** + * KeyEventForBadFocusOwnerTest.java + * + * summary: KeyEvents dispatched to old focus owner that is no longer showing + */ + + +import java.awt.Robot; +import java.awt.Toolkit; + +import java.awt.event.*; + +import javax.swing.*; +import javax.swing.event.*; +import sun.awt.SunToolkit; + +public class KeyEventForBadFocusOwnerTest { + final static String ITEM_ONE_TEXT = "one"; + final static String ITEM_TWO_TEXT = "two"; + + volatile static boolean itemOneSelected = false; + volatile static boolean itemTwoSelected = false; + volatile static boolean unexpectedItemSelected = false; + + static Robot robot; + static SunToolkit toolkit; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + JFrame frame = new JFrame("TEST"); + JMenuBar mb = new JMenuBar(); + JMenu one = new JMenu(ITEM_ONE_TEXT); + JMenu two = new JMenu(ITEM_TWO_TEXT); + + mb.add(one); + mb.add(two); + + ActionListener al = new ActionListener() { + public void actionPerformed(ActionEvent ae) { + String itemText = ((JMenuItem)ae.getSource()).getText(); + System.out.println("--> " + itemText); + unexpectedItemSelected = true; + } + }; + one.setMnemonic(KeyEvent.VK_O); + JMenuItem item = new JMenuItem("one 1"); + item.setMnemonic(KeyEvent.VK_O); + item.addActionListener(al); + one.add(item); + one.add("two"); + one.add("three"); + + two.setMnemonic(KeyEvent.VK_T); + item = new JMenuItem("two 2"); + item.setMnemonic(KeyEvent.VK_T); + item.addActionListener(al); + two.add(item); + two.add("three"); + two.add("four"); + + PopupMenuListener popupMenuListener = new PopupMenuListener() { + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + System.out.print(e); + System.out.print(e.getSource()); + String itemText = ((JPopupMenu)e.getSource()).getName(); + System.out.println("Menu " + itemText + "is opened."); + switch(itemText) { + case ITEM_ONE_TEXT: + itemOneSelected = true; + break; + case ITEM_TWO_TEXT: + itemTwoSelected = true; + break; + } + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} + public void popupMenuCanceled(PopupMenuEvent e) {} + }; + one.getPopupMenu().setName(ITEM_ONE_TEXT); + two.getPopupMenu().setName(ITEM_TWO_TEXT); + one.getPopupMenu().addPopupMenuListener(popupMenuListener); + two.getPopupMenu().addPopupMenuListener(popupMenuListener); + frame.setJMenuBar(mb); + frame.setSize(100,100); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } + }); + + toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + + robot = new Robot(); + robot.setAutoDelay(100); + + Util.hitMnemonics(robot, KeyEvent.VK_O); + Util.hitMnemonics(robot, KeyEvent.VK_T); + + toolkit.realSync(); + Thread.sleep(1000); // workaround for MacOS + + if (unexpectedItemSelected) { + throw new Exception("Test failed. KeyEvent dispatched to old focus owner. "); + } + if (!itemOneSelected || !itemTwoSelected) { + throw new Exception("Not all expected events were received"); + } + } +} diff --git a/jdk/test/java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java b/jdk/test/java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java index 3c2a636a094..0d5ada5b74b 100644 --- a/jdk/test/java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java +++ b/jdk/test/java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java @@ -42,6 +42,7 @@ public class TranslucentWindow { GraphicsDevice gd = ge.getDefaultScreenDevice(); Frame f = new Frame("Test frame"); + f.setUndecorated(true); f.setBounds(100, 100, 320, 240); // First, check it can be made fullscreen window without any effects applied diff --git a/jdk/test/java/awt/MenuBar/MenuBarSetFont/MenuBarSetFont.java b/jdk/test/java/awt/MenuBar/MenuBarSetFont/MenuBarSetFont.java index 559d7de4d97..9505c12a374 100644 --- a/jdk/test/java/awt/MenuBar/MenuBarSetFont/MenuBarSetFont.java +++ b/jdk/test/java/awt/MenuBar/MenuBarSetFont/MenuBarSetFont.java @@ -65,6 +65,12 @@ public final class MenuBarSetFont { } public static void main(final String[] args) throws Exception { + + if (sun.awt.OSInfo.getOSType() == sun.awt.OSInfo.OSType.MACOSX) { + System.err.println("This test is not for OS X. Menu.setFont() is not supported on OS X."); + return; + } + //Components initialization. frame.setMenuBar(mb); mb.setFont(new Font("Helvetica", Font.ITALIC, 5)); diff --git a/jdk/test/java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java b/jdk/test/java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java new file mode 100644 index 00000000000..e78145e4e12 --- /dev/null +++ b/jdk/test/java/awt/Modal/ModalDialogOrderingTest/ModalDialogOrderingTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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.Dialog; +import java.awt.Frame; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import sun.awt.SunToolkit; +/* + * @test + * @bug 8008728 + * @summary [macosx] Swing. JDialog. Modal dialog goes to background + * @author Alexandr Scherbatiy + * @run main ModalDialogOrderingTest + */ + +public class ModalDialogOrderingTest { + + private static final Color DIALOG_COLOR = Color.GREEN; + private static final Color FRAME_COLOR = Color.BLUE; + + public static void main(String[] args) { + + final Frame frame = new Frame("Test"); + frame.setSize(100, 100); + frame.setBackground(FRAME_COLOR); + frame.setVisible(true); + + final Dialog modalDialog = new Dialog((Frame) null, true); + modalDialog.setTitle("Modal Dialog"); + modalDialog.setSize(50, 50); + modalDialog.setBackground(DIALOG_COLOR); + modalDialog.setModal(true); + + new Thread(new Runnable() { + + @Override + public void run() { + runTest(modalDialog, frame); + } + }).start(); + + modalDialog.setVisible(true); + } + + private static void runTest(Dialog dialog, Frame frame) { + try { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(15); + robot.mouseMove(300, 300); + + while (!dialog.isVisible()) { + toolkit.realSync(); + } + + Rectangle dialogBounds = dialog.getBounds(); + Rectangle frameBounds = frame.getBounds(); + + double x0 = dialogBounds.getX(); + double y0 = dialogBounds.getY(); + double x1 = dialogBounds.getX() + dialogBounds.getWidth(); + double y1 = dialogBounds.getY() + dialogBounds.getHeight(); + double x2 = frameBounds.getX() + frameBounds.getWidth(); + double y2 = frameBounds.getY() + frameBounds.getHeight(); + + int clickX = (int) ((x2 + x1) / 2); + int clickY = (int) ((y2 + y1) / 2); + + robot.mouseMove(clickX, clickY); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + + int colorX = (int) ((x0 + x1) / 2); + int colorY = (int) ((y0 + y1) / 2); + + Color color = robot.getPixelColor(colorX, colorY); + + dialog.setVisible(false); + frame.setVisible(false); + + if (!DIALOG_COLOR.equals(color)) { + throw new RuntimeException("The frame is on top" + + " of the modal dialog!"); + } + } catch (Exception ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/jdk/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java b/jdk/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java new file mode 100644 index 00000000000..3cb1b735837 --- /dev/null +++ b/jdk/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithOverlay.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.util.concurrent.atomic.AtomicReference; + +/** + * @test + * @bug 8012026 + * @summary Component.getMousePosition() does not work in an applet on MacOS + * @author Petr Pchelko + * @library ../../regtesthelpers + * @build Util + * @compile GetMousePositionWithOverlay.java + * @run main/othervm GetMousePositionWithOverlay + */ + +public class GetMousePositionWithOverlay { + + static Frame backFrame; + static Frame frontFrame; + + public static void main(String[] args) throws Throwable { + try { + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + Util.waitForIdle(null); + + Robot r = new Robot(); + Util.pointOnComp(frontFrame, r); + Util.waitForIdle(null); + + Point pos = getMousePosition(backFrame); + if (pos != null) { + throw new RuntimeException("Test failed. Mouse position should be null but was" + pos); + } + + pos = getMousePosition(frontFrame); + if (pos == null) { + throw new RuntimeException("Test failed. Mouse position should not be null"); + } + + r.mouseMove(189, 189); + Util.waitForIdle(null); + + pos = getMousePosition(backFrame); + if (pos == null) { + throw new RuntimeException("Test failed. Mouse position should not be null"); + } + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + backFrame.dispose(); + frontFrame.dispose(); + } + }); + } + } + + private static Point getMousePosition(final Component component) throws Exception { + final AtomicReference pos = new AtomicReference(); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + pos.set(component.getMousePosition()); + } + }); + return pos.get(); + } + + private static void constructTestUI() { + backFrame = new Frame(); + backFrame.setBounds(100, 100, 100, 100); + backFrame.setVisible(true); + + frontFrame = new Frame(); + frontFrame.setBounds(120, 120, 60, 60); + frontFrame.setVisible(true); + } +} diff --git a/jdk/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java b/jdk/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java new file mode 100644 index 00000000000..d04b50087ad --- /dev/null +++ b/jdk/test/java/awt/Mouse/GetMousePositionTest/GetMousePositionWithPopup.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import test.java.awt.regtesthelpers.Util; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; + +/** + * @test + * @bug 8012026 + * @summary Component.getMousePosition() does not work in an applet on MacOS + * @author Petr Pchelko + * @library ../../regtesthelpers + * @build Util + * @compile GetMousePositionWithPopup.java + * @run main/othervm GetMousePositionWithPopup + */ + +public class GetMousePositionWithPopup { + + private static Frame frame1; + private static Frame frame2; + + public static void main(String[] args) throws Exception { + try { + Robot r = Util.createRobot(); + r.mouseMove(0, 0); + Util.waitForIdle(null); + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + constructTestUI(); + } + }); + + Util.waitForIdle(null); + r.mouseMove(149, 149); + Util.waitForIdle(null); + r.mouseMove(150, 150); + Util.waitForIdle(null); + + } finally { + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + frame1.dispose(); + frame2.dispose(); + } + }); + } + } + + private static void constructTestUI() { + frame1 = new Frame(); + frame1.setBounds(100, 100, 100, 100); + frame1.addMouseMotionListener(new MouseMotionAdapter() { + + private boolean shown = false; + + @Override + public void mouseMoved(MouseEvent e) { + if (shown) { + return; + } + + shown = true; + + frame2 = new Frame(); + frame2.setBounds(120, 120, 120, 120); + frame2.setVisible(true); + + Point positionInFrame2 = frame2.getMousePosition(); + if (positionInFrame2.x != 30 || positionInFrame2.y != 30) { + throw new RuntimeException("Wrong position reported. Should be [30, 30] but was [" + + positionInFrame2.x + ", " + positionInFrame2.y + "]"); + } + + Point positionInFrame1 = frame1.getMousePosition(); + if (positionInFrame1 != null) { + throw new RuntimeException("Wrong position reported. Should be null"); + } + + } + }); + frame1.setVisible(true); + } +} diff --git a/jdk/test/java/awt/Toolkit/DynamicLayout/bug7172833.java b/jdk/test/java/awt/Toolkit/DynamicLayout/bug7172833.java new file mode 100644 index 00000000000..3780b7deacc --- /dev/null +++ b/jdk/test/java/awt/Toolkit/DynamicLayout/bug7172833.java @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +import java.awt.*; +import java.awt.datatransfer.Clipboard; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.InvalidDnDOperationException; +import java.awt.dnd.peer.DragSourceContextPeer; +import java.awt.font.TextAttribute; +import java.awt.im.InputMethodHighlight; +import java.awt.image.ColorModel; +import java.awt.image.ImageObserver; +import java.awt.image.ImageProducer; +import java.awt.peer.*; +import java.net.URL; +import java.util.Map; +import java.util.Properties; + + +/** + * @test + * @bug 7172833 + * @summary java.awt.Toolkit methods is/setDynamicLayout() should be consistent. + * @author Sergey Bylokhov + */ +public final class bug7172833 { + + public static void main(final String[] args) throws Exception { + final StubbedToolkit t = new StubbedToolkit(); + + t.setDynamicLayout(true); + if(!t.isDynamicLayoutSet()){ + throw new RuntimeException("'true' expected but 'false' returned"); + } + + t.setDynamicLayout(false); + if(t.isDynamicLayoutSet()){ + throw new RuntimeException("'false' expected but 'true' returned"); + } + } + + static final class StubbedToolkit extends Toolkit { + + @Override + protected boolean isDynamicLayoutSet() throws HeadlessException { + return super.isDynamicLayoutSet(); + } + + @Override + protected DesktopPeer createDesktopPeer(final Desktop target) + throws HeadlessException { + return null; + } + + @Override + protected ButtonPeer createButton(final Button target) + throws HeadlessException { + return null; + } + + @Override + protected TextFieldPeer createTextField(final TextField target) + throws HeadlessException { + return null; + } + + @Override + protected LabelPeer createLabel(final Label target) throws HeadlessException { + return null; + } + + @Override + protected ListPeer createList(final List target) throws HeadlessException { + return null; + } + + @Override + protected CheckboxPeer createCheckbox(final Checkbox target) + throws HeadlessException { + return null; + } + + @Override + protected ScrollbarPeer createScrollbar(final Scrollbar target) + throws HeadlessException { + return null; + } + + @Override + protected ScrollPanePeer createScrollPane(final ScrollPane target) + throws HeadlessException { + return null; + } + + @Override + protected TextAreaPeer createTextArea(final TextArea target) + throws HeadlessException { + return null; + } + + @Override + protected ChoicePeer createChoice(final Choice target) + throws HeadlessException { + return null; + } + + @Override + protected FramePeer createFrame(final Frame target) throws HeadlessException { + return null; + } + + @Override + protected CanvasPeer createCanvas(final Canvas target) { + return null; + } + + @Override + protected PanelPeer createPanel(final Panel target) { + return null; + } + + @Override + protected WindowPeer createWindow(final Window target) + throws HeadlessException { + return null; + } + + @Override + protected DialogPeer createDialog(final Dialog target) + throws HeadlessException { + return null; + } + + @Override + protected MenuBarPeer createMenuBar(final MenuBar target) + throws HeadlessException { + return null; + } + + @Override + protected MenuPeer createMenu(final Menu target) throws HeadlessException { + return null; + } + + @Override + protected PopupMenuPeer createPopupMenu(final PopupMenu target) + throws HeadlessException { + return null; + } + + @Override + protected MenuItemPeer createMenuItem(final MenuItem target) + throws HeadlessException { + return null; + } + + @Override + protected FileDialogPeer createFileDialog(final FileDialog target) + throws HeadlessException { + return null; + } + + @Override + protected CheckboxMenuItemPeer createCheckboxMenuItem( + final CheckboxMenuItem target) throws HeadlessException { + return null; + } + + @Override + protected FontPeer getFontPeer(final String name, final int style) { + return null; + } + + @Override + public Dimension getScreenSize() throws HeadlessException { + return null; + } + + @Override + public int getScreenResolution() throws HeadlessException { + return 0; + } + + @Override + public ColorModel getColorModel() throws HeadlessException { + return null; + } + + @Override + public String[] getFontList() { + return new String[0]; + } + + @Override + public FontMetrics getFontMetrics(final Font font) { + return null; + } + + @Override + public void sync() { + + } + + @Override + public Image getImage(final String filename) { + return null; + } + + @Override + public Image getImage(final URL url) { + return null; + } + + @Override + public Image createImage(final String filename) { + return null; + } + + @Override + public Image createImage(final URL url) { + return null; + } + + @Override + public boolean prepareImage( + final Image image, final int width, final int height, + final ImageObserver observer) { + return false; + } + + @Override + public int checkImage(final Image image, final int width, final int height, + final ImageObserver observer) { + return 0; + } + + @Override + public Image createImage(final ImageProducer producer) { + return null; + } + + @Override + public Image createImage(final byte[] imagedata, final int imageoffset, + final int imagelength) { + return null; + } + + @Override + public PrintJob getPrintJob(final Frame frame, final String jobtitle, + final Properties props) { + return null; + } + + @Override + public void beep() { + + } + + @Override + public Clipboard getSystemClipboard() throws HeadlessException { + return null; + } + + @Override + protected EventQueue getSystemEventQueueImpl() { + return null; + } + + @Override + public DragSourceContextPeer createDragSourceContextPeer( + final DragGestureEvent dge) throws InvalidDnDOperationException { + return null; + } + + @Override + public boolean isModalityTypeSupported( + final Dialog.ModalityType modalityType) { + return false; + } + + @Override + public boolean isModalExclusionTypeSupported( + final Dialog.ModalExclusionType modalExclusionType) { + return false; + } + + @Override + public Map mapInputMethodHighlight( + final InputMethodHighlight highlight) throws HeadlessException { + return null; + } + } +} diff --git a/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/bug7129133.java b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/bug7129133.java new file mode 100644 index 00000000000..4578798066e --- /dev/null +++ b/jdk/test/java/awt/Toolkit/ToolkitPropertyTest/bug7129133.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7129133 + * @summary [macosx] Accelerators are displayed as Meta instead of the Command symbol + * @author leonid.romanov@oracle.com + * @run main bug7129133 + */ + +import java.awt.*; + +public class bug7129133 { + public static void main(String[] args) throws Exception { + if (sun.awt.OSInfo.getOSType() != sun.awt.OSInfo.OSType.MACOSX) { + System.out.println("This test is for MacOS only. Automatically passed on other platforms."); + return; + } + + Toolkit.getDefaultToolkit(); + + String cmdSymbol = "\u2318"; + String val = Toolkit.getProperty("AWT.meta", "Meta"); + + if (!val.equals(cmdSymbol)) { + throw new Exception("Wrong property value for AWT.meta. Expected: " + cmdSymbol + ", actual: " + val); + } + } +} diff --git a/jdk/test/java/awt/TrayIcon/ShowAfterDisposeTest/ShowAfterDisposeTest.html b/jdk/test/java/awt/TrayIcon/ShowAfterDisposeTest/ShowAfterDisposeTest.html new file mode 100644 index 00000000000..6ef452485ec --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/ShowAfterDisposeTest/ShowAfterDisposeTest.html @@ -0,0 +1,43 @@ + + + + + + ShowAfterDisposeTest + + + +

        ShowAfterDisposeTest
        Bug ID: 6384984

        + +

        See the dialog box (usually in upper left corner) for instructions

        + + + + diff --git a/jdk/test/java/awt/TrayIcon/ShowAfterDisposeTest/ShowAfterDisposeTest.java b/jdk/test/java/awt/TrayIcon/ShowAfterDisposeTest/ShowAfterDisposeTest.java new file mode 100644 index 00000000000..f107492f9d9 --- /dev/null +++ b/jdk/test/java/awt/TrayIcon/ShowAfterDisposeTest/ShowAfterDisposeTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + test + @bug 6384984 8004032 + @summary TrayIcon try to dispay a tooltip when is not visible + @author Dmitry.Cherepanov@sun.com area=awt.tray + @run applet/manual=yesno ShowAfterDisposeTest.html +*/ + +import java.applet.*; + +import java.awt.*; +import java.awt.event.*; +import java.awt.image.*; + +public class ShowAfterDisposeTest extends Applet +{ + boolean traySupported; + + public void init() + { + this.setLayout (new BorderLayout ()); + + String[] instructions; + traySupported = SystemTray.isSupported(); + if (traySupported) + { + String[] s = + { + "1) When the test starts an icon is added to the SystemTray area.", + "2a) If you use Apple OS X,", + " right click on this icon (it's important to click before the tooltip is shown).", + " The icon should disappear.", + "2b) If you use other os (Windows, Linux, Solaris),", + " double click on this icon (it's important to click before the tooltip is shown).", + " The icon should disappear.", + "3) If the bug is reproducible then the test will fail without assistance.", + "4) Just press the 'pass' button." + }; + instructions = s; + } + else + { + String[] s = + { + "The test cannot be run because SystemTray is not supported.", + "Simply press PASS button." + }; + instructions = s; + } + Sysout.createDialogWithInstructions(instructions); + } + + public void start () + { + setSize (200,200); + setVisible(true); + validate(); + + if (!traySupported) + { + return; + } + + BufferedImage img = new BufferedImage(32, 32, BufferedImage.TYPE_INT_ARGB); + Graphics g = img.createGraphics(); + g.setColor(Color.WHITE); + g.fillRect(0, 0, 32, 32); + g.setColor(Color.RED); + g.fillRect(6, 6, 20, 20); + g.dispose(); + + final SystemTray tray = SystemTray.getSystemTray(); + final TrayIcon icon = new TrayIcon(img); + icon.setImageAutoSize(true); + icon.addActionListener(new ActionListener() + { + public void actionPerformed(ActionEvent ev) + { + tray.remove(icon); + } + } + ); + + try { + tray.add(icon); + } catch (AWTException e) { + Sysout.println(e.toString()); + Sysout.println("!!! The test coudn't be performed !!!"); + return; + } + icon.setToolTip("tooltip"); + } +} + +/**************************************************** + Standard Test Machinery + DO NOT modify anything below -- it's a standard + chunk of code whose purpose is to make user + interaction uniform, and thereby make it simpler + to read and understand someone else's test. + ****************************************************/ + +/** + This is part of the standard test machinery. + It creates a dialog (with the instructions), and is the interface + for sending text messages to the user. + To print the instructions, send an array of strings to Sysout.createDialog + WithInstructions method. Put one line of instructions per array entry. + To display a message for the tester to see, simply call Sysout.println + with the string to be displayed. + This mimics System.out.println but works within the test harness as well + as standalone. + */ + +class Sysout +{ + private static TestDialog dialog; + + public static void createDialogWithInstructions( String[] instructions ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + dialog.printInstructions( instructions ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void createDialog( ) + { + dialog = new TestDialog( new Frame(), "Instructions" ); + String[] defInstr = { "Instructions will appear here. ", "" } ; + dialog.printInstructions( defInstr ); + dialog.setVisible(true); + println( "Any messages for the tester will display here." ); + } + + public static void printInstructions( String[] instructions ) + { + dialog.printInstructions( instructions ); + } + + public static void println( String messageIn ) + { + dialog.displayMessage( messageIn ); + } +} + +/** + This is part of the standard test machinery. It provides a place for the + test instructions to be displayed, and a place for interactive messages + to the user to be displayed. + To have the test instructions displayed, see Sysout. + To have a message to the user be displayed, see Sysout. + Do not call anything in this dialog directly. + */ +class TestDialog extends Dialog +{ + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog( Frame frame, String name ) + { + super( frame, name ); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); + add( "North", instructionsText ); + + messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); + add("Center", messageText); + + pack(); + + setVisible(true); + } + + //DO NOT call this directly, go through Sysout + public void printInstructions( String[] instructions ) + { + //Clear out any current instructions + instructionsText.setText( "" ); + + //Go down array of instruction strings + + String printStr, remainingStr; + for( int i=0; i < instructions.length; i++ ) + { + //chop up each into pieces maxSringLength long + remainingStr = instructions[ i ]; + while( remainingStr.length() > 0 ) + { + //if longer than max then chop off first max chars to print + if( remainingStr.length() >= maxStringLength ) + { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf( ' ', maxStringLength - 1 ); + + if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring( 0, posOfSpace + 1 ); + remainingStr = remainingStr.substring( posOfSpace + 1 ); + } + //else just print + else + { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append( printStr + "\n" ); + } + } + } + + //DO NOT call this directly, go through Sysout + public void displayMessage( String messageIn ) + { + messageText.append( messageIn + "\n" ); + System.out.println(messageIn); + } +} diff --git a/jdk/test/java/awt/Window/MaximizeOffscreen/MaximizeOffscreenTest.java b/jdk/test/java/awt/Window/MaximizeOffscreen/MaximizeOffscreenTest.java index 014637acec0..78155f3b9b3 100644 --- a/jdk/test/java/awt/Window/MaximizeOffscreen/MaximizeOffscreenTest.java +++ b/jdk/test/java/awt/Window/MaximizeOffscreen/MaximizeOffscreenTest.java @@ -23,6 +23,7 @@ /** * @test @summary JVM crash if the frame maximized from offscreen + * @bug 8020210 * @author Petr Pchelko * @library ../../regtesthelpers * @build Util diff --git a/jdk/test/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java b/jdk/test/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java new file mode 100644 index 00000000000..5d1342d171f --- /dev/null +++ b/jdk/test/java/awt/event/KeyEvent/ExtendedKeyCode/ExtendedKeyCodeTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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.Frame; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.KeyEvent; +import java.awt.event.KeyAdapter; +import sun.awt.ExtendedKeyCodes; +import sun.awt.SunToolkit; + +/* + * @test + * @bug 8007156 + * @summary Extended key code is not set for a key event + * @author Alexandr Scherbatiy + * @run main ExtendedKeyCodeTest + */ +public class ExtendedKeyCodeTest { + + private static volatile boolean setExtendedKeyCode = true; + private static volatile int eventsCount = 0; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + + Frame frame = new Frame(); + frame.setSize(300, 300); + + frame.addKeyListener(new KeyAdapter() { + + @Override + public void keyPressed(KeyEvent e) { + eventsCount++; + setExtendedKeyCode = setExtendedKeyCode && (e.getExtendedKeyCode() + == ExtendedKeyCodes.getExtendedKeyCodeForChar(e.getKeyChar())); + } + + @Override + public void keyReleased(KeyEvent e) { + eventsCount++; + setExtendedKeyCode = setExtendedKeyCode && (e.getExtendedKeyCode() + == ExtendedKeyCodes.getExtendedKeyCodeForChar(e.getKeyChar())); + } + }); + + frame.setVisible(true); + toolkit.realSync(); + + robot.keyPress(KeyEvent.VK_D); + robot.keyRelease(KeyEvent.VK_D); + toolkit.realSync(); + + frame.dispose(); + + if (eventsCount != 2 || !setExtendedKeyCode) { + throw new RuntimeException("Wrong extended key code"); + } + } +} diff --git a/jdk/test/java/awt/event/KeyEvent/KeyChar/KeyCharTest.java b/jdk/test/java/awt/event/KeyEvent/KeyChar/KeyCharTest.java new file mode 100644 index 00000000000..a482cea61dd --- /dev/null +++ b/jdk/test/java/awt/event/KeyEvent/KeyChar/KeyCharTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.AWTEvent; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.AWTEventListener; +import java.awt.event.KeyEvent; +import java.util.Locale; +import sun.awt.SunToolkit; + +/* + * @test + * @bug 8022401 + * @summary Wrong key char + * @author Alexandr Scherbatiy + * @run main KeyCharTest + */ +public class KeyCharTest { + + private static volatile int eventsCount = 0; + + static { + Locale.setDefault(Locale.ENGLISH); + + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + + @Override + public void eventDispatched(AWTEvent event) { + eventsCount++; + char delete = ((KeyEvent) event).getKeyChar(); + if (delete != '\u007f') { + throw new RuntimeException("Key char is not delete: '" + delete + "'"); + } + } + }, AWTEvent.KEY_EVENT_MASK); + } + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + + Frame frame = new Frame(); + frame.setSize(300, 300); + frame.setVisible(true); + toolkit.realSync(); + + Robot robot = new Robot(); + + robot.keyPress(KeyEvent.VK_DELETE); + robot.keyRelease(KeyEvent.VK_DELETE); + toolkit.realSync(); + + frame.dispose(); + + if (eventsCount != 3) { + throw new RuntimeException("Wrong number of key events: " + eventsCount); + } + } +} diff --git a/jdk/test/java/awt/font/TransformAttribute/TransformEqualityTest.java b/jdk/test/java/awt/font/TransformAttribute/TransformEqualityTest.java new file mode 100644 index 00000000000..5cbc9078796 --- /dev/null +++ b/jdk/test/java/awt/font/TransformAttribute/TransformEqualityTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @summary test equals method + * @bug 7092764 + */ + +import java.awt.font.TransformAttribute; +import java.awt.geom.AffineTransform; + +public class TransformEqualityTest { + + public static void main(String[] args) { + AffineTransform tx1 = new AffineTransform(1, 0, 1, 1, 0, 0); + AffineTransform tx2 = new AffineTransform(1, 0, 1, 1, 0, 0); + AffineTransform tx3 = new AffineTransform(2, 0, 1, 1, 0, 0); + TransformAttribute ta1a = new TransformAttribute(tx1); + TransformAttribute ta1b = new TransformAttribute(tx1); + TransformAttribute ta2 = new TransformAttribute(tx2); + TransformAttribute ta3 = new TransformAttribute(tx3); + if (ta1a.equals(null)) { + throw new RuntimeException("should not be equal to null."); + } + if (!ta1a.equals(ta1a)) { + throw new RuntimeException("(1) should be equal."); + } + if (!ta1a.equals(ta1b)) { + throw new RuntimeException("(2) should be equal."); + } + if (!ta1a.equals(ta2)) { + throw new RuntimeException("(3) should be equal."); + } + if (ta2.equals(ta3)) { + throw new RuntimeException("should be different."); + } + } +} + diff --git a/jdk/test/java/awt/image/DrawImage/EABlitTest.java b/jdk/test/java/awt/image/DrawImage/EABlitTest.java new file mode 100644 index 00000000000..6240ce716d6 --- /dev/null +++ b/jdk/test/java/awt/image/DrawImage/EABlitTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.awt.image.*; +import java.util.*; +import javax.swing.*; + +/** + * @test + * @bug 8024895 + * @summary tests if changing extra alpha values are honored for transformed blits + * @author ceisserer + */ +public class EABlitTest extends Frame { + protected void test() { + BufferedImage srcImg = createSrcImage(); + Image dstImg = getGraphicsConfiguration().createCompatibleVolatileImage(20, 50); + + //be over-cautious and render twice to avoid BI caching issues + renderToVI(srcImg, dstImg); + renderToVI(srcImg, dstImg); + + BufferedImage validationImg = new BufferedImage(20, 50, BufferedImage.TYPE_INT_RGB); + Graphics2D valG = (Graphics2D) validationImg.getGraphics(); + valG.drawImage(dstImg, 0, 0, null); + + //Loop over all pixel, and count the different pixel values encountered. + TreeSet colorCntSet = new TreeSet<>(); + for (int x=0; x < validationImg.getWidth(); x++) { + for (int y=0; y < validationImg.getHeight(); y++) { + int rgb = validationImg.getRGB(x, y); + colorCntSet.add(rgb); + } + } + + //Check if we encountered 3 different color values in total + if (colorCntSet.size() == 3) { + System.out.println("Passed!"); + } else { + throw new RuntimeException("Test FAILED!"); + } + } + + protected void renderToVI(BufferedImage src, Image dst) { + Graphics2D g = (Graphics2D) dst.getGraphics(); + + g.setColor(Color.WHITE); + g.fillRect(0, 0, 50, 50); + g.rotate(0.5f); + g.setRenderingHint(RenderingHints.KEY_RENDERING, + RenderingHints.VALUE_RENDER_QUALITY); + + g.setComposite(AlphaComposite.SrcOver.derive(1f)); + g.drawImage(src, 10, 10, null); + + g.setComposite(AlphaComposite.SrcOver.derive(0.5f)); + g.drawImage(src, 20, 20, null); + } + + protected BufferedImage createSrcImage() { + BufferedImage bi = new BufferedImage(10, 10, BufferedImage.TYPE_INT_RGB); + Graphics2D g = (Graphics2D) bi.getGraphics(); + g.setColor(Color.YELLOW); + g.fillRect(0, 0, 10, 10); + return bi; + } + + public static void main(String[] args) { + new EABlitTest().test(); + } +} diff --git a/jdk/test/java/awt/print/bug8023392/bug8023392.html b/jdk/test/java/awt/print/bug8023392/bug8023392.html new file mode 100644 index 00000000000..d796a21c660 --- /dev/null +++ b/jdk/test/java/awt/print/bug8023392/bug8023392.html @@ -0,0 +1,20 @@ + + + + Bug 8023392 + + + +

        Bug ID: 8023392

        + +

        See the dialog box (usually in upper left corner) for instructions

        + + + + diff --git a/jdk/test/java/awt/print/bug8023392/bug8023392.java b/jdk/test/java/awt/print/bug8023392/bug8023392.java new file mode 100644 index 00000000000..6c6fbb26ee9 --- /dev/null +++ b/jdk/test/java/awt/print/bug8023392/bug8023392.java @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 8023392 + @summary Swing text components printed with spaces between chars + @author Anton Nashatyrev + @run applet/manual=yesno bug8023392.html +*/ + +import javax.swing.*; +import javax.swing.border.LineBorder; +import java.applet.Applet; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.font.TextAttribute; +import java.awt.print.PageFormat; +import java.awt.print.Printable; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + + +public class bug8023392 extends Applet { + static final String[] instructions = { + "A Frame containing several pairs of labels ((a) and (b)) is displayed.", + "Labels of each pair look the same and are left-aligned (with spaces ", + "between chars).", + "1. Hit the print button.", + "2. Select any available printer (printing to file is also fine).", + "3. Look at the printing result (paper, PDF, PS, etc.):", + " The (a) and (b) labels should look almost the same and the (a) labels", + " shouldn't appear as if they are stretched along X axis."}; + + public void init() { + this.setLayout(new BorderLayout()); + add(new SimplePrint2(), BorderLayout.CENTER); + + Sysout.createDialogWithInstructions(instructions); + + } + + public static class SimplePrint2 extends JPanel + implements ActionListener, Printable { + JLabel label1; + JLabel label2; + JButton printButton; + + + public SimplePrint2() { + setLayout(new BorderLayout()); + label1 = new JLabel("2a) a b c d e" + + " "); + label2 = new JLabel("2b) a b c d e"); + + Box p1 = new Box(BoxLayout.Y_AXIS); + p1.add(label1); + p1.add(label2); + p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") { + String s = "3a) a b c d e "; + @Override + protected void paintComponent(Graphics g) { + sun.swing.SwingUtilities2.drawChars(this, g, s.toCharArray(), + 0, s.length(), 0, 15); + } + }); + p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") { + String s = "3b) a b c d e"; + @Override + protected void paintComponent(Graphics g) { + sun.swing.SwingUtilities2.drawChars(this, g, s.toCharArray(), + 0, s.length(), 0, 15); + } + }); + p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") { + String s = "4a) a b c d e "; + AttributedCharacterIterator it; + { + AttributedString as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, getFont()); + as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 3, 8); + it = as.getIterator(); + } + @Override + protected void paintComponent(Graphics g) { + sun.swing.SwingUtilities2.drawString(this, g, it, 0, 15); + } + }); + + p1.add(new JLabel("wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww") { + String s = "4b) a b c d e"; + AttributedCharacterIterator it; + { + AttributedString as = new AttributedString(s); + as.addAttribute(TextAttribute.FONT, getFont()); + as.addAttribute(TextAttribute.FOREGROUND, Color.RED, 3, 8); + it = as.getIterator(); + } + @Override + protected void paintComponent(Graphics g) { + sun.swing.SwingUtilities2.drawString(this, g, it, 0, 15); + } + }); + + JPanel p2 = new JPanel(); + printButton = new JButton("Print"); + printButton.addActionListener(this); + p2.add(printButton); + + Container c = this; + c.add(p1, BorderLayout.CENTER); + c.add(p2, BorderLayout.SOUTH); + + String[] data = { + "1a) \u30aa\u30f3\u30e9\u30a4\u30f3\u6d88\u8fbc" + + " ", + "1b) \u30aa\u30f3\u30e9\u30a4\u30f3\u6d88\u8fbc" + }; + JList l0 = new JList(data); + l0.setVisibleRowCount(l0.getModel().getSize()); + JScrollPane jsp = new JScrollPane(l0); + l0.setBorder(new LineBorder(Color.GRAY)); + c.add(jsp, BorderLayout.NORTH); + + for (Component comp : new Component[]{label1, label2, printButton}) { + comp.setFont(new Font("Monospaced", 0, 16)); + } + } + + public void actionPerformed(ActionEvent e) { + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintable(this); + if (job.printDialog()) { + try { + job.print(); + } catch (PrinterException ex) { + ex.printStackTrace(); + } + } + } + + public int print(Graphics graphics, + PageFormat pageFormat, + int pageIndex) + throws PrinterException { + if (pageIndex >= 1) { + return Printable.NO_SUCH_PAGE; + } + + this.paint(graphics); + return Printable.PAGE_EXISTS; + } + } +} + + +/** + * ************************************************* + * Standard Test Machinery + * DO NOT modify anything below -- it's a standard + * chunk of code whose purpose is to make user + * interaction uniform, and thereby make it simpler + * to read and understand someone else's test. + * ************************************************** + */ +class Sysout { + private static TestDialog dialog; + + public static void createDialogWithInstructions(String[] instructions) { + dialog = new TestDialog(new Frame(), "Instructions"); + dialog.printInstructions(instructions); + dialog.show(); + println("Any messages for the tester will display here."); + } + + public static void createDialog() { + dialog = new TestDialog(new Frame(), "Instructions"); + String[] defInstr = {"Instructions will appear here. ", ""}; + dialog.printInstructions(defInstr); + dialog.show(); + println("Any messages for the tester will display here."); + } + + + public static void printInstructions(String[] instructions) { + dialog.printInstructions(instructions); + } + + + public static void println(String messageIn) { + dialog.displayMessage(messageIn); + } + +}// Sysout class + + +class TestDialog extends Dialog { + + TextArea instructionsText; + TextArea messageText; + int maxStringLength = 80; + + //DO NOT call this directly, go through Sysout + public TestDialog(Frame frame, String name) { + super(frame, name); + int scrollBoth = TextArea.SCROLLBARS_BOTH; + instructionsText = new TextArea("", 15, maxStringLength, scrollBoth); + add("North", instructionsText); + + messageText = new TextArea("", 5, maxStringLength, scrollBoth); + add("South", messageText); + + pack(); + + show(); + }// TestDialog() + + //DO NOT call this directly, go through Sysout + public void printInstructions(String[] instructions) { + //Clear out any current instructions + instructionsText.setText(""); + + //Go down array of instruction strings + + String printStr, remainingStr; + for (int i = 0; i < instructions.length; i++) { + //chop up each into pieces maxSringLength long + remainingStr = instructions[i]; + while (remainingStr.length() > 0) { + //if longer than max then chop off first max chars to print + if (remainingStr.length() >= maxStringLength) { + //Try to chop on a word boundary + int posOfSpace = remainingStr. + lastIndexOf(' ', maxStringLength - 1); + + if (posOfSpace <= 0) posOfSpace = maxStringLength - 1; + + printStr = remainingStr.substring(0, posOfSpace + 1); + remainingStr = remainingStr.substring(posOfSpace + 1); + } + //else just print + else { + printStr = remainingStr; + remainingStr = ""; + } + + instructionsText.append(printStr + "\n"); + + }// while + + }// for + + }//printInstructions() + + //DO NOT call this directly, go through Sysout + public void displayMessage(String messageIn) { + messageText.append(messageIn + "\n"); + } + +}// TestDialog class + diff --git a/jdk/test/java/awt/security/Permissions.java b/jdk/test/java/awt/security/Permissions.java new file mode 100644 index 00000000000..3f0a3ad24e3 --- /dev/null +++ b/jdk/test/java/awt/security/Permissions.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 8008981 + * @summary Test that selected Toolkit and Window methods/constructors do + * the appropriate permission check + * @run main/othervm Permissions + */ + +import java.awt.AWTPermission; +import java.awt.Frame; +import java.awt.GraphicsConfiguration; +import java.awt.Toolkit; +import java.awt.Window; +import java.util.ArrayList; +import java.util.List; +import java.security.Permission; + +public class Permissions { + + static class MySecurityManager extends SecurityManager { + private List permissionsChecked = new ArrayList<>(); + + static MySecurityManager install() { + MySecurityManager sm = new MySecurityManager(); + System.setSecurityManager(sm); + return sm; + } + + @Override + public void checkPermission(Permission perm) { + permissionsChecked.add(perm); + } + + void prepare(String msg) { + System.out.println(msg); + permissionsChecked.clear(); + } + + /** + * Checks the security manager's checkPermission method was invoked + * to check the given permission and target name. + */ + void assertChecked(Class type, String name) { + for (Permission perm: permissionsChecked) { + if (type.isInstance(perm) && perm.getName().equals(name)) + return; + } + throw new RuntimeException(type.getName() + "(\"" + name + "\") not checked"); + } + } + + public static void main(String[] args) { + MySecurityManager sm = MySecurityManager.install(); + + Toolkit toolkit = Toolkit.getDefaultToolkit(); + + sm.prepare("Toolkit.getSystemClipboard()"); + toolkit.getSystemClipboard(); + sm.assertChecked(AWTPermission.class, "accessClipboard"); + + sm.prepare("Toolkit.getSystemEventQueue()"); + toolkit.getSystemEventQueue(); + sm.assertChecked(AWTPermission.class, "accessEventQueue"); + + sm.prepare("Toolkit.getSystemSelection()"); + toolkit.getSystemSelection(); + //sm.assertChecked(AWTPermission.class, "accessClipboard"); + + sm.prepare("Window(Frame)"); + new Window((Frame)null); + sm.assertChecked(AWTPermission.class, "showWindowWithoutWarningBanner"); + + sm.prepare("Window(Window)"); + new Window((Window)null); + sm.assertChecked(AWTPermission.class, "showWindowWithoutWarningBanner"); + + sm.prepare("Window(Window,GraphicsConfiguration)"); + new Window((Window)null, (GraphicsConfiguration)null); + sm.assertChecked(AWTPermission.class, "showWindowWithoutWarningBanner"); + } +} diff --git a/jdk/test/java/beans/Introspector/Test7172865.java b/jdk/test/java/beans/Introspector/Test7172865.java new file mode 100644 index 00000000000..6647225ca8f --- /dev/null +++ b/jdk/test/java/beans/Introspector/Test7172865.java @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.beans.IndexedPropertyDescriptor; +import java.beans.MethodDescriptor; +import java.beans.PropertyDescriptor; + +/* + * @test + * @bug 7172854 7172865 + * @summary Tests that cached methods are not lost + * @author Sergey Malenkov + */ + +public class Test7172865 { + public static void main(String[] args) throws Exception { + int errors = 0; + + MethodDescriptor md = new MethodDescriptor(Test7172865.class.getMethod("getGood")); + + errors += test(PropertyDescriptor.class, "good", true); + PropertyDescriptor pdGoodString = new PropertyDescriptor("good", Test7172865.class, "getGood", "setGood"); + PropertyDescriptor pdGoodMethod = new PropertyDescriptor("good", + Test7172865.class.getMethod("getGood"), + Test7172865.class.getMethod("setGood", args.getClass())); + + errors += test(PropertyDescriptor.class, "bad", false); + PropertyDescriptor pdBadString = new PropertyDescriptor("bad", Test7172865.class, "getBad", null); + PropertyDescriptor pdBadMethod = new PropertyDescriptor("bad", + Test7172865.class.getMethod("getBad"), + Test7172865.class.getMethod("setBad", args.getClass())); + + errors += test(IndexedPropertyDescriptor.class, "good", true); + IndexedPropertyDescriptor ipdGoodString = new IndexedPropertyDescriptor("good", Test7172865.class, "getGood", "setGood", "getGood", "setGood"); + IndexedPropertyDescriptor ipdGoodMethod = new IndexedPropertyDescriptor("good", + Test7172865.class.getMethod("getGood"), + Test7172865.class.getMethod("setGood", args.getClass()), + Test7172865.class.getMethod("getGood", Integer.TYPE), + Test7172865.class.getMethod("setGood", Integer.TYPE, String.class)); + + errors += test(IndexedPropertyDescriptor.class, "bad", false); + IndexedPropertyDescriptor ipdBadString = new IndexedPropertyDescriptor("bad", Test7172865.class, "getBad", null, "getBad", null); + IndexedPropertyDescriptor ipdBadMethod = new IndexedPropertyDescriptor("bad", + Test7172865.class.getMethod("getBad"), + Test7172865.class.getMethod("setBad", args.getClass()), + Test7172865.class.getMethod("getBad", Integer.TYPE), + Test7172865.class.getMethod("setBad", Integer.TYPE, String.class)); + + for (int i = 1; i <= 2; i++) { + System.out.println("STEP: " + i); + errors += test("md", null != md.getMethod()); + + errors += test("pdGoodString", pdGoodString, true, true); + errors += test("pdGoodMethod", pdGoodMethod, true, true); + + errors += test("pdBadString", pdBadString, true, false); + errors += test("pdBadMethod", pdBadMethod, true, true); + + errors += test("ipdGoodString", ipdGoodString, true, true, true, true); + errors += test("ipdGoodMethod", ipdGoodMethod, true, true, true, true); + + errors += test("ipdBadString", ipdBadString, true, false, true, false); + errors += test("ipdBadMethod", ipdBadMethod, true, true, true, true); + + try { + int[] array = new int[1024]; + while (true) { + array = new int[array.length << 1]; + } + } + catch (OutOfMemoryError error) { + System.gc(); + } + } + if (errors > 0) { + throw new Error("found " + errors + " errors"); + } + } + + private static int test(Class type, String property, boolean value) { + String message = type.getSimpleName() + "(" + property + ") "; + try { + type.getConstructor(String.class, Class.class).newInstance(property, Test7172865.class); + message += "passed"; + } + catch (Exception exception) { + message += "failed"; + value = !value; + } + if (value) { + message += " as expected"; + } + System.out.println(message); + return value ? 0 : 1; + } + + private static int test(String message, boolean value) { + System.out.println(message + ": " + (value ? "passed" : "failed")); + return value ? 0 : 1; + } + + private static int test(String message, PropertyDescriptor pd, boolean rm, boolean wm) { + return test(message + ".Read", rm == (null != pd.getReadMethod())) + + test(message + ".Write", wm == (null != pd.getWriteMethod())); + } + + private static int test(String message, IndexedPropertyDescriptor ipd, boolean rm, boolean wm, boolean irm, boolean iwm) { + return test(message, ipd, rm, wm) + + test(message + ".IndexedRead", irm == (null != ipd.getIndexedReadMethod())) + + test(message + ".IndexedWrite", iwm == (null != ipd.getIndexedWriteMethod())); + } + + public String[] getGood() { + return null; + } + + public String getGood(int index) { + return null; + } + + public void setGood(String[] good) { + } + + public void setGood(int index, String value) { + } + + public String[] getBad() { + return null; + } + + public String getBad(int index) { + return null; + } + + public Test7172865 setBad(String[] bad) { + return null; + } + + public Test7172865 setBad(int index, String value) { + return null; + } +} diff --git a/jdk/test/java/beans/Performance/Test7122740.java b/jdk/test/java/beans/Performance/Test7122740.java index 4924c6e8f77..eb0cf3fc974 100644 --- a/jdk/test/java/beans/Performance/Test7122740.java +++ b/jdk/test/java/beans/Performance/Test7122740.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7122740 + * @bug 7187618 7122740 * @summary Tests just a benchmark of PropertyDescriptor(String, Class) performance * @author Sergey Malenkov * @run main/manual Test7122740 diff --git a/jdk/test/java/beans/Performance/Test7184799.java b/jdk/test/java/beans/Performance/Test7184799.java index 563328abc7f..255638e8105 100644 --- a/jdk/test/java/beans/Performance/Test7184799.java +++ b/jdk/test/java/beans/Performance/Test7184799.java @@ -23,7 +23,7 @@ /* * @test - * @bug 7184799 + * @bug 7187618 7184799 * @summary Tests just a benchmark of Introspector.getBeanInfo(Class) performance * @author Sergey Malenkov * @run main/manual Test7184799 diff --git a/jdk/test/java/io/File/MaxPathLength.java b/jdk/test/java/io/File/MaxPathLength.java index 7ec379cf1d1..9fd6183f36d 100644 --- a/jdk/test/java/io/File/MaxPathLength.java +++ b/jdk/test/java/io/File/MaxPathLength.java @@ -22,7 +22,7 @@ */ /* @test - @bug 4759207 4403166 4165006 4403166 6182812 6274272 + @bug 4759207 4403166 4165006 4403166 6182812 6274272 7160013 @summary Test to see if win32 path length can be greater than 260 */ @@ -37,6 +37,10 @@ public class MaxPathLength { "areallylongfilenamethatsforsur"; private static boolean isWindows = false; + private final static int MAX_LENGTH = 256; + + private static int counter = 0; + public static void main(String[] args) throws Exception { String osName = System.getProperty("os.name"); if (osName.startsWith("Windows")) { @@ -45,33 +49,39 @@ public class MaxPathLength { for (int i = 4; i < 7; i++) { String name = fileName; - while (name.length() < 256) { + while (name.length() < MAX_LENGTH) { testLongPath (i, name, false); testLongPath (i, name, true); - name += "A"; + name = getNextName(name); } } // test long paths on windows + // And these long pathes cannot be handled on Solaris and Mac platforms if (isWindows) { String name = fileName; - while (name.length() < 256) { + while (name.length() < MAX_LENGTH) { testLongPath (20, name, false); testLongPath (20, name, true); - name += "A"; + name = getNextName(name); } } } + private static String getNextName(String fName) { + return (fName.length() < MAX_LENGTH/2) ? fName + fName + : fName + "A"; + } + static void testLongPath(int max, String fn, boolean tryAbsolute) throws Exception { String[] created = new String[max]; String pathString = "."; for (int i = 0; i < max -1; i++) { - pathString = pathString + pathComponent; + pathString = pathString + pathComponent + (counter++); created[max - 1 -i] = pathString; - } + File dirFile = new File(pathString); File f = new File(pathString + sep + fn); @@ -88,9 +98,10 @@ public class MaxPathLength { System.err.println("Warning: Test directory structure exists already!"); return; } - Files.createDirectories(dirFile.toPath()); try { + Files.createDirectories(dirFile.toPath()); + if (tryAbsolute) dirFile = new File(dirFile.getCanonicalPath()); if (!dirFile.isDirectory()) @@ -99,6 +110,7 @@ public class MaxPathLength { if (!f.createNewFile()) { throw new RuntimeException ("File.createNewFile() failed"); } + if (!f.exists()) throw new RuntimeException ("File.exists() failed"); if (!f.isFile()) @@ -107,11 +119,14 @@ public class MaxPathLength { throw new RuntimeException ("File.canRead() failed"); if (!f.canWrite()) throw new RuntimeException ("File.canWrite() failed"); + if (!f.delete()) throw new RuntimeException ("File.delete() failed"); + FileOutputStream fos = new FileOutputStream(f); fos.write(1); fos.close(); + if (f.length() != 1) throw new RuntimeException ("File.length() failed"); long time = System.currentTimeMillis(); @@ -148,30 +163,26 @@ public class MaxPathLength { throw new RuntimeException ("File.renameTo() failed for lenth=" + abPath.length()); } - return; + } else { + if (!nf.canRead()) + throw new RuntimeException ("Renamed file is not readable"); + if (!nf.canWrite()) + throw new RuntimeException ("Renamed file is not writable"); + if (nf.length() != 1) + throw new RuntimeException ("Renamed file's size is not correct"); + if (!nf.renameTo(f)) { + created[0] = nf.getPath(); + } + /* add a script to test these two if we got a regression later + if (!f.setReadOnly()) + throw new RuntimeException ("File.setReadOnly() failed"); + f.deleteOnExit(); + */ } - if (!nf.canRead()) - throw new RuntimeException ("Renamed file is not readable"); - if (!nf.canWrite()) - throw new RuntimeException ("Renamed file is not writable"); - if (nf.length() != 1) - throw new RuntimeException ("Renamed file's size is not correct"); - nf.renameTo(f); - /* add a script to test these two if we got a regression later - if (!f.setReadOnly()) - throw new RuntimeException ("File.setReadOnly() failed"); - f.deleteOnExit(); - */ } finally { // Clean up for (int i = 0; i < max; i++) { - pathString = created[i]; - // Only works with completex canonical paths - File df = new File(pathString); - pathString = df.getCanonicalPath(); - df = new File(pathString); - if (!df.delete()) - System.out.printf("Delete failed->%s\n", pathString); + Files.deleteIfExists((new File(created[i])).toPath()); } } } diff --git a/jdk/test/java/lang/CharSequence/DefaultTest.java b/jdk/test/java/lang/CharSequence/DefaultTest.java index dd51ce64122..856b980ff00 100644 --- a/jdk/test/java/lang/CharSequence/DefaultTest.java +++ b/jdk/test/java/lang/CharSequence/DefaultTest.java @@ -25,6 +25,7 @@ import java.util.Arrays; import java.util.List; import java.util.NoSuchElementException; import java.util.PrimitiveIterator; +import java.util.Spliterator; import java.util.stream.Collectors; import org.testng.annotations.Test; @@ -34,7 +35,7 @@ import static org.testng.Assert.*; /* * @test * @summary Unit test for CharSequence default methods - * @bug 8012665 + * @bug 8012665 8025002 * @run testng DefaultTest */ @@ -53,6 +54,12 @@ public class DefaultTest { assertEquals(list, Arrays.asList((int) 'a', (int) 'b', (int) 'c')); } + public void testCodePointsCharacteristics() { + Spliterator.OfInt s = "".codePoints().spliterator(); + assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)); + assertTrue(s.hasCharacteristics(Spliterator.ORDERED)); + } + @Test(expectedExceptions = NoSuchElementException.class) public void testEmptyCodePoints() { PrimitiveIterator.OfInt s = "".codePoints().iterator(); diff --git a/jdk/test/java/lang/Class/ArrayMethods.java b/jdk/test/java/lang/Class/ArrayMethods.java new file mode 100644 index 00000000000..294fbf08da8 --- /dev/null +++ b/jdk/test/java/lang/Class/ArrayMethods.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + * @bug 4987375 + * @summary make sure clone() isn't reflected and that Cloneable and + * Serializable are found + */ + +import java.lang.reflect.*; +import java.util.Arrays; + +public class ArrayMethods { + public int failed = 0; + + public static void main(String[] args) throws Exception { + ArrayMethods m = new ArrayMethods(); + + m.testGetMethod(); + m.testGetMethods(); + m.testGetDeclaredMethod(); + m.testGetDeclaredMethods(); + m.testGetInterfaces(); + + if (m.failed != 0) + throw new RuntimeException("Test failed, check log for details"); + } + + public void testGetMethod() { + try { + Method m = new String[0].getClass().getMethod("clone", (Class[])null); + + failed++; + System.out.println("getMethod(\"clone\", null) Should not find clone()"); + } catch (NoSuchMethodException e) { + ; //all good + } + } + + public void testGetMethods() { + Method[] m = new Integer[0][0][0].getClass().getMethods(); + for (Method mm : m) + if(mm.getName().contentEquals("clone")) { + failed++; + System.out.println("getMethods() Should not find clone()"); + } + } + + public void testGetDeclaredMethod() { + try { + Method m = new Object[0][0].getClass().getDeclaredMethod("clone", (Class[])null); + + failed++; + System.out.println("getDeclaredMethod(\"clone\", null) Should not find clone()"); + + } catch (NoSuchMethodException e) { + ; //all good + } + } + + public void testGetDeclaredMethods() { + Method[] m = new Throwable[0][0][0][0].getClass().getDeclaredMethods(); + if (m.length != 0) { + failed++; + System.out.println("getDeclaredMethods().length should be 0"); + } + } + + public void testGetInterfaces() { + Class[] is = new Integer[0].getClass().getInterfaces(); + boolean thisFailed = false; + + if (is.length != 2) + thisFailed = true; + + if (!is[0].getCanonicalName().equals("java.lang.Cloneable")) + thisFailed = true; + + if (!is[1].getCanonicalName().equals("java.io.Serializable")) + thisFailed = true; + + if (thisFailed) { + failed++; + System.out.println(Arrays.asList(is)); + System.out.println("Should contain exactly Cloneable, Serializable in that order."); + } + } +} diff --git a/jdk/test/java/lang/Class/getField/ArrayLength.java b/jdk/test/java/lang/Class/getField/ArrayLength.java new file mode 100644 index 00000000000..c03a772c043 --- /dev/null +++ b/jdk/test/java/lang/Class/getField/ArrayLength.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 5047859 + * @summary verify that for an array type class instance, getField("length") + * throws an exception, and getFields() does not contain a Field for + * 'length' + */ + +import java.lang.reflect.Field; + +public class ArrayLength { + public static void main(String [] args) { + int failed = 0; + + try { + new String[0].getClass().getField("length"); + failed++; + System.out.println("getField(\"length\") should throw NoSuchFieldException"); + } catch (NoSuchFieldException e) { + } + try { + new String[0].getClass().getDeclaredField("length"); + failed++; + System.out.println("getDeclaredField(\"length\") should throw NoSuchFieldException"); + } catch (NoSuchFieldException e) { + } + + if (new String[0].getClass().getFields().length != 0) { + failed++; + System.out.println("getFields() for an array type should return a zero length array"); + } + + if (new String[0].getClass().getDeclaredFields().length != 0) { + failed++; + System.out.println("getDeclaredFields() for an array type should return a zero length array"); + } + + if (failed != 0) + throw new RuntimeException("Test failed see log for details"); + } +} diff --git a/jdk/test/java/lang/Math/RoundTests.java b/jdk/test/java/lang/Math/RoundTests.java index 9994e97df85..cae190f9770 100644 --- a/jdk/test/java/lang/Math/RoundTests.java +++ b/jdk/test/java/lang/Math/RoundTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6430675 + * @bug 6430675 8010430 * @summary Check for correct implementation of {Math, StrictMath}.round */ public class RoundTests { @@ -32,6 +32,8 @@ public class RoundTests { failures += testNearFloatHalfCases(); failures += testNearDoubleHalfCases(); + failures += testUnityULPCases(); + failures += testSpecialCases(); if (failures > 0) { System.err.println("Testing {Math, StrictMath}.round incurred " @@ -95,4 +97,69 @@ public class RoundTests { return failures; } + + private static int testUnityULPCases() { + int failures = 0; + for (float sign : new float[]{-1, 1}) { + for (float v1 : new float[]{1 << 23, 1 << 24}) { + for (int k = -5; k <= 5; k++) { + float value = (v1 + k) * sign; + float actual = Math.round(value); + failures += Tests.test("Math.round", value, actual, value); + } + } + } + + if (failures != 0) { + System.out.println(); + } + + for (double sign : new double[]{-1, 1}) { + for (double v1 : new double[]{1L << 52, 1L << 53}) { + for (int k = -5; k <= 5; k++) { + double value = (v1 + k) * sign; + double actual = Math.round(value); + failures += Tests.test("Math.round", value, actual, value); + } + } + } + + return failures; + } + + private static int testSpecialCases() { + int failures = 0; + + failures += Tests.test("Math.round", Float.NaN, Math.round(Float.NaN), 0.0F); + failures += Tests.test("Math.round", Float.POSITIVE_INFINITY, + Math.round(Float.POSITIVE_INFINITY), Integer.MAX_VALUE); + failures += Tests.test("Math.round", Float.NEGATIVE_INFINITY, + Math.round(Float.NEGATIVE_INFINITY), Integer.MIN_VALUE); + failures += Tests.test("Math.round", -(float)Integer.MIN_VALUE, + Math.round(-(float)Integer.MIN_VALUE), Integer.MAX_VALUE); + failures += Tests.test("Math.round", (float) Integer.MIN_VALUE, + Math.round((float) Integer.MIN_VALUE), Integer.MIN_VALUE); + failures += Tests.test("Math.round", 0F, Math.round(0F), 0.0F); + failures += Tests.test("Math.round", Float.MIN_VALUE, + Math.round(Float.MIN_VALUE), 0.0F); + failures += Tests.test("Math.round", -Float.MIN_VALUE, + Math.round(-Float.MIN_VALUE), 0.0F); + + failures += Tests.test("Math.round", Double.NaN, Math.round(Double.NaN), 0.0); + failures += Tests.test("Math.round", Double.POSITIVE_INFINITY, + Math.round(Double.POSITIVE_INFINITY), Long.MAX_VALUE); + failures += Tests.test("Math.round", Double.NEGATIVE_INFINITY, + Math.round(Double.NEGATIVE_INFINITY), Long.MIN_VALUE); + failures += Tests.test("Math.round", -(double)Long.MIN_VALUE, + Math.round(-(double)Long.MIN_VALUE), Long.MAX_VALUE); + failures += Tests.test("Math.round", (double) Long.MIN_VALUE, + Math.round((double) Long.MIN_VALUE), Long.MIN_VALUE); + failures += Tests.test("Math.round", 0, Math.round(0), 0.0); + failures += Tests.test("Math.round", Double.MIN_VALUE, + Math.round(Double.MIN_VALUE), 0.0); + failures += Tests.test("Math.round", -Double.MIN_VALUE, + Math.round(-Double.MIN_VALUE), 0.0); + + return failures; + } } diff --git a/jdk/test/java/lang/ProcessBuilder/Basic.java b/jdk/test/java/lang/ProcessBuilder/Basic.java index ebccabdd9c4..5a55cb6f0f4 100644 --- a/jdk/test/java/lang/ProcessBuilder/Basic.java +++ b/jdk/test/java/lang/ProcessBuilder/Basic.java @@ -298,11 +298,15 @@ public class Basic { System.exit(5); System.err.print("standard error"); System.out.print("standard output"); - } else if (action.equals("testInheritIO")) { + } else if (action.equals("testInheritIO") + || action.equals("testRedirectInherit")) { List childArgs = new ArrayList(javaChildArgs); childArgs.add("testIO"); ProcessBuilder pb = new ProcessBuilder(childArgs); - pb.inheritIO(); + if (action.equals("testInheritIO")) + pb.inheritIO(); + else + redirectIO(pb, INHERIT, INHERIT, INHERIT); ProcessResults r = run(pb); if (! r.out().equals("")) System.exit(7); @@ -1019,10 +1023,10 @@ public class Basic { // Note that this requires __FOUR__ nested JVMs involved in one test, // if you count the harness JVM. //---------------------------------------------------------------- - { + for (String testName : new String[] { "testInheritIO", "testRedirectInherit" } ) { redirectIO(pb, PIPE, PIPE, PIPE); List command = pb.command(); - command.set(command.size() - 1, "testInheritIO"); + command.set(command.size() - 1, testName); Process p = pb.start(); new PrintStream(p.getOutputStream()).print("standard input"); p.getOutputStream().close(); diff --git a/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.java b/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.java new file mode 100644 index 00000000000..83bb23d840c --- /dev/null +++ b/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import static java.lang.ProcessBuilder.Redirect.*; + +class InheritIO { + + public static class TestInheritIO { + public static void main(String args[]) throws Throwable { + int err = new ProcessBuilder(args).inheritIO().start().waitFor(); + System.err.print("exit value: " + err); + System.exit(err); + } + } + + public static class TestRedirectInherit { + public static void main(String args[]) throws Throwable { + int err = new ProcessBuilder(args) + .redirectInput(INHERIT) + .redirectOutput(INHERIT) + .redirectError(INHERIT) + .start().waitFor(); + System.err.print("exit value: " + err); + System.exit(err); + } + } +} diff --git a/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh b/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh new file mode 100644 index 00000000000..2b33a037296 --- /dev/null +++ b/jdk/test/java/lang/ProcessBuilder/InheritIO/InheritIO.sh @@ -0,0 +1,81 @@ +# +# Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# @test +# @bug 8023130 +# @summary (process) ProcessBuilder#inheritIO does not work on Windows +# @run shell InheritIO.sh + +if [ "x${TESTSRC}" = "x" ]; then + echo "TESTSRC not set. Test cannot execute. Failed." + exit 1 +fi + +if [ "x${TESTJAVA}" = "x" ]; then + echo "TESTJAVA not set. Test cannot execute. Failed." + exit 1 +fi + + +JAVA="${TESTJAVA}/bin/java" +JAVAC="${TESTJAVA}/bin/javac" + +cp -f ${TESTSRC}/InheritIO.java . + +# compile the class ourselves, so this can run as a standalone test + +${JAVAC} InheritIO.java +RES="$?" +if [ ${RES} != 0 ]; then + echo 'FAIL: Cannot compile InheritIO.java' + exit ${RES} +fi + + +for TEST_NAME in TestInheritIO TestRedirectInherit +do + ${JAVA} ${TESTVMOPTS} -classpath . \ + 'InheritIO$'${TEST_NAME} printf message > stdout.txt 2> stderr.txt + + RES="$?" + if [ ${RES} != 0 ]; then + echo 'FAIL: InheritIO$'${TEST_NAME}' failed with '${RES} + exit ${RES} + fi + + OUT_EXPECTED='message' + OUT_RECEIVED=`cat stdout.txt` + if [ "x${OUT_RECEIVED}" != "x${OUT_EXPECTED}" ]; then + echo "FAIL: unexpected '${OUT_RECEIVED}' in stdout" + exit 1 + fi + + ERR_EXPECTED='exit value: 0' + ERR_RECEIVED=`cat stderr.txt` + if [ "x${ERR_RECEIVED}" != "x${ERR_EXPECTED}" ]; then + echo "FAIL: unexpected '${ERR_RECEIVED}' in stderr" + exit 1 + fi +done + +echo 'PASS: InheritIO works as expected' diff --git a/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java b/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java new file mode 100644 index 00000000000..909154a7c1e --- /dev/null +++ b/jdk/test/java/lang/annotation/AnnotationsInheritanceOrderRedefinitionTest.java @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8011940 + * @summary Test inheritance, order and class redefinition behaviour of RUNTIME + * class annotations + * @author plevart + */ + +import sun.reflect.annotation.AnnotationParser; + +import java.lang.annotation.Annotation; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.reflect.Field; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.StringJoiner; + +public class AnnotationsInheritanceOrderRedefinitionTest { + + @Retention(RetentionPolicy.RUNTIME) + @Inherited + @interface Ann1 { + String value(); + } + + @Retention(RetentionPolicy.RUNTIME) + @Inherited + @interface Ann2 { + String value(); + } + + @Retention(RetentionPolicy.RUNTIME) + @Inherited + @interface Ann3 { + String value(); + } + + @Ann1("A") + @Ann2("A") + static class A {} + + @Ann3("B") + static class B extends A {} + + @Ann1("C") + @Ann3("C") + static class C extends B {} + + public static void main(String[] args) { + + StringBuilder msgs = new StringBuilder(); + boolean ok = true; + + ok &= annotationsEqual(msgs, A.class, true, + ann(Ann1.class, "A"), ann(Ann2.class, "A")); + ok &= annotationsEqual(msgs, A.class, false, + ann(Ann1.class, "A"), ann(Ann2.class, "A")); + ok &= annotationsEqual(msgs, B.class, true, + ann(Ann3.class, "B")); + ok &= annotationsEqual(msgs, B.class, false, + ann(Ann1.class, "A"), ann(Ann2.class, "A"), ann(Ann3.class, "B")); + ok &= annotationsEqual(msgs, C.class, true, + ann(Ann1.class, "C"), ann(Ann3.class, "C")); + ok &= annotationsEqual(msgs, C.class, false, + ann(Ann1.class, "C"), ann(Ann2.class, "A"), ann(Ann3.class, "C")); + + Annotation[] declaredAnnotatiosA = A.class.getDeclaredAnnotations(); + Annotation[] annotationsA = A.class.getAnnotations(); + Annotation[] declaredAnnotatiosB = B.class.getDeclaredAnnotations(); + Annotation[] annotationsB = B.class.getAnnotations(); + Annotation[] declaredAnnotatiosC = C.class.getDeclaredAnnotations(); + Annotation[] annotationsC = C.class.getAnnotations(); + + incrementClassRedefinedCount(A.class); + incrementClassRedefinedCount(B.class); + incrementClassRedefinedCount(C.class); + + ok &= annotationsEqualButNotSame(msgs, A.class, true, declaredAnnotatiosA); + ok &= annotationsEqualButNotSame(msgs, A.class, false, annotationsA); + ok &= annotationsEqualButNotSame(msgs, B.class, true, declaredAnnotatiosB); + ok &= annotationsEqualButNotSame(msgs, B.class, false, annotationsB); + ok &= annotationsEqualButNotSame(msgs, C.class, true, declaredAnnotatiosC); + ok &= annotationsEqualButNotSame(msgs, C.class, false, annotationsC); + + if (!ok) { + throw new RuntimeException("test failure\n" + msgs); + } + } + + // utility methods + + private static boolean annotationsEqualButNotSame(StringBuilder msgs, + Class declaringClass, boolean declaredOnly, Annotation[] oldAnns) { + if (!annotationsEqual(msgs, declaringClass, declaredOnly, oldAnns)) { + return false; + } + Annotation[] anns = declaredOnly + ? declaringClass.getDeclaredAnnotations() + : declaringClass.getAnnotations(); + List sameAnns = new ArrayList<>(); + for (int i = 0; i < anns.length; i++) { + if (anns[i] == oldAnns[i]) { + sameAnns.add(anns[i]); + } + } + if (!sameAnns.isEmpty()) { + msgs.append(declaredOnly ? "declared " : "").append("annotations for ") + .append(declaringClass.getSimpleName()) + .append(" not re-parsed after class redefinition: ") + .append(toSimpleString(sameAnns)).append("\n"); + return false; + } else { + return true; + } + } + + private static boolean annotationsEqual(StringBuilder msgs, + Class declaringClass, boolean declaredOnly, Annotation... expectedAnns) { + Annotation[] anns = declaredOnly + ? declaringClass.getDeclaredAnnotations() + : declaringClass.getAnnotations(); + if (!Arrays.equals(anns, expectedAnns)) { + msgs.append(declaredOnly ? "declared " : "").append("annotations for ") + .append(declaringClass.getSimpleName()).append(" are: ") + .append(toSimpleString(anns)).append(", expected: ") + .append(toSimpleString(expectedAnns)).append("\n"); + return false; + } else { + return true; + } + } + + private static Annotation ann(Class annotationType, + Object value) { + return AnnotationParser.annotationForMap(annotationType, + Collections.singletonMap("value", value)); + } + + private static String toSimpleString(List anns) { + return toSimpleString(anns.toArray(new Annotation[anns.size()])); + } + + private static String toSimpleString(Annotation[] anns) { + StringJoiner joiner = new StringJoiner(", "); + for (Annotation ann : anns) { + joiner.add(toSimpleString(ann)); + } + return joiner.toString(); + } + + private static String toSimpleString(Annotation ann) { + Class annotationType = ann.annotationType(); + Object value; + try { + value = annotationType.getDeclaredMethod("value").invoke(ann); + } catch (IllegalAccessException | InvocationTargetException + | NoSuchMethodException e) { + throw new RuntimeException(e); + } + return "@" + annotationType.getSimpleName() + "(" + value + ")"; + } + + private static final Field classRedefinedCountField; + + static { + try { + classRedefinedCountField = Class.class.getDeclaredField("classRedefinedCount"); + classRedefinedCountField.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new Error(e); + } + } + + private static void incrementClassRedefinedCount(Class clazz) { + try { + classRedefinedCountField.set(clazz, + ((Integer) classRedefinedCountField.get(clazz)) + 1); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/jdk/test/java/lang/invoke/7087570/Test7087570.java b/jdk/test/java/lang/invoke/7087570/Test7087570.java index 572faccdf5a..732467b8c62 100644 --- a/jdk/test/java/lang/invoke/7087570/Test7087570.java +++ b/jdk/test/java/lang/invoke/7087570/Test7087570.java @@ -35,20 +35,9 @@ import java.util.*; import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.*; +import static java.lang.invoke.MethodHandleInfo.*; public class Test7087570 { - // XXX may remove the following constant declarations when MethodHandleInfo is made public - private static final int - REF_getField = 1, - REF_getStatic = 2, - REF_putField = 3, - REF_putStatic = 4, - REF_invokeVirtual = 5, - REF_invokeStatic = 6, - REF_invokeSpecial = 7, - REF_newInvokeSpecial = 8, - REF_invokeInterface = 9, - REF_LIMIT = 10; private static final TestMethodData[] TESTS = new TestMethodData[] { // field accessors @@ -87,17 +76,17 @@ public class Test7087570 { } private static void doTest(MethodHandle mh, TestMethodData testMethod) { - Object mhi = newMethodHandleInfo(mh); + MethodHandleInfo mhi = LOOKUP.revealDirect(mh); System.out.printf("%s.%s: %s, nominal refKind: %s, actual refKind: %s\n", testMethod.clazz.getName(), testMethod.name, testMethod.methodType, - REF_KIND_NAMES[testMethod.referenceKind], - REF_KIND_NAMES[getReferenceKind(mhi)]); - assertEquals(testMethod.name, getName(mhi)); - assertEquals(testMethod.methodType, getMethodType(mhi)); - assertEquals(testMethod.declaringClass, getDeclaringClass(mhi)); + referenceKindToString(testMethod.referenceKind), + referenceKindToString(mhi.getReferenceKind())); + assertEquals(testMethod.name, mhi.getName()); + assertEquals(testMethod.methodType, mhi.getMethodType()); + assertEquals(testMethod.declaringClass, mhi.getDeclaringClass()); assertEquals(testMethod.referenceKind == REF_invokeSpecial, isInvokeSpecial(mh)); - assertRefKindEquals(testMethod.referenceKind, getReferenceKind(mhi)); + assertRefKindEquals(testMethod.referenceKind, mhi.getReferenceKind()); } private static void testWithLookup() throws Throwable { @@ -122,50 +111,8 @@ public class Test7087570 { return methodType(void.class, clazz); } - private static final String[] REF_KIND_NAMES = { - "MH::invokeBasic", - "REF_getField", "REF_getStatic", "REF_putField", "REF_putStatic", - "REF_invokeVirtual", "REF_invokeStatic", "REF_invokeSpecial", - "REF_newInvokeSpecial", "REF_invokeInterface" - }; - private static final Lookup LOOKUP = lookup(); - // XXX may remove the following reflective logic when MethodHandleInfo is made public - private static final MethodHandle MH_IS_INVOKESPECIAL; - private static final MethodHandle MHI_CONSTRUCTOR; - private static final MethodHandle MHI_GET_NAME; - private static final MethodHandle MHI_GET_METHOD_TYPE; - private static final MethodHandle MHI_GET_DECLARING_CLASS; - private static final MethodHandle MHI_GET_REFERENCE_KIND; - - static { - try { - // This is white box testing. Use reflection to grab private implementation bits. - String magicName = "IMPL_LOOKUP"; - Field magicLookup = MethodHandles.Lookup.class.getDeclaredField(magicName); - // This unit test will fail if a security manager is installed. - magicLookup.setAccessible(true); - // Forbidden fruit... - Lookup directInvokeLookup = (Lookup) magicLookup.get(null); - Class mhiClass = Class.forName("java.lang.invoke.MethodHandleInfo", false, MethodHandle.class.getClassLoader()); - MH_IS_INVOKESPECIAL = directInvokeLookup - .findVirtual(MethodHandle.class, "isInvokeSpecial", methodType(boolean.class)); - MHI_CONSTRUCTOR = directInvokeLookup - .findConstructor(mhiClass, methodType(void.class, MethodHandle.class)); - MHI_GET_NAME = directInvokeLookup - .findVirtual(mhiClass, "getName", methodType(String.class)); - MHI_GET_METHOD_TYPE = directInvokeLookup - .findVirtual(mhiClass, "getMethodType", methodType(MethodType.class)); - MHI_GET_DECLARING_CLASS = directInvokeLookup - .findVirtual(mhiClass, "getDeclaringClass", methodType(Class.class)); - MHI_GET_REFERENCE_KIND = directInvokeLookup - .findVirtual(mhiClass, "getReferenceKind", methodType(int.class)); - } catch (ReflectiveOperationException ex) { - throw new Error(ex); - } - } - private static class TestMethodData { final Class clazz; final String name; @@ -208,7 +155,9 @@ public class Test7087570 { return LOOKUP.findStatic(testMethod.clazz, testMethod.name, testMethod.methodType); case REF_invokeSpecial: Class thisClass = LOOKUP.lookupClass(); - return LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass); + MethodHandle smh = LOOKUP.findSpecial(testMethod.clazz, testMethod.name, testMethod.methodType, thisClass); + noteInvokeSpecial(smh); + return smh; case REF_newInvokeSpecial: return LOOKUP.findConstructor(testMethod.clazz, testMethod.methodType); default: @@ -238,7 +187,9 @@ public class Test7087570 { case REF_invokeSpecial: { Method m = testMethod.clazz.getDeclaredMethod(testMethod.name, testMethod.methodType.parameterArray()); Class thisClass = LOOKUP.lookupClass(); - return LOOKUP.unreflectSpecial(m, thisClass); + MethodHandle smh = LOOKUP.unreflectSpecial(m, thisClass); + noteInvokeSpecial(smh); + return smh; } case REF_newInvokeSpecial: { Constructor c = testMethod.clazz.getDeclaredConstructor(testMethod.methodType.parameterArray()); @@ -249,59 +200,20 @@ public class Test7087570 { } } - private static Object newMethodHandleInfo(MethodHandle mh) { - try { - return MHI_CONSTRUCTOR.invoke(mh); - } catch (Throwable ex) { - throw new Error(ex); - } + private static List specialMethodHandles = new ArrayList<>(); + private static void noteInvokeSpecial(MethodHandle mh) { + specialMethodHandles.add(mh); + assert(isInvokeSpecial(mh)); } - private static boolean isInvokeSpecial(MethodHandle mh) { - try { - return (boolean) MH_IS_INVOKESPECIAL.invokeExact(mh); - } catch (Throwable ex) { - throw new Error(ex); - } - } - - private static String getName(Object mhi) { - try { - return (String) MHI_GET_NAME.invoke(mhi); - } catch (Throwable ex) { - throw new Error(ex); - } - } - - private static MethodType getMethodType(Object mhi) { - try { - return (MethodType) MHI_GET_METHOD_TYPE.invoke(mhi); - } catch (Throwable ex) { - throw new Error(ex); - } - } - - private static Class getDeclaringClass(Object mhi) { - try { - return (Class) MHI_GET_DECLARING_CLASS.invoke(mhi); - } catch (Throwable ex) { - throw new Error(ex); - } - } - - private static int getReferenceKind(Object mhi) { - try { - return (int) MHI_GET_REFERENCE_KIND.invoke(mhi); - } catch (Throwable ex) { - throw new Error(ex); - } + return specialMethodHandles.contains(mh); } private static void assertRefKindEquals(int expect, int observed) { if (expect == observed) return; - String msg = "expected " + REF_KIND_NAMES[(int) expect] + - " but observed " + REF_KIND_NAMES[(int) observed]; + String msg = "expected " + referenceKindToString(expect) + + " but observed " + referenceKindToString(observed); System.out.println("FAILED: " + msg); throw new AssertionError(msg); } diff --git a/jdk/test/java/lang/invoke/RevealDirectTest.java b/jdk/test/java/lang/invoke/RevealDirectTest.java new file mode 100644 index 00000000000..f05b19077c1 --- /dev/null +++ b/jdk/test/java/lang/invoke/RevealDirectTest.java @@ -0,0 +1,753 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 verify Lookup.revealDirect on a variety of input handles + * @compile -XDignore.symbol.file RevealDirectTest.java + * @run junit/othervm -ea -esa test.java.lang.invoke.RevealDirectTest + * + * @test + * @summary verify Lookup.revealDirect on a variety of input handles, with security manager + * @run main/othervm/policy=jtreg.security.policy/secure=java.lang.SecurityManager -ea -esa test.java.lang.invoke.RevealDirectTest + */ + +/* To run manually: + * $ $JAVA8X_HOME/bin/javac -cp $JUNIT4_JAR -d ../../../.. -XDignore.symbol.file RevealDirectTest.java + * $ $JAVA8X_HOME/bin/java -cp $JUNIT4_JAR:../../../.. -ea -esa org.junit.runner.JUnitCore test.java.lang.invoke.RevealDirectTest + * $ $JAVA8X_HOME/bin/java -cp $JUNIT4_JAR:../../../.. -ea -esa -Djava.security.manager test.java.lang.invoke.RevealDirectTest + */ + +package test.java.lang.invoke; + +import java.lang.reflect.*; +import java.lang.invoke.*; +import static java.lang.invoke.MethodHandles.*; +import static java.lang.invoke.MethodType.*; +import static java.lang.invoke.MethodHandleInfo.*; +import java.util.*; +import static org.junit.Assert.*; +import org.junit.*; + +public class RevealDirectTest { + public static void main(String... av) throws Throwable { + // Run the @Test methods explicitly, in case we don't want to use the JUnitCore driver. + // This appears to be necessary when running with a security manager. + Throwable fail = null; + for (Method test : RevealDirectTest.class.getDeclaredMethods()) { + if (!test.isAnnotationPresent(Test.class)) continue; + try { + test.invoke(new RevealDirectTest()); + } catch (Throwable ex) { + if (ex instanceof InvocationTargetException) + ex = ex.getCause(); + if (fail == null) fail = ex; + System.out.println("Testcase: "+test.getName() + +"("+test.getDeclaringClass().getName() + +"):\tCaused an ERROR"); + System.out.println(ex); + ex.printStackTrace(System.out); + } + } + if (fail != null) throw fail; + } + + public interface SimpleSuperInterface { + public abstract int getInt(); + public static void printAll(String... args) { + System.out.println(Arrays.toString(args)); + } + public int NICE_CONSTANT = 42; + } + public interface SimpleInterface extends SimpleSuperInterface { + default float getFloat() { return getInt(); } + public static void printAll(String[] args) { + System.out.println(Arrays.toString(args)); + } + } + public static class Simple implements SimpleInterface, Cloneable { + public int intField; + public final int finalField; + private static String stringField; + public int getInt() { return NICE_CONSTANT; } + private static Number getNum() { return 804; } + public Simple clone() { + try { + return (Simple) super.clone(); + } catch (CloneNotSupportedException ex) { + throw new RuntimeException(ex); + } + } + Simple() { finalField = -NICE_CONSTANT; } + private static Lookup localLookup() { return lookup(); } + private static List members() { return getMembers(lookup().lookupClass()); }; + } + + static boolean VERBOSE = false; + + @Test public void testSimple() throws Throwable { + if (VERBOSE) System.out.println("@Test testSimple"); + testOnMembers("testSimple", Simple.members(), Simple.localLookup()); + } + @Test public void testPublicLookup() throws Throwable { + if (VERBOSE) System.out.println("@Test testPublicLookup"); + List mems = publicOnly(Simple.members()); + Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup(); + testOnMembers("testPublicLookup/1", mems, pubLookup); + // reveal using publicLookup: + testOnMembers("testPublicLookup/2", mems, privLookup, pubLookup); + // lookup using publicLookup, but reveal using private: + testOnMembers("testPublicLookup/3", mems, pubLookup, privLookup); + } + @Test public void testPublicLookupNegative() throws Throwable { + if (VERBOSE) System.out.println("@Test testPublicLookupNegative"); + List mems = nonPublicOnly(Simple.members()); + Lookup pubLookup = publicLookup(), privLookup = Simple.localLookup(); + testOnMembersNoLookup("testPublicLookupNegative/1", mems, pubLookup); + testOnMembersNoReveal("testPublicLookupNegative/2", mems, privLookup, pubLookup); + testOnMembersNoReflect("testPublicLookupNegative/3", mems, privLookup, pubLookup); + } + @Test public void testJavaLangClass() throws Throwable { + if (VERBOSE) System.out.println("@Test testJavaLangClass"); + List mems = callerSensitive(false, publicOnly(getMembers(Class.class))); + mems = limit(20, mems); + testOnMembers("testJavaLangClass", mems, Simple.localLookup()); + } + @Test public void testCallerSensitive() throws Throwable { + if (VERBOSE) System.out.println("@Test testCallerSensitive"); + List mems = union(getMembers(MethodHandles.class, "lookup"), + getMembers(Method.class, "invoke"), + getMembers(Field.class, "get", "set", "getLong"), + getMembers(Class.class)); + mems = callerSensitive(true, publicOnly(mems)); + mems = limit(10, mems); + testOnMembers("testCallerSensitive", mems, Simple.localLookup()); + } + @Test public void testCallerSensitiveNegative() throws Throwable { + if (VERBOSE) System.out.println("@Test testCallerSensitiveNegative"); + List mems = union(getMembers(MethodHandles.class, "lookup"), + getMembers(Class.class, "forName"), + getMembers(Method.class, "invoke")); + mems = callerSensitive(true, publicOnly(mems)); + // CS methods cannot be looked up with publicLookup + testOnMembersNoLookup("testCallerSensitiveNegative", mems, publicLookup()); + } + @Test public void testMethodHandleNatives() throws Throwable { + if (VERBOSE) System.out.println("@Test testMethodHandleNatives"); + List mems = getMembers(MethodHandle.class, "invoke", "invokeExact"); + testOnMembers("testMethodHandleNatives", mems, Simple.localLookup()); + } + @Test public void testMethodHandleInvokes() throws Throwable { + if (VERBOSE) System.out.println("@Test testMethodHandleInvokes"); + List types = new ArrayList<>(); + Class[] someParamTypes = { void.class, int.class, Object.class, Object[].class }; + for (Class rt : someParamTypes) { + for (Class p0 : someParamTypes) { + if (p0 == void.class) { types.add(methodType(rt)); continue; } + for (Class p1 : someParamTypes) { + if (p1 == void.class) { types.add(methodType(rt, p0)); continue; } + for (Class p2 : someParamTypes) { + if (p2 == void.class) { types.add(methodType(rt, p0, p1)); continue; } + types.add(methodType(rt, p0, p1, p2)); + } + } + } + } + List mems = union(getPolyMembers(MethodHandle.class, "invoke", types), + getPolyMembers(MethodHandle.class, "invokeExact", types)); + testOnMembers("testMethodHandleInvokes/1", mems, Simple.localLookup()); + testOnMembers("testMethodHandleInvokes/2", mems, publicLookup()); + } + + static List getPolyMembers(Class cls, String name, List types) { + assert(cls == MethodHandle.class); + ArrayList mems = new ArrayList<>(); + for (MethodType type : types) { + mems.add(new SignaturePolymorphicMethod(name, type)); + } + return mems; + } + static List getMembers(Class cls) { + return getMembers(cls, (String[]) null); + } + static List getMembers(Class cls, String... onlyNames) { + List names = (onlyNames == null || onlyNames.length == 0 ? null : Arrays.asList(onlyNames)); + ArrayList res = new ArrayList<>(); + for (Class sup : getSupers(cls)) { + res.addAll(getDeclaredMembers(sup, "getDeclaredFields")); + res.addAll(getDeclaredMembers(sup, "getDeclaredMethods")); + res.addAll(getDeclaredMembers(sup, "getDeclaredConstructors")); + } + res = new ArrayList<>(new LinkedHashSet<>(res)); + for (int i = 0; i < res.size(); i++) { + Member mem = res.get(i); + if (!canBeReached(mem, cls) || + res.indexOf(mem) != i || + mem.isSynthetic() || + (names != null && !names.contains(mem.getName())) + ) { + res.remove(i--); + } + } + return res; + } + static List> getSupers(Class cls) { + ArrayList> res = new ArrayList<>(); + ArrayList> intfs = new ArrayList<>(); + for (Class sup = cls; sup != null; sup = sup.getSuperclass()) { + res.add(sup); + for (Class intf : cls.getInterfaces()) { + if (!intfs.contains(intf)) + intfs.add(intf); + } + } + for (int i = 0; i < intfs.size(); i++) { + for (Class intf : intfs.get(i).getInterfaces()) { + if (!intfs.contains(intf)) + intfs.add(intf); + } + } + res.addAll(intfs); + //System.out.println("getSupers => "+res); + return res; + } + static boolean hasSM() { + return (System.getSecurityManager() != null); + } + static List getDeclaredMembers(Class cls, String accessor) { + Member[] mems = {}; + Method getter = getMethod(Class.class, accessor); + if (hasSM()) { + try { + mems = (Member[]) invokeMethod(getter, cls); + } catch (SecurityException ex) { + //if (VERBOSE) ex.printStackTrace(); + accessor = accessor.replace("Declared", ""); + getter = getMethod(Class.class, accessor); + if (VERBOSE) System.out.println("replaced accessor: "+getter); + } + } + if (mems.length == 0) { + try { + mems = (Member[]) invokeMethod(getter, cls); + } catch (SecurityException ex) { + ex.printStackTrace(); + } + } + if (VERBOSE) System.out.println(accessor+" "+cls.getName()+" => "+mems.length+" members"); + return Arrays.asList(mems); + } + static Method getMethod(Class cls, String name) { + try { + return cls.getMethod(name); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + static Object invokeMethod(Method m, Object recv, Object... args) { + try { + return m.invoke(recv, args); + } catch (InvocationTargetException ex) { + Throwable ex2 = ex.getCause(); + if (ex2 instanceof RuntimeException) throw (RuntimeException) ex2; + if (ex2 instanceof Error) throw (Error) ex2; + throw new AssertionError(ex); + } catch (ReflectiveOperationException ex) { + throw new AssertionError(ex); + } + } + + static List limit(int len, List mems) { + if (mems.size() <= len) return mems; + return mems.subList(0, len); + } + @SafeVarargs + static List union(List mems, List... mem2s) { + for (List mem2 : mem2s) { + for (Member m : mem2) { + if (!mems.contains(m)) + mems.add(m); + } + } + return mems; + } + static List callerSensitive(boolean cond, List members) { + for (Iterator i = members.iterator(); i.hasNext(); ) { + Member mem = i.next(); + if (isCallerSensitive(mem) != cond) + i.remove(); + } + if (members.isEmpty()) throw new AssertionError("trivial result"); + return members; + } + static boolean isCallerSensitive(Member mem) { + if (!(mem instanceof AnnotatedElement)) return false; + AnnotatedElement ae = (AnnotatedElement) mem; + if (CS_CLASS != null) + return ae.isAnnotationPresent(sun.reflect.CallerSensitive.class); + for (java.lang.annotation.Annotation a : ae.getDeclaredAnnotations()) { + if (a.toString().contains(".CallerSensitive")) + return true; + } + return false; + } + static final Class CS_CLASS; + static { + Class c = null; + try { + c = sun.reflect.CallerSensitive.class; + } catch (SecurityException | LinkageError ex) { + } + CS_CLASS = c; + } + static List publicOnly(List members) { + return removeMods(members, Modifier.PUBLIC, 0); + } + static List nonPublicOnly(List members) { + return removeMods(members, Modifier.PUBLIC, -1); + } + static List removeMods(List members, int mask, int bits) { + int publicMods = (mask & Modifier.PUBLIC); + members = new ArrayList<>(members); + for (Iterator i = members.iterator(); i.hasNext(); ) { + Member mem = i.next(); + int mods = mem.getModifiers(); + if ((publicMods & mods) != 0 && + (publicMods & mem.getDeclaringClass().getModifiers()) == 0) + mods -= publicMods; + if ((mods & mask) == (bits & mask)) + i.remove(); + } + return members; + } + + void testOnMembers(String tname, List mems, Lookup lookup, Lookup... lookups) throws Throwable { + if (VERBOSE) System.out.println("testOnMembers "+mems); + Lookup revLookup = (lookups.length > 0) ? lookups[0] : null; + if (revLookup == null) revLookup = lookup; + Lookup refLookup = (lookups.length > 1) ? lookups[1] : null; + if (refLookup == null) refLookup = lookup; + assert(lookups.length <= 2); + testOnMembersImpl(tname, mems, lookup, revLookup, refLookup, NO_FAIL); + } + void testOnMembersNoLookup(String tname, List mems, Lookup lookup) throws Throwable { + if (VERBOSE) System.out.println("testOnMembersNoLookup "+mems); + testOnMembersImpl(tname, mems, lookup, null, null, FAIL_LOOKUP); + } + void testOnMembersNoReveal(String tname, List mems, + Lookup lookup, Lookup negLookup) throws Throwable { + if (VERBOSE) System.out.println("testOnMembersNoReveal "+mems); + testOnMembersImpl(tname, mems, lookup, negLookup, null, FAIL_REVEAL); + } + void testOnMembersNoReflect(String tname, List mems, + Lookup lookup, Lookup negLookup) throws Throwable { + if (VERBOSE) System.out.println("testOnMembersNoReflect "+mems); + testOnMembersImpl(tname, mems, lookup, lookup, negLookup, FAIL_REFLECT); + } + void testOnMembersImpl(String tname, List mems, + Lookup lookup, + Lookup revLookup, + Lookup refLookup, + int failureMode) throws Throwable { + Throwable fail = null; + int failCount = 0; + failureModeCounts = new int[FAIL_MODE_COUNT]; + long tm0 = System.currentTimeMillis(); + for (Member mem : mems) { + try { + testWithMember(mem, lookup, revLookup, refLookup, failureMode); + } catch (Throwable ex) { + if (fail == null) fail = ex; + if (++failCount > 10) { System.out.println("*** FAIL: too many failures"); break; } + System.out.println("*** FAIL: "+mem+" => "+ex); + if (VERBOSE) ex.printStackTrace(System.out); + } + } + long tm1 = System.currentTimeMillis(); + System.out.printf("@Test %s executed %s tests in %d ms", + tname, testKinds(failureModeCounts), (tm1-tm0)).println(); + if (fail != null) throw fail; + } + static String testKinds(int[] modes) { + int pos = modes[0], neg = -pos; + for (int n : modes) neg += n; + if (neg == 0) return pos + " positive"; + String negs = ""; + for (int n : modes) negs += "/"+n; + negs = negs.replaceFirst("/"+pos+"/", ""); + negs += " negative"; + if (pos == 0) return negs; + return pos + " positive, " + negs; + } + static class SignaturePolymorphicMethod implements Member { // non-reflected instance of MH.invoke* + final String name; + final MethodType type; + SignaturePolymorphicMethod(String name, MethodType type) { + this.name = name; + this.type = type; + } + public String toString() { + String typeStr = type.toString(); + if (isVarArgs()) typeStr = typeStr.replaceFirst("\\[\\])$", "...)"); + return (Modifier.toString(getModifiers()) + +typeStr.substring(0, typeStr.indexOf('('))+" " + +getDeclaringClass().getTypeName()+"." + +getName()+typeStr.substring(typeStr.indexOf('('))); + } + public boolean equals(Object x) { + return (x instanceof SignaturePolymorphicMethod && equals((SignaturePolymorphicMethod)x)); + } + public boolean equals(SignaturePolymorphicMethod that) { + return this.name.equals(that.name) && this.type.equals(that.type); + } + public int hashCode() { + return name.hashCode() * 31 + type.hashCode(); + } + public Class getDeclaringClass() { return MethodHandle.class; } + public String getName() { return name; } + public MethodType getMethodType() { return type; } + public int getModifiers() { return Modifier.PUBLIC | Modifier.FINAL | Modifier.NATIVE | SYNTHETIC; } + public boolean isVarArgs() { return Modifier.isTransient(getModifiers()); } + public boolean isSynthetic() { return true; } + public Class getReturnType() { return type.returnType(); } + public Class[] getParameterTypes() { return type.parameterArray(); } + static final int SYNTHETIC = 0x00001000; + } + static class UnreflectResult { // a tuple + final MethodHandle mh; + final Throwable ex; + final byte kind; + final Member mem; + final int var; + UnreflectResult(MethodHandle mh, byte kind, Member mem, int var) { + this.mh = mh; + this.ex = null; + this.kind = kind; + this.mem = mem; + this.var = var; + } + UnreflectResult(Throwable ex, byte kind, Member mem, int var) { + this.mh = null; + this.ex = ex; + this.kind = kind; + this.mem = mem; + this.var = var; + } + public String toString() { + return toInfoString()+"/v"+var; + } + public String toInfoString() { + return String.format("%s %s.%s:%s", MethodHandleInfo.referenceKindToString(kind), + mem.getDeclaringClass().getName(), name(mem), type(mem, kind)); + } + static String name(Member mem) { + if (mem instanceof Constructor) return ""; + return mem.getName(); + } + static MethodType type(Member mem, byte kind) { + if (mem instanceof Field) { + Class type = ((Field)mem).getType(); + if (kind == REF_putStatic || kind == REF_putField) + return methodType(void.class, type); + return methodType(type); + } else if (mem instanceof SignaturePolymorphicMethod) { + return ((SignaturePolymorphicMethod)mem).getMethodType(); + } + Class[] params = ((Executable)mem).getParameterTypes(); + if (mem instanceof Constructor) + return methodType(void.class, params); + Class type = ((Method)mem).getReturnType(); + return methodType(type, params); + } + } + static UnreflectResult unreflectMember(Lookup lookup, Member mem, int variation) { + byte[] refKind = {0}; + try { + return unreflectMemberOrThrow(lookup, mem, variation, refKind); + } catch (ReflectiveOperationException|SecurityException ex) { + return new UnreflectResult(ex, refKind[0], mem, variation); + } + } + static UnreflectResult unreflectMemberOrThrow(Lookup lookup, Member mem, int variation, + byte[] refKind) throws ReflectiveOperationException { + Class cls = lookup.lookupClass(); + Class defc = mem.getDeclaringClass(); + String name = mem.getName(); + int mods = mem.getModifiers(); + boolean isStatic = Modifier.isStatic(mods); + MethodHandle mh = null; + byte kind = 0; + if (mem instanceof Method) { + Method m = (Method) mem; + MethodType type = methodType(m.getReturnType(), m.getParameterTypes()); + boolean canBeSpecial = (!isStatic && + (lookup.lookupModes() & Modifier.PRIVATE) != 0 && + defc.isAssignableFrom(cls) && + (!defc.isInterface() || Arrays.asList(cls.getInterfaces()).contains(defc))); + if (variation >= 2) + kind = REF_invokeSpecial; + else if (isStatic) + kind = REF_invokeStatic; + else if (defc.isInterface()) + kind = REF_invokeInterface; + else + kind = REF_invokeVirtual; + refKind[0] = kind; + switch (variation) { + case 0: + mh = lookup.unreflect(m); + break; + case 1: + if (defc == MethodHandle.class && + !isStatic && + m.isVarArgs() && + Modifier.isFinal(mods) && + Modifier.isNative(mods)) { + break; + } + if (isStatic) + mh = lookup.findStatic(defc, name, type); + else + mh = lookup.findVirtual(defc, name, type); + break; + case 2: + if (!canBeSpecial) + break; + mh = lookup.unreflectSpecial(m, lookup.lookupClass()); + break; + case 3: + if (!canBeSpecial) + break; + mh = lookup.findSpecial(defc, name, type, lookup.lookupClass()); + break; + } + } else if (mem instanceof SignaturePolymorphicMethod) { + SignaturePolymorphicMethod m = (SignaturePolymorphicMethod) mem; + MethodType type = methodType(m.getReturnType(), m.getParameterTypes()); + kind = REF_invokeVirtual; + refKind[0] = kind; + switch (variation) { + case 0: + mh = lookup.findVirtual(defc, name, type); + break; + } + } else if (mem instanceof Constructor) { + name = ""; // not used + Constructor m = (Constructor) mem; + MethodType type = methodType(void.class, m.getParameterTypes()); + kind = REF_newInvokeSpecial; + refKind[0] = kind; + switch (variation) { + case 0: + mh = lookup.unreflectConstructor(m); + break; + case 1: + mh = lookup.findConstructor(defc, type); + break; + } + } else if (mem instanceof Field) { + Field m = (Field) mem; + Class type = m.getType(); + boolean canHaveSetter = !Modifier.isFinal(mods); + if (variation >= 2) + kind = (byte)(isStatic ? REF_putStatic : REF_putField); + else + kind = (byte)(isStatic ? REF_getStatic : REF_getField); + refKind[0] = kind; + switch (variation) { + case 0: + mh = lookup.unreflectGetter(m); + break; + case 1: + if (isStatic) + mh = lookup.findStaticGetter(defc, name, type); + else + mh = lookup.findGetter(defc, name, type); + break; + case 3: + if (!canHaveSetter) + break; + mh = lookup.unreflectSetter(m); + break; + case 2: + if (!canHaveSetter) + break; + if (isStatic) + mh = lookup.findStaticSetter(defc, name, type); + else + mh = lookup.findSetter(defc, name, type); + break; + } + } else { + throw new IllegalArgumentException(String.valueOf(mem)); + } + if (mh == null) + // ran out of valid variations; return null to caller + return null; + return new UnreflectResult(mh, kind, mem, variation); + } + static boolean canBeReached(Member mem, Class cls) { + Class defc = mem.getDeclaringClass(); + String name = mem.getName(); + int mods = mem.getModifiers(); + if (mem instanceof Constructor) { + name = ""; // according to 292 spec. + } + if (defc == cls) + return true; + if (name.startsWith("<")) + return false; // only my own constructors + if (Modifier.isPrivate(mods)) + return false; // only my own constructors + if (defc.getPackage() == cls.getPackage()) + return true; // package access or greater OK + if (Modifier.isPublic(mods)) + return true; // publics always OK + if (Modifier.isProtected(mods) && defc.isAssignableFrom(cls)) + return true; // protected OK + return false; + } + static boolean consistent(UnreflectResult res, MethodHandleInfo info) { + assert(res.mh != null); + assertEquals(res.kind, info.getReferenceKind()); + assertEquals(res.mem.getModifiers(), info.getModifiers()); + assertEquals(res.mem.getDeclaringClass(), info.getDeclaringClass()); + String expectName = res.mem.getName(); + if (res.kind == REF_newInvokeSpecial) + expectName = ""; + assertEquals(expectName, info.getName()); + MethodType expectType = res.mh.type(); + if ((res.kind & 1) == (REF_getField & 1)) + expectType = expectType.dropParameterTypes(0, 1); + if (res.kind == REF_newInvokeSpecial) + expectType = expectType.changeReturnType(void.class); + assertEquals(expectType, info.getMethodType()); + assertEquals(res.mh.isVarargsCollector(), isVarArgs(info)); + assertEquals(res.toInfoString(), info.toString()); + assertEquals(res.toInfoString(), MethodHandleInfo.toString(info.getReferenceKind(), info.getDeclaringClass(), info.getName(), info.getMethodType())); + return true; + } + static boolean isVarArgs(MethodHandleInfo info) { + return info.isVarArgs(); + } + static boolean consistent(Member mem, Member mem2) { + assertEquals(mem, mem2); + return true; + } + static boolean consistent(MethodHandleInfo info, MethodHandleInfo info2) { + assertEquals(info.getReferenceKind(), info2.getReferenceKind()); + assertEquals(info.getModifiers(), info2.getModifiers()); + assertEquals(info.getDeclaringClass(), info2.getDeclaringClass()); + assertEquals(info.getName(), info2.getName()); + assertEquals(info.getMethodType(), info2.getMethodType()); + assertEquals(isVarArgs(info), isVarArgs(info)); + return true; + } + static boolean consistent(MethodHandle mh, MethodHandle mh2) { + assertEquals(mh.type(), mh2.type()); + assertEquals(mh.isVarargsCollector(), mh2.isVarargsCollector()); + return true; + } + int[] failureModeCounts; + static final int NO_FAIL=0, FAIL_LOOKUP=1, FAIL_REVEAL=2, FAIL_REFLECT=3, FAIL_MODE_COUNT=4; + void testWithMember(Member mem, + Lookup lookup, // initial lookup of member => MH + Lookup revLookup, // reveal MH => info + Lookup refLookup, // reflect info => member + int failureMode) throws Throwable { + boolean expectEx1 = (failureMode == FAIL_LOOKUP); // testOnMembersNoLookup + boolean expectEx2 = (failureMode == FAIL_REVEAL); // testOnMembersNoReveal + boolean expectEx3 = (failureMode == FAIL_REFLECT); // testOnMembersNoReflect + for (int variation = 0; ; variation++) { + UnreflectResult res = unreflectMember(lookup, mem, variation); + failureModeCounts[failureMode] += 1; + if (variation == 0) assert(res != null); + if (res == null) break; + if (VERBOSE && variation == 0) + System.out.println("from "+mem.getDeclaringClass().getSimpleName()); + MethodHandle mh = res.mh; + Throwable ex1 = res.ex; + if (VERBOSE) System.out.println(" "+variation+": "+res+" << "+(mh != null ? mh : ex1)); + if (expectEx1 && ex1 != null) + continue; // this is OK; we expected that lookup to fail + if (expectEx1) + throw new AssertionError("unexpected lookup for negative test"); + if (ex1 != null && !expectEx1) { + if (failureMode != NO_FAIL) + throw new AssertionError("unexpected lookup failure for negative test", ex1); + throw ex1; + } + MethodHandleInfo info; + try { + info = revLookup.revealDirect(mh); + if (expectEx2) throw new AssertionError("unexpected revelation for negative test"); + } catch (Throwable ex2) { + if (VERBOSE) System.out.println(" "+variation+": "+res+" => "+mh.getClass().getName()+" => (EX2)"+ex2); + if (expectEx2) + continue; // this is OK; we expected the reflect to fail + if (failureMode != NO_FAIL) + throw new AssertionError("unexpected revelation failure for negative test", ex2); + throw ex2; + } + assert(consistent(res, info)); + Member mem2; + try { + mem2 = info.reflectAs(Member.class, refLookup); + if (expectEx3) throw new AssertionError("unexpected reflection for negative test"); + assert(!(mem instanceof SignaturePolymorphicMethod)); + } catch (IllegalArgumentException ex3) { + if (VERBOSE) System.out.println(" "+variation+": "+info+" => (EX3)"+ex3); + if (expectEx3) + continue; // this is OK; we expected the reflect to fail + if (mem instanceof SignaturePolymorphicMethod) + continue; // this is OK; we cannot reflect MH.invokeExact(a,b,c) + if (failureMode != NO_FAIL) + throw new AssertionError("unexpected reflection failure for negative test", ex3); + throw ex3; + } + assert(consistent(mem, mem2)); + UnreflectResult res2 = unreflectMember(lookup, mem2, variation); + MethodHandle mh2 = res2.mh; + assert(consistent(mh, mh2)); + MethodHandleInfo info2 = lookup.revealDirect(mh2); + assert(consistent(info, info2)); + assert(consistent(res, info2)); + Member mem3; + if (hasSM()) + mem3 = info2.reflectAs(Member.class, lookup); + else + mem3 = MethodHandles.reflectAs(Member.class, mh2); + assert(consistent(mem2, mem3)); + if (hasSM()) { + try { + MethodHandles.reflectAs(Member.class, mh2); + throw new AssertionError("failed to throw on "+mem3); + } catch (SecurityException ex3) { + // OK... + } + } + } + } +} diff --git a/jdk/test/java/lang/invoke/jtreg.security.policy b/jdk/test/java/lang/invoke/jtreg.security.policy new file mode 100644 index 00000000000..d32c7af9b3f --- /dev/null +++ b/jdk/test/java/lang/invoke/jtreg.security.policy @@ -0,0 +1,9 @@ +/* + * security policy used by the test process + * must allow file reads so that jtreg itself can run + */ + +grant { + // standard test activation permissions + permission java.io.FilePermission "*", "read"; +}; diff --git a/jdk/test/java/lang/management/ThreadMXBean/LockedMonitors.java b/jdk/test/java/lang/management/ThreadMXBean/LockedMonitors.java index 5c9747eaf9e..a693d71a841 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/LockedMonitors.java +++ b/jdk/test/java/lang/management/ThreadMXBean/LockedMonitors.java @@ -37,7 +37,7 @@ * @build Barrier * @build LockingThread * @build ThreadDump - * @run main LockedMonitors + * @run main/othervm LockedMonitors */ import java.lang.management.*; diff --git a/jdk/test/java/lang/management/ThreadMXBean/LockedSynchronizers.java b/jdk/test/java/lang/management/ThreadMXBean/LockedSynchronizers.java index b732d43f311..0fc35325926 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/LockedSynchronizers.java +++ b/jdk/test/java/lang/management/ThreadMXBean/LockedSynchronizers.java @@ -33,7 +33,7 @@ * @build Barrier * @build SynchronizerLockingThread * @build ThreadDump - * @run main LockedSynchronizers + * @run main/othervm LockedSynchronizers */ import java.lang.management.*; diff --git a/jdk/test/java/lang/management/ThreadMXBean/Locks.java b/jdk/test/java/lang/management/ThreadMXBean/Locks.java index 5969aebc6d0..c078dccd62d 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/Locks.java +++ b/jdk/test/java/lang/management/ThreadMXBean/Locks.java @@ -193,16 +193,18 @@ public class Locks { public CheckerThread() { super("CheckerThread"); } + + private void waitForState(Thread.State state) { + thrsync.waitForSignal(); + while (waiter.getState() != state) { + goSleep(10); + } + } + public void run() { synchronized (ready) { // wait until WaitingThread about to wait for objC - thrsync.waitForSignal(); - - int retryCount = 0; - while (waiter.getState() != Thread.State.WAITING - && retryCount++ < 500) { - goSleep(100); - } + waitForState(Thread.State.WAITING); checkBlockedObject(waiter, objC, null, Thread.State.WAITING); synchronized (objC) { @@ -211,16 +213,13 @@ public class Locks { // wait for waiter thread to about to enter // synchronized object ready. - thrsync.waitForSignal(); - // give chance for waiter thread to get blocked on - // object ready. - goSleep(50); + waitForState(Thread.State.BLOCKED); checkBlockedObject(waiter, ready, this, Thread.State.BLOCKED); } // wait for signal from waiting thread that it is about // wait for objC. - thrsync.waitForSignal(); + waitForState(Thread.State.WAITING); synchronized(objC) { checkBlockedObject(waiter, objC, Thread.currentThread(), Thread.State.WAITING); objC.notify(); diff --git a/jdk/test/java/lang/management/ThreadMXBean/MyOwnSynchronizer.java b/jdk/test/java/lang/management/ThreadMXBean/MyOwnSynchronizer.java index 3968a5aab6f..c102583ddbf 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/MyOwnSynchronizer.java +++ b/jdk/test/java/lang/management/ThreadMXBean/MyOwnSynchronizer.java @@ -30,7 +30,7 @@ * * @build Barrier * @build ThreadDump - * @run main MyOwnSynchronizer + * @run main/othervm MyOwnSynchronizer */ import java.lang.management.*; diff --git a/jdk/test/java/lang/management/ThreadMXBean/SharedSynchronizer.java b/jdk/test/java/lang/management/ThreadMXBean/SharedSynchronizer.java index 6f5065dda03..6fc9e9ee0e5 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/SharedSynchronizer.java +++ b/jdk/test/java/lang/management/ThreadMXBean/SharedSynchronizer.java @@ -28,7 +28,7 @@ * in shared mode which has no owner when a thread is parked. * @author Mandy Chung * - * @run main SharedSynchronizer + * @run main/othervm SharedSynchronizer */ diff --git a/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java b/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java index ae65ca924a2..e03042864c9 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java +++ b/jdk/test/java/lang/management/ThreadMXBean/SynchronizationStatistics.java @@ -30,7 +30,7 @@ * * @ignore 6309226 * @build Semaphore - * @run main SynchronizationStatistics + * @run main/othervm SynchronizationStatistics */ import java.lang.management.*; diff --git a/jdk/test/java/lang/management/ThreadMXBean/ThreadExecutionSynchronizer.java b/jdk/test/java/lang/management/ThreadMXBean/ThreadExecutionSynchronizer.java index dc887829bdf..6cba7e73521 100644 --- a/jdk/test/java/lang/management/ThreadMXBean/ThreadExecutionSynchronizer.java +++ b/jdk/test/java/lang/management/ThreadMXBean/ThreadExecutionSynchronizer.java @@ -23,7 +23,7 @@ /* * - * @summary Thiseclass is used to synchronize execution off two threads. + * @summary This class is used to synchronize execution of two threads. * @author Swamy Venkataramanappa */ @@ -31,8 +31,8 @@ import java.util.concurrent.Semaphore; public class ThreadExecutionSynchronizer { - private boolean waiting; - private Semaphore semaphore; + private volatile boolean waiting; + private final Semaphore semaphore; public ThreadExecutionSynchronizer() { semaphore = new Semaphore(1); diff --git a/jdk/test/java/lang/reflect/Generics/Probe.java b/jdk/test/java/lang/reflect/Generics/Probe.java index 1cdd5af3bdd..ebd98465e0c 100644 --- a/jdk/test/java/lang/reflect/Generics/Probe.java +++ b/jdk/test/java/lang/reflect/Generics/Probe.java @@ -50,9 +50,9 @@ import static java.util.Arrays.*; "java.util.HashMap$EntryIterator", "java.util.HashMap$KeyIterator", "java.util.HashMap$ValueIterator", - "java.util.LinkedHashMap$EntryIterator", - "java.util.LinkedHashMap$KeyIterator", - "java.util.LinkedHashMap$ValueIterator"}) + "java.util.LinkedHashMap$LinkedEntryIterator", + "java.util.LinkedHashMap$LinkedKeyIterator", + "java.util.LinkedHashMap$LinkedValueIterator"}) public class Probe { public static void main (String... args) throws Throwable { Classes classesAnnotation = (Probe.class).getAnnotation(Classes.class); diff --git a/jdk/test/java/net/CookieHandler/LocalHostCookie.java b/jdk/test/java/net/CookieHandler/LocalHostCookie.java index ac8d61622ef..56db947126e 100644 --- a/jdk/test/java/net/CookieHandler/LocalHostCookie.java +++ b/jdk/test/java/net/CookieHandler/LocalHostCookie.java @@ -72,7 +72,9 @@ public class LocalHostCookie { } } } finally { - s.stopServer(); + if (s != null) { + s.stopServer(); + } } } @@ -96,7 +98,9 @@ public class LocalHostCookie { } public void stopServer() { - server.stop(0); + if (server != null) { + server.stop(0); + } } } diff --git a/jdk/test/java/net/IDN/UseSTD3ASCIIRules.java b/jdk/test/java/net/IDN/UseSTD3ASCIIRules.java new file mode 100644 index 00000000000..0afc4a912ca --- /dev/null +++ b/jdk/test/java/net/IDN/UseSTD3ASCIIRules.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023881 + * @summary IDN.USE_STD3_ASCII_RULES option is too strict to use Unicode + * in IDN.toASCII + */ + +import java.net.*; + +public class UseSTD3ASCIIRules { + + public static void main(String[] args) throws Exception { + // Per Section 4.1, RFC 3490, if the UseSTD3ASCIIRules flag is set, + // then perform these checks: + // + // (a) Verify the absence of non-LDH ASCII code points; that is, the + // absence of 0..2C, 2E..2F, 3A..40, 5B..60, and 7B..7F. + // + // (b) Verify the absence of leading and trailing hyphen-minus; that + // is, the absence of U+002D at the beginning and end of the + // sequence. + String[] illegalNames = { + "www.example.com-", + "-www.example.com", + "-www.example.com-", + "www.ex\u002Cmple.com", + "www.ex\u007Bmple.com", + "www.ex\u007Fmple.com" + }; + + String[] legalNames = { + "www.ex-ample.com", + "www.ex\u002Dmple.com", // www.ex-mple.com + "www.ex\u007Ample.com", // www.exzmple.com + "www.ex\u3042mple.com", // www.xn--exmple-j43e.com + "www.\u3042\u3044\u3046.com", // www.xn--l8jeg.com + "www.\u793A\u4F8B.com" // www.xn--fsq092h.com + }; + + for (String name : illegalNames) { + try { + System.out.println("Convering illegal IDN: " + name); + IDN.toASCII(name, IDN.USE_STD3_ASCII_RULES); + throw new Exception( + "Expected to get IllegalArgumentException for " + name); + } catch (IllegalArgumentException iae) { + // That's the right behavior. + } + } + + for (String name : legalNames) { + System.out.println("Convering legal IDN: " + name); + System.out.println("\tThe ACE form is: " + + IDN.toASCII(name, IDN.USE_STD3_ASCII_RULES)); + } + } +} diff --git a/jdk/test/java/net/MulticastSocket/SetGetNetworkInterfaceTest.java b/jdk/test/java/net/MulticastSocket/SetGetNetworkInterfaceTest.java new file mode 100644 index 00000000000..b46bdbedbce --- /dev/null +++ b/jdk/test/java/net/MulticastSocket/SetGetNetworkInterfaceTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @bug 6458027 + * @summary Disabling IPv6 on a specific network interface causes problems. + * + */ + +import java.io.IOException; +import java.net.InetAddress; +import java.net.MulticastSocket; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Arrays; +import java.util.Enumeration; + + +public class SetGetNetworkInterfaceTest { + + public static void main(String[] args) throws Exception { + + boolean passed = true; + try { + MulticastSocket ms = new MulticastSocket(); + Enumeration networkInterfaces = NetworkInterface + .getNetworkInterfaces(); + while (networkInterfaces.hasMoreElements()) { + NetworkInterface netIf = networkInterfaces.nextElement(); + if (isNetworkInterfaceTestable(netIf)) { + printNetIfDetails(netIf); + ms.setNetworkInterface(netIf); + NetworkInterface msNetIf = ms.getNetworkInterface(); + if (netIf.equals(msNetIf)) { + System.out.println(" OK"); + } else { + System.out.println("FAILED!!!"); + printNetIfDetails(msNetIf); + passed = false; + } + System.out.println("------------------"); + } + } + } catch (IOException e) { + e.printStackTrace(); + passed = false; + } + if (!passed) { + throw new RuntimeException("Test Fail"); + } + System.out.println("Test passed "); + } + + private static boolean isNetworkInterfaceTestable(NetworkInterface netIf) throws Exception { + System.out.println("checking netif == " + netIf.getName()); + return (netIf.isUp() && netIf.supportsMulticast() && isIpAddrAvailable(netIf)); + } + + private static boolean isIpAddrAvailable (NetworkInterface netIf) { + boolean ipAddrAvailable = false; + byte[] nullIpAddr = {'0', '0', '0', '0'}; + byte[] testIpAddr = null; + + Enumeration ipAddresses = netIf.getInetAddresses(); + while (ipAddresses.hasMoreElements()) { + InetAddress testAddr = ipAddresses.nextElement(); + testIpAddr = testAddr.getAddress(); + if ((testIpAddr != null) && (!Arrays.equals(testIpAddr, nullIpAddr))) { + ipAddrAvailable = true; + break; + } else { + System.out.println("ignore netif " + netIf.getName()); + } + } + return ipAddrAvailable; + } + + private static void printNetIfDetails(NetworkInterface ni) + throws SocketException { + System.out.println("Name " + ni.getName() + " index " + ni.getIndex()); + Enumeration en = ni.getInetAddresses(); + while (en.hasMoreElements()) { + System.out.println(" InetAdress: " + en.nextElement()); + } + System.out.println("HardwareAddress: " + createMacAddrString(ni)); + System.out.println("loopback: " + ni.isLoopback() + "; pointToPoint: " + + ni.isPointToPoint() + "; virtual: " + ni.isVirtual() + + "; MTU: " + ni.getMTU()); + } + + private static String createMacAddrString(NetworkInterface netIf) + throws SocketException { + byte[] macAddr = netIf.getHardwareAddress(); + StringBuilder sb = new StringBuilder(); + if (macAddr != null) { + for (int i = 0; i < macAddr.length; i++) { + sb.append(String.format("%02X%s", macAddr[i], + (i < macAddr.length - 1) ? "-" : "")); + } + } + return sb.toString(); + } +} diff --git a/jdk/test/java/net/NetworkInterface/Equals.java b/jdk/test/java/net/NetworkInterface/Equals.java index 003fb7113ab..1c33ee835cd 100644 --- a/jdk/test/java/net/NetworkInterface/Equals.java +++ b/jdk/test/java/net/NetworkInterface/Equals.java @@ -25,41 +25,83 @@ * @bug 7003398 * @run main/othervm Equals */ -import java.net.NetworkInterface; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.Arrays; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; public class Equals { public static void main(String args[]) throws Exception { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + PrintStream bufferedOut = new PrintStream(baos); - Enumeration nifs1 = NetworkInterface.getNetworkInterfaces(); + Enumeration nifs1 = NetworkInterface.getNetworkInterfaces(); HashMap hashes = new HashMap<>(); HashMap nicMap = new HashMap<>(); while (nifs1.hasMoreElements()) { - NetworkInterface ni = (NetworkInterface)nifs1.nextElement(); + NetworkInterface ni = nifs1.nextElement(); hashes.put(ni.getName(),ni.hashCode()); nicMap.put(ni.getName(),ni); + displayInterfaceInformation(ni, bufferedOut); + bufferedOut.flush(); } System.setSecurityManager(new SecurityManager()); - Enumeration nifs2 = NetworkInterface.getNetworkInterfaces(); + Enumeration nifs2 = NetworkInterface.getNetworkInterfaces(); while (nifs2.hasMoreElements()) { - NetworkInterface ni = (NetworkInterface)nifs2.nextElement(); + NetworkInterface ni = nifs2.nextElement(); NetworkInterface niOrig = nicMap.get(ni.getName()); - int h = hashes.get(ni.getName()); - if (h != ni.hashCode()) { - throw new RuntimeException ("Hashcodes different for " + + int h = ni.hashCode(); + if (h != hashes.get(ni.getName())) { + System.out.printf("%nSystem information:%n"); + System.out.printf("%s", baos.toString("UTF8")); + System.out.printf("%nni.hashCode() returned %d, expected %d, for:%n", + h, hashes.get(ni.getName())); + displayInterfaceInformation(ni, System.out); + throw new RuntimeException("Hashcodes different for " + ni.getName()); } if (!ni.equals(niOrig)) { - throw new RuntimeException ("equality different for " + + System.out.printf("%nSystem information:%n"); + System.out.printf("%s", baos.toString("UTF8")); + System.out.printf("%nExpected the following interfaces to be the same:%n"); + displayInterfaceInformation(niOrig, System.out); + displayInterfaceInformation(ni, System.out); + throw new RuntimeException("equality different for " + ni.getName()); } } } + + static void displayInterfaceInformation(NetworkInterface netint, + PrintStream out) throws SocketException { + out.printf("Display name: %s%n", netint.getDisplayName()); + out.printf("Name: %s%n", netint.getName()); + Enumeration inetAddresses = netint.getInetAddresses(); + + for (InetAddress inetAddress : Collections.list(inetAddresses)) + out.printf("InetAddress: %s%n", inetAddress); + + out.printf("Up? %s%n", netint.isUp()); + out.printf("Loopback? %s%n", netint.isLoopback()); + out.printf("PointToPoint? %s%n", netint.isPointToPoint()); + out.printf("Supports multicast? %s%n", netint.supportsMulticast()); + out.printf("Virtual? %s%n", netint.isVirtual()); + out.printf("Hardware address: %s%n", + Arrays.toString(netint.getHardwareAddress())); + out.printf("MTU: %s%n", netint.getMTU()); + out.printf("Index: %s%n", netint.getIndex()); + out.printf("%n"); + } } + diff --git a/jdk/test/java/net/NetworkInterface/UniqueMacAddressesTest.java b/jdk/test/java/net/NetworkInterface/UniqueMacAddressesTest.java new file mode 100644 index 00000000000..4017c0702ed --- /dev/null +++ b/jdk/test/java/net/NetworkInterface/UniqueMacAddressesTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.net.InetAddress; +import java.net.NetworkInterface; +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Enumeration; +import java.util.List; + + +/* + * @test + * @bug 8021372 + * @summary Tests that the MAC addresses returned by NetworkInterface.getNetworkInterfaces are unique for each adapter. + * + */ +public class UniqueMacAddressesTest { + + public static void main(String[] args) throws Exception { + new UniqueMacAddressesTest().execute(); + System.out.println("UniqueMacAddressesTest: OK"); + } + + public UniqueMacAddressesTest() { + System.out.println("UniqueMacAddressesTest: start "); + } + + public void execute() throws Exception { + Enumeration networkInterfaces; + boolean areMacAddressesUnique = false; + List networkInterfaceList = new ArrayList(); + networkInterfaces = NetworkInterface.getNetworkInterfaces(); + + // build a list of NetworkInterface objects to test MAC address + // uniqueness + createNetworkInterfaceList(networkInterfaces, networkInterfaceList); + areMacAddressesUnique = checkMacAddressesAreUnique(networkInterfaceList); + if (!areMacAddressesUnique) { + throw new RuntimeException("mac address uniqueness test failed"); + } + } + + private boolean checkMacAddressesAreUnique ( + List networkInterfaces) throws Exception { + boolean uniqueMacAddresses = true; + for (NetworkInterface networkInterface : networkInterfaces) { + for (NetworkInterface comparisonNetIf : networkInterfaces) { + System.out.println("Comparing netif " + + networkInterface.getName() + " and netif " + + comparisonNetIf.getName()); + if (testMacAddressesEqual(networkInterface, comparisonNetIf)) { + uniqueMacAddresses = false; + break; + } + } + if (uniqueMacAddresses != true) + break; + } + return uniqueMacAddresses; + } + + private boolean testMacAddressesEqual(NetworkInterface netIf1, + NetworkInterface netIf2) throws Exception { + + byte[] rawMacAddress1 = null; + byte[] rawMacAddress2 = null; + boolean macAddressesEqual = false; + if (!netIf1.getName().equals(netIf2.getName())) { + System.out.println("compare hardware addresses " + + createMacAddressString(netIf1) + " and " + createMacAddressString(netIf2)); + rawMacAddress1 = netIf1.getHardwareAddress(); + rawMacAddress2 = netIf2.getHardwareAddress(); + macAddressesEqual = Arrays.equals(rawMacAddress1, rawMacAddress2); + } else { + // same interface + macAddressesEqual = false; + } + return macAddressesEqual; + } + + private String createMacAddressString (NetworkInterface netIf) throws Exception { + byte[] macAddr = netIf.getHardwareAddress(); + StringBuilder sb = new StringBuilder(); + if (macAddr != null) { + for (int i = 0; i < macAddr.length; i++) { + sb.append(String.format("%02X%s", macAddr[i], + (i < macAddr.length - 1) ? "-" : "")); + } + } + return sb.toString(); + } + + private void createNetworkInterfaceList(Enumeration nis, + List networkInterfaceList) throws Exception { + byte[] macAddr = null; + NetworkInterface netIf = null; + while (nis.hasMoreElements()) { + netIf = (NetworkInterface) nis.nextElement(); + if (netIf.isUp()) { + macAddr = netIf.getHardwareAddress(); + if (macAddr != null) { + System.out.println("Adding NetworkInterface " + + netIf.getName() + " with mac address " + + createMacAddressString(netIf)); + networkInterfaceList.add(netIf); + } + } + } + } +} diff --git a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java index 1763ef3a11e..dbeb491acfe 100644 --- a/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java +++ b/jdk/test/java/nio/channels/DatagramChannel/AdaptDatagramSocket.java @@ -136,7 +136,7 @@ public class AdaptDatagramSocket { echoServer.getPort()); test(address, 0, false, false); test(address, 0, false, true); - test(address, 5000, false, false); + test(address, 15000, false, false); } try (TestServers.UdpDiscardServer discardServer = TestServers.UdpDiscardServer.startNewServer()) { diff --git a/jdk/test/java/nio/channels/Selector/LotsOfChannels.java b/jdk/test/java/nio/channels/Selector/LotsOfChannels.java index d88655d807f..2db6366a7fd 100644 --- a/jdk/test/java/nio/channels/Selector/LotsOfChannels.java +++ b/jdk/test/java/nio/channels/Selector/LotsOfChannels.java @@ -22,9 +22,10 @@ */ /* @test - * @bug 4503092 + * @bug 4503092 8024883 * @summary Tests that Windows Selector can use more than 63 channels - * @run main/timeout=300 LotsOfChannels + * @run main LotsOfChannels + * @run main/othervm -Dsun.nio.ch.maxUpdateArraySize=64 LotsOfChannels * @author kladko */ diff --git a/jdk/test/java/nio/channels/Selector/SelectorLimit.java b/jdk/test/java/nio/channels/Selector/SelectorLimit.java index 27589e24665..69963db8e04 100644 --- a/jdk/test/java/nio/channels/Selector/SelectorLimit.java +++ b/jdk/test/java/nio/channels/Selector/SelectorLimit.java @@ -22,12 +22,13 @@ */ /* @test - * @bug 4777504 + * @bug 4777504 8024883 * @summary Ensure that a Selector can return at least 100 selected keys * @author Mark Reinhold * @library .. * @build SelectorLimit * @run main/othervm SelectorLimit + * @run main/othervm -Dsun.nio.ch.maxUpdateArraySize=128 SelectorLimit */ import java.io.*; diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Makefile b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Makefile index c868afe9a26..9b474913aaa 100644 --- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Makefile +++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/Makefile @@ -21,33 +21,14 @@ uname := $(shell uname) ifeq ($(uname), SunOS) PLATFORM = solaris ISAINFO = isainfo - ifndef ARCH_DATA_MODEL - ARCH_DATA_MODEL=32 - endif - ifeq ($(ARCH_DATA_MODEL), 32) - archExpr = case "`$(UNAME) -p`" in \ - i386) \ - $(ECHO) i586 \ - ;; \ - sparc*) \ - $(ECHO) sparc \ - ;; \ - *) \ - $(UNAME) -p \ - ;; \ - esac - ARCH := $(shell $(archExpr) ) - else - ARCH := $(shell $(ISAINFO) -n) - endif + ARCH_DATA_MODEL=64 + ARCH := $(shell $(ISAINFO) -n) CC = cc LD = ld CFLAGS = -D_REENTRANT -D__solaris__ LDFLAGS_COMMON = -G EXTRA_LIBS = -lc - ifeq ($(ARCH_DATA_MODEL), 64) - CC += -xarch=v9 - endif + CC += -m64 -Kpic endif ifeq ($(uname), Linux) diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-amd64/libLauncher.so b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-amd64/libLauncher.so new file mode 100644 index 00000000000..6e7c2d8f5bf Binary files /dev/null and b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-amd64/libLauncher.so differ diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-i586/libLauncher.so b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-i586/libLauncher.so deleted file mode 100644 index 440f6d7c084..00000000000 Binary files a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-i586/libLauncher.so and /dev/null differ diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-sparc/libLauncher.so b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-sparc/libLauncher.so deleted file mode 100644 index 9e3ae2b177f..00000000000 Binary files a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/lib/solaris-sparc/libLauncher.so and /dev/null differ diff --git a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh index 6d9c4afd1aa..dca835c6525 100644 --- a/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh +++ b/jdk/test/java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh @@ -1,7 +1,7 @@ #!/bin/sh # -# Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ # questions. # - # @test # @bug 4673940 # @bug 4930794 @@ -39,7 +38,6 @@ if [ "$os" != "Linux" -a "$os" != "SunOS" ]; then exit 0 fi - # if TESTJAVA isn't set then we assume an interactive run. So that it's # clear which version of 'java' is running we do a 'which java' and # a 'java -version'. @@ -64,24 +62,17 @@ export CLASSPATH # Check that we have libLauncher.so for the right platform. -# On Solaris we assume 64-bit if java -d64 works. +# On Solaris we assume 64-bit DFLAG= if [ "$os" = "SunOS" ]; then PLATFORM=solaris case "`uname -p`" in i[3-9]86) - ARCH=i586 + ARCH=amd64 ;; sparc) - ARCH=sparc - ${JAVA} -d64 -version > /dev/null 2<&1 - if [ $? = 1 ]; then - ARCH=sparc - else - ARCH=sparcv9 - DFLAG=-d64 - fi + ARCH=sparcv9 ;; esac fi diff --git a/jdk/test/java/nio/file/Files/StreamTest.java b/jdk/test/java/nio/file/Files/StreamTest.java index b5ff2977257..5304492f1db 100644 --- a/jdk/test/java/nio/file/Files/StreamTest.java +++ b/jdk/test/java/nio/file/Files/StreamTest.java @@ -43,14 +43,13 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.Arrays; -import java.util.Comparator; import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.Set; import java.util.TreeSet; import java.util.function.BiPredicate; -import java.util.stream.CloseableStream; +import java.util.stream.Stream; import java.util.stream.Collectors; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; @@ -138,14 +137,14 @@ public class StreamTest { } public void testBasic() { - try (CloseableStream s = Files.list(testFolder)) { - Object[] actual = s.sorted(Comparator.naturalOrder()).toArray(); + try (Stream s = Files.list(testFolder)) { + Object[] actual = s.sorted().toArray(); assertEquals(actual, level1); } catch (IOException ioe) { fail("Unexpected IOException"); } - try (CloseableStream s = Files.list(testFolder.resolve("empty"))) { + try (Stream s = Files.list(testFolder.resolve("empty"))) { int count = s.mapToInt(p -> 1).reduce(0, Integer::sum); assertEquals(count, 0, "Expect empty stream."); } catch (IOException ioe) { @@ -154,8 +153,8 @@ public class StreamTest { } public void testWalk() { - try (CloseableStream s = Files.walk(testFolder)) { - Object[] actual = s.sorted(Comparator.naturalOrder()).toArray(); + try (Stream s = Files.walk(testFolder)) { + Object[] actual = s.sorted().toArray(); assertEquals(actual, all); } catch (IOException ioe) { fail("Unexpected IOException"); @@ -163,9 +162,9 @@ public class StreamTest { } public void testWalkOneLevel() { - try (CloseableStream s = Files.walk(testFolder, 1)) { + try (Stream s = Files.walk(testFolder, 1)) { Object[] actual = s.filter(path -> ! path.equals(testFolder)) - .sorted(Comparator.naturalOrder()) + .sorted() .toArray(); assertEquals(actual, level1); } catch (IOException ioe) { @@ -176,8 +175,8 @@ public class StreamTest { public void testWalkFollowLink() { // If link is not supported, the directory structure won't have link. // We still want to test the behavior with FOLLOW_LINKS option. - try (CloseableStream s = Files.walk(testFolder, FileVisitOption.FOLLOW_LINKS)) { - Object[] actual = s.sorted(Comparator.naturalOrder()).toArray(); + try (Stream s = Files.walk(testFolder, FileVisitOption.FOLLOW_LINKS)) { + Object[] actual = s.sorted().toArray(); assertEquals(actual, all_folowLinks); } catch (IOException ioe) { fail("Unexpected IOException"); @@ -185,7 +184,7 @@ public class StreamTest { } private void validateFileSystemLoopException(Path start, Path... causes) { - try (CloseableStream s = Files.walk(start, FileVisitOption.FOLLOW_LINKS)) { + try (Stream s = Files.walk(start, FileVisitOption.FOLLOW_LINKS)) { try { int count = s.mapToInt(p -> 1).reduce(0, Integer::sum); fail("Should got FileSystemLoopException, but got " + count + "elements."); @@ -282,28 +281,28 @@ public class StreamTest { public void testFind() throws IOException { PathBiPredicate pred = new PathBiPredicate((path, attrs) -> true); - try (CloseableStream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { + try (Stream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { Set result = s.collect(Collectors.toCollection(TreeSet::new)); assertEquals(pred.visited(), all); assertEquals(result.toArray(new Path[0]), pred.visited()); } pred = new PathBiPredicate((path, attrs) -> attrs.isSymbolicLink()); - try (CloseableStream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { + try (Stream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { s.forEach(path -> assertTrue(Files.isSymbolicLink(path))); assertEquals(pred.visited(), all); } pred = new PathBiPredicate((path, attrs) -> path.getFileName().toString().startsWith("e")); - try (CloseableStream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { + try (Stream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { s.forEach(path -> assertEquals(path.getFileName().toString(), "empty")); assertEquals(pred.visited(), all); } pred = new PathBiPredicate((path, attrs) -> path.getFileName().toString().startsWith("l") && attrs.isRegularFile()); - try (CloseableStream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { + try (Stream s = Files.find(testFolder, Integer.MAX_VALUE, pred)) { s.forEach(path -> fail("Expect empty stream")); assertEquals(pred.visited(), all); } @@ -317,14 +316,14 @@ public class StreamTest { try { // zero lines assertTrue(Files.size(tmpfile) == 0, "File should be empty"); - try (CloseableStream s = Files.lines(tmpfile, US_ASCII)) { + try (Stream s = Files.lines(tmpfile, US_ASCII)) { assertEquals(s.mapToInt(l -> 1).reduce(0, Integer::sum), 0, "No line expected"); } // one line byte[] hi = { (byte)'h', (byte)'i' }; Files.write(tmpfile, hi); - try (CloseableStream s = Files.lines(tmpfile, US_ASCII)) { + try (Stream s = Files.lines(tmpfile, US_ASCII)) { List lines = s.collect(Collectors.toList()); assertTrue(lines.size() == 1, "One line expected"); assertTrue(lines.get(0).equals("hi"), "'Hi' expected"); @@ -334,7 +333,7 @@ public class StreamTest { List expected = Arrays.asList("hi", "there"); Files.write(tmpfile, expected, US_ASCII); assertTrue(Files.size(tmpfile) > 0, "File is empty"); - try (CloseableStream s = Files.lines(tmpfile, US_ASCII)) { + try (Stream s = Files.lines(tmpfile, US_ASCII)) { List lines = s.collect(Collectors.toList()); assertTrue(lines.equals(expected), "Unexpected lines"); } @@ -342,7 +341,7 @@ public class StreamTest { // MalformedInputException byte[] bad = { (byte)0xff, (byte)0xff }; Files.write(tmpfile, bad); - try (CloseableStream s = Files.lines(tmpfile, US_ASCII)) { + try (Stream s = Files.lines(tmpfile, US_ASCII)) { try { List lines = s.collect(Collectors.toList()); throw new RuntimeException("UncheckedIOException expected"); @@ -378,7 +377,7 @@ public class StreamTest { fsp.setFaultyMode(false); Path fakeRoot = fs.getRoot(); try { - try (CloseableStream s = Files.list(fakeRoot)) { + try (Stream s = Files.list(fakeRoot)) { s.forEach(path -> assertEquals(path.getFileName().toString(), "DirectoryIteratorException")); } } catch (UncheckedIOException uioe) { @@ -398,7 +397,7 @@ public class StreamTest { } try { - try (CloseableStream s = Files.list(fakeRoot)) { + try (Stream s = Files.list(fakeRoot)) { s.forEach(path -> fail("should not get here")); } } catch (UncheckedIOException uioe) { @@ -427,12 +426,12 @@ public class StreamTest { try { fsp.setFaultyMode(false); Path fakeRoot = fs.getRoot(); - try (CloseableStream s = Files.list(fakeRoot.resolve("dir2"))) { + try (Stream s = Files.list(fakeRoot.resolve("dir2"))) { // only one file s.forEach(path -> assertEquals(path.getFileName().toString(), "IOException")); } - try (CloseableStream s = Files.walk(fakeRoot.resolve("empty"))) { + try (Stream s = Files.walk(fakeRoot.resolve("empty"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); // ordered as depth-first @@ -440,13 +439,13 @@ public class StreamTest { } fsp.setFaultyMode(true); - try (CloseableStream s = Files.list(fakeRoot.resolve("dir2"))) { + try (Stream s = Files.list(fakeRoot.resolve("dir2"))) { s.forEach(path -> fail("should have caused exception")); } catch (UncheckedIOException uioe) { assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException); } - try (CloseableStream s = Files.walk(fakeRoot.resolve("empty"))) { + try (Stream s = Files.walk(fakeRoot.resolve("empty"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); fail("should not reach here due to IOException"); @@ -454,7 +453,7 @@ public class StreamTest { assertTrue(uioe.getCause() instanceof FaultyFileSystem.FaultyException); } - try (CloseableStream s = Files.walk( + try (Stream s = Files.walk( fakeRoot.resolve("empty").resolve("IOException"))) { String[] result = s.map(path -> path.getFileName().toString()) @@ -502,20 +501,20 @@ public class StreamTest { fsp.setFaultyMode(false); Path fakeRoot = fs.getRoot(); // validate setting - try (CloseableStream s = Files.list(fakeRoot.resolve("empty"))) { + try (Stream s = Files.list(fakeRoot.resolve("empty"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "SecurityException", "sample" }); } - try (CloseableStream s = Files.walk(fakeRoot.resolve("dir2"))) { + try (Stream s = Files.walk(fakeRoot.resolve("dir2"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "dir2", "SecurityException", "fileInSE", "file" }); } if (supportsLinks) { - try (CloseableStream s = Files.list(fakeRoot.resolve("dir"))) { + try (Stream s = Files.list(fakeRoot.resolve("dir"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "d1", "f1", "lnDir2", "SecurityException", "lnDirSE", "lnFileSE" }); @@ -525,13 +524,13 @@ public class StreamTest { // execute test fsp.setFaultyMode(true); // ignore file cause SecurityException - try (CloseableStream s = Files.walk(fakeRoot.resolve("empty"))) { + try (Stream s = Files.walk(fakeRoot.resolve("empty"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "empty", "sample" }); } // skip folder cause SecurityException - try (CloseableStream s = Files.walk(fakeRoot.resolve("dir2"))) { + try (Stream s = Files.walk(fakeRoot.resolve("dir2"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "dir2", "file" }); @@ -539,14 +538,14 @@ public class StreamTest { if (supportsLinks) { // not following links - try (CloseableStream s = Files.walk(fakeRoot.resolve("dir"))) { + try (Stream s = Files.walk(fakeRoot.resolve("dir"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "dir", "d1", "f1", "lnDir2", "lnDirSE", "lnFileSE" }); } // following links - try (CloseableStream s = Files.walk(fakeRoot.resolve("dir"), FileVisitOption.FOLLOW_LINKS)) { + try (Stream s = Files.walk(fakeRoot.resolve("dir"), FileVisitOption.FOLLOW_LINKS)) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); // ?? Should fileInSE show up? @@ -556,19 +555,19 @@ public class StreamTest { } // list instead of walk - try (CloseableStream s = Files.list(fakeRoot.resolve("empty"))) { + try (Stream s = Files.list(fakeRoot.resolve("empty"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "sample" }); } - try (CloseableStream s = Files.list(fakeRoot.resolve("dir2"))) { + try (Stream s = Files.list(fakeRoot.resolve("dir2"))) { String[] result = s.map(path -> path.getFileName().toString()) .toArray(String[]::new); assertEqualsNoOrder(result, new String[] { "file" }); } // root cause SecurityException should be reported - try (CloseableStream s = Files.walk( + try (Stream s = Files.walk( fakeRoot.resolve("dir2").resolve("SecurityException"))) { String[] result = s.map(path -> path.getFileName().toString()) @@ -579,7 +578,7 @@ public class StreamTest { } // Walk a file cause SecurityException, we should get SE - try (CloseableStream s = Files.walk( + try (Stream s = Files.walk( fakeRoot.resolve("dir").resolve("SecurityException"))) { String[] result = s.map(path -> path.getFileName().toString()) @@ -590,7 +589,7 @@ public class StreamTest { } // List a file cause SecurityException, we should get SE as cannot read attribute - try (CloseableStream s = Files.list( + try (Stream s = Files.list( fakeRoot.resolve("dir2").resolve("SecurityException"))) { String[] result = s.map(path -> path.getFileName().toString()) @@ -600,7 +599,7 @@ public class StreamTest { assertTrue(se.getCause() instanceof FaultyFileSystem.FaultyException); } - try (CloseableStream s = Files.list( + try (Stream s = Files.list( fakeRoot.resolve("dir").resolve("SecurityException"))) { String[] result = s.map(path -> path.getFileName().toString()) @@ -627,7 +626,7 @@ public class StreamTest { } public void testConstructException() { - try (CloseableStream s = Files.lines(testFolder.resolve("notExist"), Charset.forName("UTF-8"))) { + try (Stream s = Files.lines(testFolder.resolve("notExist"), Charset.forName("UTF-8"))) { s.forEach(l -> fail("File is not even exist!")); } catch (IOException ioe) { assertTrue(ioe instanceof NoSuchFileException); @@ -635,24 +634,26 @@ public class StreamTest { } public void testClosedStream() throws IOException { - try (CloseableStream s = Files.list(testFolder)) { + try (Stream s = Files.list(testFolder)) { s.close(); - Object[] actual = s.sorted(Comparator.naturalOrder()).toArray(); - assertTrue(actual.length <= level1.length); - } - - try (CloseableStream s = Files.walk(testFolder)) { - s.close(); - Object[] actual = s.sorted(Comparator.naturalOrder()).toArray(); + Object[] actual = s.sorted().toArray(); fail("Operate on closed stream should throw IllegalStateException"); } catch (IllegalStateException ex) { // expected } - try (CloseableStream s = Files.find(testFolder, Integer.MAX_VALUE, + try (Stream s = Files.walk(testFolder)) { + s.close(); + Object[] actual = s.sorted().toArray(); + fail("Operate on closed stream should throw IllegalStateException"); + } catch (IllegalStateException ex) { + // expected + } + + try (Stream s = Files.find(testFolder, Integer.MAX_VALUE, (p, attr) -> true)) { s.close(); - Object[] actual = s.sorted(Comparator.naturalOrder()).toArray(); + Object[] actual = s.sorted().toArray(); fail("Operate on closed stream should throw IllegalStateException"); } catch (IllegalStateException ex) { // expected diff --git a/jdk/test/java/nio/file/WatchService/SensitivityModifier.java b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java index 08722048b63..185c4caf8b5 100644 --- a/jdk/test/java/nio/file/WatchService/SensitivityModifier.java +++ b/jdk/test/java/nio/file/WatchService/SensitivityModifier.java @@ -100,7 +100,7 @@ public class SensitivityModifier { } key.reset(); key = watcher.poll(1, TimeUnit.SECONDS); - } while (key != null && !eventReceived); + } while (key != null); // we should have received at least one ENTRY_MODIFY event if (eventReceived) { diff --git a/jdk/test/java/security/cert/PKIXRevocationChecker/OcspUnauthorized.java b/jdk/test/java/security/cert/PKIXRevocationChecker/OcspUnauthorized.java new file mode 100644 index 00000000000..83f19248959 --- /dev/null +++ b/jdk/test/java/security/cert/PKIXRevocationChecker/OcspUnauthorized.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8023362 + * @summary Make sure Ocsp UNAUTHORIZED response is treated as failure when + * SOFT_FAIL option is set + */ + +import java.io.ByteArrayInputStream; +import java.security.cert.*; +import java.security.cert.PKIXRevocationChecker.Option; +import java.util.Base64; +import java.util.Collections; +import java.util.EnumSet; + +public class OcspUnauthorized { + + private final static String OCSP_RESPONSE = "MAMKAQY="; + + private final static String EE_CERT = + "MIICADCCAWmgAwIBAgIEOvxUmjANBgkqhkiG9w0BAQQFADAqMQswCQYDVQQGEwJ1czE" + + "MMAoGA1UEChMDc3VuMQ0wCwYDVQQLEwRsYWJzMB4XDTAxMDUxNDIwNDQyMVoXDTI4MD" + + "kyOTIwNDQyMVowOTELMAkGA1UEBhMCdXMxDDAKBgNVBAoTA3N1bjENMAsGA1UECxMEb" + + "GFiczENMAsGA1UECxMEaXNyZzCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA4MmP" + + "GDriFJ+OhDlTuLpHzPy0nawDKyIYUJPZmU9M/pCAUbZewAOyAXGPYVU1og2ZiO9tWBi" + + "ZBeJGoFHEkkhfeqSVb2PsRckiXvPZ3AiSVmdX0uD/a963abmhRMYB1gDO2+jBe3F/DU" + + "pHwpyThchy8tYUMh7Gr7+m/8FwZbdbSpMCAwEAAaMkMCIwDwYDVR0PAQH/BAUDAwekA" + + "DAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBBAUAA4GBAME3fmXvES0FVDXSD1iC" + + "TJLf86kUy3H+uMG7h5pOQmcfF1o9PVWlNByVf4r2b4GRgftPQ3Ao0SAvq1aSkW7YpkN" + + "pcartYqNk2E5brPajOC0v+Pkxf/g/pkRTT6Zp+9erGQF4Ta62q0iwOyc3FovSbh0Ph2" + + "WidZRP4qUG5I6JmGkI"; + + private final static String TRUST_ANCHOR = + "MIICIzCCAYygAwIBAgIEOvxT7DANBgkqhkiG9w0BAQQFADAbMQswCQYDVQQGEwJ1czE" + + "MMAoGA1UEChMDc3VuMB4XDTAxMDUxNDIxMDQyOVoXDTI4MDkyOTIxMDQyOVowKjELMA" + + "kGA1UEBhMCdXMxDDAKBgNVBAoTA3N1bjENMAsGA1UECxMEbGFiczCBnzANBgkqhkiG9" + + "w0BAQEFAAOBjQAwgYkCgYEA0/16V87rhznCM0y7IqyGcfQBentG+PglA+1hiqCuQY/A" + + "jFiDKr5N+LpcfU28P41E4M+DSDrMIEe4JchRcXeJY6aIVhpOveVV9mgtBaEKlsScrIJ" + + "zmVqM07PG9JENg2FibECnB5TNUSfVbFKfvtAqaZ7Pc971oZVoIePBWnfKV9kCAwEAAa" + + "NlMGMwPwYDVR0eAQH/BDUwM6AxMC+kKjELMAkGA1UEBhMCdXMxDDAKBgNVBAoTA3N1b" + + "jENMAsGA1UECxMEbGFic4ABAzAPBgNVHQ8BAf8EBQMDB6QAMA8GA1UdEwEB/wQFMAMB" + + "Af8wDQYJKoZIhvcNAQEEBQADgYEAfJ5HWd7K5PmX0+Vbsux4SYhoaejDwwgS43BRNa+" + + "AmFq9LIZ+ZcjBMVte8Y3sJF+nz9+1qBaUhNhbaECCqsgmWSwvI+0kUzJXL89k9AdQ8m" + + "AYf6CB6+kaZQBgrdSdqSGz3tCVa2MIK8wmb0ROM40oJ7vt3qSwgFi3UTltxkFfwQ0="; + + private static CertificateFactory cf; + private static Base64.Decoder base64Decoder = Base64.getDecoder(); + + public static void main(String[] args) throws Exception { + cf = CertificateFactory.getInstance("X.509"); + X509Certificate taCert = getX509Cert(TRUST_ANCHOR); + X509Certificate eeCert = getX509Cert(EE_CERT); + CertPath cp = cf.generateCertPath(Collections.singletonList(eeCert)); + + CertPathValidator cpv = CertPathValidator.getInstance("PKIX"); + PKIXRevocationChecker prc = + (PKIXRevocationChecker)cpv.getRevocationChecker(); + prc.setOptions(EnumSet.of(Option.SOFT_FAIL, Option.NO_FALLBACK)); + byte[] response = base64Decoder.decode(OCSP_RESPONSE); + + prc.setOcspResponses(Collections.singletonMap(eeCert, response)); + + TrustAnchor ta = new TrustAnchor(taCert, null); + PKIXParameters params = new PKIXParameters(Collections.singleton(ta)); + + params.addCertPathChecker(prc); + + try { + cpv.validate(cp, params); + throw new Exception("FAILED: expected CertPathValidatorException"); + } catch (CertPathValidatorException cpve) { + cpve.printStackTrace(); + } + } + + private static X509Certificate getX509Cert(String enc) throws Exception { + byte[] bytes = base64Decoder.decode(enc); + ByteArrayInputStream is = new ByteArrayInputStream(bytes); + return (X509Certificate)cf.generateCertificate(is); + } +} diff --git a/jdk/test/java/time/tck/java/time/TCKLocalTime.java b/jdk/test/java/time/tck/java/time/TCKLocalTime.java index e0ef94cdadc..dbba80d1cec 100644 --- a/jdk/test/java/time/tck/java/time/TCKLocalTime.java +++ b/jdk/test/java/time/tck/java/time/TCKLocalTime.java @@ -282,17 +282,6 @@ public class TCKLocalTime extends AbstractDateTimeTest { check(LocalTime.MAX, 23, 59, 59, 999999999); } - //----------------------------------------------------------------------- - // now() - //----------------------------------------------------------------------- - @Test - public void now() { - LocalTime expected = LocalTime.now(Clock.systemDefaultZone()); - LocalTime test = LocalTime.now(); - long diff = Math.abs(test.toNanoOfDay() - expected.toNanoOfDay()); - assertTrue(diff < 100000000); // less than 0.1 secs - } - //----------------------------------------------------------------------- // now(ZoneId) //----------------------------------------------------------------------- diff --git a/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java b/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java index e9d5fb4f1da..35620ad755e 100644 --- a/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java +++ b/jdk/test/java/time/tck/java/time/chrono/TCKChronologySerialization.java @@ -97,7 +97,9 @@ public class TCKChronologySerialization { ObjectOutputStream out = new ObjectOutputStream(baos); out.writeObject(chrono); out.close(); - ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); + + byte[] bytes = baos.toByteArray(); + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); ObjectInputStream in = new ObjectInputStream(bais); @SuppressWarnings("unchecked") diff --git a/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java b/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java index 52f51369a0c..b547a837fb8 100644 --- a/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java +++ b/jdk/test/java/time/tck/java/time/format/TCKDateTimeTextPrinting.java @@ -155,23 +155,6 @@ public class TCKDateTimeTextPrinting { } } - //----------------------------------------------------------------------- - @Test - public void test_print_appendText2arg_french_long() throws Exception { - DateTimeFormatter f = builder.appendText(MONTH_OF_YEAR, TextStyle.FULL).toFormatter(Locale.FRENCH); - LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); - String text = f.format(dt); - assertEquals(text, "janvier"); - } - - @Test - public void test_print_appendText2arg_french_short() throws Exception { - DateTimeFormatter f = builder.appendText(MONTH_OF_YEAR, TextStyle.SHORT).toFormatter(Locale.FRENCH); - LocalDateTime dt = LocalDateTime.of(2010, 1, 1, 0, 0); - String text = f.format(dt); - assertEquals(text, "janv."); - } - //----------------------------------------------------------------------- @Test public void test_appendTextMap() throws Exception { diff --git a/jdk/test/java/time/test/java/time/TestLocalTime.java b/jdk/test/java/time/test/java/time/TestLocalTime.java index ddd7b0f572e..8e25a85f198 100644 --- a/jdk/test/java/time/test/java/time/TestLocalTime.java +++ b/jdk/test/java/time/test/java/time/TestLocalTime.java @@ -61,7 +61,9 @@ package test.java.time; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertSame; +import static org.testng.Assert.assertTrue; +import java.time.Clock; import java.time.LocalTime; import org.testng.annotations.Test; @@ -71,6 +73,9 @@ import org.testng.annotations.Test; */ @Test public class TestLocalTime extends AbstractTest { + static final long NANOS_PER_SECOND = 1_000_000_000L; + static final long NANOS_PER_MINUTE = 60 * NANOS_PER_SECOND; + static final long NANOS_PER_DAY = 24 * 60 * NANOS_PER_MINUTE; //----------------------------------------------------------------------- @Test @@ -176,4 +181,31 @@ public class TestLocalTime extends AbstractTest { } } + //----------------------------------------------------------------------- + // now() + //----------------------------------------------------------------------- + @Test + @SuppressWarnings("unused") + public void now() { + // Warmup the TimeZone data so the following test does not include + // one-time initialization + LocalTime.now(Clock.systemDefaultZone()); + + long diff = Integer.MAX_VALUE; + for (int i = 0; i < 2; i++) { + LocalTime expected = LocalTime.now(Clock.systemDefaultZone()); + LocalTime test = LocalTime.now(); + diff = test.toNanoOfDay() - expected.toNanoOfDay(); + // Normalize for wrap-around midnight + diff = Math.floorMod(NANOS_PER_DAY + diff, NANOS_PER_DAY); + if (diff < 100000000) { + break; + } + // A second iteration may be needed if the clock changed + // due to a DST change between the two calls to now. + } + assertTrue(diff < 100000000, // less than 0.1 sec + "LocalTime.now vs LocalTime.now(Clock.systemDefaultZone()) not close"); + } + } diff --git a/jdk/test/java/util/Arrays/SetAllTest.java b/jdk/test/java/util/Arrays/SetAllTest.java index 2388a7bfd55..528d3c57b54 100644 --- a/jdk/test/java/util/Arrays/SetAllTest.java +++ b/jdk/test/java/util/Arrays/SetAllTest.java @@ -167,13 +167,13 @@ public class SetAllTest { public void testStringSetNulls() { String[] ar = new String[2]; try { - Arrays.setAll(null, i -> "X"); + Arrays.setAll(null, (IntFunction) i -> "X"); fail("Arrays.setAll(null, foo) should throw NPE"); } catch (NullPointerException npe) { // expected } try { - Arrays.parallelSetAll(null, i -> "X"); + Arrays.parallelSetAll(null, (IntFunction) i -> "X"); fail("Arrays.parallelSetAll(null, foo) should throw NPE"); } catch (NullPointerException npe) { // expected diff --git a/jdk/test/java/util/Collection/CollectionDefaults.java b/jdk/test/java/util/Collection/CollectionDefaults.java index 36fd8da5469..594b67adae8 100644 --- a/jdk/test/java/util/Collection/CollectionDefaults.java +++ b/jdk/test/java/util/Collection/CollectionDefaults.java @@ -21,15 +21,19 @@ * questions. */ +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; +import java.util.SortedSet; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -38,43 +42,68 @@ import static org.testng.Assert.fail; import java.util.TreeMap; import java.util.TreeSet; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListMap; import java.util.function.Predicate; +import java.util.function.Supplier; /** * @test - * @library testlibrary - * @build CollectionAsserts CollectionSupplier - * @run testng CollectionDefaults * @summary Unit tests for extension methods on Collection + * @library testlibrary + * @build CollectionAsserts CollectionSupplier ExtendsAbstractSet ExtendsAbstractCollection + * @run testng CollectionDefaults */ public class CollectionDefaults { public static final Predicate pEven = x -> 0 == x % 2; public static final Predicate pOdd = x -> 1 == x % 2; - private static final String[] SET_CLASSES = { - "java.util.HashSet", - "java.util.LinkedHashSet", - "java.util.TreeSet" + @SuppressWarnings("unchecked") + private static final Supplier[] TEST_CLASSES = { + // Collection + ExtendsAbstractCollection::new, + + // Lists + java.util.ArrayList::new, + java.util.LinkedList::new, + java.util.Vector::new, + java.util.concurrent.CopyOnWriteArrayList::new, + ExtendsAbstractList::new, + + // Sets + java.util.HashSet::new, + java.util.LinkedHashSet::new, + java.util.TreeSet::new, + java.util.concurrent.ConcurrentSkipListSet::new, + java.util.concurrent.CopyOnWriteArraySet::new, + ExtendsAbstractSet::new }; private static final int SIZE = 100; @DataProvider(name="setProvider", parallel=true) - public static Object[][] setCases() { + public static Iterator setCases() { final List cases = new LinkedList<>(); cases.add(new Object[] { new HashSet<>() }); cases.add(new Object[] { new LinkedHashSet<>() }); cases.add(new Object[] { new TreeSet<>() }); + cases.add(new Object[] { new java.util.concurrent.ConcurrentSkipListSet<>() }); + cases.add(new Object[] { new java.util.concurrent.CopyOnWriteArraySet<>() }); + + cases.add(new Object[] { new ExtendsAbstractSet<>() }); cases.add(new Object[] { Collections.newSetFromMap(new HashMap<>()) }); cases.add(new Object[] { Collections.newSetFromMap(new LinkedHashMap()) }); cases.add(new Object[] { Collections.newSetFromMap(new TreeMap<>()) }); + cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentHashMap<>()) }); + cases.add(new Object[] { Collections.newSetFromMap(new ConcurrentSkipListMap<>()) }); - cases.add(new Object[] { new HashSet(){{add(42);}} }); - cases.add(new Object[] { new LinkedHashSet(){{add(42);}} }); - cases.add(new Object[] { new TreeSet(){{add(42);}} }); - return cases.toArray(new Object[0][cases.size()]); + cases.add(new Object[] { new HashSet(){{add(42);}} }); + cases.add(new Object[] { new ExtendsAbstractSet(){{add(42);}} }); + cases.add(new Object[] { new LinkedHashSet(){{add(42);}} }); + cases.add(new Object[] { new TreeSet(){{add(42);}} }); + return cases.iterator(); } @Test(dataProvider = "setProvider") @@ -82,57 +111,66 @@ public class CollectionDefaults { try { set.forEach(null); fail("expected NPE not thrown"); - } catch (NullPointerException npe) {} + } catch (NullPointerException expected) { + ; // expected + } try { set.removeIf(null); fail("expected NPE not thrown"); - } catch (NullPointerException npe) {} + } catch (NullPointerException expected) { + ; // expected + } } @Test public void testForEach() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(SET_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { - final Set original = ((Set) test.original); - final Set set = ((Set) test.collection); + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[]) TEST_CLASSES, SIZE); + + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final Collection original = test.expected; + final Collection set = test.collection; try { set.forEach(null); fail("expected NPE not thrown"); - } catch (NullPointerException npe) {} - if (test.className.equals("java.util.HashSet")) { - CollectionAsserts.assertContentsUnordered(set, original); + } catch (NullPointerException expected) { + ; // expected + } + if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) { + CollectionAsserts.assertContentsUnordered(set, original, test.toString()); } else { - CollectionAsserts.assertContents(set, original); + CollectionAsserts.assertContents(set, original, test.toString()); } final List actual = new LinkedList<>(); set.forEach(actual::add); - if (test.className.equals("java.util.HashSet")) { - CollectionAsserts.assertContentsUnordered(actual, set); - CollectionAsserts.assertContentsUnordered(actual, original); + if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) { + CollectionAsserts.assertContentsUnordered(actual, set, test.toString()); + CollectionAsserts.assertContentsUnordered(actual, original, test.toString()); } else { - CollectionAsserts.assertContents(actual, set); - CollectionAsserts.assertContents(actual, original); + CollectionAsserts.assertContents(actual, set, test.toString()); + CollectionAsserts.assertContents(actual, original, test.toString()); } } } @Test public void testRemoveIf() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(SET_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { - final Set original = ((Set) test.original); - final Set set = ((Set) test.collection); + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[]) TEST_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final Collection original = test.expected; + final Collection set = test.collection; try { set.removeIf(null); fail("expected NPE not thrown"); - } catch (NullPointerException npe) {} - if (test.className.equals("java.util.HashSet")) { - CollectionAsserts.assertContentsUnordered(set, original); + } catch (NullPointerException expected) { + ; // expected + } + if (set instanceof Set && !((set instanceof SortedSet) || (set instanceof LinkedHashSet))) { + CollectionAsserts.assertContentsUnordered(set, original, test.toString()); } else { - CollectionAsserts.assertContents(set, original); + CollectionAsserts.assertContents(set, original, test.toString()); } set.removeIf(pEven); diff --git a/jdk/test/java/util/Collection/MOAT.java b/jdk/test/java/util/Collection/MOAT.java index 37720016c3c..a039461e2b7 100644 --- a/jdk/test/java/util/Collection/MOAT.java +++ b/jdk/test/java/util/Collection/MOAT.java @@ -400,8 +400,6 @@ public class MOAT { // If add(null) succeeds, contains(null) & remove(null) should succeed //---------------------------------------------------------------- private static void testNullElement(Collection c) { - // !!!! 5018849: (coll) TreeSet.contains(null) does not agree with Javadoc - if (c instanceof TreeSet) return; try { check(c.add(null)); diff --git a/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java b/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java index a03f975152e..575dc796204 100644 --- a/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java +++ b/jdk/test/java/util/Collection/testlibrary/CollectionAsserts.java @@ -41,6 +41,10 @@ import static org.testng.Assert.fail; */ public class CollectionAsserts { + private CollectionAsserts() { + // no instances + } + public static void assertCountSum(Iterable it, int count, int sum) { assertCountSum(it.iterator(), count, sum); } @@ -117,10 +121,18 @@ public class CollectionAsserts { } public static void assertContents(Iterable actual, Iterable expected) { - assertContents(actual.iterator(), expected.iterator()); + assertContents(actual, expected, null); + } + + public static void assertContents(Iterable actual, Iterable expected, String msg) { + assertContents(actual.iterator(), expected.iterator(), msg); } public static void assertContents(Iterator actual, Iterator expected) { + assertContents(actual, expected, null); + } + + public static void assertContents(Iterator actual, Iterator expected, String msg) { List history = new ArrayList<>(); while (expected.hasNext()) { @@ -128,20 +140,23 @@ public class CollectionAsserts { List expectedData = new ArrayList<>(history); while (expected.hasNext()) expectedData.add(expected.next()); - fail(String.format("Premature end of data; expected=%s, found=%s", expectedData, history)); + fail(String.format("%s Premature end of data; expected=%s, found=%s", + (msg == null ? "" : msg), expectedData, history)); } T a = actual.next(); T e = expected.next(); history.add(a); if (!Objects.equals(a, e)) - fail(String.format("Data mismatch; preceding=%s, nextExpected=%s, nextFound=%s", history, e, a)); + fail(String.format("%s Data mismatch; preceding=%s, nextExpected=%s, nextFound=%s", + (msg == null ? "" : msg), history, e, a)); } if (actual.hasNext()) { List rest = new ArrayList<>(); while (actual.hasNext()) rest.add(actual.next()); - fail(String.format("Unexpected data %s after %s", rest, history)); + fail(String.format("%s Unexpected data %s after %s", + (msg == null ? "" : msg), rest, history)); } } @@ -151,30 +166,21 @@ public class CollectionAsserts { assertContents(actual, Arrays.asList(expected).iterator()); } - public static boolean equalsContentsUnordered(Iterable a, Iterable b) { - Set sa = new HashSet<>(); - for (T t : a) { - sa.add(t); - } - - Set sb = new HashSet<>(); - for (T t : b) { - sb.add(t); - } - - return Objects.equals(sa, sb); + public static> void assertContentsUnordered(Iterable actual, Iterable expected) { + assertContentsUnordered(actual, expected, null); } - public static> void assertContentsUnordered(Iterable actual, Iterable expected) { - ArrayList one = new ArrayList<>(); - for (T t : actual) - one.add(t); - ArrayList two = new ArrayList<>(); - for (T t : expected) - two.add(t); - Collections.sort(one); - Collections.sort(two); - assertContents(one, two); + public static> void assertContentsUnordered(Iterable actual, Iterable expected, String msg) { + List allExpected = new ArrayList<>(); + for (T t : expected) { + allExpected.add(t); + } + + for (T t : actual) { + assertTrue(allExpected.remove(t), msg + " element '" + String.valueOf(t) + "' not found"); + } + + assertTrue(allExpected.isEmpty(), msg + "expected contained additional elements"); } static void assertSplitContents(Iterable> splits, Iterable list) { diff --git a/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java b/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java index c26aaa7385f..37b3e53739c 100644 --- a/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java +++ b/jdk/test/java/util/Collection/testlibrary/CollectionSupplier.java @@ -29,13 +29,11 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Random; -import java.util.Set; import org.testng.TestException; import static org.testng.Assert.assertTrue; -import java.lang.reflect.Constructor; import java.util.Collection; import java.util.Collections; import java.util.function.Supplier; @@ -44,73 +42,61 @@ import java.util.function.Supplier; * @library * @summary A Supplier of test cases for Collection tests */ -public final class CollectionSupplier implements Supplier> { +public final class CollectionSupplier> implements Supplier>> { - private final String[] classNames; + private final Supplier[] classes; private final int size; /** * A Collection test case. */ - public static final class TestCase { + public static final class TestCase> { /** * The name of the test case. */ public final String name; - /** - * Class name of the instantiated Collection. - */ - public final String className; - /** * Unmodifiable reference collection, useful for comparisons. */ - public final Collection original; + public final List expected; /** * A modifiable test collection. */ - public final Collection collection; + public final C collection; /** * Create a Collection test case. + * * @param name name of the test case - * @param className class name of the instantiated collection - * @param original reference collection + * @param expected reference collection * @param collection the modifiable test collection */ - public TestCase(String name, String className, - Collection original, Collection collection) { + public TestCase(String name, C collection) { this.name = name; - this.className = className; - this.original = - List.class.isAssignableFrom(original.getClass()) ? - Collections.unmodifiableList((List) original) : - Set.class.isAssignableFrom(original.getClass()) ? - Collections.unmodifiableSet((Set) original) : - Collections.unmodifiableCollection(original); + this.expected = Collections.unmodifiableList( + Arrays.asList(collection.toArray(new Integer[0]))); this.collection = collection; } @Override public String toString() { - return name + " " + className + - "\n original: " + original + - "\n target: " + collection; + return name + " " + collection.getClass().toString(); } } /** * Shuffle a list using a PRNG with known seed for repeatability + * * @param list the list to be shuffled */ public static void shuffle(final List list) { // PRNG with known seed for repeatable tests final Random prng = new Random(13); final int size = list.size(); - for (int i=0; i < size; i++) { + for (int i = 0; i < size; i++) { // random index in interval [i, size) final int j = i + prng.nextInt(size - i); // swap elements at indices i & j @@ -127,178 +113,133 @@ public final class CollectionSupplier implements Supplier[] classes, int size) { + this.classes = Arrays.copyOf(classes, classes.length); this.size = size; } @Override - public Iterable get() { - try { - return getThrows(); - } catch (Exception e) { - throw new TestException(e); - } - } + public Iterable> get() { + final Collection> cases = new LinkedList<>(); + for (final Supplier type : classes) { + try { + final Collection empty = type.get(); + cases.add(new TestCase("empty", empty)); - private Iterable getThrows() throws Exception { - final Collection collections = new LinkedList<>(); - for (final String className : classNames) { - @SuppressWarnings("unchecked") - final Class> type = - (Class>) Class.forName(className); - final Constructor> - defaultConstructor = type.getConstructor(); - final Constructor> - copyConstructor = type.getConstructor(Collection.class); + final Collection single = type.get(); + single.add(42); + cases.add(new TestCase("single", single)); - final Collection empty = defaultConstructor.newInstance(); - collections.add(new TestCase("empty", - className, - copyConstructor.newInstance(empty), - empty)); - - final Collection single = defaultConstructor.newInstance(); - single.add(42); - collections.add(new TestCase("single", - className, - copyConstructor.newInstance(single), - single)); - - final Collection regular = defaultConstructor.newInstance(); - for (int i=0; i < size; i++) { - regular.add(i); - } - collections.add(new TestCase("regular", - className, - copyConstructor.newInstance(regular), - regular)); - - final Collection reverse = defaultConstructor.newInstance(); - for (int i=size; i >= 0; i--) { - reverse.add(i); - } - collections.add(new TestCase("reverse", - className, - copyConstructor.newInstance(reverse), - reverse)); - - final Collection odds = defaultConstructor.newInstance(); - for (int i=0; i < size; i++) { - odds.add((i * 2) + 1); - } - collections.add(new TestCase("odds", - className, - copyConstructor.newInstance(odds), - odds)); - - final Collection evens = defaultConstructor.newInstance(); - for (int i=0; i < size; i++) { - evens.add(i * 2); - } - collections.add(new TestCase("evens", - className, - copyConstructor.newInstance(evens), - evens)); - - final Collection fibonacci = defaultConstructor.newInstance(); - int prev2 = 0; - int prev1 = 1; - for (int i=0; i < size; i++) { - final int n = prev1 + prev2; - if (n < 0) { // stop on overflow - break; + final Collection regular = type.get(); + for (int i = 0; i < size; i++) { + regular.add(i); } - fibonacci.add(n); - prev2 = prev1; - prev1 = n; - } - collections.add(new TestCase("fibonacci", - className, - copyConstructor.newInstance(fibonacci), - fibonacci)); + cases.add(new TestCase("regular", regular)); + + final Collection reverse = type.get(); + for (int i = size; i >= 0; i--) { + reverse.add(i); + } + cases.add(new TestCase("reverse", reverse)); + + final Collection odds = type.get(); + for (int i = 0; i < size; i++) { + odds.add((i * 2) + 1); + } + cases.add(new TestCase("odds", odds)); + + final Collection evens = type.get(); + for (int i = 0; i < size; i++) { + evens.add(i * 2); + } + cases.add(new TestCase("evens", evens)); + + final Collection fibonacci = type.get(); + int prev2 = 0; + int prev1 = 1; + for (int i = 0; i < size; i++) { + final int n = prev1 + prev2; + if (n < 0) { // stop on overflow + break; + } + fibonacci.add(n); + prev2 = prev1; + prev1 = n; + } + cases.add(new TestCase("fibonacci", fibonacci)); // variants where the size of the backing storage != reported size - // created by removing half of the elements + // created by removing half of the elements + final Collection emptyWithSlack = type.get(); + emptyWithSlack.add(42); + assertTrue(emptyWithSlack.remove(42)); + cases.add(new TestCase("emptyWithSlack", emptyWithSlack)); - final Collection emptyWithSlack = defaultConstructor.newInstance(); - emptyWithSlack.add(42); - assertTrue(emptyWithSlack.remove(42)); - collections.add(new TestCase("emptyWithSlack", - className, - copyConstructor.newInstance(emptyWithSlack), - emptyWithSlack)); + final Collection singleWithSlack = type.get(); + singleWithSlack.add(42); + singleWithSlack.add(43); + assertTrue(singleWithSlack.remove(43)); + cases.add(new TestCase("singleWithSlack", singleWithSlack)); - final Collection singleWithSlack = defaultConstructor.newInstance(); - singleWithSlack.add(42); - singleWithSlack.add(43); - assertTrue(singleWithSlack.remove(43)); - collections.add(new TestCase("singleWithSlack", - className, - copyConstructor.newInstance(singleWithSlack), - singleWithSlack)); - - final Collection regularWithSlack = defaultConstructor.newInstance(); - for (int i=0; i < (2 * size); i++) { - regularWithSlack.add(i); - } - assertTrue(regularWithSlack.removeIf((x) -> {return x >= size;})); - collections.add(new TestCase("regularWithSlack", - className, - copyConstructor.newInstance(regularWithSlack), - regularWithSlack)); - - final Collection reverseWithSlack = defaultConstructor.newInstance(); - for (int i=2 * size; i >= 0; i--) { - reverseWithSlack.add(i); - } - assertTrue(reverseWithSlack.removeIf((x) -> {return x < size;})); - collections.add(new TestCase("reverseWithSlack", - className, - copyConstructor.newInstance(reverseWithSlack), - reverseWithSlack)); - - final Collection oddsWithSlack = defaultConstructor.newInstance(); - for (int i = 0; i < 2 * size; i++) { - oddsWithSlack.add((i * 2) + 1); - } - assertTrue(oddsWithSlack.removeIf((x) -> {return x >= size;})); - collections.add(new TestCase("oddsWithSlack", - className, - copyConstructor.newInstance(oddsWithSlack), - oddsWithSlack)); - - final Collection evensWithSlack = defaultConstructor.newInstance(); - for (int i = 0; i < 2 * size; i++) { - evensWithSlack.add(i * 2); - } - assertTrue(evensWithSlack.removeIf((x) -> {return x >= size;})); - collections.add(new TestCase("evensWithSlack", - className, - copyConstructor.newInstance(evensWithSlack), - evensWithSlack)); - - final Collection fibonacciWithSlack = defaultConstructor.newInstance(); - prev2 = 0; - prev1 = 1; - for (int i=0; i < size; i++) { - final int n = prev1 + prev2; - if (n < 0) { // stop on overflow - break; + final Collection regularWithSlack = type.get(); + for (int i = 0; i < (2 * size); i++) { + regularWithSlack.add(i); } - fibonacciWithSlack.add(n); - prev2 = prev1; - prev1 = n; - } - assertTrue(fibonacciWithSlack.removeIf((x) -> {return x < 20;})); - collections.add(new TestCase("fibonacciWithSlack", - className, - copyConstructor.newInstance(fibonacciWithSlack), - fibonacciWithSlack)); + assertTrue(regularWithSlack.removeIf((x) -> { + return x >= size; + })); + cases.add(new TestCase("regularWithSlack", regularWithSlack)); + final Collection reverseWithSlack = type.get(); + for (int i = 2 * size; i >= 0; i--) { + reverseWithSlack.add(i); + } + assertTrue(reverseWithSlack.removeIf((x) -> { + return x < size; + })); + cases.add(new TestCase("reverseWithSlack", reverseWithSlack)); + + final Collection oddsWithSlack = type.get(); + for (int i = 0; i < 2 * size; i++) { + oddsWithSlack.add((i * 2) + 1); + } + assertTrue(oddsWithSlack.removeIf((x) -> { + return x >= size; + })); + cases.add(new TestCase("oddsWithSlack", oddsWithSlack)); + + final Collection evensWithSlack = type.get(); + for (int i = 0; i < 2 * size; i++) { + evensWithSlack.add(i * 2); + } + assertTrue(evensWithSlack.removeIf((x) -> { + return x >= size; + })); + cases.add(new TestCase("evensWithSlack", evensWithSlack)); + + final Collection fibonacciWithSlack = type.get(); + prev2 = 0; + prev1 = 1; + for (int i = 0; i < size; i++) { + final int n = prev1 + prev2; + if (n < 0) { // stop on overflow + break; + } + fibonacciWithSlack.add(n); + prev2 = prev1; + prev1 = n; + } + assertTrue(fibonacciWithSlack.removeIf((x) -> { + return x < 20; + })); + cases.add(new TestCase("fibonacciWithSlack", + fibonacciWithSlack)); + } catch (Exception failed) { + throw new TestException(failed); + } } - return collections; + return cases; } } diff --git a/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java b/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java new file mode 100644 index 00000000000..a22d3d75d15 --- /dev/null +++ b/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractCollection.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.util.AbstractCollection; +import java.util.HashSet; +import java.util.AbstractSet; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.function.Supplier; + +/** + * @library + * + * A simple mutable collection implementation that provides only default + * implementations of all methods. ie. none of the Collection interface default + * methods have overridden implementations. + * + * @param type of collection elements + */ +public class ExtendsAbstractCollection extends AbstractCollection { + + protected final Collection coll; + + public ExtendsAbstractCollection() { + this(ArrayList::new); + } + + public ExtendsAbstractCollection(Collection source) { + this(); + coll.addAll(source); + } + + protected ExtendsAbstractCollection(Supplier> backer) { + this.coll = backer.get(); + } + + public boolean add(E element) { + return coll.add(element); + } + + public boolean remove(Object element) { + return coll.remove(element); + } + + public Iterator iterator() { + return new Iterator() { + Iterator source = coll.iterator(); + + public boolean hasNext() { + return source.hasNext(); + } + + public E next() { + return source.next(); + } + + public void remove() { + source.remove(); + } + }; + } + + public int size() { + return coll.size(); + } +} diff --git a/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractList.java b/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractList.java new file mode 100644 index 00000000000..fb2af523d44 --- /dev/null +++ b/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractList.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.util.ArrayList; +import java.util.AbstractList; +import java.util.Collection; +import java.util.Iterator; +import java.util.List; +import java.util.function.Supplier; + +/** + * @library + * + * A simple mutable list implementation that provides only default + * implementations of all methods. ie. none of the List interface default + * methods have overridden implementations. + * + * @param type of list elements + */ +public class ExtendsAbstractList extends AbstractList { + + protected final List list; + + public ExtendsAbstractList() { + this(ArrayList::new); + } + + protected ExtendsAbstractList(Supplier> supplier) { + this.list = supplier.get(); + } + + public ExtendsAbstractList(Collection source) { + this(); + addAll(source); + } + + public boolean add(E element) { + return list.add(element); + } + + public E get(int index) { + return list.get(index); + } + + public boolean remove(Object element) { + return list.remove(element); + } + + public E set(int index, E element) { + return list.set(index, element); + } + + public void add(int index, E element) { + list.add(index, element); + } + + public E remove(int index) { + return list.remove(index); + } + + public Iterator iterator() { + return new Iterator() { + Iterator source = list.iterator(); + + public boolean hasNext() { + return source.hasNext(); + } + + public E next() { + return source.next(); + } + + public void remove() { + source.remove(); + } + }; + } + + public int size() { + return list.size(); + } +} diff --git a/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java b/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java new file mode 100644 index 00000000000..23661a357a9 --- /dev/null +++ b/jdk/test/java/util/Collection/testlibrary/ExtendsAbstractSet.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.util.HashSet; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Iterator; +import java.util.Set; +import java.util.function.Supplier; + +/** + * @library + * + * A simple mutable set implementation that provides only default + * implementations of all methods. ie. none of the Set interface default methods + * have overridden implementations. + * + * @param type of set members + */ +public class ExtendsAbstractSet extends AbstractSet { + + protected final Set set; + + public ExtendsAbstractSet() { + this(HashSet::new); + } + + public ExtendsAbstractSet(Collection source) { + this(); + addAll(source); + } + + protected ExtendsAbstractSet(Supplier> backer) { + this.set = backer.get(); + } + + public boolean add(E element) { + return set.add(element); + } + + public boolean remove(Object element) { + return set.remove(element); + } + + public Iterator iterator() { + return new Iterator() { + Iterator source = set.iterator(); + + public boolean hasNext() { + return source.hasNext(); + } + + public E next() { + return source.next(); + } + + public void remove() { + source.remove(); + } + }; + } + + public int size() { + return set.size(); + } +} diff --git a/jdk/test/java/util/Collections/SingletonIterator.java b/jdk/test/java/util/Collections/SingletonIterator.java new file mode 100644 index 00000000000..966cce07414 --- /dev/null +++ b/jdk/test/java/util/Collections/SingletonIterator.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @run testng SingletonIterator + */ + +import java.util.Collections; +import java.util.Iterator; +import java.util.NoSuchElementException; +import java.util.concurrent.atomic.AtomicInteger; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.fail; + +@Test(groups = "unit") +public class SingletonIterator { + public void testForEachRemaining() { + Iterator it = Collections.singleton("TheOne").iterator(); + AtomicInteger cnt = new AtomicInteger(0); + + it.forEachRemaining(s -> { + assertEquals("TheOne", s); + cnt.incrementAndGet(); + }); + + assertEquals(cnt.get(), 1); + assertFalse(it.hasNext()); + + try { + String str = it.next(); + fail("Should throw NoSuchElementException at end"); + } catch (NoSuchElementException ex) { + // ignore; + } + } +} diff --git a/jdk/test/java/util/HashMap/ReplaceExisting.java b/jdk/test/java/util/HashMap/ReplaceExisting.java new file mode 100644 index 00000000000..81795b30b1f --- /dev/null +++ b/jdk/test/java/util/HashMap/ReplaceExisting.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8025173 + * @summary Verify that replacing the value for an existing key does not + * corrupt active iterators, in particular due to a resize() occurring and + * not updating modCount. + * @run main ReplaceExisting + */ + +import java.util.ConcurrentModificationException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; + +public class ReplaceExisting { + /* Number of entries required to trigger a resize for cap=16, load=0.75*/ + private static int ENTRIES = 13; + + public static void main(String[] args) { + for (int i = 0; i <= ENTRIES; i++) { + HashMap hm = prepHashMap(); + testItr(hm, i); + } + } + + /* Prepare a HashMap that will resize on next put() */ + private static HashMap prepHashMap() { + HashMap hm = new HashMap<>(16, 0.75f); + // Add items to one more than the resize threshold + for (int i = 0; i < ENTRIES; i++) { + hm.put(i*10, i*10); + } + return hm; + } + + /* Iterate hm for elemBeforePut elements, then call put() to replace value + * for existing key. With bug 8025173, this will also cause a resize, but + * not increase the modCount. + * Finish the iteration to check for a corrupt iterator. + */ + private static void testItr(HashMap hm, int elemBeforePut) { + if (elemBeforePut > hm.size()) { + throw new IllegalArgumentException("Error in test: elemBeforePut must be <= HashMap size"); + } + // Create a copy of the keys + HashSet keys = new HashSet<>(hm.size()); + keys.addAll(hm.keySet()); + + HashSet collected = new HashSet<>(hm.size()); + + // Run itr for elemBeforePut items, collecting returned elems + Iterator itr = hm.keySet().iterator(); + for (int i = 0; i < elemBeforePut; i++) { + Integer retVal = itr.next(); + if (!collected.add(retVal)) { + throw new RuntimeException("Corrupt iterator: key " + retVal + " already encountered"); + } + } + + // Do put() to replace entry (and resize table when bug present) + if (null == hm.put(0, 100)) { + throw new RuntimeException("Error in test: expected key 0 to be in the HashMap"); + } + + // Finish itr + collecting returned elems + while(itr.hasNext()) { + Integer retVal = itr.next(); + if (!collected.add(retVal)) { + throw new RuntimeException("Corrupt iterator: key " + retVal + " already encountered"); + } + } + + // Compare returned elems to original copy of keys + if (!keys.equals(collected)) { + throw new RuntimeException("Collected keys do not match original set of keys"); + } + } +} diff --git a/jdk/test/java/util/Collection/ListDefaults.java b/jdk/test/java/util/List/ListDefaults.java similarity index 88% rename from jdk/test/java/util/Collection/ListDefaults.java rename to jdk/test/java/util/List/ListDefaults.java index 0d7a29152f6..76734b4e4be 100644 --- a/jdk/test/java/util/Collection/ListDefaults.java +++ b/jdk/test/java/util/List/ListDefaults.java @@ -28,8 +28,6 @@ import java.util.Comparator; import java.util.List; import java.util.LinkedList; import java.util.Stack; -import java.util.TreeMap; -import java.util.TreeSet; import java.util.Vector; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.atomic.AtomicBoolean; @@ -46,28 +44,30 @@ import static org.testng.Assert.fail; import java.lang.reflect.Constructor; import java.util.ConcurrentModificationException; import java.util.function.Predicate; +import java.util.function.Supplier; /** * @test - * @bug 8023367 - * @library testlibrary - * @build CollectionAsserts CollectionSupplier - * @run testng ListDefaults * @summary Unit tests for extension methods on List + * @bug 8023367 + * @library ../Collection/testlibrary + * @build CollectionAsserts CollectionSupplier ExtendsAbstractList + * @run testng ListDefaults */ public class ListDefaults { - private static final String[] LIST_CLASSES = { - "java.util.ArrayList", - "java.util.LinkedList", - "java.util.Vector", - "java.util.concurrent.CopyOnWriteArrayList" - }; + private static final Supplier[] LIST_CLASSES = { + java.util.ArrayList::new, + java.util.LinkedList::new, + java.util.Vector::new, + java.util.concurrent.CopyOnWriteArrayList::new, + ExtendsAbstractList::new + }; - private static final String[] LIST_CME_CLASSES = { - "java.util.ArrayList", - "java.util.Vector" - }; + private static final Supplier[] LIST_CME_CLASSES = { + java.util.ArrayList::new, + java.util.Vector::new + }; private static final Predicate pEven = x -> 0 == x % 2; private static final Predicate pOdd = x -> 1 == x % 2; @@ -139,13 +139,9 @@ public class ListDefaults { @Test public void testForEach() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); - final List list = ((List) test.collection); - } - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final List original = ((List) test.expected); final List list = ((List) test.collection); try { @@ -182,10 +178,9 @@ public class ListDefaults { @Test public void testRemoveIf() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE); - - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final List original = ((List) test.expected); final List list = ((List) test.collection); try { @@ -201,7 +196,7 @@ public class ListDefaults { } for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); + final List original = ((List) test.expected); final List list = ((List) test.collection); list.removeIf(pOdd); for (int i : list) { @@ -217,7 +212,7 @@ public class ListDefaults { } for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); + final List original = ((List) test.expected); final List list = ((List) test.collection); final List listCopy = new ArrayList<>(list); if (original.size() > SUBLIST_SIZE) { @@ -274,9 +269,9 @@ public class ListDefaults { @Test public void testReplaceAll() throws Exception { final int scale = 3; - final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final List original = ((List) test.expected); final List list = ((List) test.collection); try { @@ -329,9 +324,9 @@ public class ListDefaults { @Test public void testSort() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { - final List original = ((List) test.original); + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final List original = ((List) test.expected); final List list = ((List) test.collection); CollectionSupplier.shuffle(list); list.sort(Integer::compare); @@ -378,17 +373,15 @@ public class ListDefaults { } @SuppressWarnings("unchecked") - final Class> type = - (Class>) Class.forName(test.className); - final Constructor> defaultConstructor = type.getConstructor(); + final Constructor> defaultConstructor = ((Class>)test.collection.getClass()).getConstructor(); final List incomparables = (List) defaultConstructor.newInstance(); - for (int i=0; i < test.original.size(); i++) { + for (int i=0; i < test.expected.size(); i++) { incomparables.add(new AtomicInteger(i)); } CollectionSupplier.shuffle(incomparables); incomparables.sort(ATOMIC_INTEGER_COMPARATOR); - for (int i=0; i < test.original.size(); i++) { + for (int i=0; i < test.expected.size(); i++) { assertEquals(i, incomparables.get(i).intValue()); } @@ -427,9 +420,10 @@ public class ListDefaults { @Test public void testForEachThrowsCME() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CME_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { final List list = ((List) test.collection); + if (list.size() <= 1) { continue; } @@ -448,9 +442,11 @@ public class ListDefaults { @Test public void testRemoveIfThrowsCME() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CME_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { + final List original = ((List) test.expected); final List list = ((List) test.collection); + if (list.size() <= 1) { continue; } @@ -469,9 +465,10 @@ public class ListDefaults { @Test public void testReplaceAllThrowsCME() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CME_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { final List list = ((List) test.collection); + if (list.size() <= 1) { continue; } @@ -490,9 +487,10 @@ public class ListDefaults { @Test public void testSortThrowsCME() throws Exception { - final CollectionSupplier supplier = new CollectionSupplier(LIST_CME_CLASSES, SIZE); - for (final CollectionSupplier.TestCase test : supplier.get()) { + final CollectionSupplier> supplier = new CollectionSupplier((Supplier>[])LIST_CME_CLASSES, SIZE); + for (final CollectionSupplier.TestCase> test : supplier.get()) { final List list = ((List) test.collection); + if (list.size() <= 1) { continue; } @@ -520,6 +518,7 @@ public class ListDefaults { cases.add(new Object[] { new LinkedList<>(Arrays.asList(DATA)) }); cases.add(new Object[] { new Vector<>(Arrays.asList(DATA)) }); cases.add(new Object[] { new CopyOnWriteArrayList<>(Arrays.asList(DATA)) }); + cases.add(new Object[] { new ExtendsAbstractList<>(Arrays.asList(DATA)) }); return cases.toArray(new Object[0][cases.size()]); } diff --git a/jdk/test/java/util/Map/CheckRandomHashSeed.java b/jdk/test/java/util/Map/CheckRandomHashSeed.java deleted file mode 100644 index 5395ec999ee..00000000000 --- a/jdk/test/java/util/Map/CheckRandomHashSeed.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * @test - * @bug 8005698 - * @summary Check operation of jdk.map.useRandomSeed property - * @run main CheckRandomHashSeed - * @run main/othervm -Djdk.map.useRandomSeed=false CheckRandomHashSeed - * @run main/othervm -Djdk.map.useRandomSeed=bogus CheckRandomHashSeed - * @run main/othervm -Djdk.map.useRandomSeed=true CheckRandomHashSeed true - * @author Brent Christian - */ -import java.lang.reflect.Field; -import java.util.Map; -import java.util.HashMap; -import java.util.LinkedHashMap; -import java.util.Hashtable; -import java.util.WeakHashMap; - -public class CheckRandomHashSeed { - private final static String PROP_NAME = "jdk.map.useRandomSeed"; - static boolean expectRandom = false; - - public static void main(String[] args) { - if (args.length > 0 && args[0].equals("true")) { - expectRandom = true; - } - String hashSeedProp = System.getProperty(PROP_NAME); - boolean propSet = (null != hashSeedProp) - ? Boolean.parseBoolean(hashSeedProp) : false; - if (expectRandom != propSet) { - throw new Error("Error in test setup: " + (expectRandom ? "" : "not " ) + "expecting random hashSeed, but " + PROP_NAME + " is " + (propSet ? "" : "not ") + "enabled"); - } - - testMap(new HashMap()); - testMap(new LinkedHashMap()); - testMap(new WeakHashMap()); - testMap(new Hashtable()); - } - - private static void testMap(Map map) { - int hashSeed = getHashSeed(map); - boolean hashSeedIsZero = (hashSeed == 0); - - if (expectRandom != hashSeedIsZero) { - System.out.println("Test passed for " + map.getClass().getSimpleName() + " - expectRandom: " + expectRandom + ", hashSeed: " + hashSeed); - } else { - throw new Error ("Test FAILED for " + map.getClass().getSimpleName() + " - expectRandom: " + expectRandom + ", hashSeed: " + hashSeed); - } - } - - private static int getHashSeed(Map map) { - try { - if (map instanceof HashMap || map instanceof LinkedHashMap) { - map.put("Key", "Value"); - Field hashSeedField = HashMap.class.getDeclaredField("hashSeed"); - hashSeedField.setAccessible(true); - int hashSeed = hashSeedField.getInt(map); - return hashSeed; - } else { - map.put("Key", "Value"); - Field hashSeedField = map.getClass().getDeclaredField("hashSeed"); - hashSeedField.setAccessible(true); - int hashSeed = hashSeedField.getInt(map); - return hashSeed; - } - } catch(Exception e) { - e.printStackTrace(); - throw new Error(e); - } - } -} diff --git a/jdk/test/java/util/Map/Collisions.java b/jdk/test/java/util/Map/Collisions.java index b7170791777..05e9e1f95e0 100644 --- a/jdk/test/java/util/Map/Collisions.java +++ b/jdk/test/java/util/Map/Collisions.java @@ -25,8 +25,6 @@ * @test * @bug 7126277 * @run main Collisions -shortrun - * @run main/othervm -Djdk.map.althashing.threshold=0 Collisions -shortrun - * @run main/othervm -Djdk.map.useRandomSeed=true Collisions -shortrun * @summary Ensure Maps behave well with lots of hashCode() collisions. * @author Mike Duigou */ diff --git a/jdk/test/java/util/Map/Defaults.java b/jdk/test/java/util/Map/Defaults.java index 48a93525b7f..f14cd8aaa4b 100644 --- a/jdk/test/java/util/Map/Defaults.java +++ b/jdk/test/java/util/Map/Defaults.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8010122 8004518 + * @bug 8010122 8004518 8024331 * @summary Test Map default methods * @author Mike Duigou * @run testng Defaults @@ -155,7 +155,7 @@ public class Defaults { assertThrows( () -> { map.replaceAll((k,v) -> null); }, NullPointerException.class, - description); + description + " should not allow replacement with null value"); } @Test(dataProvider = "Map rw=true keys=withNull values=withNull") @@ -194,6 +194,15 @@ public class Defaults { assertSame(map.get(null), EXTRA_VALUE); } + @Test(dataProvider = "Map rw=true keys=nonNull values=nonNull") + public void testReplaceKVNoNulls(String description, Map map) { + assertTrue(map.containsKey(FIRST_KEY), "expected key missing"); + assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value"); + assertThrows( () -> {map.replace(FIRST_KEY, null);}, NullPointerException.class, description + ": should throw NPE"); + assertSame(map.replace(FIRST_KEY, EXTRA_VALUE), FIRST_VALUE, description + ": replaced wrong value"); + assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value"); + } + @Test(dataProvider = "Map rw=true keys=all values=all") public void testReplaceKV(String description, Map map) { assertTrue(map.containsKey(KEYS[1])); @@ -224,6 +233,16 @@ public class Defaults { assertSame(map.get(null), EXTRA_VALUE); } + @Test(dataProvider = "Map rw=true keys=nonNull values=nonNull") + public void testReplaceKVVNoNulls(String description, Map map) { + assertTrue(map.containsKey(FIRST_KEY), "expected key missing"); + assertSame(map.get(FIRST_KEY), FIRST_VALUE, "found wrong value"); + assertThrows( () -> {map.replace(FIRST_KEY, FIRST_VALUE, null);}, NullPointerException.class, description + ": should throw NPE"); + assertThrows( () -> {if (!map.replace(FIRST_KEY, null, EXTRA_VALUE)) throw new NullPointerException("default returns false rather than throwing");}, NullPointerException.class, description + ": should throw NPE"); + assertTrue(map.replace(FIRST_KEY, FIRST_VALUE, EXTRA_VALUE), description + ": replaced wrong value"); + assertSame(map.get(FIRST_KEY), EXTRA_VALUE, "found wrong value"); + } + @Test(dataProvider = "Map rw=true keys=all values=all") public void testReplaceKVV(String description, Map map) { assertTrue(map.containsKey(KEYS[1])); @@ -269,6 +288,21 @@ public class Defaults { assertSame(map.get(EXTRA_KEY), EXTRA_VALUE); } + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeIfAbsentNPEHashMap() { + Object value = new HashMap().computeIfAbsent(KEYS[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeIfAbsentNPEHashtable() { + Object value = new Hashtable().computeIfAbsent(KEYS[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeIfAbsentNPETreeMap() { + Object value = new TreeMap().computeIfAbsent(KEYS[1], null); + } + @Test(dataProvider = "Map rw=true keys=withNull values=withNull") public void testComputeIfPresentNulls(String description, Map map) { assertTrue(map.containsKey(null), description + ": null key absent"); @@ -309,6 +343,21 @@ public class Defaults { assertSame(map.get(EXTRA_KEY), null); } + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeIfPresentNPEHashMap() { + Object value = new HashMap().computeIfPresent(KEYS[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeIfPresentNPEHashtable() { + Object value = new Hashtable().computeIfPresent(KEYS[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeIfPresentNPETreeMap() { + Object value = new TreeMap().computeIfPresent(KEYS[1], null); + } + @Test(dataProvider = "Map rw=true keys=withNull values=withNull") public void testComputeNulls(String description, Map map) { assertTrue(map.containsKey(null), "null key absent"); @@ -395,6 +444,20 @@ public class Defaults { assertSame(map.get(EXTRA_KEY), EXTRA_VALUE); } + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeNPEHashMap() { + Object value = new HashMap().compute(KEYS[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeNPEHashtable() { + Object value = new Hashtable().compute(KEYS[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testComputeNPETreeMap() { + Object value = new TreeMap().compute(KEYS[1], null); + } @Test(dataProvider = "Map rw=true keys=withNull values=withNull") public void testMergeNulls(String description, Map map) { @@ -437,6 +500,21 @@ public class Defaults { assertSame(map.get(EXTRA_KEY), EXTRA_VALUE); } + @Test(expectedExceptions = {NullPointerException.class}) + public void testMergeNPEHashMap() { + Object value = new HashMap().merge(KEYS[1], VALUES[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testMergeNPEHashtable() { + Object value = new Hashtable().merge(KEYS[1], VALUES[1], null); + } + + @Test(expectedExceptions = {NullPointerException.class}) + public void testMergeNPETreeMap() { + Object value = new TreeMap().merge(KEYS[1], VALUES[1], null); + } + enum IntegerEnum { e0, e1, e2, e3, e4, e5, e6, e7, e8, e9, @@ -470,6 +548,9 @@ public class Defaults { VALUES[each] = String.valueOf(each); } } + + private static final IntegerEnum FIRST_KEY = KEYS[0]; + private static final String FIRST_VALUE = VALUES[0]; private static final IntegerEnum EXTRA_KEY = IntegerEnum.EXTRA_KEY; private static final String EXTRA_VALUE = String.valueOf(TEST_SIZE); @@ -583,6 +664,8 @@ public class Defaults { return Arrays.asList( // null key hostile new Object[]{"EnumMap", makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls)}, + new Object[]{"TreeMap", makeMap(TreeMap::new, false, nulls)}, + new Object[]{"ExtendsAbstractMap(TreeMap)", makeMap(() -> {return new ExtendsAbstractMap(new TreeMap());}, false, nulls)}, new Object[]{"Collections.synchronizedMap(EnumMap)", Collections.synchronizedMap(makeMap(() -> new EnumMap(IntegerEnum.class), false, nulls))} ); } @@ -591,10 +674,11 @@ public class Defaults { return Arrays.asList( // null key and value hostile new Object[]{"Hashtable", makeMap(Hashtable::new, false, false)}, - new Object[]{"TreeMap", makeMap(TreeMap::new, false, false)}, new Object[]{"ConcurrentHashMap", makeMap(ConcurrentHashMap::new, false, false)}, new Object[]{"ConcurrentSkipListMap", makeMap(ConcurrentSkipListMap::new, false, false)}, + new Object[]{"Collections.synchronizedMap(ConcurrentHashMap)", Collections.synchronizedMap(makeMap(ConcurrentHashMap::new, false, false))}, new Object[]{"Collections.checkedMap(ConcurrentHashMap)", Collections.checkedMap(makeMap(ConcurrentHashMap::new, false, false), IntegerEnum.class, String.class)}, + new Object[]{"ExtendsAbstractMap(ConcurrentHashMap)", makeMap(() -> {return new ExtendsAbstractMap(new ConcurrentHashMap());}, false, false)}, new Object[]{"ImplementsConcurrentMap", makeMap(ImplementsConcurrentMap::new, false, false)} ); } @@ -641,18 +725,17 @@ public class Defaults { } public static void assertThrows(Thrower thrower, Class throwable, String message) { - Throwable result; + Throwable thrown; try { thrower.run(); - result = null; + thrown = null; } catch (Throwable caught) { - result = caught; + thrown = caught; } - assertInstance(result, throwable, - (null != message) - ? message - : "Failed to throw " + throwable.getCanonicalName()); + assertInstance(thrown, throwable, + ((null != message) ? message : "") + + " Failed to throw " + throwable.getCanonicalName()); } public static void assertThrows(Class throwable, String message, Thrower... throwers) { @@ -661,11 +744,11 @@ public class Defaults { } } - public static void assertInstance(T actual, Class expected) { + public static void assertInstance(Object actual, Class expected) { assertInstance(expected.isInstance(actual), null); } - public static void assertInstance(T actual, Class expected, String message) { + public static void assertInstance(Object actual, Class expected, String message) { assertTrue(expected.isInstance(actual), message); } diff --git a/jdk/test/java/util/Map/InPlaceOpsCollisions.java b/jdk/test/java/util/Map/InPlaceOpsCollisions.java index 4a755bd4415..e24ba6ac508 100644 --- a/jdk/test/java/util/Map/InPlaceOpsCollisions.java +++ b/jdk/test/java/util/Map/InPlaceOpsCollisions.java @@ -25,7 +25,6 @@ * @test * @bug 8005698 * @run main InPlaceOpsCollisions -shortrun - * @run main/othervm -Djdk.map.randomseed=true InPlaceOpsCollisions -shortrun * @summary Ensure overrides of in-place operations in Maps behave well with lots of collisions. * @author Brent Christian */ diff --git a/jdk/test/java/util/Map/MapBinToFromTreeTest.java b/jdk/test/java/util/Map/MapBinToFromTreeTest.java new file mode 100644 index 00000000000..0b40a4ef16e --- /dev/null +++ b/jdk/test/java/util/Map/MapBinToFromTreeTest.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; +import java.util.stream.Collector; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @bug 8023463 + * @summary Test the case where a bin is treeified and vice verser + * @run testng MapBinToFromTreeTest + */ + +@Test +public class MapBinToFromTreeTest { + + // Initial capacity of map + // Should be >= the map capacity for treeifiying, see HashMap/ConcurrentMap.MIN_TREEIFY_CAPACITY + static final int INITIAL_CAPACITY = 64; + + // Maximum size of map + // Should be > the treeify threshold, see HashMap/ConcurrentMap.TREEIFY_THRESHOLD + // Should be > INITIAL_CAPACITY to ensure resize occurs + static final int SIZE = 256; + + // Load factor of map + // A value 1.0 will ensure that a new threshold == capacity + static final float LOAD_FACTOR = 1.0f; + + @DataProvider(name = "maps") + static Object[][] mapProvider() { + return new Object[][] { + // Pass in the class name as a description for test reporting + // purposes + { HashMap.class.getName(), new HashMap(INITIAL_CAPACITY, LOAD_FACTOR) }, + { LinkedHashMap.class.getName(), new LinkedHashMap(INITIAL_CAPACITY, LOAD_FACTOR) }, + { ConcurrentHashMap.class.getName(), new ConcurrentHashMap(INITIAL_CAPACITY, LOAD_FACTOR) }, + }; + } + + @Test(dataProvider = "maps") + public void testPutThenGet(String d, Map m) { + put(SIZE, m, (i, s) -> { + for (int j = 0; j < s; j++) { + assertEquals(m.get(new HashCodeInteger(j)).intValue(), j, + String.format("Map.get(%d)", j)); + } + }); + } + + @Test(dataProvider = "maps") + public void testPutThenTraverse(String d, Map m) { + Collector> c = getCollector(m); + + put(SIZE, m, (i, s) -> { + // Note that it is OK to collect to a Set (HashSet) as long as + // integer values are used since these tests only check for + // collisions and other tests will verify more general functionality + Collection actual = m.keySet().stream().map(e -> e.value).collect(c); + Collection expected = IntStream.range(0, s).boxed().collect(c); + assertEquals(actual, expected, "Map.keySet()"); + }); + } + + @Test(dataProvider = "maps") + public void testRemoveThenGet(String d, Map m) { + put(SIZE, m, (i, s) -> { }); + + remove(m, (i, s) -> { + for (int j = i + 1; j < SIZE; j++) { + assertEquals(m.get(new HashCodeInteger(j)).intValue(), j, + String.format("Map.get(%d)", j)); + } + }); + } + + @Test(dataProvider = "maps") + public void testRemoveThenTraverse(String d, Map m) { + put(SIZE, m, (i, s) -> { }); + + Collector> c = getCollector(m); + + remove(m, (i, s) -> { + Collection actual = m.keySet().stream().map(e -> e.value).collect(c); + Collection expected = IntStream.range(i + 1, SIZE).boxed().collect(c); + assertEquals(actual, expected, "Map.keySet()"); + }); + } + + @Test(dataProvider = "maps") + public void testUntreeifyOnResizeWithGet(String d, Map m) { + // Fill the map with 64 entries grouped into 4 buckets + put(INITIAL_CAPACITY, m, (i, s) -> { }); + + for (int i = INITIAL_CAPACITY; i < SIZE; i++) { + // Add further entries in the 0'th bucket so as not to disturb + // other buckets, entries of which may be distributed and/or + // the bucket untreeified on resize + m.put(new HashCodeInteger(i, 0), i); + + for (int j = 0; j < INITIAL_CAPACITY; j++) { + assertEquals(m.get(new HashCodeInteger(j)).intValue(), j, + String.format("Map.get(%d) < INITIAL_CAPACITY", j)); + } + for (int j = INITIAL_CAPACITY; j <= i; j++) { + assertEquals(m.get(new HashCodeInteger(j, 0)).intValue(), j, + String.format("Map.get(%d) >= INITIAL_CAPACITY", j)); + } + } + } + + @Test(dataProvider = "maps") + public void testUntreeifyOnResizeWithTraverse(String d, Map m) { + // Fill the map with 64 entries grouped into 4 buckets + put(INITIAL_CAPACITY, m, (i, s) -> { }); + + Collector> c = getCollector(m); + + for (int i = INITIAL_CAPACITY; i < SIZE; i++) { + // Add further entries in the 0'th bucket so as not to disturb + // other buckets, entries of which may be distributed and/or + // the bucket untreeified on resize + m.put(new HashCodeInteger(i, 0), i); + + Collection actual = m.keySet().stream().map(e -> e.value).collect(c); + Collection expected = IntStream.rangeClosed(0, i).boxed().collect(c); + assertEquals(actual, expected, "Key set"); + } + } + + Collector> getCollector(Map m) { + Collector> collector = m instanceof LinkedHashMap + ? Collectors.toList() + : Collectors.toSet(); + return collector; + } + + void put(int size, Map m, BiConsumer c) { + for (int i = 0; i < size; i++) { + m.put(new HashCodeInteger(i), i); + + c.accept(i, m.size()); + } + } + + void remove(Map m, BiConsumer c) { + int size = m.size(); + // Remove all elements thus ensuring at some point trees will be + // converting back to bins + for (int i = 0; i < size; i++) { + m.remove(new HashCodeInteger(i)); + + c.accept(i, m.size()); + } + } + + final static class HashCodeInteger implements Comparable { + final int value; + + final int hashcode; + + HashCodeInteger(int value) { + this(value, hash(value)); + } + + HashCodeInteger(int value, int hashcode) { + this.value = value; + this.hashcode = hashcode; + } + + static int hash(int i) { + // Assuming 64 entries with keys from 0 to 63 then a map: + // - of capacity 64 will have 4 buckets with 16 entries per-bucket + // - of capacity 128 will have 8 buckets with 8 entries per-bucket + // - of capacity 256 will have 16 buckets with 4 entries per-bucket + // + // Re-sizing will result in re-distribution, doubling the buckets + // and reducing the entries by half. This will result in + // untreeifying when the number of entries is less than untreeify + // threshold (see HashMap/ConcurrentMap.UNTREEIFY_THRESHOLD) + return (i % 4) + (i / 4) * INITIAL_CAPACITY; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HashCodeInteger) { + HashCodeInteger other = (HashCodeInteger) obj; + return other.value == value; + } + return false; + } + + @Override + public int hashCode() { + return hashcode; + } + + @Override + public int compareTo(HashCodeInteger o) { + return value - o.value; + } + + @Override + public String toString() { + return Integer.toString(value); + } + } +} diff --git a/jdk/test/java/util/Map/TreeBinSplitBackToEntries.java b/jdk/test/java/util/Map/TreeBinSplitBackToEntries.java deleted file mode 100644 index 6093147a24d..00000000000 --- a/jdk/test/java/util/Map/TreeBinSplitBackToEntries.java +++ /dev/null @@ -1,255 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -import java.util.*; -import java.lang.reflect.Field; - -/* - * @test - * @bug 8005698 - * @summary Test the case where TreeBin.splitTreeBin() converts a bin back to an Entry list - * @run main TreeBinSplitBackToEntries unused - * @author Brent Christian - */ - -public class TreeBinSplitBackToEntries { - private static int EXPECTED_TREE_THRESHOLD = 16; - - // Easiest if this covers one bit higher then 'bit' in splitTreeBin() on the - // call where the TreeBin is converted back to an Entry list - private static int HASHMASK = 0x7F; - private static boolean verbose = false; - private static boolean fastFail = false; - private static boolean failed = false; - - static void printlnIfVerbose(String msg) { - if (verbose) {System.out.println(msg); } - } - - public static void main(String[] args) { - for (String arg : args) { - switch(arg) { - case "-verbose": - verbose = true; - break; - case "-fastfail": - fastFail = true; - break; - } - } - checkTreeThreshold(); - testMapHiTree(); - testMapLoTree(); - if (failed) { - System.out.println("Test Failed"); - System.exit(1); - } else { - System.out.println("Test Passed"); - } - } - - public static void checkTreeThreshold() { - int threshold = -1; - try { - Class treeBinClass = Class.forName("java.util.HashMap$TreeBin"); - Field treeThreshold = treeBinClass.getDeclaredField("TREE_THRESHOLD"); - treeThreshold.setAccessible(true); - threshold = treeThreshold.getInt(treeBinClass); - } catch (ClassNotFoundException|NoSuchFieldException|IllegalAccessException e) { - e.printStackTrace(); - throw new Error("Problem accessing TreeBin.TREE_THRESHOLD", e); - } - check("Expected TREE_THRESHOLD: " + EXPECTED_TREE_THRESHOLD +", found: " + threshold, - threshold == EXPECTED_TREE_THRESHOLD); - printlnIfVerbose("TREE_THRESHOLD: " + threshold); - } - - public static void testMapHiTree() { - Object[][] mapKeys = makeHiTreeTestData(); - testMapsForKeys(mapKeys, "hiTree"); - } - - public static void testMapLoTree() { - Object[][] mapKeys = makeLoTreeTestData(); - - testMapsForKeys(mapKeys, "loTree"); - } - - public static void testMapsForKeys(Object[][] mapKeys, String desc) { - // loop through data sets - for (Object[] keys_desc : mapKeys) { - Map[] maps = (Map[]) new Map[]{ - new HashMap<>(4, 0.8f), - new LinkedHashMap<>(4, 0.8f), - }; - // for each map type. - for (Map map : maps) { - Object[] keys = (Object[]) keys_desc[1]; - System.out.println(desc + ": testPutThenGet() for " + map.getClass()); - testPutThenGet(map, keys); - } - } - } - - private static void testPutThenGet(Map map, T[] keys) { - for (T key : keys) { - printlnIfVerbose("put()ing 0x" + Integer.toHexString(Integer.parseInt(key.toString())) + ", hashCode=" + Integer.toHexString(key.hashCode())); - map.put(key, key); - } - for (T key : keys) { - check("key: 0x" + Integer.toHexString(Integer.parseInt(key.toString())) + " not found in resulting " + map.getClass().getSimpleName(), map.get(key) != null); - } - } - - /* Data to force a non-empty loTree in TreeBin.splitTreeBin() to be converted back - * into an Entry list - */ - private static Object[][] makeLoTreeTestData() { - HashableInteger COLLIDING_OBJECTS[] = new HashableInteger[] { - new HashableInteger( 0x23, HASHMASK), - new HashableInteger( 0x123, HASHMASK), - new HashableInteger( 0x323, HASHMASK), - new HashableInteger( 0x523, HASHMASK), - - new HashableInteger( 0x723, HASHMASK), - new HashableInteger( 0x923, HASHMASK), - new HashableInteger( 0xB23, HASHMASK), - new HashableInteger( 0xD23, HASHMASK), - - new HashableInteger( 0xF23, HASHMASK), - new HashableInteger( 0xF123, HASHMASK), - new HashableInteger( 0x1023, HASHMASK), - new HashableInteger( 0x1123, HASHMASK), - - new HashableInteger( 0x1323, HASHMASK), - new HashableInteger( 0x1523, HASHMASK), - new HashableInteger( 0x1723, HASHMASK), - new HashableInteger( 0x1923, HASHMASK), - - new HashableInteger( 0x1B23, HASHMASK), - new HashableInteger( 0x1D23, HASHMASK), - new HashableInteger( 0x3123, HASHMASK), - new HashableInteger( 0x3323, HASHMASK), - new HashableInteger( 0x3523, HASHMASK), - - new HashableInteger( 0x3723, HASHMASK), - new HashableInteger( 0x1001, HASHMASK), - new HashableInteger( 0x4001, HASHMASK), - new HashableInteger( 0x1, HASHMASK), - }; - return new Object[][] { - new Object[]{"Colliding Objects", COLLIDING_OBJECTS}, - }; - } - - /* Data to force the hiTree in TreeBin.splitTreeBin() to be converted back - * into an Entry list - */ - private static Object[][] makeHiTreeTestData() { - HashableInteger COLLIDING_OBJECTS[] = new HashableInteger[] { - new HashableInteger( 0x1, HASHMASK), - new HashableInteger( 0x101, HASHMASK), - new HashableInteger( 0x301, HASHMASK), - new HashableInteger( 0x501, HASHMASK), - new HashableInteger( 0x701, HASHMASK), - - new HashableInteger( 0x1001, HASHMASK), - new HashableInteger( 0x1101, HASHMASK), - new HashableInteger( 0x1301, HASHMASK), - - new HashableInteger( 0x1501, HASHMASK), - new HashableInteger( 0x1701, HASHMASK), - new HashableInteger( 0x4001, HASHMASK), - new HashableInteger( 0x4101, HASHMASK), - new HashableInteger( 0x4301, HASHMASK), - - new HashableInteger( 0x4501, HASHMASK), - new HashableInteger( 0x4701, HASHMASK), - new HashableInteger( 0x8001, HASHMASK), - new HashableInteger( 0x8101, HASHMASK), - - - new HashableInteger( 0x8301, HASHMASK), - new HashableInteger( 0x8501, HASHMASK), - new HashableInteger( 0x8701, HASHMASK), - new HashableInteger( 0x9001, HASHMASK), - - new HashableInteger( 0x23, HASHMASK), - new HashableInteger( 0x123, HASHMASK), - new HashableInteger( 0x323, HASHMASK), - new HashableInteger( 0x523, HASHMASK), - }; - return new Object[][] { - new Object[]{"Colliding Objects", COLLIDING_OBJECTS}, - }; - } - - static void check(String desc, boolean cond) { - if (!cond) { - fail(desc); - } - } - - static void fail(String msg) { - failed = true; - (new Error("Failure: " + msg)).printStackTrace(System.err); - if (fastFail) { - System.exit(1); - } - } - - final static class HashableInteger implements Comparable { - final int value; - final int hashmask; //yes duplication - - HashableInteger(int value, int hashmask) { - this.value = value; - this.hashmask = hashmask; - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof HashableInteger) { - HashableInteger other = (HashableInteger) obj; - return other.value == value; - } - return false; - } - - @Override - public int hashCode() { - // This version ANDs the mask - return value & hashmask; - } - - @Override - public int compareTo(HashableInteger o) { - return value - o.value; - } - - @Override - public String toString() { - return Integer.toString(value); - } - } -} diff --git a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java index bb0b7ecd976..37fbcc769d0 100644 --- a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java +++ b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8020156 8020009 8022326 + * @bug 8020156 8020009 8022326 8012913 8024405 * @run testng SpliteratorCharacteristics */ @@ -32,22 +32,175 @@ import org.testng.annotations.Test; import java.util.Arrays; import java.util.Collection; import java.util.Comparator; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedHashSet; +import java.util.List; import java.util.Map; +import java.util.PrimitiveIterator; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; import java.util.Spliterator; +import java.util.Spliterators; import java.util.TreeMap; import java.util.TreeSet; import java.util.concurrent.ConcurrentSkipListMap; import java.util.concurrent.ConcurrentSkipListSet; +import java.util.function.Supplier; +import java.util.stream.DoubleStream; +import java.util.stream.IntStream; +import java.util.stream.LongStream; import static org.testng.Assert.*; @Test public class SpliteratorCharacteristics { - // TreeMap + public void testSpliteratorFromCollection() { + List l = Arrays.asList(1, 2, 3, 4); + + { + Spliterator s = Spliterators.spliterator(l, 0); + assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliterator(l, Spliterator.CONCURRENT); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliterator(l.iterator( ), 1, 0); + assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliterator(l.iterator( ), 1, Spliterator.CONCURRENT); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize(l.iterator( ), 0); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize( + l.iterator(), Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + } + + public void testSpliteratorOfIntFromIterator() { + Supplier si = () -> IntStream.of(1, 2, 3, 4).iterator(); + + { + Spliterator s = Spliterators.spliterator(si.get(), 1, 0); + assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize(si.get(), 0); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize( + si.get(), Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + } + + public void testSpliteratorOfLongFromIterator() { + Supplier si = () -> LongStream.of(1, 2, 3, 4).iterator(); + + { + Spliterator s = Spliterators.spliterator(si.get(), 1, 0); + assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize(si.get(), 0); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize( + si.get(), Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + } + + public void testSpliteratorOfDoubleFromIterator() { + Supplier si = () -> DoubleStream.of(1, 2, 3, 4).iterator(); + + { + Spliterator s = Spliterators.spliterator(si.get(), 1, 0); + assertCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliterator(si.get(), 1, Spliterator.CONCURRENT); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + assertCharacteristics(s, Spliterator.CONCURRENT); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize(si.get(), 0); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + + { + Spliterator s = Spliterators.spliteratorUnknownSize( + si.get(), Spliterator.SIZED | Spliterator.SUBSIZED); + assertHasNotCharacteristics(s, Spliterator.SIZED | Spliterator.SUBSIZED); + } + } + + // + + public void testHashMap() { + assertMapCharacteristics(new HashMap<>(), + Spliterator.SIZED | Spliterator.DISTINCT); + } + + public void testHashSet() { + assertSetCharacteristics(new HashSet<>(), + Spliterator.SIZED | Spliterator.DISTINCT); + } + + public void testLinkedHashMap() { + assertMapCharacteristics(new LinkedHashMap<>(), + Spliterator.SIZED | Spliterator.DISTINCT | + Spliterator.ORDERED); + } + + public void testLinkedHashSet() { + assertSetCharacteristics(new LinkedHashSet<>(), + Spliterator.SIZED | Spliterator.DISTINCT | + Spliterator.ORDERED); + } public void testTreeMap() { assertSortedMapCharacteristics(new TreeMap<>(), @@ -61,9 +214,6 @@ public class SpliteratorCharacteristics { Spliterator.SORTED | Spliterator.ORDERED); } - - // TreeSet - public void testTreeSet() { assertSortedSetCharacteristics(new TreeSet<>(), Spliterator.SIZED | Spliterator.DISTINCT | @@ -76,9 +226,6 @@ public class SpliteratorCharacteristics { Spliterator.SORTED | Spliterator.ORDERED); } - - // ConcurrentSkipListMap - public void testConcurrentSkipListMap() { assertSortedMapCharacteristics(new ConcurrentSkipListMap<>(), Spliterator.CONCURRENT | Spliterator.NONNULL | @@ -93,9 +240,6 @@ public class SpliteratorCharacteristics { Spliterator.ORDERED); } - - // ConcurrentSkipListSet - public void testConcurrentSkipListSet() { assertSortedSetCharacteristics(new ConcurrentSkipListSet<>(), Spliterator.CONCURRENT | Spliterator.NONNULL | @@ -113,35 +257,58 @@ public class SpliteratorCharacteristics { // - void assertSortedMapCharacteristics(SortedMap m, int keyCharacteristics) { + + void assertMapCharacteristics(Map m, int keyCharacteristics) { + assertMapCharacteristics(m, keyCharacteristics, 0); + } + + void assertMapCharacteristics(Map m, int keyCharacteristics, int notValueCharacteristics) { initMap(m); - boolean hasComparator = m.comparator() != null; + assertCharacteristics(m.keySet(), keyCharacteristics); + + assertCharacteristics(m.values(), + keyCharacteristics & ~(Spliterator.DISTINCT | notValueCharacteristics)); + + assertCharacteristics(m.entrySet(), keyCharacteristics); + + if ((keyCharacteristics & Spliterator.SORTED) == 0) { + assertISEComparator(m.keySet()); + assertISEComparator(m.values()); + assertISEComparator(m.entrySet()); + } + } + + void assertSetCharacteristics(Set s, int keyCharacteristics) { + initSet(s); + + assertCharacteristics(s, keyCharacteristics); + + if ((keyCharacteristics & Spliterator.SORTED) == 0) { + assertISEComparator(s); + } + } + + void assertSortedMapCharacteristics(SortedMap m, int keyCharacteristics) { + assertMapCharacteristics(m, keyCharacteristics, Spliterator.SORTED); Set keys = m.keySet(); - assertCharacteristics(keys, keyCharacteristics); - if (hasComparator) { + if (m.comparator() != null) { assertNotNullComparator(keys); } else { assertNullComparator(keys); } - assertCharacteristics(m.values(), - keyCharacteristics & ~(Spliterator.DISTINCT | Spliterator.SORTED)); assertISEComparator(m.values()); - assertCharacteristics(m.entrySet(), keyCharacteristics); assertNotNullComparator(m.entrySet()); } void assertSortedSetCharacteristics(SortedSet s, int keyCharacteristics) { - initSet(s); + assertSetCharacteristics(s, keyCharacteristics); - boolean hasComparator = s.comparator() != null; - - assertCharacteristics(s, keyCharacteristics); - if (hasComparator) { + if (s.comparator() != null) { assertNotNullComparator(s); } else { @@ -165,23 +332,23 @@ public class SpliteratorCharacteristics { } void assertCharacteristics(Spliterator s, int expectedCharacteristics) { - assertTrue(s.hasCharacteristics(expectedCharacteristics)); + assertTrue(s.hasCharacteristics(expectedCharacteristics), + "Spliterator characteristics"); + } + + void assertHasNotCharacteristics(Spliterator s, int expectedCharacteristics) { + assertFalse(s.hasCharacteristics(expectedCharacteristics), + "Spliterator characteristics"); } void assertNullComparator(Collection c) { - assertNullComparator(c.spliterator()); - } - - void assertNullComparator(Spliterator s) { - assertNull(s.getComparator()); + assertNull(c.spliterator().getComparator(), + "Comparator of Spliterator of Collection"); } void assertNotNullComparator(Collection c) { - assertNotNullComparator(c.spliterator()); - } - - void assertNotNullComparator(Spliterator s) { - assertNotNull(s.getComparator()); + assertNotNull(c.spliterator().getComparator(), + "Comparator of Spliterator of Collection"); } void assertISEComparator(Collection c) { @@ -196,6 +363,6 @@ public class SpliteratorCharacteristics { catch (IllegalStateException e) { caught = true; } - assertTrue(caught); + assertTrue(caught, "Throwing IllegalStateException"); } } diff --git a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java index a84cbbeaebe..69c7cf57436 100644 --- a/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java +++ b/jdk/test/java/util/Spliterator/SpliteratorTraversingAndSplittingTest.java @@ -1159,7 +1159,7 @@ public class SpliteratorTraversingAndSplittingTest { List dest = new ArrayList<>(); spliterator = supplier.get(); - assertSpliterator(spliterator); + assertRootSpliterator(spliterator); // verify splitting with forEach visit(depth, 0, dest, spliterator, boxingAdapter, spliterator.characteristics(), false); @@ -1234,7 +1234,7 @@ public class SpliteratorTraversingAndSplittingTest { UnaryOperator> boxingAdapter) { Spliterator s = supplier.get(); boolean isOrdered = s.hasCharacteristics(Spliterator.ORDERED); - assertSpliterator(s); + assertRootSpliterator(s); List splits = new ArrayList<>(); Consumer c = boxingAdapter.apply(splits::add); @@ -1326,6 +1326,13 @@ public class SpliteratorTraversingAndSplittingTest { } } + private static void assertRootSpliterator(Spliterator s) { + assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.CONCURRENT), + "Root spliterator should not be SIZED and CONCURRENT"); + + assertSpliterator(s); + } + private static void assertSpliterator(Spliterator s, int rootCharacteristics) { if ((rootCharacteristics & Spliterator.SUBSIZED) != 0) { assertTrue(s.hasCharacteristics(Spliterator.SUBSIZED), diff --git a/jdk/test/java/util/concurrent/ConcurrentHashMap/ToArray.java b/jdk/test/java/util/concurrent/ConcurrentHashMap/ToArray.java new file mode 100644 index 00000000000..dca07084162 --- /dev/null +++ b/jdk/test/java/util/concurrent/ConcurrentHashMap/ToArray.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 4486658 8010293 + * @summary thread safety of toArray methods of subCollections + * @author Martin Buchholz + */ + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.stream.IntStream; + +public class ToArray { + + public static void main(String[] args) throws Throwable { + // Execute a number of times to increase the probability of + // failure if there is an issue + for (int i = 0; i < 16; i++) { + executeTest(); + } + } + + static void executeTest() throws Throwable { + final Throwable throwable[] = new Throwable[1]; + final ConcurrentHashMap m = new ConcurrentHashMap<>(); + + // Number of workers equal to the number of processors + // Each worker will put globally unique keys into the map + final int nWorkers = Runtime.getRuntime().availableProcessors(); + final int sizePerWorker = 1024; + final int maxSize = nWorkers * sizePerWorker; + + // The foreman keeps checking that the size of the arrays + // obtained from the key and value sets is never less than the + // previously observed size and is never greater than the maximum size + // NOTE: these size constraints are not specific to toArray and are + // applicable to any form of traversal of the collection views + CompletableFuture foreman = CompletableFuture.runAsync(new Runnable() { + private int prevSize = 0; + + private boolean checkProgress(Object[] a) { + int size = a.length; + if (size < prevSize) throw new RuntimeException("WRONG WAY"); + if (size > maxSize) throw new RuntimeException("OVERSHOOT"); + if (size == maxSize) return true; + prevSize = size; + return false; + } + + @Override + public void run() { + try { + Integer[] empty = new Integer[0]; + while (true) { + if (checkProgress(m.values().toArray())) return; + if (checkProgress(m.keySet().toArray())) return; + if (checkProgress(m.values().toArray(empty))) return; + if (checkProgress(m.keySet().toArray(empty))) return; + } + } + catch (Throwable t) { + throwable[0] = t; + } + } + }); + + // Create workers + // Each worker will put globally unique keys into the map + CompletableFuture[] workers = IntStream.range(0, nWorkers). + mapToObj(w -> CompletableFuture.runAsync(() -> { + for (int i = 0, o = w * sizePerWorker; i < sizePerWorker; i++) + m.put(o + i, i); + })). + toArray(CompletableFuture[]::new); + + // Wait for workers and then foreman to complete + CompletableFuture.allOf(workers).join(); + foreman.join(); + + if (throwable[0] != null) + throw throwable[0]; + } +} diff --git a/jdk/test/java/util/concurrent/ConcurrentHashMap/toArray.java b/jdk/test/java/util/concurrent/ConcurrentHashMap/toArray.java deleted file mode 100644 index 0280c0c4658..00000000000 --- a/jdk/test/java/util/concurrent/ConcurrentHashMap/toArray.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 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. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 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 4486658 - * @summary thread safety of toArray methods of subCollections - * @author Martin Buchholz - */ - -import java.util.*; -import java.util.concurrent.*; - -public class toArray { - - public static void main(String[] args) throws Throwable { - final Throwable throwable[] = new Throwable[1]; - final int maxSize = 1000; - final ConcurrentHashMap m - = new ConcurrentHashMap(); - - final Thread t1 = new Thread() { public void run() { - for (int i = 0; i < maxSize; i++) - m.put(i,i);}}; - - final Thread t2 = new Thread() { - public Throwable exception = null; - private int prevSize = 0; - - private boolean checkProgress(Object[] a) { - int size = a.length; - if (size < prevSize) throw new RuntimeException("WRONG WAY"); - if (size > maxSize) throw new RuntimeException("OVERSHOOT"); - if (size == maxSize) return true; - prevSize = size; - return false; - } - - public void run() { - try { - Integer[] empty = new Integer[0]; - while (true) { - if (checkProgress(m.values().toArray())) return; - if (checkProgress(m.keySet().toArray())) return; - if (checkProgress(m.values().toArray(empty))) return; - if (checkProgress(m.keySet().toArray(empty))) return; - } - } catch (Throwable t) { - throwable[0] = t; - }}}; - - t2.start(); - t1.start(); - - t1.join(); - t2.join(); - - if (throwable[0] != null) - throw throwable[0]; - } -} diff --git a/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java b/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java index e4e91f597bb..f159b67d348 100644 --- a/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java +++ b/jdk/test/java/util/concurrent/ThreadLocalRandom/ThreadLocalRandomTest.java @@ -33,7 +33,9 @@ import static org.testng.Assert.*; /** * @test + * @bug 8024253 * @run testng ThreadLocalRandomTest + * @run testng/othervm -Djava.util.secureRandomSeed=true ThreadLocalRandomTest * @summary test methods on ThreadLocalRandom */ @Test diff --git a/jdk/test/java/util/function/BiFunction/BiFunctionTest.java b/jdk/test/java/util/function/BiFunction/BiFunctionTest.java new file mode 100644 index 00000000000..e837b105beb --- /dev/null +++ b/jdk/test/java/util/function/BiFunction/BiFunctionTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8024500 + * @run testng BiFunctionTest + */ + +import java.util.function.BiFunction; +import java.util.function.Function; +import org.testng.annotations.Test; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.fail; + +@Test(groups = "unit") +public class BiFunctionTest { + static class Quote { + double unit_price; + + Quote(double price) { + unit_price = price; + } + }; + + static class Order { + int quantity; + + Order(int quantity) { + this.quantity = quantity; + } + }; + + BiFunction estimate = (quote, order) -> { + if (quote.unit_price < 0) { + throw new IllegalArgumentException("quote"); + } + + if (order.quantity < 0) { + throw new IllegalArgumentException("order"); + } + + return quote.unit_price * order.quantity; + }; + + Function creditcheck = total -> { + if (total > 100.00) { + throw new RuntimeException("overlimit"); + } + return total.longValue(); + }; + + public void testAndThen() { + try { + BiFunction checkout = estimate.andThen(null); + fail("Null argument should throw NPE"); + } catch (NullPointerException npe) { + // ignore + } + + BiFunction checkout = estimate.andThen(creditcheck); + try { + checkout.apply(new Quote(20.0), new Order(-1)); + fail("First function delivers exception"); + } catch (IllegalArgumentException e) { + assertEquals(e.getMessage(), "order"); + } + + try { + checkout.apply(new Quote(20.0), new Order(10)); + fail("Second function delivers exception"); + } catch (RuntimeException e) { + assertEquals(e.getMessage(), "overlimit"); + } + + assertEquals(49, checkout.apply(new Quote(24.99), new Order(2)).longValue()); + assertEquals(50, checkout.apply(new Quote(25), new Order(2)).longValue()); + } +} diff --git a/jdk/test/java/util/logging/LocalizedLevelName.java b/jdk/test/java/util/logging/LocalizedLevelName.java new file mode 100644 index 00000000000..cdb425a294f --- /dev/null +++ b/jdk/test/java/util/logging/LocalizedLevelName.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.util.*; +import java.util.logging.*; + +/* + * @test + * @bug 8016127 8024131 + * @summary test logging.properties localized + * @run main/othervm LocalizedLevelName + */ + +public class LocalizedLevelName { + private static Object[] namesMap = { + "SEVERE", Locale.ENGLISH, "Severe", Level.SEVERE, + "WARNING", Locale.FRENCH, "Avertissement", Level.WARNING, + "INFO", Locale.ITALIAN, "Informazioni", Level.INFO, + "SEVERE", Locale.FRENCH, "Grave", Level.SEVERE, + "CONFIG", Locale.GERMAN, "Konfiguration", Level.CONFIG, + "ALL", Locale.ROOT, "All", Level.ALL, + "SEVERE", Locale.ROOT, "Severe", Level.SEVERE, + "WARNING", Locale.ROOT, "Warning", Level.WARNING, + "CONFIG", Locale.ROOT, "Config", Level.CONFIG, + "INFO", Locale.ROOT, "Info", Level.INFO, + "FINE", Locale.ROOT, "Fine", Level.FINE, + "FINER", Locale.ROOT, "Finer", Level.FINER, + "FINEST", Locale.ROOT, "Finest", Level.FINEST + }; + + public static void main(String args[]) throws Exception { + Locale defaultLocale = Locale.getDefault(); + for (int i=0; i localized(" + Locale.ENGLISH + ", " + + key + ")=" + en); + System.out.println(" => localized(" + locale + ", " + key + + ")=" + other); + if (!key.equals(en.toUpperCase(Locale.ROOT))) { + throw new RuntimeException("Expect " + key + + " equals upperCase(" + en + ")"); + } + if (!Locale.ENGLISH.equals(locale) && !Locale.ROOT.equals(locale) + && key.equals(other.toUpperCase(Locale.ROOT))) { + throw new RuntimeException("Expect " + key + + " not equals upperCase(" + other +")"); + } + if ((Locale.ENGLISH.equals(locale) || Locale.ROOT.equals(locale)) + && !key.equals(other.toUpperCase(Locale.ROOT))) { + throw new RuntimeException("Expect " + key + + " equals upperCase(" + other +")"); + } + if (!other.equals(expectedTranslation)) { + throw new RuntimeException("Expected \"" + expectedTranslation + + "\" for '" + locale + "' but got \"" + other + "\""); + } + Locale.setDefault(locale); + final String levelName = level.getLocalizedName(); + System.out.println("Level.getLocalizedName() is: " + levelName); + if (!levelName.equals(other.toUpperCase(locale))) { + throw new RuntimeException("Expected \"" + + other.toUpperCase(locale) + "\" for '" + + locale + "' but got \"" + levelName + "\""); + } + Locale.setDefault(defaultLocale); + } + } + + private static final String RBNAME = "sun.util.logging.resources.logging"; + private static String getLocalizedMessage(Locale locale, String key) { + ResourceBundle rb = ResourceBundle.getBundle(RBNAME, locale); + return rb.getString(key); + } +} diff --git a/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobal.java b/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobal.java index dd901ed5f92..e87e15f81fc 100644 --- a/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobal.java +++ b/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobal.java @@ -29,18 +29,18 @@ import java.util.logging.Logger; * @bug 7184195 * @summary checks that java.util.logging.Logger.getGlobal().info() logs without configuration * @build TestGetGlobal testgetglobal.HandlerImpl testgetglobal.LogManagerImpl1 testgetglobal.LogManagerImpl2 testgetglobal.LogManagerImpl3 testgetglobal.BadLogManagerImpl testgetglobal.DummyLogManagerImpl - * @run main/othervm/timeout=10 TestGetGlobal - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager TestGetGlobal - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobal - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobal - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobal - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobal - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobal - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobal - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobal - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobal - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobal - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobal + * @run main/othervm TestGetGlobal + * @run main/othervm/policy=policy -Djava.security.manager TestGetGlobal + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobal + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobal + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobal + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobal + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobal + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobal + * @run main/othervm -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobal + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobal + * @run main/othervm -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobal + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobal * @author danielfuchs */ public class TestGetGlobal { @@ -57,6 +57,12 @@ public class TestGetGlobal { } public static void main(String... args) { + final String manager = System.getProperty("java.util.logging.manager", null); + + final String description = "TestGetGlobal" + + (System.getSecurityManager() == null ? " " : + " -Djava.security.manager ") + + (manager == null ? "" : "-Djava.util.logging.manager=" + manager); Logger.global.info(messages[0]); // at this point LogManager is not // initialized yet, so this message should not appear. @@ -67,7 +73,9 @@ public class TestGetGlobal { final List expected = Arrays.asList(Arrays.copyOfRange(messages, 1, messages.length)); if (!testgetglobal.HandlerImpl.received.equals(expected)) { - throw new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected); + System.err.println("Test case failed: " + description); + throw new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected + + "\n\t"+description); } } } diff --git a/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalByName.java b/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalByName.java index 62580a8bc3b..91968db400b 100644 --- a/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalByName.java +++ b/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalByName.java @@ -29,18 +29,18 @@ import java.util.logging.Logger; * @bug 7184195 * @summary checks that java.util.logging.Logger.getLogger(Logger.GLOBAL_LOGGER_NAME).info() logs without configuration * @build TestGetGlobalByName testgetglobal.HandlerImpl testgetglobal.LogManagerImpl1 testgetglobal.LogManagerImpl2 testgetglobal.LogManagerImpl3 testgetglobal.BadLogManagerImpl testgetglobal.DummyLogManagerImpl - * @run main/othervm/timeout=10 TestGetGlobalByName - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager TestGetGlobalByName - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobalByName - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl TestGetGlobalByName - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalByName - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalByName - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalByName - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalByName - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalByName - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalByName - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalByName - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalByName + * @run main/othervm TestGetGlobalByName + * @run main/othervm/policy=policy -Djava.security.manager TestGetGlobalByName + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobalByName + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl TestGetGlobalByName + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalByName + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalByName + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalByName + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalByName + * @run main/othervm -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalByName + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalByName + * @run main/othervm -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalByName + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalByName * @author danielfuchs */ public class TestGetGlobalByName { diff --git a/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalConcurrent.java b/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalConcurrent.java index 4ef38ce3611..23688e1bca5 100644 --- a/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalConcurrent.java +++ b/jdk/test/java/util/logging/Logger/getGlobal/TestGetGlobalConcurrent.java @@ -22,25 +22,26 @@ */ import java.util.Arrays; import java.util.List; +import java.util.logging.Level; import java.util.logging.Logger; /** * @test - * @bug 7184195 - * @summary checks that java.util.logging.Logger.getGlobal().info() logs without configuration + * @bug 7184195 8021003 + * @summary Test that the global logger can log with no configuration when accessed from multiple threads. * @build TestGetGlobalConcurrent testgetglobal.HandlerImpl testgetglobal.LogManagerImpl1 testgetglobal.LogManagerImpl2 testgetglobal.LogManagerImpl3 testgetglobal.BadLogManagerImpl testgetglobal.DummyLogManagerImpl - * @run main/othervm/timeout=10 TestGetGlobalConcurrent - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager TestGetGlobalConcurrent - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl TestGetGlobalConcurrent - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl TestGetGlobalConcurrent - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalConcurrent - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalConcurrent - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalConcurrent - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalConcurrent - * @run main/othervm/timeout=10 -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalConcurrent - * @run main/othervm/timeout=10/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalConcurrent + * @run main/othervm TestGetGlobalConcurrent + * @run main/othervm/policy=policy -Djava.security.manager TestGetGlobalConcurrent + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobalConcurrent + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl1 TestGetGlobalConcurrent + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl2 TestGetGlobalConcurrent + * @run main/othervm -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalConcurrent + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.LogManagerImpl3 TestGetGlobalConcurrent + * @run main/othervm -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalConcurrent + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.BadLogManagerImpl TestGetGlobalConcurrent + * @run main/othervm -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalConcurrent + * @run main/othervm/policy=policy -Djava.security.manager -Djava.util.logging.manager=testgetglobal.DummyLogManagerImpl TestGetGlobalConcurrent * @author danielfuchs */ public class TestGetGlobalConcurrent { @@ -69,7 +70,6 @@ public class TestGetGlobalConcurrent { // initialize the LogManager - and thus this message should appear. Logger.global.info(messages[i+1]); // Now that the LogManager is // initialized, this message should appear too. - final List expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2)); if (!testgetglobal.HandlerImpl.received.containsAll(expected)) { fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected)); @@ -82,7 +82,6 @@ public class TestGetGlobalConcurrent { // initialize the LogManager - and thus this message should appear. Logger.global.info(messages[i+1]); // Now that the LogManager is // initialized, this message should appear too. - final List expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2)); if (!testgetglobal.HandlerImpl.received.containsAll(expected)) { fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected)); @@ -96,7 +95,6 @@ public class TestGetGlobalConcurrent { // initialize the LogManager - and thus this message should appear. Logger.global.info(messages[i+1]); // Now that the LogManager is // initialized, this message should appear too. - final List expected = Arrays.asList(Arrays.copyOfRange(messages, i, i+2)); if (!testgetglobal.HandlerImpl.received.containsAll(expected)) { fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected)); @@ -150,8 +148,17 @@ public class TestGetGlobalConcurrent { public void run() { test4(); } } + static String description = "Unknown"; + public static void main(String... args) throws Exception { + final String manager = System.getProperty("java.util.logging.manager", null); + + description = "TestGetGlobalConcurrent" + + (System.getSecurityManager() == null ? " " : + " -Djava.security.manager ") + + (manager == null ? "" : "-Djava.util.logging.manager=" + manager); + final Thread t1 = new Thread(new WaitAndRun(new Run1()), "test1"); final Thread t2 = new Thread(new WaitAndRun(new Run2()), "test2"); final Thread t3 = new Thread(new WaitAndRun(new Run3()), "test3"); @@ -169,14 +176,13 @@ public class TestGetGlobalConcurrent { final List expected = Arrays.asList(Arrays.copyOfRange(messages, 1, 3)); if (!testgetglobal.HandlerImpl.received.containsAll(expected)) { - throw new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected); + fail(new Error("Unexpected message list: "+testgetglobal.HandlerImpl.received+" vs "+ expected)); } - t1.join(); t2.join(); t3.join(); t4.join(); if (failed != null) { - throw new Error("Test failed.", failed); + throw new Error("Test failed: "+description, failed); } System.out.println("Test passed"); diff --git a/jdk/test/java/util/logging/Logger/getGlobal/policy b/jdk/test/java/util/logging/Logger/getGlobal/policy index bcb7cde0da3..fad24d0b814 100644 --- a/jdk/test/java/util/logging/Logger/getGlobal/policy +++ b/jdk/test/java/util/logging/Logger/getGlobal/policy @@ -1,6 +1,7 @@ grant { permission java.util.PropertyPermission "java.util.logging.config.file", "write"; permission java.util.PropertyPermission "test.src", "read"; + permission java.util.PropertyPermission "java.util.logging.manager", "read"; permission java.lang.RuntimePermission "setContextClassLoader"; permission java.lang.RuntimePermission "shutdownHooks"; permission java.util.logging.LoggingPermission "control"; diff --git a/jdk/test/java/util/logging/Logger/isLoggable/TestIsLoggable.java b/jdk/test/java/util/logging/Logger/isLoggable/TestIsLoggable.java new file mode 100644 index 00000000000..a6f95b83364 --- /dev/null +++ b/jdk/test/java/util/logging/Logger/isLoggable/TestIsLoggable.java @@ -0,0 +1,512 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.logging.Handler; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.LogRecord; +import java.util.logging.Logger; + +/** + * @test + * @bug 8024525 + * @summary checks that isLoggable() can be overridden to control logging. + * @author danielfuchs + * @run main/othervm TestIsLoggable + */ +public class TestIsLoggable { + + // This logger can be configured to override its default level + // for a particular set of thread ids + public static final class ThreadLogger extends Logger { + + final Map threadMap = + Collections.synchronizedMap(new HashMap()); + + public ThreadLogger(String name) { + super(name, null); + } + + @Override + public boolean isLoggable(Level level) { + final Level threadLevel = threadMap.get(Thread.currentThread().getId()); + if (threadLevel == null) return super.isLoggable(level); + final int levelValue = threadLevel.intValue(); + final int offValue = Level.OFF.intValue(); + if (level.intValue() < levelValue || levelValue == offValue) { + return false; + } + return true; + } + + } + + public static final class TestHandler extends Handler { + + final List messages = new CopyOnWriteArrayList<>(); + + @Override + public void publish(LogRecord record) { + messages.add(record.getMessage()); + } + + @Override + public void flush() { + } + + @Override + public void close() throws SecurityException { + messages.clear(); + } + + } + + // Sorted list of standard levels + static final List LEVELS = Collections.unmodifiableList( + java.util.Arrays.asList(new Level[] { + Level.SEVERE, Level.WARNING, Level.INFO, Level.CONFIG, + Level.FINE, Level.FINER, Level.FINEST + })); + + // Test cases: + // LEV_ test logger.severe(msg) .. logger.finest(msg) + // LOG_ logger.log(Level.SEVERE, msg) ... logger.log(Level.FINEST, msg) + // LOG1_ logger.log(Level.SEVERE, msg, param1) ... + // LOG2_ logger.log(Level.SEVERE, msg, params[]) ... + // LOG3_ logger.log(Level.SEVERE, msg, throwable) ... + // LOGP_ logger.logp(Level.SEVERE, class, method, msg) ... + // LOGP1_ logger.logp(Level.SEVERE, class, method, msg, param1) ... + // LOGP2_ logger.logp(Level.SEVERE, class, method, msg, params[]) ... + // LOGP3_ logger.logp(Level.SEVERE, class, method, msg, throwable) ... + public static enum LogTest { + LEV_SEVERE, LEV_WARNING, LEV_INFO, LEV_CONFIG, LEV_FINE, LEV_FINER, LEV_FINEST, + LOG_SEVERE, LOG_WARNING, LOG_INFO, LOG_CONFIG, LOG_FINE, LOG_FINER, LOG_FINEST, + LOG1_SEVERE, LOG1_WARNING, LOG1_INFO, LOG1_CONFIG, LOG1_FINE, LOG1_FINER, LOG1_FINEST, + LOG2_SEVERE, LOG2_WARNING, LOG2_INFO, LOG2_CONFIG, LOG2_FINE, LOG2_FINER, LOG2_FINEST, + LOG3_SEVERE, LOG3_WARNING, LOG3_INFO, LOG3_CONFIG, LOG3_FINE, LOG3_FINER, LOG3_FINEST, + LOGP_SEVERE, LOGP_WARNING, LOGP_INFO, LOGP_CONFIG, LOGP_FINE, LOGP_FINER, LOGP_FINEST, + LOGP1_SEVERE, LOGP1_WARNING, LOGP1_INFO, LOGP1_CONFIG, LOGP1_FINE, LOGP1_FINER, LOGP1_FINEST, + LOGP2_SEVERE, LOGP2_WARNING, LOGP2_INFO, LOGP2_CONFIG, LOGP2_FINE, LOGP2_FINER, LOGP2_FINEST, + LOGP3_SEVERE, LOGP3_WARNING, LOGP3_INFO, LOGP3_CONFIG, LOGP3_FINE, LOGP3_FINER, LOGP3_FINEST; + + // call the method Logger.severe() ... Logger.finest() corresponding + // to the given level 'l' (severe() for SEVERE etc...) + public void loglevel(Level l, Logger logger, String message) { + LogTest test = LogTest.valueOf("LEV_"+l.getName()); + switch(test) { + case LEV_SEVERE: + logger.severe(message); + break; + case LEV_WARNING: + logger.warning(message); + break; + case LEV_INFO: + logger.info(message); + break; + case LEV_CONFIG: + logger.config(message); + break; + case LEV_FINE: + logger.fine(message); + break; + case LEV_FINER: + logger.finer(message); + break; + case LEV_FINEST: + logger.finest(message); + break; + } + } + + // The threshold at which the logger is expected to start logging. + // trick: we derive the threshold level from the testcase name... + public Level threshold() { + for (Level l : LEVELS ) { + if (this.toString().endsWith(l.getName())) { + return l; + } + } + return Level.OFF; + } + + // Levels for which the logger is expected to log something. + public List loggable() { + return LEVELS.subList(0, LEVELS.indexOf(threshold())+1); + } + + // Levels which will be blocked because they are weaker than the + // threshold() + public List weaker() { + return LEVELS.subList(LEVELS.indexOf(threshold())+1, LEVELS.size()); + } + + // Log a message at this testcase threshold, using this testcase method. + public void log(Logger logger, String message) { + log(threshold(), logger, message); + } + + // Log a message at the given level, using this testcase method. + public void log(Level level, Logger logger, String message) { + if (this.toString().startsWith("LOG_")) { + logger.log(level, message); + } else if (this.toString().startsWith("LOG1_")) { + logger.log(level, message, "dummy param"); + } else if (this.toString().startsWith("LOG2_")) { + logger.log(level, message, new Object[] {"dummy", "param"}); + } else if (this.toString().startsWith("LOG3_")) { + logger.log(level, message, new Exception("dummy exception")); + } else if (this.toString().startsWith("LOGP_")) { + logger.logp(level, "TestCase", "log", message); + } else if (this.toString().startsWith("LOGP1_")) { + logger.logp(level, "TestCase", "log", message, "dummy param"); + } else if (this.toString().startsWith("LOGP2_")) { + logger.logp(level, "TestCase", "log", message, + new Object[] {"dummy", "param"}); + } else if (this.toString().startsWith("LOGP3_")) { + logger.logp(level, "TestCase", "log", message, + new Exception("dummy exception")); + } else if (this.toString().startsWith("LEV_")) { + loglevel(level, logger, message); + } + } + + // String description of the logging method called. + public String method() { + if (this.toString().startsWith("LOG_")) { + return "Logger.log(Level." + threshold().getName() +", msg): "; + } else if (this.toString().startsWith("LOG1_")) { + return "Logger.log(Level." + threshold().getName() +", msg, param1): "; + } else if (this.toString().startsWith("LOG2_")) { + return "Logger.log(Level." + threshold().getName() +", msg, params[]): "; + } else if (this.toString().startsWith("LOG3_")) { + return "Logger.log(Level." + threshold().getName() +", msg, throwable): "; + } else if (this.toString().startsWith("LEV_")) { + return "Logger."+threshold().getName().toLowerCase(Locale.ROOT)+"(): "; + } else if (this.toString().startsWith("LOGP_")) { + return "Logger.logp(Level." + threshold().getName() +", msg): "; + } else if (this.toString().startsWith("LOGP1_")) { + return "Logger.logp(Level." + threshold().getName() +", msg, param1): "; + } else if (this.toString().startsWith("LOGP2_")) { + return "Logger.logp(Level." + threshold().getName() +", msg, params[]): "; + } else if (this.toString().startsWith("LOGP3_")) { + return "Logger.logp(Level." + threshold().getName() +", msg, throwable): "; + } + throw new RuntimeException("Unknown test case: "+this); + } + } + + // The purpose of this test is to verify that the various log methods in + // Logger now call Logger.isLoggable(). + // To do that - we're going to use a subclass of Logger, ThreadLogger, which + // only overrides isLoggable() - and compare the level it is given to a level + // it finds in a map indexed with the current thread id. + // We will register a TestHandler with our ThreadLogger which will store + // the messages in a messages map. This will allow us to verify whether the + // logging method we're testing has or hasn't logged. + // + // The TestCase enum above allows us to test a combination of every possible + // log method with every possible level inside a loop - with the + // exception of exiting/entering/throwing that we will be testing + // outside of that loop. + // + public static void main(String... args) { + LogManager manager = LogManager.getLogManager(); + ThreadLogger logger = new ThreadLogger("foo.bar"); + //manager.addLogger(logger); + TestHandler handler = new TestHandler(); + logger.addHandler(handler); + + //By default, logger's level is Level.INFO + final List loggable = LEVELS.subList(0, LEVELS.indexOf(Level.INFO)+1); + + // Check our test implementation of logger.isLoggable(); + // + // Since we haven't put anything in the threadMap, isLoggable() should + // return true for all levels stronger or equals to Level.INFO. + // here we're just checking that our implementation of + // ThreadLogger.isLoggable() returns what we want - we're just testing + // the test code... + for (Level level : LEVELS) { + if (logger.isLoggable(level) != loggable.contains(level)) { + throw new RuntimeException(level + + ": unexpected result for isLoggable(): expected " + + (loggable.contains(level))); + } + } + + // Test that entering/exiting/throwing call isLoggable() + + // Here we test the default behavior: this call shouldn't log anything + // because by default the logger level is Level.INFO and these + // methods log at Level.FINER. + // So by default - these methods don't log anything. We check it here. + logger.entering("blah", "blah"); + logger.entering("blah", "blah", "blah"); + logger.entering("blah", "blah", new Object[] {"blah"}); + if (!handler.messages.isEmpty()) { + throw new RuntimeException("Expected empty, got "+handler.messages); + } + + logger.exiting("blah", "blah"); + logger.exiting("blah", "blah", "blah"); + logger.exiting("blah", "blah", new Object[] {"blah"}); + if (!handler.messages.isEmpty()) { + throw new RuntimeException("Expected empty, got "+handler.messages); + } + + logger.throwing("blah", "blah", new Exception("blah")); + if (!handler.messages.isEmpty()) { + throw new RuntimeException("Expected empty, got "+handler.messages); + } + + // Now we're going to put each level in turn in the threadMap. + // This means that isLoggable(Level.FINER) should now return true if the + // level in the map is not one of the level in the 'stronger' list below + // (here stronger=stronger than FINER) + final List stronger = LEVELS.subList(0, LEVELS.indexOf(Level.FINER)); + for (Level l : LEVELS) { + + logger.threadMap.put(Thread.currentThread().getId(), l); + + // Check that our implementation of isLoggable(level) now returns true + // if 'level' is stronger or equals to 'l' - here we're just checking + // that our implementation of ThreadLogger.isLoggable() returns what + // we want - we're just testing the test code... + final List loggableLevels = LEVELS.subList(0, LEVELS.indexOf(l)+1); + for (Level level : LEVELS) { + if (logger.isLoggable(level) != loggableLevels.contains(level)) { + throw new RuntimeException(level + + ": unexpected result for isLoggable(): expected " + + (loggableLevels.contains(level))); + } + } + + // These methods should now start to log when the level we put in + // the map is weaker or equals to Level.FINER. + // This validates that these methods now call ThreadLogger.isLoggable() + // since the default level for our logger is still Level.INFO. + // If the methods didn't call ThreadLogger.isLoggable() they wouldn't + // log anything, whatever we put in the threadMap... + + logger.entering("blah", "blah"); + logger.entering("blah", "blah", "blah"); + logger.entering("blah", "blah", new Object[] {"blah"}); + if (stronger.contains(l)) { + if (!handler.messages.isEmpty()) { + throw new RuntimeException(l + + ": Expected empty, got " + handler.messages); + } + } else { + if (handler.messages.size() != 3) { + throw new RuntimeException(l + + ": Expected size 3, got " + handler.messages); + } + } + + logger.exiting("blah", "blah"); + logger.exiting("blah", "blah", "blah"); + logger.exiting("blah", "blah", new Object[] {"blah"}); + if (stronger.contains(l)) { + if (!handler.messages.isEmpty()) { + throw new RuntimeException(l + + ": Expected empty, got " + handler.messages); + } + } else { + if (handler.messages.size() != 6) { + throw new RuntimeException(l + + ": Expected size 6, got " + handler.messages); + } + } + + logger.throwing("blah", "blah", new Exception("blah")); + if (stronger.contains(l)) { + if (!handler.messages.isEmpty()) { + throw new RuntimeException(l + + ": Expected empty, got " + handler.messages); + } + } else { + if (handler.messages.size() != 7) { + throw new RuntimeException(l + + ": Expected size 7, got " + handler.messages); + } + } + if (!stronger.contains(l)) { + System.out.println(l + ": Logger.entering/exiting/throwing: " + + handler.messages); + } + handler.messages.clear(); + } + + // Cleanup so that we can start the next test with a clean plate... + handler.messages.clear(); + logger.threadMap.clear(); + + // Test that each logging method calls isLoggable() + // + for (LogTest testCase : LogTest.values()) { + // Each test case is a combination of: + // 1. A level to put in the threadMap. + // 2. A log method to call + final String method = testCase.method(); + + // check our implementation of logger.isLoggable(); + // by default the logger level is Level.INFO, so our implementation + // of isLoggable() should return true for all levels stronger or + // equal to INFO and false for the others. + // We check that here. + for (Level level : LEVELS) { + if (logger.isLoggable(level) != loggable.contains(level)) { + throw new RuntimeException(level + + ": unexpected result for isLoggable(): expected " + + (loggable.contains(level))); + } + } + + // Check that by default the log method will not log for level + // weaker than Level.INFO. + for (Level l : LEVELS.subList(LEVELS.indexOf(Level.INFO) + 1, LEVELS.size())) { + final String test = method + l + ": "; + testCase.log(l, logger, "blah"); + if (!handler.messages.isEmpty()) { + throw new RuntimeException(test + + "Expected empty, got " + handler.messages); + } + } + + // Let's put Level.OFF in the threadMap. Nothing should be logged, + // whichever level is used... + logger.threadMap.put(Thread.currentThread().getId(), Level.OFF); + + // Check that isLoggable() now always return false. + for (Level level : LEVELS) { + if (logger.isLoggable(level)) { + throw new RuntimeException(level + + ": unexpected result for isLoggable(): expected " + + false); + } + } + + // Check that the log method of the test case won't log, whatever + // level we pass to it. This validates that level method calls + // isLoggable() - because otherwise it would log for levels stronger + // or equal to INFO. + for (Level l : LEVELS) { + final String test = "[threadMap=OFF] " + method + l + ": "; + testCase.log(l, logger, "blah"); + if (!handler.messages.isEmpty()) { + throw new RuntimeException(test + + "Expected empty, got " + handler.messages); + } + } + System.out.println("[threadMap=OFF] " + method + "logged " + handler.messages); + + // Now put the testcase's level in the threadMap. + logger.threadMap.put(Thread.currentThread().getId(), testCase.threshold()); + + // The levels for which logging should happen are those that are stronger + // or equals to the testcase's thresholds. + final List loggableLevels = + LEVELS.subList(0, LEVELS.indexOf(testCase.threshold())+1); + + // Check that our implementation of isLoggable() is taking into account + // what we put in the map. + for (Level level : LEVELS) { + if (logger.isLoggable(level) != loggableLevels.contains(level)) { + throw new RuntimeException(level + + ": unexpected result for isLoggable(): expected " + + (loggableLevels.contains(level))); + } + } + + // Now check that the log method is indeed calling our implementation + // of isLoggable(). We do this by first verifying that it won't log + // for levels weaker than what we put in the map. + // + for (Level l : testCase.weaker()) { + final String test = method + l + ": "; + testCase.log(l, logger, "blah"); + if (!handler.messages.isEmpty()) { + throw new RuntimeException(test + + "Expected empty, got " + handler.messages); + } + } + + // Then we check that it will log for the testcase threshold. + final String test2 = method + testCase.threshold() + ": "; + testCase.log(logger, testCase.threshold() + " blah"); + if (handler.messages.isEmpty()) { + throw new RuntimeException(test2 + + "Expected 1 message, but list is empty"); + } + if (!handler.messages.contains(testCase.threshold() + " blah")) { + throw new RuntimeException(test2 + " blah not found: " + + handler.messages); + } + handler.messages.clear(); + + // Now we check that it logs for all 'loggable' level (and doesn't + // log for the others). + for (Level l : LEVELS) { + final String test = method + l + ": "; + testCase.log(l, logger, l + ": blah"); + if (testCase.loggable().contains(l)) { + if (!handler.messages.contains(l + ": blah")) { + throw new RuntimeException(test + "blah not found: " + + handler.messages); + } + } else { + if (handler.messages.contains(l + ": blah")) { + throw new RuntimeException(test + "blah found: " + + handler.messages); + } + } + } + if (handler.messages.size() != testCase.loggable().size()) { + throw new RuntimeException(method + + " Sizes don't match: expected " + + testCase.loggable().size() + " got " + + handler.messages); + } + + // Some visual feedback on what happened. + System.out.println(method + "logged " + handler.messages); + + // Cleanup for next step. + // Since we're iterating over all possible levels we can be + // sure that we haven't missed anything. + // For instance - it could be argued that logger.severe() will + // always log. But since we have 1 case where we put Level.OFF in + // the map and we have verified that severe() didn't log in that + // case, but that it logged in any other case, then we know + // beyond doubt that it called our implementation of isLoggable(). + logger.threadMap.clear(); + handler.messages.clear(); + } + + } +} diff --git a/jdk/test/java/util/logging/ParentLoggersTest.java b/jdk/test/java/util/logging/ParentLoggersTest.java index 72d5ddadc0f..a5070a375e3 100644 --- a/jdk/test/java/util/logging/ParentLoggersTest.java +++ b/jdk/test/java/util/logging/ParentLoggersTest.java @@ -29,7 +29,7 @@ * @author ss45998 * * @build ParentLoggersTest - * @run main/othervm ParentLoggersTest + * @run main ParentLoggersTest */ /* diff --git a/jdk/test/java/util/logging/TestAppletLoggerContext.java b/jdk/test/java/util/logging/TestAppletLoggerContext.java index c7f3d4f4991..3db67543245 100644 --- a/jdk/test/java/util/logging/TestAppletLoggerContext.java +++ b/jdk/test/java/util/logging/TestAppletLoggerContext.java @@ -38,7 +38,7 @@ import sun.misc.SharedSecrets; /* * @test - * @bug 8017174 8010727 + * @bug 8017174 8010727 8019945 * @summary NPE when using Logger.getAnonymousLogger or * LogManager.getLogManager().getLogger * @@ -110,28 +110,19 @@ public class TestAppletLoggerContext { } TestExc exc; - TestExc global = new TestExc(); @Override - public Object getContext() { return active ? global : null; } + public Object getAppletContext() { return active ? exc : null; } @Override - public Object getExecutionContext() { return active ? exc : null; } + public Object get(Object o) { return exc.get(o); } @Override - public Object get(Object o, Object o1) { return TestExc.exc(o).get(o1); } + public void put(Object o, Object o1) { exc.put(o, o1); } @Override - public void put(Object o, Object o1, Object o2) { TestExc.exc(o).put(o1, o2); } - @Override - public void remove(Object o, Object o1) { TestExc.exc(o).remove(o1); } - @Override - public Object get(Object o) { return global.get(o); } - @Override - public void put(Object o, Object o1) { global.put(o, o1); } - @Override - public void remove(Object o) { global.remove(o); } + public void remove(Object o) { exc.remove(o); } @Override public boolean isDisposed() { return false; } @Override - public boolean isMainAppContext() { return exc == null; } + public boolean isMainAppContext() { return !active || exc == null; } } final static JavaAWTAccessStub javaAwtAccess = new JavaAWTAccessStub(); @@ -441,45 +432,36 @@ public class TestAppletLoggerContext { assertNull(manager.getLogger("")); assertNull(manager.getLogger("")); - Bridge.changeContext(); + for (int j = 0; j<3; j++) { + Bridge.changeContext(); - // this is not a supported configuration: - // We are in an applet context with several log managers. - // We however need to check our assumptions... + // this is not a supported configuration: + // We are in an applet context with several log managers. + // We however need to check our assumptions... - // Applet context => root logger and global logger are not null. - // root == LogManager.getLogManager().rootLogger - // global == Logger.global + // Applet context => root logger and global logger should also be null. - Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); - Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); - assertNotNull(logger3); - assertNotNull(logger3b); - Logger expected = (System.getSecurityManager() != null - ? Logger.getGlobal() - : global); - assertEquals(logger3, expected); // in applet context, we will not see - // the LogManager's custom global logger added above... - assertEquals(logger3b, expected); // in applet context, we will not see - // the LogManager's custom global logger added above... - Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); - manager.addLogger(global2); // adding a global logger will not work in applet context - // we will always get back the global logger. - // this could be considered as a bug... - Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); - Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); - assertNotNull(logger4); - assertNotNull(logger4b); - assertEquals(logger4, expected); // adding a global logger will not work in applet context - assertEquals(logger4b, expected); // adding a global logger will not work in applet context + Logger expected = (System.getSecurityManager() == null ? global : null); + Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); + Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); + assertEquals(expected, logger3); + assertEquals(expected, logger3b); + Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); + manager.addLogger(global2); + Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); + Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); + assertNotNull(logger4); + assertNotNull(logger4b); + expected = (System.getSecurityManager() == null ? global : global2);; + assertEquals(logger4, expected); + assertEquals(logger4b, expected); - Logger logger5 = manager.getLogger(""); - Logger logger5b = manager.getLogger(""); - Logger expectedRoot = (System.getSecurityManager() != null - ? LogManager.getLogManager().getLogger("") - : null); - assertEquals(logger5, expectedRoot); - assertEquals(logger5b, expectedRoot); + Logger logger5 = manager.getLogger(""); + Logger logger5b = manager.getLogger(""); + Logger expectedRoot = null; + assertEquals(logger5, expectedRoot); + assertEquals(logger5b, expectedRoot); + } } } @@ -520,57 +502,53 @@ public class TestAppletLoggerContext { assertEquals(logger4, root); assertEquals(logger4b, root); - Bridge.changeContext(); + for (int j = 0 ; j < 3 ; j++) { + Bridge.changeContext(); - // this is not a supported configuration: - // We are in an applet context with several log managers. - // We haowever need to check our assumptions... + // this is not a supported configuration: + // We are in an applet context with several log managers. + // We however need to check our assumptions... - // Applet context => root logger and global logger are not null. - // root == LogManager.getLogManager().rootLogger - // global == Logger.global + // Applet context => root logger and global logger should also be null. - Logger logger5 = manager.getLogger(""); - Logger logger5b = manager.getLogger(""); - Logger expectedRoot = (System.getSecurityManager() != null - ? LogManager.getLogManager().getLogger("") - : root); + Logger logger5 = manager.getLogger(""); + Logger logger5b = manager.getLogger(""); + Logger expectedRoot = (System.getSecurityManager() == null ? root : null); + assertEquals(logger5, expectedRoot); + assertEquals(logger5b, expectedRoot); - assertNotNull(logger5); - assertNotNull(logger5b); - assertEquals(logger5, expectedRoot); - assertEquals(logger5b, expectedRoot); - if (System.getSecurityManager() != null) { - assertNotEquals(logger5, root); - assertNotEquals(logger5b, root); + if (System.getSecurityManager() != null) { + assertNull(manager.getLogger(Logger.GLOBAL_LOGGER_NAME)); + } else { + assertEquals(global, manager.getLogger(Logger.GLOBAL_LOGGER_NAME)); + } + + Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); + manager.addLogger(global2); + Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); + Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); + Logger expectedGlobal = (System.getSecurityManager() == null ? global : global2); + + assertNotNull(logger6); + assertNotNull(logger6b); + assertEquals(logger6, expectedGlobal); + assertEquals(logger6b, expectedGlobal); + if (System.getSecurityManager() != null) { + assertNull(manager.getLogger("")); + } else { + assertEquals(root, manager.getLogger("")); + } + + Logger root2 = new Bridge.CustomLogger(""); + manager.addLogger(root2); + expectedRoot = (System.getSecurityManager() == null ? root : root2); + Logger logger7 = manager.getLogger(""); + Logger logger7b = manager.getLogger(""); + assertNotNull(logger7); + assertNotNull(logger7b); + assertEquals(logger7, expectedRoot); + assertEquals(logger7b, expectedRoot); } - - Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); - manager.addLogger(global2); // adding a global logger will not work in applet context - // we will always get back the global logger. - // this could be considered as a bug... - Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); - Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); - Logger expectedGlobal = (System.getSecurityManager() != null - ? Logger.getGlobal() - : global); - assertNotNull(logger6); - assertNotNull(logger6b); - assertEquals(logger6, expectedGlobal); // adding a global logger will not work in applet context - assertEquals(logger6b, expectedGlobal); // adding a global logger will not work in applet context - - Logger root2 = new Bridge.CustomLogger(""); - manager.addLogger(root2); // adding a root logger will not work in applet context - // we will always get back the default manager's root logger. - // this could be considered as a bug... - Logger logger7 = manager.getLogger(""); - Logger logger7b = manager.getLogger(""); - assertNotNull(logger7); - assertNotNull(logger7b); - assertEquals(logger7, expectedRoot); // adding a global logger will not work in applet context - assertEquals(logger7b, expectedRoot); // adding a global logger will not work in applet context - assertNotEquals(logger7, root2); - assertNotEquals(logger7b, root2); } } diff --git a/jdk/test/java/util/logging/TestLoggingWithMainAppContext.java b/jdk/test/java/util/logging/TestLoggingWithMainAppContext.java new file mode 100644 index 00000000000..5489acee22a --- /dev/null +++ b/jdk/test/java/util/logging/TestLoggingWithMainAppContext.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.util.logging.Logger; +import javax.imageio.ImageIO; + +/** + * @test + * @bug 8019853 8023258 + * @summary Test that the default user context is used when in the main + * application context. This test must not be run in same VM or agent + * VM mode: it would not test the intended behavior. + * @run main/othervm TestLoggingWithMainAppContext + */ +public class TestLoggingWithMainAppContext { + + public static void main(String[] args) throws IOException { + System.out.println("Creating loggers."); + + // These loggers will be created in the default user context. + final Logger foo1 = Logger.getLogger( "foo" ); + final Logger bar1 = Logger.getLogger( "foo.bar" ); + if (bar1.getParent() != foo1) { + throw new RuntimeException("Parent logger of bar1 "+bar1+" is not "+foo1); + } + System.out.println("bar1.getParent() is the same as foo1"); + + // Set a security manager + System.setSecurityManager(new SecurityManager()); + System.out.println("Now running with security manager"); + + // Triggers the creation of the main AppContext + ByteArrayInputStream is = new ByteArrayInputStream(new byte[] { 0, 1 }); + ImageIO.read(is); // triggers calls to system loggers & creation of main AppContext + + // verify that we're still using the default user context + final Logger bar2 = Logger.getLogger( "foo.bar" ); + if (bar1 != bar2) { + throw new RuntimeException("bar2 "+bar2+" is not the same as bar1 "+bar1); + } + System.out.println("bar2 is the same as bar1"); + if (bar2.getParent() != foo1) { + throw new RuntimeException("Parent logger of bar2 "+bar2+" is not foo1 "+foo1); + } + System.out.println("bar2.getParent() is the same as foo1"); + final Logger foo2 = Logger.getLogger("foo"); + if (foo1 != foo2) { + throw new RuntimeException("foo2 "+foo2+" is not the same as foo1 "+foo1); + } + System.out.println("foo2 is the same as foo1"); + + System.out.println("Test passed."); + } +} diff --git a/jdk/test/java/util/regex/PatternTest.java b/jdk/test/java/util/regex/PatternStreamTest.java similarity index 82% rename from jdk/test/java/util/regex/PatternTest.java rename to jdk/test/java/util/regex/PatternStreamTest.java index aab17319ae4..374b62378e9 100644 --- a/jdk/test/java/util/regex/PatternTest.java +++ b/jdk/test/java/util/regex/PatternStreamTest.java @@ -23,10 +23,11 @@ /** * @test + * @bug 8016846 8024341 * @summary Unit tests for wrapping classes should delegate to default methods * @library ../stream/bootlib * @build java.util.stream.OpTestCase - * @run testng/othervm PatternTest + * @run testng/othervm PatternStreamTest */ import org.testng.annotations.DataProvider; @@ -42,7 +43,7 @@ import java.util.stream.Stream; import java.util.stream.TestData; @Test -public class PatternTest extends OpTestCase { +public class PatternStreamTest extends OpTestCase { @DataProvider(name = "Stream") public static Object[][] makeStreamTestData() { @@ -132,6 +133,38 @@ public class PatternTest extends OpTestCase { expected.add("different"); expected.add("separators"); + + description = "Repeated separators within and at end"; + input = "boo:and:foo"; + pattern = Pattern.compile("o"); + expected = new ArrayList<>(); + expected.add("b"); + expected.add(""); + expected.add(":and:f"); + + + description = "Many repeated separators within and at end"; + input = "booooo:and:fooooo"; + pattern = Pattern.compile("o"); + expected = new ArrayList<>(); + expected.add("b"); + expected.add(""); + expected.add(""); + expected.add(""); + expected.add(""); + expected.add(":and:f"); + + description = "Many repeated separators before last match"; + input = "fooooo:"; + pattern = Pattern.compile("o"); + expected = new ArrayList<>(); + expected.add("f"); + expected.add(""); + expected.add(""); + expected.add(""); + expected.add(""); + expected.add(":"); + data.add(new Object[] {description, input, pattern, expected}); return data.toArray(new Object[0][]); } diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java index d4459cf0c9b..43b99973dd2 100644 --- a/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/DoubleStreamTestScenario.java @@ -40,7 +40,7 @@ import java.util.function.Function; @SuppressWarnings({"rawtypes", "unchecked"}) public enum DoubleStreamTestScenario implements OpTestCase.BaseStreamTestScenario { - STREAM_FOR_EACH(false) { + STREAM_FOR_EACH_WITH_CLOSE(false) { > void _run(TestData data, DoubleConsumer b, Function m) { DoubleStream s = m.apply(data.stream()); @@ -48,6 +48,7 @@ public enum DoubleStreamTestScenario implements OpTestCase.BaseStreamTestScenari s = s.sequential(); } s.forEach(b); + s.close(); } }, diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java index f399cdeef25..4127a7b5a81 100644 --- a/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/IntStreamTestScenario.java @@ -40,7 +40,7 @@ import java.util.function.IntConsumer; @SuppressWarnings({"rawtypes", "unchecked"}) public enum IntStreamTestScenario implements OpTestCase.BaseStreamTestScenario { - STREAM_FOR_EACH(false) { + STREAM_FOR_EACH_WITH_CLOSE(false) { > void _run(TestData data, IntConsumer b, Function m) { IntStream s = m.apply(data.stream()); @@ -48,6 +48,7 @@ public enum IntStreamTestScenario implements OpTestCase.BaseStreamTestScenario { s = s.sequential(); } s.forEach(b); + s.close(); } }, diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java index 3010745a55d..0a334bc0261 100644 --- a/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/LongStreamTestScenario.java @@ -40,7 +40,7 @@ import java.util.function.LongConsumer; @SuppressWarnings({"rawtypes", "unchecked"}) public enum LongStreamTestScenario implements OpTestCase.BaseStreamTestScenario { - STREAM_FOR_EACH(false) { + STREAM_FOR_EACH_WITH_CLOSE(false) { > void _run(TestData data, LongConsumer b, Function m) { LongStream s = m.apply(data.stream()); @@ -48,6 +48,7 @@ public enum LongStreamTestScenario implements OpTestCase.BaseStreamTestScenario s = s.sequential(); } s.forEach(b); + s.close(); } }, diff --git a/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java index b1abd4320db..d1a446234a7 100644 --- a/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java +++ b/jdk/test/java/util/stream/bootlib/java/util/stream/StreamTestScenario.java @@ -39,7 +39,7 @@ import java.util.function.Function; @SuppressWarnings({"rawtypes", "unchecked"}) public enum StreamTestScenario implements OpTestCase.BaseStreamTestScenario { - STREAM_FOR_EACH(false) { + STREAM_FOR_EACH_WITH_CLOSE(false) { > void _run(TestData data, Consumer b, Function> m) { Stream s = m.apply(data.stream()); @@ -47,6 +47,7 @@ public enum StreamTestScenario implements OpTestCase.BaseStreamTestScenario { s = s.sequential(); } s.forEach(b); + s.close(); } }, 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 new file mode 100644 index 00000000000..51ffd4b9010 --- /dev/null +++ b/jdk/test/java/util/stream/test/org/openjdk/tests/java/util/stream/StreamCloseTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package org.openjdk.tests.java.util.stream; + +import java.util.Arrays; +import java.util.stream.OpTestCase; +import java.util.stream.Stream; + +import org.testng.annotations.Test; + +import static java.util.stream.LambdaTestHelpers.countTo; + +/** + * StreamCloseTest + * + * @author Brian Goetz + */ +@Test(groups = { "serialization-hostile" }) +public class StreamCloseTest extends OpTestCase { + public void testEmptyCloseHandler() { + try (Stream ints = countTo(100).stream()) { + ints.forEach(i -> {}); + } + } + + public void testOneCloseHandler() { + final boolean[] holder = new boolean[1]; + Runnable closer = () -> { holder[0] = true; }; + + try (Stream ints = countTo(100).stream()) { + ints.onClose(closer); + ints.forEach(i -> {}); + } + assertTrue(holder[0]); + + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().onClose(closer)) { + ints.forEach(i -> {}); + } + assertTrue(holder[0]); + + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().filter(e -> true).onClose(closer)) { + ints.forEach(i -> {}); + } + assertTrue(holder[0]); + + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().filter(e -> true).onClose(closer).filter(e -> true)) { + ints.forEach(i -> {}); + } + assertTrue(holder[0]); + } + + public void testTwoCloseHandlers() { + final boolean[] holder = new boolean[2]; + Runnable close1 = () -> { holder[0] = true; }; + Runnable close2 = () -> { holder[1] = true; }; + + try (Stream ints = countTo(100).stream()) { + ints.onClose(close1).onClose(close2); + ints.forEach(i -> {}); + } + assertTrue(holder[0] && holder[1]); + + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().onClose(close1).onClose(close2)) { + ints.forEach(i -> {}); + } + assertTrue(holder[0] && holder[1]); + + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2)) { + ints.forEach(i -> {}); + } + assertTrue(holder[0] && holder[1]); + + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2).filter(e -> true)) { + ints.forEach(i -> {}); + } + assertTrue(holder[0] && holder[1]); + } + + public void testCascadedExceptions() { + final boolean[] holder = new boolean[3]; + boolean caught = false; + Runnable close1 = () -> { holder[0] = true; throw new RuntimeException("1"); }; + Runnable close2 = () -> { holder[1] = true; throw new RuntimeException("2"); }; + Runnable close3 = () -> { holder[2] = true; throw new RuntimeException("3"); }; + + try (Stream ints = countTo(100).stream()) { + ints.onClose(close1).onClose(close2).onClose(close3); + ints.forEach(i -> {}); + } + catch (RuntimeException e) { + assertCascaded(e, 3); + assertTrue(holder[0] && holder[1] && holder[2]); + caught = true; + } + assertTrue(caught); + + Arrays.fill(holder, false); + caught = false; + try (Stream ints = countTo(100).stream().onClose(close1).onClose(close2).onClose(close3)) { + ints.forEach(i -> {}); + } + catch (RuntimeException e) { + assertCascaded(e, 3); + assertTrue(holder[0] && holder[1] && holder[2]); + caught = true; + } + assertTrue(caught); + + caught = false; + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2).onClose(close3)) { + ints.forEach(i -> {}); + } + catch (RuntimeException e) { + assertCascaded(e, 3); + assertTrue(holder[0] && holder[1] && holder[2]); + caught = true; + } + assertTrue(caught); + + caught = false; + Arrays.fill(holder, false); + try (Stream ints = countTo(100).stream().filter(e -> true).onClose(close1).onClose(close2).filter(e -> true).onClose(close3)) { + ints.forEach(i -> {}); + } + catch (RuntimeException e) { + assertCascaded(e, 3); + assertTrue(holder[0] && holder[1] && holder[2]); + caught = true; + } + assertTrue(caught); + } + + private void assertCascaded(RuntimeException e, int n) { + assertTrue(e.getMessage().equals("1")); + assertTrue(e.getSuppressed().length == n - 1); + for (int i=0; i 0) { + throw new RuntimeException("Test failed: "+failed); + } else { + System.out.println("---Test: PASSED"); + } + } + + private static void test(Object obj1, Object obj2, String param) { + try { + obj1.equals(obj2); + System.out.println("OK-1: "+obj1.getClass().getSimpleName()+".equals worked with a null paramer: "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO-1!!! "+obj1.getClass().getSimpleName()+".equals got NPE with a null paramer: "+param); + npe.printStackTrace(); + failed++; + } + + try { + obj2.equals(obj1); + System.out.println("OK-2: "+obj2.getClass().getSimpleName()+".equals worked with a null paramer: "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO-2!!! "+obj2.getClass().getSimpleName()+".equals got NPE with a null paramer: "+param); + npe.printStackTrace(); + failed++; + } + + try { + obj1.equals(null); + obj2.equals(null); + + System.out.println("OK-3: "+obj1.getClass().getSimpleName()+".equals worked with a null field."); + } catch (NullPointerException npe) { + System.out.println("--->KO-3!!! "+obj1.getClass().getSimpleName()+".equals got NPE with a null field."); + npe.printStackTrace(); + failed++; + } + } +} diff --git a/jdk/test/javax/management/MBeanInfo/MBeanInfoHashCodeNPETest.java b/jdk/test/javax/management/MBeanInfo/MBeanInfoHashCodeNPETest.java new file mode 100644 index 00000000000..bb35da38ba6 --- /dev/null +++ b/jdk/test/javax/management/MBeanInfo/MBeanInfoHashCodeNPETest.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.management.MBeanAttributeInfo; +import javax.management.MBeanConstructorInfo; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.modelmbean.DescriptorSupport; +import javax.management.openmbean.SimpleType; + +/* + * @test + * @bug 8023669 + * @summary Test that hashCode()throws NullPointerException + * @author Shanliang JIANG + * @run clean MBeanInfoHashCodeNPETest + * @run build MBeanInfoHashCodeNPETest + * @run main MBeanInfoHashCodeNPETest + */ +public class MBeanInfoHashCodeNPETest { + private static int failed = 0; + + public static void main(String[] args) throws Exception { + System.out.println("---MBeanInfoHashCodeNPETest-main ..."); + + // ---- + System.out.println("\n---Testing on MBeanAttributeInfo..."); + MBeanAttributeInfo mbeanAttributeInfo = new MBeanAttributeInfo( + null, SimpleType.INTEGER.getClassName(), "description", true, true, false); + test(mbeanAttributeInfo, "class name"); + + mbeanAttributeInfo = new MBeanAttributeInfo( + "name", null, "description", true, true, false); + test(mbeanAttributeInfo, "type"); + + mbeanAttributeInfo = new MBeanAttributeInfo( + "name", SimpleType.INTEGER.getClassName(), null, true, true, false); + test(mbeanAttributeInfo, "description"); + + // ---- + System.out.println("\n---Testing on MBeanConstructorInfo..."); + MBeanConstructorInfo mbeanConstructorInfo = new MBeanConstructorInfo( + null, "", new MBeanParameterInfo[]{}, new DescriptorSupport()); + test(mbeanConstructorInfo, "name"); + + mbeanConstructorInfo = new MBeanConstructorInfo( + "", null, new MBeanParameterInfo[]{}, new DescriptorSupport()); + test(mbeanConstructorInfo, "description"); + + mbeanConstructorInfo = new MBeanConstructorInfo( + "", "", null, new DescriptorSupport()); + test(mbeanConstructorInfo, "MBeanParameterInfo"); + + mbeanConstructorInfo = new MBeanConstructorInfo( + "", "", new MBeanParameterInfo[]{}, null); + test(mbeanConstructorInfo, "descriptor"); + + // ---- + System.out.println("\n---Testing on MBeanOperationInfo..."); + MBeanOperationInfo mbeanOperationInfo = new MBeanOperationInfo( + null, "description", new MBeanParameterInfo[]{}, "type", 1, new DescriptorSupport()); + test(mbeanOperationInfo, "name"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", null, new MBeanParameterInfo[]{}, "type", 1, new DescriptorSupport()); + test(mbeanOperationInfo, "description"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", null, "type", 1, new DescriptorSupport()); + test(mbeanOperationInfo, "MBeanParameterInfo"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", new MBeanParameterInfo[]{}, null, 1, new DescriptorSupport()); + test(mbeanOperationInfo, "type"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", new MBeanParameterInfo[]{}, "type", -1, new DescriptorSupport()); + test(mbeanOperationInfo, "native impact"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", new MBeanParameterInfo[]{}, "type", 1, null); + test(mbeanOperationInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on MBeanParameterInfo..."); + MBeanParameterInfo mbeanParameterInfo = new MBeanParameterInfo( + null, "type", "description", new DescriptorSupport()); + test(mbeanParameterInfo, "name"); + + mbeanParameterInfo = new MBeanParameterInfo( + "name", null, "description", new DescriptorSupport()); + test(mbeanParameterInfo, "description"); + + mbeanParameterInfo = new MBeanParameterInfo( + "name", "type", null, new DescriptorSupport()); + test(mbeanParameterInfo, "description"); + + mbeanParameterInfo = new MBeanParameterInfo( + "name", "type", "description", null); + test(mbeanParameterInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on MBeanInfo..."); + String className = "toto"; + String description = "titi"; + MBeanAttributeInfo[] attrInfos = new MBeanAttributeInfo[]{}; + MBeanConstructorInfo[] constrInfos = new MBeanConstructorInfo[]{}; + MBeanOperationInfo[] operaInfos = new MBeanOperationInfo[]{}; + MBeanNotificationInfo[] notifInfos = new MBeanNotificationInfo[]{}; + + MBeanInfo minfo = new MBeanInfo(null, description, attrInfos, constrInfos, operaInfos, notifInfos); + test(minfo, "class name"); + + minfo = new MBeanInfo(className, description, attrInfos, constrInfos, operaInfos, notifInfos); + test(minfo, "name"); + + minfo = new MBeanInfo(className, null, attrInfos, constrInfos, operaInfos, notifInfos); + test(minfo, "description"); + + minfo = new MBeanInfo(className, description, null, constrInfos, operaInfos, notifInfos); + test(minfo, "attrInfos"); + + minfo = new MBeanInfo(className, description, attrInfos, constrInfos, null, notifInfos); + test(minfo, "operaInfos"); + + minfo = new MBeanInfo(className, description, attrInfos, constrInfos, operaInfos, null); + test(minfo, "notifInfos"); + + Thread.sleep(100); + if (failed > 0) { + throw new RuntimeException("Test failed: "+failed); + } else { + System.out.println("---Test: PASSED"); + } + } + + private static void test(Object obj, String param) { + try { + obj.hashCode(); + System.out.println("OK: "+obj.getClass().getSimpleName()+".hashCode worked with a null "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO!!! "+obj.getClass().getSimpleName()+".hashCode got NPE with a null "+param); + failed++; + } + + try { + obj.toString(); + System.out.println("OK: "+obj.getClass().getSimpleName()+".toString worked with a null "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO!!! "+obj.getClass().getSimpleName()+".toString got NPE."); + failed++; + } + } +} diff --git a/jdk/test/javax/management/openmbean/OpenMBeanInfoEqualsNPETest.java b/jdk/test/javax/management/openmbean/OpenMBeanInfoEqualsNPETest.java new file mode 100644 index 00000000000..452e940b0fd --- /dev/null +++ b/jdk/test/javax/management/openmbean/OpenMBeanInfoEqualsNPETest.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.modelmbean.DescriptorSupport; +import javax.management.openmbean.OpenMBeanAttributeInfo; +import javax.management.openmbean.OpenMBeanAttributeInfoSupport; +import javax.management.openmbean.OpenMBeanConstructorInfo; +import javax.management.openmbean.OpenMBeanConstructorInfoSupport; +import javax.management.openmbean.OpenMBeanInfo; +import javax.management.openmbean.OpenMBeanInfoSupport; +import javax.management.openmbean.OpenMBeanOperationInfo; +import javax.management.openmbean.OpenMBeanOperationInfoSupport; +import javax.management.openmbean.OpenMBeanParameterInfo; +import javax.management.openmbean.OpenMBeanParameterInfoSupport; +import javax.management.openmbean.SimpleType; + +/* + * @test + * @bug 8023529 + * @summary Test that OpenMBean*Info.equals do not throw NPE + * @author Shanliang JIANG + * @run clean OpenMBeanInfoEqualsNPETest + * @run build OpenMBeanInfoEqualsNPETest + * @run main OpenMBeanInfoEqualsNPETest + */ +public class OpenMBeanInfoEqualsNPETest { + private static int failed = 0; + + public static void main(String[] args) throws Exception { + System.out.println("---OpenMBeanInfoEqualsNPETest-main ..."); + + // ---- + System.out.println("\n---Testing on OpenMBeanAttributeInfoSupport..."); + OpenMBeanAttributeInfo openMBeanAttributeInfo0 = new OpenMBeanAttributeInfoSupport( + "name", "description", SimpleType.INTEGER, true, true, false, 1, new Integer[]{1, 2, 3}); + OpenMBeanAttributeInfo openMBeanAttributeInfo = new OpenMBeanAttributeInfoSupport( + "name", "description", SimpleType.INTEGER, true, true, false, null, new Integer[]{1, 2, 3}); + test(openMBeanAttributeInfo0, openMBeanAttributeInfo, "defaultValue"); + + openMBeanAttributeInfo = new OpenMBeanAttributeInfoSupport( + "name", "description", SimpleType.INTEGER, true, true, false, 1, null); + test(openMBeanAttributeInfo0, openMBeanAttributeInfo, "legalValues"); + + // ---- + System.out.println("\n---Testing on OpenMBeanConstructorInfoSupport..."); + OpenMBeanConstructorInfo openMBeanConstructorInfo0 = new OpenMBeanConstructorInfoSupport( + "name", "description", new OpenMBeanParameterInfo[]{}, new DescriptorSupport()); + OpenMBeanConstructorInfo openMBeanConstructorInfo; + + openMBeanConstructorInfo = new OpenMBeanConstructorInfoSupport( + "name", "description", null, new DescriptorSupport()); + test(openMBeanConstructorInfo0, openMBeanConstructorInfo, "sigs"); + + openMBeanConstructorInfo = new OpenMBeanConstructorInfoSupport( + "name", "description", new OpenMBeanParameterInfo[]{}, null); + test(openMBeanConstructorInfo0, openMBeanConstructorInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on OpenMBeanOperationInfoSupport..."); + OpenMBeanOperationInfo openMBeanOperationInfo0 = new OpenMBeanOperationInfoSupport( + "name", "description", new OpenMBeanParameterInfo[]{}, SimpleType.INTEGER, 1, new DescriptorSupport()); + OpenMBeanOperationInfo openMBeanOperationInfo; + + openMBeanOperationInfo = new OpenMBeanOperationInfoSupport( + "name", "description", null, SimpleType.INTEGER, 1, new DescriptorSupport()); + test(openMBeanOperationInfo0, openMBeanOperationInfo, "sigs"); + + openMBeanOperationInfo = new OpenMBeanOperationInfoSupport( + "name", "description", new OpenMBeanParameterInfo[]{}, SimpleType.INTEGER, MBeanOperationInfo.UNKNOWN, null); + test(openMBeanOperationInfo0, openMBeanOperationInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on OpenMBeanParameterInfoSupport 1..."); + OpenMBeanParameterInfo openMBeanParameterInfo0 = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 0, -1, 1); + OpenMBeanParameterInfo openMBeanParameterInfo; + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, null, -1, 1); + test(openMBeanParameterInfo0, openMBeanParameterInfo, "default value"); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 0, null, 1); + test(openMBeanParameterInfo0, openMBeanParameterInfo, "min value"); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 0, -1, null); + test(openMBeanParameterInfo0, openMBeanParameterInfo, "max value"); + + // ---- + System.out.println("\n---Testing on OpenMBeanParameterInfoSupport 2..."); + openMBeanParameterInfo0 = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 1, new Integer[]{-1, 1, 2}); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, null, new Integer[]{-1, 1, 2}); + test(openMBeanParameterInfo0, openMBeanParameterInfo, "default value"); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 1, null); + test(openMBeanParameterInfo0, openMBeanParameterInfo, "legal values"); + + // ---- + System.out.println("\n---Testing on OpenMBeanInfoSupport..."); + String className = "toto"; + String description = "titi"; + OpenMBeanAttributeInfo[] attrInfos = new OpenMBeanAttributeInfo[]{}; + OpenMBeanConstructorInfo[] constrInfos = new OpenMBeanConstructorInfo[]{}; + OpenMBeanOperationInfo[] operaInfos = new OpenMBeanOperationInfo[]{}; + MBeanNotificationInfo[] notifInfos = new MBeanNotificationInfo[]{}; + + OpenMBeanInfo ominfo0 = new OpenMBeanInfoSupport("toto", description, attrInfos, constrInfos, operaInfos, notifInfos); + OpenMBeanInfo ominfo = new OpenMBeanInfoSupport(null, description, attrInfos, constrInfos, operaInfos, notifInfos); + test(ominfo0, ominfo, "class name"); + + ominfo = new OpenMBeanInfoSupport(className, null, attrInfos, constrInfos, operaInfos, notifInfos); + test(ominfo0, ominfo, "description"); + + ominfo = new OpenMBeanInfoSupport(className, description, null, constrInfos, operaInfos, notifInfos); + test(ominfo0, ominfo, "attrInfos"); + + ominfo = new OpenMBeanInfoSupport(className, description, attrInfos, null, operaInfos, notifInfos); + test(ominfo0, ominfo, "constructor infos"); + + ominfo = new OpenMBeanInfoSupport(className, description, attrInfos, constrInfos, null, notifInfos); + test(ominfo0, ominfo, "operation infos"); + + ominfo = new OpenMBeanInfoSupport(className, description, attrInfos, constrInfos, operaInfos, null); + test(ominfo0, ominfo, "notif infos"); + + if (failed > 0) { + throw new RuntimeException("Test failed: "+failed); + } else { + System.out.println("---Test: PASSED"); + } + } + + private static void test(Object obj1, Object obj2, String param) { + try { + obj1.equals(obj2); + System.out.println("OK-1: "+obj1.getClass().getSimpleName()+ + ".equals worked with a null field: "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO-1!!! "+obj1.getClass().getSimpleName()+ + ".equals got NPE with a null field: "+param); + npe.printStackTrace(); + failed++; + } + + try { + obj2.equals(obj1); + System.out.println("OK-2: "+obj2.getClass().getSimpleName()+ + ".equals worked with a null field: "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO-2!!! "+obj2.getClass().getSimpleName()+ + ".equals got NPE with a null field: "+param); + npe.printStackTrace(); + failed++; + } + + try { + obj1.equals(null); + obj2.equals(null); + + System.out.println("OK-3: "+obj1.getClass().getSimpleName()+ + ".equals worked with a null object."); + } catch (NullPointerException npe) { + System.out.println("--->KO-3!!! "+obj1.getClass().getSimpleName()+ + ".equals got NPE with a null object."); + npe.printStackTrace(); + failed++; + } + } +} diff --git a/jdk/test/javax/management/openmbean/OpenMBeanInfoHashCodeNPETest.java b/jdk/test/javax/management/openmbean/OpenMBeanInfoHashCodeNPETest.java new file mode 100644 index 00000000000..3c829434193 --- /dev/null +++ b/jdk/test/javax/management/openmbean/OpenMBeanInfoHashCodeNPETest.java @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.management.MBeanNotificationInfo; +import javax.management.modelmbean.DescriptorSupport; +import javax.management.openmbean.OpenMBeanAttributeInfo; +import javax.management.openmbean.OpenMBeanAttributeInfoSupport; +import javax.management.openmbean.OpenMBeanConstructorInfo; +import javax.management.openmbean.OpenMBeanConstructorInfoSupport; +import javax.management.openmbean.OpenMBeanInfo; +import javax.management.openmbean.OpenMBeanInfoSupport; +import javax.management.openmbean.OpenMBeanOperationInfo; +import javax.management.openmbean.OpenMBeanOperationInfoSupport; +import javax.management.openmbean.OpenMBeanParameterInfo; +import javax.management.openmbean.OpenMBeanParameterInfoSupport; +import javax.management.openmbean.SimpleType; + +/* + * @test + * @bug 8023529 + * @summary Test that OpenMBean*Info.hashCode do not throw NPE + * @author Shanliang JIANG + * @run clean OpenMBeanInfoHashCodeNPETest + * @run build OpenMBeanInfoHashCodeNPETest + * @run main OpenMBeanInfoHashCodeNPETest + */ +public class OpenMBeanInfoHashCodeNPETest { + private static int failed = 0; + + public static void main(String[] args) throws Exception { + System.out.println("---OpenMBeanInfoHashCodeNPETest-main ..."); + + // ---- + System.out.println("\n---Testing on OpenMBeanInfohashCodeTest..."); + OpenMBeanAttributeInfo openMBeanAttributeInfo = new OpenMBeanAttributeInfoSupport( + "name", "description", SimpleType.INTEGER, true, true, false, null, new Integer[]{1, 2, 3}); + test(openMBeanAttributeInfo, "defaultValue"); + + openMBeanAttributeInfo = new OpenMBeanAttributeInfoSupport( + "name", "description", SimpleType.INTEGER, true, true, false, 1, null); + test(openMBeanAttributeInfo, "legalValues"); + + // ---- + System.out.println("\n---Testing on OpenMBeanConstructorInfoSupport..."); + OpenMBeanConstructorInfo openMBeanConstructorInfo; + + openMBeanConstructorInfo = new OpenMBeanConstructorInfoSupport( + "name", "description", null, new DescriptorSupport()); + test(openMBeanConstructorInfo, "sigs"); + + openMBeanConstructorInfo = new OpenMBeanConstructorInfoSupport( + "name", "description", new OpenMBeanParameterInfo[]{}, null); + test(openMBeanConstructorInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on OpenMBeanOperationInfoSupport..."); + OpenMBeanOperationInfo openMBeanOperationInfo; + + openMBeanOperationInfo = new OpenMBeanOperationInfoSupport( + "name", "description", null, SimpleType.INTEGER, 1, new DescriptorSupport()); + test(openMBeanOperationInfo, "sigs"); + + openMBeanOperationInfo = new OpenMBeanOperationInfoSupport( + "name", "description", new OpenMBeanParameterInfo[]{}, SimpleType.INTEGER, 1, null); + test(openMBeanOperationInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on OpenMBeanParameterInfoSupport 1..."); + OpenMBeanParameterInfo openMBeanParameterInfo; + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, null, -1, 1); + test(openMBeanParameterInfo, "default value"); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 0, null, 1); + test(openMBeanParameterInfo, "min value"); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 0, -1, null); + test(openMBeanParameterInfo, "max value"); + + // ---- + System.out.println("\n---Testing on OpenMBeanParameterInfoSupport 2..."); + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 1, new Integer[]{-1, 1, 2}); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, null, new Integer[]{-1, 1, 2}); + test(openMBeanParameterInfo, "default value"); + + openMBeanParameterInfo = new OpenMBeanParameterInfoSupport( + "name", "description", SimpleType.INTEGER, 1, null); + test(openMBeanParameterInfo, "legal values"); + + // ---- + System.out.println("\n---Testing on OpenMBeanInfoSupport..."); + String className = "toto"; + String description = "titi"; + OpenMBeanAttributeInfo[] attrInfos = new OpenMBeanAttributeInfo[]{}; + OpenMBeanConstructorInfo[] constrInfos = new OpenMBeanConstructorInfo[]{}; + OpenMBeanOperationInfo[] operaInfos = new OpenMBeanOperationInfo[]{}; + MBeanNotificationInfo[] notifInfos = new MBeanNotificationInfo[]{}; + + OpenMBeanInfo ominfo = new OpenMBeanInfoSupport(null, description, attrInfos, constrInfos, operaInfos, notifInfos); + test(ominfo, "class name"); + + ominfo = new OpenMBeanInfoSupport(className, null, attrInfos, constrInfos, operaInfos, notifInfos); + test(ominfo, "description"); + + ominfo = new OpenMBeanInfoSupport(className, description, null, constrInfos, operaInfos, notifInfos); + test(ominfo, "attrInfos"); + + ominfo = new OpenMBeanInfoSupport(className, description, attrInfos, null, operaInfos, notifInfos); + test(ominfo, "constructor infos"); + + ominfo = new OpenMBeanInfoSupport(className, description, attrInfos, constrInfos, null, notifInfos); + test(ominfo, "operation infos"); + + ominfo = new OpenMBeanInfoSupport(className, description, attrInfos, constrInfos, operaInfos, null); + test(ominfo, "notif infos"); + + if (failed > 0) { + throw new RuntimeException("Test failed: "+failed); + } else { + System.out.println("---Test: PASSED"); + } + } + + private static void test(Object obj, String param) { + try { + obj.hashCode(); + System.out.println("OK-1: "+obj.getClass().getSimpleName()+ + ".hashCode worked with a null paramer: "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO-1!!! "+obj.getClass().getSimpleName()+ + ".hashCode got NPE with null paramer: "+param); + npe.printStackTrace(); + failed++; + } + + try { + obj.toString(); + System.out.println("OK-1: "+obj.getClass().getSimpleName()+ + ".toString worked with a null paramer: "+param); + } catch (NullPointerException npe) { + System.out.println("--->KO-1!!! "+obj.getClass().getSimpleName()+ + ".toString got NPE with null paramer: "+param); + npe.printStackTrace(); + failed++; + } + } +} diff --git a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java new file mode 100644 index 00000000000..86efed134f3 --- /dev/null +++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorInternalMapTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.management.ManagementFactory; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.Map; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXPrincipal; +import javax.management.remote.JMXServiceURL; +import javax.management.remote.rmi.RMIConnector; +import javax.security.auth.Subject; + +/* + * @test + * @bug 6566891 + * @summary Check no memory leak on RMIConnector's rmbscMap + * @author Shanliang JIANG + * @run clean RMIConnectorInternalMapTest + * @run build RMIConnectorInternalMapTest + * @run main RMIConnectorInternalMapTest + */ + +public class RMIConnectorInternalMapTest { + public static void main(String[] args) throws Exception { + System.out.println("---RMIConnectorInternalMapTest starting..."); + + JMXConnectorServer connectorServer = null; + JMXConnector connectorClient = null; + + try { + MBeanServer mserver = ManagementFactory.getPlatformMBeanServer(); + JMXServiceURL serverURL = new JMXServiceURL("rmi", "localhost", 0); + connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(serverURL, null, mserver); + connectorServer.start(); + + JMXServiceURL serverAddr = connectorServer.getAddress(); + connectorClient = JMXConnectorFactory.connect(serverAddr, null); + connectorClient.connect(); + + Field rmbscMapField = RMIConnector.class.getDeclaredField("rmbscMap"); + rmbscMapField.setAccessible(true); + Map> map = + (Map>) rmbscMapField.get(connectorClient); + if (map != null && !map.isEmpty()) { // failed + throw new RuntimeException("RMIConnector's rmbscMap must be empty at the initial time."); + } + + Subject delegationSubject = + new Subject(true, + Collections.singleton(new JMXPrincipal("delegate")), + Collections.EMPTY_SET, + Collections.EMPTY_SET); + MBeanServerConnection mbsc1 = + connectorClient.getMBeanServerConnection(delegationSubject); + MBeanServerConnection mbsc2 = + connectorClient.getMBeanServerConnection(delegationSubject); + + if (mbsc1 == null) { + throw new RuntimeException("Got null connection."); + } + if (mbsc1 != mbsc2) { + throw new RuntimeException("Not got same connection with a same subject."); + } + + map = (Map>) rmbscMapField.get(connectorClient); + if (map == null || map.isEmpty()) { // failed + throw new RuntimeException("RMIConnector's rmbscMap has wrong size " + + "after creating a delegated connection."); + } + + delegationSubject = null; + mbsc1 = null; + mbsc2 = null; + + int i = 0; + while (!map.isEmpty() && i++ < 60) { + System.gc(); + Thread.sleep(100); + } + System.out.println("---GC times: " + i); + + if (!map.isEmpty()) { + throw new RuntimeException("Failed to clean RMIConnector's rmbscMap"); + } else { + System.out.println("---RMIConnectorInternalMapTest: PASSED!"); + } + } finally { + try { + connectorClient.close(); + connectorServer.stop(); + } catch (Exception e) { + } + } + } +} diff --git a/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java new file mode 100644 index 00000000000..7b5224e9b92 --- /dev/null +++ b/jdk/test/javax/management/remote/mandatory/connection/RMIConnectorNullSubjectConnTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.management.ManagementFactory; +import java.lang.ref.WeakReference; +import java.lang.reflect.Field; +import javax.management.MBeanServer; +import javax.management.MBeanServerConnection; +import javax.management.remote.JMXConnector; +import javax.management.remote.JMXConnectorFactory; +import javax.management.remote.JMXConnectorServer; +import javax.management.remote.JMXConnectorServerFactory; +import javax.management.remote.JMXServiceURL; +import javax.management.remote.rmi.RMIConnector; + +/* + * @test + * @bug 6566891 + * @summary Check no memory leak on RMIConnector's nullSubjectConn + * @author Shanliang JIANG + * @run clean RMIConnectorNullSubjectConnTest + * @run build RMIConnectorNullSubjectConnTest + * @run main RMIConnectorNullSubjectConnTest + */ + +public class RMIConnectorNullSubjectConnTest { + public static void main(String[] args) throws Exception { + System.out.println("---RMIConnectorNullSubjectConnTest starting..."); + + JMXConnectorServer connectorServer = null; + JMXConnector connectorClient = null; + + try { + MBeanServer mserver = ManagementFactory.getPlatformMBeanServer(); + JMXServiceURL serverURL = new JMXServiceURL("rmi", "localhost", 0); + connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(serverURL, null, mserver); + connectorServer.start(); + + JMXServiceURL serverAddr = connectorServer.getAddress(); + connectorClient = JMXConnectorFactory.connect(serverAddr, null); + connectorClient.connect(); + + Field nullSubjectConnField = RMIConnector.class.getDeclaredField("nullSubjectConnRef"); + nullSubjectConnField.setAccessible(true); + + WeakReference weak = + (WeakReference)nullSubjectConnField.get(connectorClient); + + if (weak != null && weak.get() != null) { + throw new RuntimeException("nullSubjectConnRef must be null at initial time."); + } + + MBeanServerConnection conn1 = connectorClient.getMBeanServerConnection(null); + MBeanServerConnection conn2 = connectorClient.getMBeanServerConnection(null); + if (conn1 == null) { + throw new RuntimeException("A connection with null subject should not be null."); + } else if (conn1 != conn2) { + throw new RuntimeException("The 2 connections with null subject are not equal."); + } + + conn1 = null; + conn2 = null; + int i = 1; + do { + System.gc(); + Thread.sleep(100); + weak = (WeakReference)nullSubjectConnField.get(connectorClient); + } while ((weak != null && weak.get() != null) && i++ < 60); + + System.out.println("---GC times: " + i); + + if (weak != null && weak.get() != null) { + throw new RuntimeException("Failed to clean RMIConnector's nullSubjectConn"); + } else { + System.out.println("---RMIConnectorNullSubjectConnTest: PASSED!"); + } + } finally { + try { + connectorClient.close(); + connectorServer.stop(); + } catch (Exception e) { + } + } + } +} diff --git a/jdk/test/javax/swing/JComboBox/6236162/bug6236162.java b/jdk/test/javax/swing/JComboBox/6236162/bug6236162.java new file mode 100644 index 00000000000..6e0ad44e734 --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/6236162/bug6236162.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* @test + @bug 6236162 + @summary Checks that there is no an inconsistence in combo box + behavior when user points an item in combo popup + by mouse and then uses UP/DOWN keys. + @library ../../regtesthelpers + @build Util + @author Mikhail Lapshin + @run main bug6236162 +*/ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.plaf.basic.*; +import javax.swing.plaf.metal.MetalComboBoxUI; +import java.awt.*; +import java.awt.event.KeyEvent; + +public class bug6236162 { + private static final SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + private static JFrame frame; + private static JComboBox combo; + private static MyComboUI comboUI; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + toolkit.realSync(); + test(); + System.out.println("Test passed"); + } + + private static void createAndShowGUI() { + frame = new JFrame("bug6236162"); + + combo = new JComboBox(new String[]{"one", "two", "three", "four", "five"}); + combo.setEditable(true); + comboUI = new MyComboUI(); + combo.setUI(comboUI); + combo.setSelectedIndex(3); + frame.getContentPane().add(combo); + + frame.pack(); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void test() throws AWTException { + Robot robot = new Robot(); + robot.setAutoDelay(50); + + // Open popup menu + realSync(); + Util.hitKeys(robot, KeyEvent.VK_DOWN); + + // Move mouse to the first popup menu item + realSync(); + Point p = combo.getLocationOnScreen(); + Dimension size = combo.getSize(); + p.x += size.width / 2; + p.y += size.height; + float dy = 1; + robot.mouseMove(p.x, p.y - 5); + for (int i=1; i <= 10; i++) { + robot.mouseMove((int)(p.x), (int)(p.y - 5 + dy*i)); + } + + // Select the second popup menu item + realSync(); + Util.hitKeys(robot, KeyEvent.VK_DOWN); + + realSync(); + JList list = comboUI.getComboPopup().getList(); + if (list.getSelectedIndex() != 1) { + throw new RuntimeException("There is an inconsistence in combo box " + + "behavior when user points an item in combo popup " + + "by mouse and then uses UP/DOWN keys."); + } + } + + private static void realSync() { + ((SunToolkit)Toolkit.getDefaultToolkit()).realSync(); + } + + // Gives access to BasicComboBoxUI.popup field + private static class MyComboUI extends MetalComboBoxUI { + public ComboPopup getComboPopup() { + return popup; + } + } +} diff --git a/jdk/test/javax/swing/JComboBox/7195179/Test7195179.java b/jdk/test/javax/swing/JComboBox/7195179/Test7195179.java new file mode 100644 index 00000000000..f22084a87bc --- /dev/null +++ b/jdk/test/javax/swing/JComboBox/7195179/Test7195179.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Component; +import javax.swing.GroupLayout; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.ListCellRenderer; +import javax.swing.plaf.basic.BasicComboBoxRenderer; + +import static javax.swing.SwingUtilities.invokeAndWait; + +/* + * @test + * @bug 7195179 + * @summary Tests that combobox works with generified renderers + * @author Sergey Malenkov + */ + +public class Test7195179 { + public static void main(String[] args) throws Exception { + invokeAndWait(new Runnable() { + @Override + public void run() { + Integer[] items = {null, 1, 2, 3}; + JComboBox combo = new JComboBox<>(items); + JLabel label = new JLabel("choose:"); + JPanel panel = new JPanel(); + GroupLayout layout = new GroupLayout(panel); + panel.setLayout(layout); + label.setLabelFor(combo); + combo.setSelectedIndex(0); + combo.setRenderer(new ListCellRenderer() { + private final BasicComboBoxRenderer renderer = new BasicComboBoxRenderer(); + + @Override + public Component getListCellRendererComponent(JList list, Integer value, int index, boolean isSelected, boolean cellHasFocus) { + return this.renderer.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); + } + }); + layout.setAutoCreateContainerGaps(true); + layout.setAutoCreateGaps(true); + layout.setHorizontalGroup(layout.createSequentialGroup() + .addGroup(layout.createParallelGroup().addComponent(label)) + .addGroup(layout.createParallelGroup().addComponent(combo))); + layout.setVerticalGroup(layout + .createSequentialGroup() + .addGroup(layout + .createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(label) + .addComponent(combo))); + + JFrame frame = new JFrame(getClass().getSimpleName()); + frame.add(panel); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } + }); + } +} diff --git a/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.html b/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.html index 15620bf05a3..902dda5b6c9 100644 --- a/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.html +++ b/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.html @@ -1,6 +1,38 @@ + + + + +Follow the instructions below. 1.Go into 'subDir' folder. 2.Press BACKSPACE key. 3.Push OPEN button. diff --git a/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.java b/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.java index d71bbf46828..bc4b1a8ef43 100644 --- a/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.java +++ b/jdk/test/javax/swing/JFileChooser/4150029/bug4150029.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,11 +21,10 @@ * questions. */ -/* @test - @bug 4150029 - @summary BackSpace keyboard button does not lead to parent directory - @author Oleg Mokhovikov - @run applet/manual=done bug4150029.html +/* + bug 4150029 8006087 + summary BackSpace keyboard button does not lead to parent directory + author Oleg Mokhovikov */ import javax.swing.*; @@ -36,6 +35,14 @@ public class bug4150029 extends JApplet { private boolean res; public void init() { + if (sun.awt.OSInfo.getOSType() == sun.awt.OSInfo.OSType.MACOSX) { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + String tmpDir = System.getProperty("java.io.tmpdir"); if (tmpDir.length() == 0) {//'java.io.tmpdir' isn't guaranteed to be defined diff --git a/jdk/test/javax/swing/JFileChooser/7199708/bug7199708.java b/jdk/test/javax/swing/JFileChooser/7199708/bug7199708.java new file mode 100644 index 00000000000..339c6553a18 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/7199708/bug7199708.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Component; +import java.awt.Container; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.IOException; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; + +import java.nio.file.Files; +import javax.swing.AbstractButton; +import javax.swing.JTable; +import javax.swing.UIManager; +import sun.awt.SunToolkit; + +/** + * @test + * @bug 7199708 + * @author Alexander Scherbatiy + * @summary FileChooser crashs when opening large folder + * @run main bug7199708 + */ +public class bug7199708 { + + private static int FILE_NUMBER = 30000; + private static volatile JFileChooser fileChooser; + private static volatile int locationX; + private static volatile int locationY; + private static volatile int width; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + final File folder = createLargeFolder(); + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + fileChooser = new JFileChooser(folder); + fileChooser.showSaveDialog(null); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + final String detailsTooltip = UIManager.getString("FileChooser." + + "detailsViewButtonToolTipText", fileChooser.getLocale()); + + doAction(fileChooser, new ComponentAction() { + @Override + public boolean accept(Component component) { + return (component instanceof AbstractButton) + && detailsTooltip.equals( + ((AbstractButton) component).getToolTipText()); + } + + @Override + public void perform(Component component) { + ((AbstractButton) component).doClick(); + } + }); + + doAction(fileChooser, new ComponentAction() { + @Override + public boolean accept(Component component) { + return (component instanceof JTable); + } + + @Override + public void perform(Component component) { + Point tableLocation = component.getLocationOnScreen(); + locationX = (int) tableLocation.getX(); + locationY = (int) tableLocation.getY(); + width = (int) fileChooser.getBounds().getWidth(); + } + }); + } + }); + + toolkit.realSync(); + + int d = 25; + for (int i = 0; i < width / d; i++) { + robot.mouseMove(locationX + i * d, locationY + 5); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + toolkit.realSync(); + } + + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + } + + static void doAction(Component component, ComponentAction action) { + if (action.accept(component)) { + action.perform(component); + } else if (component instanceof Container) { + for (Component comp : ((Container) component).getComponents()) { + doAction(comp, action); + } + } + } + + private static File createLargeFolder() { + try { + + File largeFolder = Files.createTempDirectory("large_folder").toFile(); + largeFolder.deleteOnExit(); + + for (int i = 0; i < FILE_NUMBER; i++) { + File file = new File(largeFolder, "File_" + i + ".txt"); + file.createNewFile(); + file.deleteOnExit(); + } + return largeFolder; + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } + + interface ComponentAction { + + boolean accept(Component component); + + void perform(Component component); + } +} diff --git a/jdk/test/javax/swing/JFileChooser/8002077/bug8002077.java b/jdk/test/javax/swing/JFileChooser/8002077/bug8002077.java new file mode 100644 index 00000000000..ea1470d4ed5 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/8002077/bug8002077.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.KeyEvent; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; +import sun.awt.SunToolkit; + +/** + * @test + * @bug 8002077 + * @author Alexander Scherbatiy + * @summary Possible mnemonic issue on JFileChooser Save button on nimbus L&F + * @library ../../regtesthelpers/ + * @build Util + * @run main bug8002077 + */ +public class bug8002077 { + + private static volatile int fileChooserState = JFileChooser.ERROR_OPTION; + + public static void main(String[] args) throws Exception { + for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { + if ("Nimbus".equals(info.getName())) { + UIManager.setLookAndFeel(info.getClassName()); + runTest(); + break; + } + } + } + + private static void runTest() throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + fileChooserState = new JFileChooser().showSaveDialog(null); + } + }); + toolkit.realSync(); + + Util.hitMnemonics(robot, KeyEvent.VK_N); + toolkit.realSync(); + + robot.keyPress(KeyEvent.VK_A); + robot.keyRelease(KeyEvent.VK_A); + toolkit.realSync(); + + Util.hitMnemonics(robot, KeyEvent.VK_S); + toolkit.realSync(); + + if (fileChooserState != JFileChooser.APPROVE_OPTION) { + throw new RuntimeException("Save button is not pressed!"); + } + } +} diff --git a/jdk/test/javax/swing/JFileChooser/8021253/bug8021253.java b/jdk/test/javax/swing/JFileChooser/8021253/bug8021253.java new file mode 100644 index 00000000000..5e833926a00 --- /dev/null +++ b/jdk/test/javax/swing/JFileChooser/8021253/bug8021253.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.io.File; +import java.io.IOException; +import java.awt.BorderLayout; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import sun.awt.SunToolkit; + +/** + * @test + * @bug 8021253 + * @author Alexander Scherbatiy + * @summary JFileChooser does not react on pressing enter since java 7 + * @run main bug8021253 + */ + +public class bug8021253 { + + private static volatile boolean defaultKeyPressed; + private static JFileChooser fileChooser; + private static File file; + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + fileChooser.setSelectedFile(file); + } + }); + + toolkit.realSync(); + + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + toolkit.realSync(); + + if (!defaultKeyPressed) { + throw new RuntimeException("Default button is not pressed"); + } + } + + private static void createAndShowGUI() { + + file = getTempFile(); + + final JFrame frame = new JFrame("Test"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(200, 300); + + fileChooser = new JFileChooser(file.getParentFile()); + fileChooser.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + defaultKeyPressed = true; + frame.dispose(); + } + }); + + frame.getContentPane().add(BorderLayout.CENTER, fileChooser); + frame.setSize(fileChooser.getPreferredSize()); + frame.setVisible(true); + } + + private static File getTempFile() { + try { + File temp = File.createTempFile("test", ".txt"); + temp.deleteOnExit(); + return temp; + } catch (IOException ex) { + throw new RuntimeException(ex); + } + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/4193219/IconCoord.java b/jdk/test/javax/swing/JInternalFrame/4193219/IconCoord.java new file mode 100644 index 00000000000..709a197f2ae --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/4193219/IconCoord.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* + @test + @bug 4193219 + @summary + @author Your Name: Hania Gajewska area=swing + @run main/manual IconCoord +*/ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; + +public class IconCoord { + static Test test = new Test(); + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new IconCoord().createAndShowGUI(); + } + }); + test.waitTestResult(); + } + + private void createAndShowGUI() { + StringBuilder instrText = new StringBuilder(); + instrText.append("First, iconify internal frame \"Frame 1\" by clicking on its iconify button.\n"); + instrText.append("Now, maximize the top-level window \"IconCoord\".\n"); + instrText.append("The \"Frame 1\" icon should stay in the lower left corner of the desktop; "); + instrText.append("if it doesn't, press \"Fail\".\n"); + instrText.append("Now move the icon to the middle of the desktop by dragging it by its "); + instrText.append("bumpy left side. Then iconify \"Frame 2\" by clicking on its iconify button.\n"); + instrText.append("If the icon for frame two gets placed in the lower left corner of the "); + instrText.append("desktop (where the icon for \"Frame 1\" used to be before you moved it), "); + instrText.append("press \"Pass\". Otherwise, press \"Fail\".\n"); + + JDesktopPane dt = new JDesktopPane(); + + JButton tf; + JInternalFrame if1 = new JInternalFrame("Frame 1", false, false, false, true); + JComponent c = (JComponent) if1.getContentPane(); + c.setLayout(new BorderLayout()); + + tf = new JButton ("ignore"); + c.add (tf, BorderLayout.NORTH); + + tf = new JButton ("ignore"); + c.add (tf, BorderLayout.CENTER); + + JInternalFrame if2 = new JInternalFrame("Frame 2", false, false, false, true); + c = (JComponent) if2.getContentPane(); + c.setLayout(new BorderLayout()); + + tf = new JButton ("ignore"); + c.add (tf, BorderLayout.NORTH); + + tf = new JButton ("ignore"); + c.add (tf, BorderLayout.CENTER); + + if1.pack(); + if1.setBounds(300, 0, 300, 80); + if2.pack(); + if2.setBounds(0, 0, 300, 80); + dt.add(if1); + dt.add(if2); + + if1.setVisible(true); + if2.setVisible(true); + + int frameHeight = 500; + + JScrollPane dtScrollPane = new JScrollPane(dt); + JFrame frame = test.createTestFrame("IconCoord", dtScrollPane, instrText.toString(), 250); + dt.setPreferredSize(new Dimension(650, frameHeight - 250)); + frame.setSize (600,500); + frame.setVisible(true); + } + + static class Test { + private boolean pass; + JFrame createTestFrame(String name, Component topComponent, String instructions, int instrHeight) { + final String PASS = "Pass"; + final String FAIL = "Fail"; + JFrame frame = new JFrame(name); + frame.setLayout(new BorderLayout()); + + JPanel testButtonsPanel = new JPanel(); + testButtonsPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 20)); + + ActionListener btnAL = new ActionListener() { + public void actionPerformed(ActionEvent event) { + switch (event.getActionCommand()) { + case PASS: + pass(); + break; + default: + throw new RuntimeException("Test failed."); + } + } + }; + JButton passBtn = new JButton(PASS); + passBtn.addActionListener(btnAL); + passBtn.setActionCommand(PASS); + + JButton failBtn = new JButton(FAIL); + failBtn.addActionListener(btnAL); + failBtn.setActionCommand(FAIL); + + testButtonsPanel.add(BorderLayout.WEST, passBtn); + testButtonsPanel.add(BorderLayout.EAST, failBtn); + + JTextArea instrText = new JTextArea(); + instrText.setLineWrap(true); + instrText.setEditable(false); + JScrollPane instrScrollPane = new JScrollPane(instrText); + instrScrollPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, instrHeight)); + instrText.append(instructions); + + JPanel servicePanel = new JPanel(); + servicePanel.setLayout(new BorderLayout()); + servicePanel.add(BorderLayout.CENTER, instrScrollPane); + servicePanel.add(BorderLayout.SOUTH, testButtonsPanel); + + frame.add(BorderLayout.SOUTH, servicePanel); + frame.add(BorderLayout.CENTER, topComponent); + return frame; + } + synchronized void pass() { + pass = true; + notifyAll(); + } + synchronized void waitTestResult() throws InterruptedException { + while (!pass) { + wait(); + } + } + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/4251301/bug4251301.java b/jdk/test/javax/swing/JInternalFrame/4251301/bug4251301.java new file mode 100644 index 00000000000..304d0582407 --- /dev/null +++ b/jdk/test/javax/swing/JInternalFrame/4251301/bug4251301.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* @test + @bug 4251301 + @summary Keybinding for show/hide the system menu. + @author Andrey Pikalev + @run main/manual bug4251301 +*/ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.beans.*; +import sun.awt.OSInfo; +import sun.awt.SunToolkit; + + +public class bug4251301 { + private static final SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + static Test test = new Test(); + public static void main(String[] args) throws Exception { + if (OSInfo.getOSType() == OSInfo.OSType.MACOSX) { + System.out.println("This test is not applicable for MacOS. Passed."); + return; + } + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + toolkit.realSync(); + test.waitTestResult(); + } + + public static void createAndShowGUI() { + final StringBuilder instructions = new StringBuilder(); + instructions.append("Click with your mouse the content area of the internal frame with the title \"IFrame\" "); + instructions.append("and press Ctrl+Space. \n"); + instructions.append("If the system menu shows up, press Esc. Then system menu should hide. \n"); + instructions.append("If you success then press \"Pass\", else press \"Fail\".\n"); + + JDesktopPane dp = new JDesktopPane(); + JInternalFrame jif = new JInternalFrame("IFrame",true,true,true,true); + dp.add(jif); + jif.setBounds(20, 20, 220, 100); + jif.setVisible(true); + try { + jif.setSelected(true); + } catch(PropertyVetoException pve) { + pve.printStackTrace(); + throw new Error("Occures PropertyVetoException while set selection..."); + } + JScrollPane dtScrollPane = new JScrollPane(dp); + JFrame testFrame = test.createTestFrame("Instructions", dtScrollPane, instructions.toString(), 500); + testFrame.setSize(500, 400); + testFrame.setVisible(true); + } + static class Test { + private boolean pass; + JFrame createTestFrame(String name, Component topComponent, String instructions, int instrHeight) { + final String PASS = "Pass"; + final String FAIL = "Fail"; + JFrame frame = new JFrame(name); + frame.setLayout(new BorderLayout()); + + JPanel testButtonsPanel = new JPanel(); + testButtonsPanel.setMaximumSize(new Dimension(Integer.MAX_VALUE, 20)); + + ActionListener btnAL = new ActionListener() { + public void actionPerformed(ActionEvent event) { + switch (event.getActionCommand()) { + case PASS: + pass(); + break; + default: + throw new RuntimeException("Test failed."); + } + } + }; + JButton passBtn = new JButton(PASS); + passBtn.addActionListener(btnAL); + passBtn.setActionCommand(PASS); + + JButton failBtn = new JButton(FAIL); + failBtn.addActionListener(btnAL); + failBtn.setActionCommand(FAIL); + + testButtonsPanel.add(BorderLayout.WEST, passBtn); + testButtonsPanel.add(BorderLayout.EAST, failBtn); + + JTextArea instrText = new JTextArea(); + instrText.setLineWrap(true); + instrText.setEditable(false); + JScrollPane instrScrollPane = new JScrollPane(instrText); + instrScrollPane.setMaximumSize(new Dimension(Integer.MAX_VALUE, instrHeight)); + instrText.append(instructions); + + JPanel servicePanel = new JPanel(); + servicePanel.setLayout(new BorderLayout()); + servicePanel.add(BorderLayout.CENTER, instrScrollPane); + servicePanel.add(BorderLayout.SOUTH, testButtonsPanel); + + frame.add(BorderLayout.SOUTH, servicePanel); + frame.add(BorderLayout.CENTER, topComponent); + return frame; + } + synchronized void pass() { + pass = true; + notifyAll(); + } + synchronized void waitTestResult() throws InterruptedException { + while (!pass) { + wait(); + } + } + } +} diff --git a/jdk/test/javax/swing/JInternalFrame/InternalFrameIsNotCollectedTest.java b/jdk/test/javax/swing/JInternalFrame/InternalFrameIsNotCollectedTest.java index 182e57eef55..fff9c8e1d94 100644 --- a/jdk/test/javax/swing/JInternalFrame/InternalFrameIsNotCollectedTest.java +++ b/jdk/test/javax/swing/JInternalFrame/InternalFrameIsNotCollectedTest.java @@ -27,19 +27,19 @@ @author mcherkas @run main InternalFrameIsNotCollectedTest */ - import sun.awt.SunToolkit; import javax.swing.*; import java.awt.*; -import java.awt.event.KeyEvent; import java.beans.PropertyVetoException; import java.util.Date; public class InternalFrameIsNotCollectedTest { - public static final int waitTime = 10000; + public static final int maxWaitTime = 100000; + public static final int waitTime = 5000; private static Robot robot; + private static CustomInternalFrame iFrame; public static void sync() { @@ -62,12 +62,13 @@ public class InternalFrameIsNotCollectedTest { }); sync(); invokeGC(); + System.runFinalization(); Thread.sleep(1000); // it's better to wait 1 sec now then 10 sec later Date startWaiting = new Date(); synchronized (CustomInternalFrame.waiter) { // Sync with finalization thread. Date now = new Date(); - while (now.getTime() - startWaiting.getTime() < waitTime && !CustomInternalFrame.finalized) { + while (now.getTime() - startWaiting.getTime() < maxWaitTime && !CustomInternalFrame.finalized) { CustomInternalFrame.waiter.wait(waitTime); now = new Date(); } @@ -83,10 +84,8 @@ public class InternalFrameIsNotCollectedTest { } private static void closeInternalFrame() throws PropertyVetoException { - robot.keyPress(KeyEvent.VK_CONTROL); - robot.keyPress(KeyEvent.VK_F4); - robot.keyRelease(KeyEvent.VK_F4); - robot.keyRelease(KeyEvent.VK_CONTROL); + iFrame.setClosed(true); + iFrame = null; } private static void initUI() { @@ -96,7 +95,7 @@ public class InternalFrameIsNotCollectedTest { desktopPane.setDesktopManager(new DefaultDesktopManager()); frame.getContentPane().add(desktopPane, BorderLayout.CENTER); - CustomInternalFrame iFrame = new CustomInternalFrame("Dummy Frame"); + iFrame = new CustomInternalFrame("Dummy Frame"); iFrame.setSize(200, 200); iFrame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); diff --git a/jdk/test/javax/swing/JMenuBar/4750590/bug4750590.java b/jdk/test/javax/swing/JMenuBar/4750590/bug4750590.java new file mode 100644 index 00000000000..2ba8a51ebae --- /dev/null +++ b/jdk/test/javax/swing/JMenuBar/4750590/bug4750590.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @library ../../regtesthelpers + @build Util + @bug 4750590 8015597 + @summary SwingSet: Cannot change Themes using menu accelerators + @author Alexander Zuev + @run main bug4750590 + */ + +import javax.swing.*; +import java.awt.event.*; +import java.awt.*; + +public class bug4750590 { + + public static PassedListener pass = new PassedListener(); + public static volatile boolean passed = false; + + public static void main(String args[]) throws Throwable { + + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + createAndShowGUI(); + } + }); + + sun.awt.SunToolkit toolkit = (sun.awt.SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + + Robot robo = new Robot(); + robo.setAutoDelay(500); + Util.hitMnemonics(robo, KeyEvent.VK_F); + robo.keyPress(KeyEvent.VK_M); + robo.keyRelease(KeyEvent.VK_M); + + toolkit.realSync(); + + if (passed) { + System.out.println("Test passed!"); + } else { + throw new RuntimeException("Test FAILED!"); + } + } + + private static void createAndShowGUI() { + JFrame mainFrame = new JFrame("Bug 4750590"); + JMenuBar mbar = new JMenuBar(); + JMenu menu = new JMenu("File"); + menu.setMnemonic('F'); + JMenu submenu = new JMenu("Submenu"); + submenu.add(new JMenuItem("SubMenu Item 1")).setMnemonic('S'); + submenu.add(new JMenuItem("SubMenu Item 2")); + menu.add(submenu); + + menu.add(new JMenuItem("Menu Item 1")); + JMenuItem menuItem = menu.add(new JMenuItem("Menu Item 2")); + menuItem.setMnemonic('M'); + menuItem.addActionListener(pass); + mbar.add(menu); + mainFrame.setJMenuBar(mbar); + + mainFrame.setSize(200, 200); + mainFrame.setLocation(200, 200); + mainFrame.setVisible(true); + mainFrame.toFront(); + } + + public static class PassedListener implements ActionListener { + public void actionPerformed(ActionEvent ev) { + passed = true; + } + } + +} diff --git a/jdk/test/javax/swing/JMenuItem/4171437/bug4171437.java b/jdk/test/javax/swing/JMenuItem/4171437/bug4171437.java new file mode 100644 index 00000000000..378bd2a3c66 --- /dev/null +++ b/jdk/test/javax/swing/JMenuItem/4171437/bug4171437.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* @test + @bug 4171437 + @library ../../regtesthelpers + @build Util + @author Georges Saab + @run main bug4171437 +*/ +import java.awt.*; +import java.awt.event.*; +import java.util.ArrayList; +import javax.swing.*; +import javax.swing.event.*; +import sun.awt.SunToolkit; + +public class bug4171437 { + static volatile boolean closeActivated = false; + static volatile boolean customActivated = false; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + Util.hitMnemonics(robot, KeyEvent.VK_F); + Util.hitKeys(robot, KeyEvent.VK_C); + + toolkit.realSync(); + Thread.sleep(1000); + + if (!closeActivated || customActivated) { + throw new RuntimeException("Didn't pass the muster"); + } + } + public static void createAndShowGUI() { + JMenuBar menubar = new JMenuBar(); + + JMenu fileMenu = new JMenu("File"); + fileMenu.setMnemonic('f'); + + JMenuItem fmi1 = new JMenuItem(); + fmi1 = new JMenuItem("Open"); + JMenuItem fmi2 = new JMenuItem(); + fmi2 = new JMenuItem("Close"); + fmi2.setMnemonic('c'); + fmi2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + closeActivated = true; + } + }); + + fileMenu.add( fmi1); + fileMenu.add( fmi2); + + menubar.add( fileMenu); + + JMenu custom = new JMenu("Custom"); + custom.setMnemonic('c'); + JMenuItem cmi = new JMenuItem(); + cmi = new JMenuItem("Properties"); + cmi.setMnemonic('p'); + custom.add( cmi); + custom.addMenuListener(new MenuListener() { + public void menuSelected(MenuEvent e) { + customActivated = true; + } + public void menuDeselected(MenuEvent e) {} + public void menuCanceled(MenuEvent e) {} + }); + menubar.add( custom); + + JFrame frame = new JFrame(); + frame.setJMenuBar( menubar); + frame.setSize(300, 300); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.pack(); + frame.setVisible(true); + } +} diff --git a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java index 4b78bb98a0e..69a42d7834b 100644 --- a/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java +++ b/jdk/test/javax/swing/JMenuItem/ActionListenerCalledTwice/ActionListenerCalledTwiceTest.java @@ -35,12 +35,13 @@ import java.awt.event.*; import javax.swing.*; public class ActionListenerCalledTwiceTest { - static String menuItems[] = { "Item1", "Item2", "Item3", "Item4" }; + static String menuItems[] = { "Item1", "Item2", "Item3", "Item4", "Item5" }; static KeyStroke keyStrokes[] = { KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.META_MASK), KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0), KeyStroke.getKeyStroke(KeyEvent.VK_UP, InputEvent.SHIFT_MASK), - KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.META_MASK) + KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, InputEvent.META_MASK), + KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_MASK) }; static volatile int listenerCallCounter = 0; diff --git a/jdk/test/javax/swing/JPopupMenu/4458079/bug4458079.java b/jdk/test/javax/swing/JPopupMenu/4458079/bug4458079.java new file mode 100644 index 00000000000..a9807d316c1 --- /dev/null +++ b/jdk/test/javax/swing/JPopupMenu/4458079/bug4458079.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* @test + @bug 4458079 + @library ../../regtesthelpers + @build Util + @summary Tests calling removeAll() from PopupMenuListener + @author Peter Zhelezniakov + @run main bug4458079 +*/ +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; +import java.awt.event.KeyEvent; +import java.util.ArrayList; +import sun.awt.SunToolkit; + +public class bug4458079 extends JFrame implements PopupMenuListener { + public JMenu menu; + + static volatile boolean itemASelected = false; + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + new bug4458079().createAndShowGUI(); + } + }); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + + Robot robot = new Robot(); + robot.setAutoDelay(50); + + Util.hitMnemonics(robot, KeyEvent.VK_M); + + toolkit.realSync(); + Thread.sleep(1000); + + Util.hitKeys(robot, KeyEvent.VK_DOWN); + Util.hitKeys(robot, KeyEvent.VK_ENTER); + + toolkit.realSync(); + Thread.sleep(1000); + + if (!itemASelected) { + throw new RuntimeException("Test failed: arrow key traversal in JMenu broken!"); + } + } + public void createAndShowGUI() { + JMenuBar bar = new JMenuBar(); + menu = new JMenu("Menu"); + menu.add(new JMenuItem("1")); + menu.add(new JMenuItem("2")); + menu.setMnemonic(KeyEvent.VK_M); + menu.getPopupMenu().addPopupMenuListener(this); + bar.add(menu); + + setJMenuBar(bar); + getContentPane().add(new JButton("")); + setSize(300, 300); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + pack(); + setVisible(true); + } + + public void rebuildMenu() { + menu.removeAll(); + final String itemCommand = "A"; + JMenuItem item = new JMenuItem(itemCommand); + item.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + JMenuItem item = ((JMenuItem)e.getSource()); + if (e.getActionCommand() == itemCommand) { + itemASelected = true; + } + } + }); + menu.add(item); + menu.add(new JMenuItem("B")); + } + + public void popupMenuWillBecomeVisible(PopupMenuEvent e) { + rebuildMenu(); + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {} + public void popupMenuCanceled(PopupMenuEvent e) {} +} diff --git a/jdk/test/javax/swing/JScrollBar/7163696/Test7163696.java b/jdk/test/javax/swing/JScrollBar/7163696/Test7163696.java index 922bf2e4963..759012ebe74 100644 --- a/jdk/test/javax/swing/JScrollBar/7163696/Test7163696.java +++ b/jdk/test/javax/swing/JScrollBar/7163696/Test7163696.java @@ -59,7 +59,8 @@ public class Test7163696 implements Runnable { UIManager.setLookAndFeel(info.getClassName()); SwingUtilities.invokeAndWait(this); - toolkit.realSync(500); // after creation + toolkit.realSync(); // after creation + Thread.sleep(1000); Point point = this.bar.getLocation(); SwingUtilities.convertPointToScreen(point, this.bar); @@ -69,7 +70,8 @@ public class Test7163696 implements Runnable { robot.mousePress(InputEvent.BUTTON1_MASK); robot.mouseRelease(InputEvent.BUTTON1_MASK); - toolkit.realSync(500); // before validation + toolkit.realSync(); // before validation + Thread.sleep(1000); SwingUtilities.invokeAndWait(this); if (this.bar != null) { diff --git a/jdk/test/javax/swing/JSplitPane/4816114/bug4816114.java b/jdk/test/javax/swing/JSplitPane/4816114/bug4816114.java new file mode 100644 index 00000000000..0b3247f9746 --- /dev/null +++ b/jdk/test/javax/swing/JSplitPane/4816114/bug4816114.java @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* @test + @bug 4816114 + @summary REGRESSION: Regression in divider location behavior when JSplitPane is resized + @author Andrey Pikalev + @run main bug4816114 +*/ + +import javax.swing.*; +import java.awt.*; +import java.lang.reflect.*; +import sun.awt.SunToolkit; + + +public class bug4816114 { + + JFrame fr; + JSplitPane splitPane; + + boolean[] resized = new boolean[] { false, false, false, + false, false, false }; + static int step = 0; + boolean h_passed = false; + boolean v_passed = false; + + static bug4816114 test = new bug4816114(); + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test.createAndShowGUI(); + } + }); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + Thread.sleep(1000); + Thread.sleep(2000); + + step++; + test.doTest(150, 300); + + step++; + test.doTest(650, 300); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test.splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT); + } + }); + + step++; + test.doTest(300, 650); + + step++; + test.doTest(300, 150); + + step++; + test.doTest(300, 650); + + if ( !test.isPassed() ) { + throw new Error("The divider location is wrong."); + } + } + public void createAndShowGUI() { + fr = new JFrame("Test"); + + splitPane = new TestSplitPane(); + splitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT); + splitPane.setResizeWeight(0); + splitPane.setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1)); + + JButton leftButton = new JButton("LEFT"); + leftButton.setPreferredSize(new Dimension(300, 300)); + leftButton.setMinimumSize(new Dimension(150, 150)); + splitPane.setLeftComponent(leftButton); + + JButton rightButton = new JButton("RIGHT"); + rightButton.setPreferredSize(new Dimension(300, 300)); + rightButton.setMinimumSize(new Dimension(150, 150)); + splitPane.setRightComponent(rightButton); + + fr.getContentPane().add(splitPane, BorderLayout.CENTER); + + fr.pack(); + fr.setVisible(true); + } + + void doTest(final int width, final int height) throws InterruptedException, InvocationTargetException { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + splitPane.setPreferredSize(new Dimension(width, height)); + fr.pack(); + } + }); + + synchronized (bug4816114.this) { + while (!resized[step]) { + bug4816114.this.wait(); + } + } + } + + synchronized void setPassed(int orientation, boolean passed) { + if (orientation == JSplitPane.HORIZONTAL_SPLIT) { + this.h_passed = passed; + } + else { + this.v_passed = passed; + } + } + + synchronized boolean isPassed() { + return h_passed && v_passed; + } + + + class TestSplitPane extends JSplitPane { + public void setDividerLocation(int location) { + super.setDividerLocation(location); + + if ( splitPane.getDividerLocation() == 151 ) { + setPassed(getOrientation(), true); + } + + synchronized (bug4816114.this) { + resized[step] = true; + bug4816114.this.notifyAll(); + } + } + } +} diff --git a/jdk/test/javax/swing/JTabbedPane/7024235/Test7024235.java b/jdk/test/javax/swing/JTabbedPane/7024235/Test7024235.java new file mode 100644 index 00000000000..228aa008567 --- /dev/null +++ b/jdk/test/javax/swing/JTabbedPane/7024235/Test7024235.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.BorderLayout; +import sun.awt.SunToolkit; + +import java.awt.Container; +import java.awt.Rectangle; +import java.awt.Toolkit; + +import javax.swing.JButton; +import javax.swing.JCheckBox; +import javax.swing.JTabbedPane; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.UIManager.LookAndFeelInfo; + +/* + * @test + * @bug 7024235 + * @summary Tests JFrame.pack() with the JTabbedPane + * @author Sergey Malenkov + */ + +public class Test7024235 implements Runnable { + + private static final boolean AUTO = null != System.getProperty("test.src", null); + + public static void main(String[] args) throws Exception { + Test7024235 test = new Test7024235(); + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { + UIManager.setLookAndFeel(info.getClassName()); + + test.test(); + toolkit.realSync(); + Thread.sleep(1000); + test.test(); + } + } + + private volatile JTabbedPane pane; + private volatile boolean passed; + + public void run() { + if (this.pane == null) { + this.pane = new JTabbedPane(); + this.pane.addTab("1", new Container()); + this.pane.addTab("2", new JButton()); + this.pane.addTab("3", new JCheckBox()); + + JFrame frame = new JFrame(); + frame.add(BorderLayout.WEST, this.pane); + frame.pack(); + frame.setVisible(true); + + test("first"); + } + else { + test("second"); + if (this.passed || AUTO) { // do not close a frame for manual review + SwingUtilities.getWindowAncestor(this.pane).dispose(); + } + this.pane = null; + } + } + + private void test() throws Exception { + SwingUtilities.invokeAndWait(this); + if (!this.passed && AUTO) { // error reporting only for automatic testing + throw new Error("TEST FAILED"); + } + } + + private void test(String step) { + this.passed = true; + for (int index = 0; index < this.pane.getTabCount(); index++) { + Rectangle bounds = this.pane.getBoundsAt(index); + int centerX = bounds.x + bounds.width / 2; + int centerY = bounds.y + bounds.height / 2; + int actual = this.pane.indexAtLocation(centerX, centerY); + if (index != actual) { + System.out.println("name = " + UIManager.getLookAndFeel().getName()); + System.out.println("step = " + step); + System.out.println("index = " + index); + System.out.println("bounds = " + bounds); + System.out.println("indexAtLocation(" + centerX + "," + centerX + ") returns " + actual); + this.passed = false; + } + } + } +} diff --git a/jdk/test/javax/swing/JTable/7068740/bug7068740.java b/jdk/test/javax/swing/JTable/7068740/bug7068740.java index 7073779f6e6..4dac9cd288c 100644 --- a/jdk/test/javax/swing/JTable/7068740/bug7068740.java +++ b/jdk/test/javax/swing/JTable/7068740/bug7068740.java @@ -37,6 +37,7 @@ import javax.swing.table.DefaultTableModel; import java.awt.*; import java.awt.event.KeyEvent; import java.lang.reflect.InvocationTargetException; +import java.util.concurrent.atomic.AtomicInteger; public class bug7068740 extends JFrame { @@ -66,6 +67,7 @@ public class bug7068740 extends JFrame { }; table = new JTable(model); + table.setRowSelectionInterval(0, 0); LayerUI layerUI = new LayerUI<>(); JLayer layer = new JLayer<>(table, layerUI); JScrollPane scrollPane = new JScrollPane(layer); @@ -78,7 +80,7 @@ public class bug7068740 extends JFrame { try { if (robot == null) { robot = new Robot(); - robot.setAutoDelay(20); + robot.setAutoDelay(50); } if (toolkit == null) { @@ -104,24 +106,37 @@ public class bug7068740 extends JFrame { } } - private static void doTest() { + private static int getSelectedRow() throws Exception { + final AtomicInteger row = new AtomicInteger(-1); + SwingUtilities.invokeAndWait(new Runnable() { + @Override + public void run() { + row.set(table.getSelectedRow()); + } + }); + return row.intValue(); + } + + private static void doTest() throws Exception { toolkit.realSync(); - table.setRowSelectionInterval(0, 0); robot.keyPress(KeyEvent.VK_PAGE_DOWN); + robot.keyRelease(KeyEvent.VK_PAGE_DOWN); toolkit.realSync(); - if (table.getSelectedRow() != 19) { + + if (getSelectedRow() != 19) { throw new RuntimeException("Test failed"); } robot.keyPress(KeyEvent.VK_PAGE_UP); + robot.keyRelease(KeyEvent.VK_PAGE_UP); toolkit.realSync(); - if (table.getSelectedRow() != 0) { + if (getSelectedRow() != 0) { throw new RuntimeException("Test failed"); } } - public static void main(String[] args) { + public static void main(String[] args) throws Exception { try { UIManager.setLookAndFeel(new MetalLookAndFeel()); setUp(); diff --git a/jdk/test/javax/swing/JTree/4927934/bug4927934.java b/jdk/test/javax/swing/JTree/4927934/bug4927934.java new file mode 100644 index 00000000000..b242e57ce46 --- /dev/null +++ b/jdk/test/javax/swing/JTree/4927934/bug4927934.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +/* @test + @bug 4927934 + @summary JTree traversal is unlike Native windows tree traversal + @author Andrey Pikalev + @run main bug4927934 +*/ + +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.tree.*; +import java.awt.*; +import java.awt.event.*; +import java.lang.reflect.InvocationTargetException; +import sun.awt.*; + +public class bug4927934 implements TreeSelectionListener, TreeExpansionListener, FocusListener { + + final static Object listener = new bug4927934(); + + static boolean focusGained = false; + public static boolean selectionChanged = false; + public static boolean treeExpanded = false; + public static boolean treeCollapsed = false; + + static JFrame frame; + static JTree tree; + static Robot robot; + + public static void main(String args[]) throws Exception { + UIManager.setLookAndFeel(new javax.swing.plaf.metal.MetalLookAndFeel()); + + robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + frame = new JFrame(); + + DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); + createNodes(root); + tree = new JTree(root); + JScrollPane scrollPane = new JScrollPane(tree); + frame.getContentPane().add(scrollPane); + + tree.addFocusListener((FocusListener)listener); + tree.addTreeSelectionListener((TreeSelectionListener)listener); + tree.addTreeExpansionListener((TreeExpansionListener)listener); + + frame.setSize(300, 300); + frame.setVisible(true); + } + }); + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + toolkit.realSync(); + Thread.sleep(1000); + + SwingUtilities.invokeLater(new Runnable() { + public void run() { + tree.requestFocus(); + } + }); + + synchronized(listener) { + if (!focusGained) { + System.out.println("waiting focusGained..."); + try { + listener.wait(10000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + // GO TO RIGHT + selectionChanged = false; + hitKey(KeyEvent.VK_RIGHT); + toolkit.realSync(); + if (!checkSelectionChanged(tree, 0)) { + throw new RuntimeException("Root should be selected"); + } + + selectionChanged = false; + hitKey(KeyEvent.VK_RIGHT); + toolkit.realSync(); + if (!checkSelectionChanged(tree, 1)) { + throw new RuntimeException("Node should be selected"); + } + + treeExpanded = false; + hitKey(KeyEvent.VK_RIGHT); + toolkit.realSync(); + if (!isTreeExpanded()) { + throw new RuntimeException("Node should be expanded"); + } + + selectionChanged = false; + hitKey(KeyEvent.VK_RIGHT); + toolkit.realSync(); + if (!checkSelectionChanged(tree, 2)) { + throw new RuntimeException("Leaf1 should be selected"); + } + + selectionChanged = false; + hitKey(KeyEvent.VK_RIGHT); + toolkit.realSync(); + if (!checkSelectionChanged(tree, 2)) { + throw new RuntimeException("Leaf1 should be selected"); + } + + // GO TO LEFT + selectionChanged = false; + hitKey(KeyEvent.VK_LEFT); + toolkit.realSync(); + if (!checkSelectionChanged(tree, 1)) { + throw new RuntimeException("Node should be selected"); + } + + treeCollapsed = false; + hitKey(KeyEvent.VK_LEFT); + if (!isTreeCollapsed()) { + throw new RuntimeException("Node should be collapsed"); + } + + selectionChanged = false; + hitKey(KeyEvent.VK_LEFT); + toolkit.realSync(); + if (!checkSelectionChanged(tree, 0)) { + throw new RuntimeException("Root should be selected"); + } + + treeCollapsed = false; + hitKey(KeyEvent.VK_LEFT); + toolkit.realSync(); + if (!isTreeCollapsed()) { + throw new RuntimeException("Root should be collapsed"); + } + } + + + synchronized public void focusLost(FocusEvent e) { + } + + synchronized public void focusGained(FocusEvent e) { + focusGained = true; + System.out.println("focusGained"); + listener.notifyAll(); + } + + private static void createNodes(DefaultMutableTreeNode root) { + DefaultMutableTreeNode node = new DefaultMutableTreeNode("Node"); + node.add(new DefaultMutableTreeNode("Leaf1")); + node.add(new DefaultMutableTreeNode("Leaf2")); + root.add(node); + root.add(new DefaultMutableTreeNode("Leaf3")); + } + + synchronized public void valueChanged(TreeSelectionEvent e) { + selectionChanged = true; + System.out.println("selectionChanged"); + notifyAll(); + } + + synchronized public void treeCollapsed(TreeExpansionEvent e) { + System.out.println("treeCollapsed"); + treeCollapsed = true; + notifyAll(); + } + + synchronized public void treeExpanded(TreeExpansionEvent e) { + System.out.println("treeExpanded"); + treeExpanded = true; + notifyAll(); + } + + private static void hitKey(int key) { + System.out.println("key " + key + " pressed"); + robot.keyPress(key); + robot.keyRelease(key); + } + + private static boolean checkSelectionChanged(JTree tree, int shouldBeSel) { + synchronized(listener) { + if (!selectionChanged) { + System.out.println("waiting for selectionChanged..."); + try { + listener.wait(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + int selRow = tree.getLeadSelectionRow(); + System.out.println("Selected row: " + selRow); + return selRow == shouldBeSel; + } + + private static boolean isTreeExpanded() { + synchronized(listener) { + if (!treeExpanded) { + System.out.println("waiting for treeExpanded..."); + try { + listener.wait(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + return treeExpanded; + } + + private static boolean isTreeCollapsed() { + synchronized(listener) { + if (!treeCollapsed) { + System.out.println("waiting for treeCollapsed..."); + try { + listener.wait(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + return treeCollapsed; + } +} diff --git a/jdk/test/javax/swing/JTree/8013571/Test8013571.java b/jdk/test/javax/swing/JTree/8013571/Test8013571.java index 15ad391dcf2..7ad92cdb3e3 100644 --- a/jdk/test/javax/swing/JTree/8013571/Test8013571.java +++ b/jdk/test/javax/swing/JTree/8013571/Test8013571.java @@ -27,8 +27,8 @@ import javax.swing.tree.DefaultTreeModel; /* * @test - * @bug 8016545 - * @summary Tests beans with public fields + * @bug 8013571 + * @summary Tests null as a root of TreeModelEvent * @author Sergey Malenkov */ diff --git a/jdk/test/javax/swing/Popup/TaskbarPositionTest.java b/jdk/test/javax/swing/Popup/TaskbarPositionTest.java new file mode 100644 index 00000000000..b4f8989c9db --- /dev/null +++ b/jdk/test/javax/swing/Popup/TaskbarPositionTest.java @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.awt.*; +import java.awt.event.*; +import javax.swing.*; +import javax.swing.event.*; + +/** + * @test @bug 4245587 4474813 4425878 4767478 8015599 + * @author Mark Davidson + * @summary Tests the location of the heavy weight popup portion of JComboBox, + * JMenu and JPopupMenu. + * @library ../regtesthelpers + * @build Util + * @run main TaskbarPositionTest + */ +public class TaskbarPositionTest extends JFrame implements ActionListener { + + private boolean done; + private Throwable error; + private static TaskbarPositionTest test; + private static JPopupMenu popupMenu; + private static JPanel panel; + private static JComboBox combo1; + private static JComboBox combo2; + private static JMenuBar menubar; + private static JMenu menu1; + private static JMenu menu2; + private static Rectangle fullScreenBounds; + // The usable desktop space: screen size - screen insets. + private static Rectangle screenBounds; + private static String[] numData = { + "One", "Two", "Three", "Four", "Five", "Six", "Seven" + }; + private static String[] dayData = { + "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" + }; + private static char[] mnDayData = { + 'M', 'T', 'W', 'R', 'F', 'S', 'U' + }; + + public TaskbarPositionTest() { + super("Use CTRL-down to show a JPopupMenu"); + setContentPane(panel = createContentPane()); + setJMenuBar(createMenuBar("1 - First Menu", true)); + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + + // CTRL-down will show the popup. + panel.getInputMap().put(KeyStroke.getKeyStroke( + KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); + panel.getActionMap().put("OPEN_POPUP", new PopupHandler()); + + pack(); + + Toolkit toolkit = Toolkit.getDefaultToolkit(); + fullScreenBounds = new Rectangle(new Point(), toolkit.getScreenSize()); + screenBounds = new Rectangle(new Point(), toolkit.getScreenSize()); + + // Place the frame near the bottom. This is a pretty wild guess. + this.setLocation(0, (int) screenBounds.getHeight() - 2 * this.getHeight()); + + // Reduce the screen bounds by the insets. + GraphicsConfiguration gc = this.getGraphicsConfiguration(); + if (gc != null) { + Insets screenInsets = toolkit.getScreenInsets(gc); + screenBounds = gc.getBounds(); + screenBounds.width -= (screenInsets.left + screenInsets.right); + screenBounds.height -= (screenInsets.top + screenInsets.bottom); + screenBounds.x += screenInsets.left; + screenBounds.y += screenInsets.top; + } + + setVisible(true); + } + + public static class ComboPopupCheckListener implements PopupMenuListener { + + public void popupMenuCanceled(PopupMenuEvent ev) { + } + + public void popupMenuWillBecomeVisible(PopupMenuEvent ev) { + } + + public void popupMenuWillBecomeInvisible(PopupMenuEvent ev) { + Point cpos = combo1.getLocation(); + SwingUtilities.convertPointToScreen(cpos, panel); + + JPopupMenu pm = (JPopupMenu) combo1.getUI().getAccessibleChild(combo1, 0); + + if (pm != null) { + Point p = pm.getLocation(); + SwingUtilities.convertPointToScreen(p, pm); + if (p.y < cpos.y) { + throw new RuntimeException("ComboBox popup is wrongly aligned"); + } // check that popup was opened down + } + } + } + + private class PopupHandler extends AbstractAction { + + public void actionPerformed(ActionEvent e) { + if (!popupMenu.isVisible()) { + popupMenu.show((Component) e.getSource(), 40, 40); + } + isPopupOnScreen(popupMenu, fullScreenBounds); + } + } + + class PopupListener extends MouseAdapter { + + private JPopupMenu popup; + + public PopupListener(JPopupMenu popup) { + this.popup = popup; + } + + public void mousePressed(MouseEvent e) { + maybeShowPopup(e); + } + + public void mouseReleased(MouseEvent e) { + maybeShowPopup(e); + } + + private void maybeShowPopup(MouseEvent e) { + if (e.isPopupTrigger()) { + popup.show(e.getComponent(), e.getX(), e.getY()); + isPopupOnScreen(popup, fullScreenBounds); + } + } + } + + /** + * Tests if the popup is on the screen. + */ + public static void isPopupOnScreen(JPopupMenu popup, Rectangle checkBounds) { + Dimension dim = popup.getSize(); + Point pt = new Point(); + SwingUtilities.convertPointToScreen(pt, popup); + Rectangle bounds = new Rectangle(pt, dim); + + if (!SwingUtilities.isRectangleContainingRectangle(checkBounds, bounds)) { + throw new RuntimeException("We do not match! " + checkBounds + " / " + bounds); + } + + } + + private JPanel createContentPane() { + JPanel panel = new JPanel(); + + combo1 = new JComboBox<>(numData); + panel.add(combo1); + combo2 = new JComboBox<>(dayData); + combo2.setEditable(true); + panel.add(combo2); + panel.setSize(300, 200); + + popupMenu = new JPopupMenu(); + JMenuItem item; + for (int i = 0; i < dayData.length; i++) { + item = popupMenu.add(new JMenuItem(dayData[i], mnDayData[i])); + item.addActionListener(this); + } + panel.addMouseListener(new PopupListener(popupMenu)); + + JTextField field = new JTextField("CTRL+down for Popup"); + // CTRL-down will show the popup. + field.getInputMap().put(KeyStroke.getKeyStroke( + KeyEvent.VK_DOWN, InputEvent.CTRL_MASK), "OPEN_POPUP"); + field.getActionMap().put("OPEN_POPUP", new PopupHandler()); + + panel.add(field); + + return panel; + } + + /** + * @param str name of Menu + * @param bFlag set mnemonics on menu items + */ + private JMenuBar createMenuBar(String str, boolean bFlag) { + menubar = new JMenuBar(); + + menu1 = new JMenu(str); + menu1.setMnemonic(str.charAt(0)); + menu1.addActionListener(this); + + menubar.add(menu1); + for (int i = 0; i < 8; i++) { + JMenuItem menuitem = new JMenuItem("1 JMenuItem" + i); + menuitem.addActionListener(this); + if (bFlag) { + menuitem.setMnemonic('0' + i); + } + menu1.add(menuitem); + } + + // second menu + menu2 = new JMenu("2 - Second Menu"); + menu2.addActionListener(this); + menu2.setMnemonic('2'); + + menubar.add(menu2); + for (int i = 0; i < 5; i++) { + JMenuItem menuitem = new JMenuItem("2 JMenuItem" + i); + menuitem.addActionListener(this); + + if (bFlag) { + menuitem.setMnemonic('0' + i); + } + menu2.add(menuitem); + } + JMenu submenu = new JMenu("Sub Menu"); + submenu.setMnemonic('S'); + submenu.addActionListener(this); + for (int i = 0; i < 5; i++) { + JMenuItem menuitem = new JMenuItem("S JMenuItem" + i); + menuitem.addActionListener(this); + if (bFlag) { + menuitem.setMnemonic('0' + i); + } + submenu.add(menuitem); + } + menu2.add(new JSeparator()); + menu2.add(submenu); + + return menubar; + } + + public void actionPerformed(ActionEvent evt) { + Object obj = evt.getSource(); + if (obj instanceof JMenuItem) { + // put the focus on the noneditable combo. + combo1.requestFocus(); + } + } + + public static void main(String[] args) throws Throwable { + + sun.awt.SunToolkit toolkit = (sun.awt.SunToolkit) Toolkit.getDefaultToolkit(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test = new TaskbarPositionTest(); + } + }); + + // Use Robot to automate the test + Robot robot; + robot = new Robot(); + robot.setAutoDelay(125); + + // 1 - menu + Util.hitMnemonics(robot, KeyEvent.VK_1); + + toolkit.realSync(); + isPopupOnScreen(menu1.getPopupMenu(), screenBounds); + + // 2 menu with sub menu + robot.keyPress(KeyEvent.VK_RIGHT); + robot.keyRelease(KeyEvent.VK_RIGHT); + Util.hitMnemonics(robot, KeyEvent.VK_S); + + toolkit.realSync(); + isPopupOnScreen(menu2.getPopupMenu(), screenBounds); + + robot.keyPress(KeyEvent.VK_ENTER); + robot.keyRelease(KeyEvent.VK_ENTER); + + // Focus should go to non editable combo box + toolkit.realSync(); + Thread.sleep(500); + + robot.keyPress(KeyEvent.VK_DOWN); + + // How do we check combo boxes? + + // Editable combo box + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + + // combo1.getUI(); + + // Popup from Text field + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_CONTROL); + + // Popup from a mouse click. + Point pt = new Point(2, 2); + SwingUtilities.convertPointToScreen(pt, panel); + robot.mouseMove((int) pt.getX(), (int) pt.getY()); + robot.mousePress(InputEvent.BUTTON3_MASK); + robot.mouseRelease(InputEvent.BUTTON3_MASK); + + toolkit.realSync(); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + test.setLocation(-30, 100); + combo1.addPopupMenuListener(new ComboPopupCheckListener()); + combo1.requestFocus(); + } + }); + + robot.keyPress(KeyEvent.VK_DOWN); + robot.keyRelease(KeyEvent.VK_DOWN); + robot.keyPress(KeyEvent.VK_ESCAPE); + robot.keyRelease(KeyEvent.VK_ESCAPE); + + toolkit.realSync(); + Thread.sleep(500); + } +} diff --git a/jdk/test/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java b/jdk/test/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java new file mode 100644 index 00000000000..a09a3480f6d --- /dev/null +++ b/jdk/test/javax/swing/plaf/basic/BasicMenuUI/4983388/bug4983388.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* @test + @bug 4983388 8015600 + @summary shortcuts on menus do not work on JDS + @author Oleg Mokhovikov + @library ../../../../regtesthelpers + @build Util + @run main bug4983388 +*/ + +import sun.awt.*; +import java.awt.*; +import javax.swing.*; +import javax.swing.event.MenuListener; +import javax.swing.event.MenuEvent; +import java.awt.event.KeyEvent; + +public class bug4983388 { + static volatile boolean bMenuSelected = false; + + private static class TestMenuListener implements MenuListener { + public void menuCanceled(MenuEvent e) {} + public void menuDeselected(MenuEvent e) {} + public void menuSelected(MenuEvent e) { + System.out.println("menuSelected"); + bMenuSelected = true; + } + } + + private static void createAndShowGUI() { + JMenuBar menuBar = new JMenuBar(); + JMenu menu = new JMenu("File"); + menu.setMnemonic('F'); + menuBar.add(menu); + JFrame frame = new JFrame(); + frame.setJMenuBar(menuBar); + frame.pack(); + frame.setVisible(true); + MenuListener listener = new TestMenuListener(); + menu.addMenuListener(listener); + } + + public static void main(String[] args) throws Exception { + + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + try { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.gtk.GTKLookAndFeel"); + } catch (UnsupportedLookAndFeelException | ClassNotFoundException ex) { + System.err.println("GTKLookAndFeel is not supported on this platform. Using defailt LaF for this platform."); + } + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + Robot robot = new Robot(); + Util.hitMnemonics(robot, KeyEvent.VK_F); + + toolkit.realSync(); + + if (!bMenuSelected) { + throw new RuntimeException("shortcuts on menus do not work"); + } + } +} diff --git a/jdk/test/javax/swing/plaf/basic/BasicTabbedPaneUI/Test6943780.java b/jdk/test/javax/swing/plaf/basic/BasicTabbedPaneUI/Test6943780.java new file mode 100644 index 00000000000..d1739a33574 --- /dev/null +++ b/jdk/test/javax/swing/plaf/basic/BasicTabbedPaneUI/Test6943780.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.JButton; +import javax.swing.JTabbedPane; +import java.awt.Component; + +import static javax.swing.SwingUtilities.invokeAndWait; + +/* + * @test + * @bug 4873983 6943780 + * @summary Tests JTabbedPane with SCROLL_TAB_LAYOUT + * @author Sergey Malenkov + */ +public class Test6943780 implements Runnable, Thread.UncaughtExceptionHandler { + public static void main(String[] args) throws Exception { + invokeAndWait(new Test6943780()); + } + + @Override + public void uncaughtException(Thread thread, Throwable throwable) { + throwable.printStackTrace(); + System.exit(1); + } + + @Override + public void run() { + JTabbedPane pane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT); + pane.addTab("first", new JButton("first")); + pane.addTab("second", new JButton("second")); + for (Component component : pane.getComponents()) { + component.setSize(100, 100); + } + } +} diff --git a/jdk/test/javax/swing/plaf/basic/BasicTreeUI/8023474/bug8023474.java b/jdk/test/javax/swing/plaf/basic/BasicTreeUI/8023474/bug8023474.java new file mode 100644 index 00000000000..6802db66945 --- /dev/null +++ b/jdk/test/javax/swing/plaf/basic/BasicTreeUI/8023474/bug8023474.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023474 + * @summary Tests that the first mouse press starts editing in JTree + * @author Dmitry Markov + * @run main bug8023474 + */ + +import sun.awt.SunToolkit; + +import javax.swing.*; +import javax.swing.event.CellEditorListener; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.DefaultTreeModel; +import javax.swing.tree.TreeCellEditor; +import javax.swing.tree.TreeCellRenderer; +import java.awt.*; +import java.awt.event.InputEvent; +import java.util.EventObject; + +public class bug8023474 { + private static JTree tree; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); + Robot robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + + toolkit.realSync(); + + Point point = getRowPointToClick(1); + robot.mouseMove(point.x, point.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + toolkit.realSync(); + + Boolean result = (Boolean)tree.getCellEditor().getCellEditorValue(); + if (!result) { + throw new RuntimeException("Test Failed!"); + } + } + + private static void createAndShowGUI() { + try { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + } catch (Exception e) { + throw new RuntimeException(e); + } + + DefaultMutableTreeNode root = new DefaultMutableTreeNode("root"); + DefaultMutableTreeNode item = new DefaultMutableTreeNode("item"); + DefaultMutableTreeNode subItem = new DefaultMutableTreeNode("subItem"); + + root.add(item); + item.add(subItem); + + DefaultTreeModel model = new DefaultTreeModel(root); + tree = new JTree(model); + + tree.setCellEditor(new Editor()); + tree.setEditable(true); + tree.setRowHeight(30); + tree.setCellRenderer(new CheckboxCellRenderer()); + + JFrame frame = new JFrame("bug8023474"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.add(new JScrollPane(tree)); + frame.setSize(400, 300); + frame.setVisible(true); + } + + private static Point getRowPointToClick(final int row) throws Exception { + final Point[] result = new Point[1]; + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + Rectangle rect = tree.getRowBounds(row); + Point point = new Point(rect.x + 10, rect.y + rect.height / 2); + SwingUtilities.convertPointToScreen(point, tree); + result[0] = point; + } + }); + return result[0]; + } + + private static class Editor extends JPanel implements TreeCellEditor { + private JCheckBox checkbox; + + public Editor() { + setOpaque(false); + checkbox = new JCheckBox(); + add(checkbox); + } + + public Component getTreeCellEditorComponent(JTree tree, Object value, boolean isSelected, + boolean expanded, boolean leaf, int row) { + checkbox.setText(value.toString()); + checkbox.setSelected(false); + return this; + } + + public Object getCellEditorValue() { + return checkbox.isSelected(); + } + + public boolean isCellEditable(EventObject anEvent) { + return true; + } + + public boolean shouldSelectCell(EventObject anEvent) { + return true; + } + + public boolean stopCellEditing() { + return true; + } + + public void cancelCellEditing() { + } + + public void addCellEditorListener(CellEditorListener l) { + } + + public void removeCellEditorListener(CellEditorListener l) { + } + } + + private static class CheckboxCellRenderer extends JPanel implements TreeCellRenderer { + private JCheckBox checkbox; + + public CheckboxCellRenderer() { + setOpaque(false); + checkbox = new JCheckBox(); + add(checkbox); + } + + public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, + boolean leaf, int row, boolean hasFocus) { + checkbox.setText(value.toString()); + checkbox.setSelected(false); + return this; + } + } +} diff --git a/jdk/test/javax/swing/text/AbstractDocument/6968363/Test6968363.java b/jdk/test/javax/swing/text/AbstractDocument/6968363/Test6968363.java new file mode 100644 index 00000000000..624a2522356 --- /dev/null +++ b/jdk/test/javax/swing/text/AbstractDocument/6968363/Test6968363.java @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import sun.awt.SunToolkit; + +import java.awt.Robot; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JTextField; +import javax.swing.event.DocumentListener; +import javax.swing.event.UndoableEditListener; +import javax.swing.text.AttributeSet; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; +import javax.swing.text.PlainDocument; +import javax.swing.text.Position; +import javax.swing.text.Segment; + +import static java.awt.BorderLayout.NORTH; +import static java.awt.BorderLayout.SOUTH; +import static java.awt.Toolkit.getDefaultToolkit; +import static java.awt.event.KeyEvent.VK_LEFT; +import static javax.swing.SwingUtilities.invokeAndWait; + +/* + * @test + * @bug 6968363 + * @summary Ensures that a custom document may not extend AbstractDocument + * @author Sergey Malenkov + */ +public class Test6968363 implements Runnable, Thread.UncaughtExceptionHandler { + private JFrame frame; + + public static void main(String[] args) throws Exception { + SunToolkit toolkit = (SunToolkit) getDefaultToolkit(); + Runnable task = new Test6968363(); + invokeAndWait(task); + toolkit.realSync(100); + new Robot().keyPress(VK_LEFT); + toolkit.realSync(100); + invokeAndWait(task); + } + + @Override + public void uncaughtException(Thread thread, Throwable throwable) { + throwable.printStackTrace(); + System.exit(1); + } + + @Override + public void run() { + if (this.frame == null) { + Thread.setDefaultUncaughtExceptionHandler(this); + this.frame = new JFrame(getClass().getSimpleName()); + this.frame.add(NORTH, new JLabel("Copy Paste a HINDI text into the field below")); + this.frame.add(SOUTH, new JTextField(new MyDocument(), "\u0938", 10)); + this.frame.pack(); + this.frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + this.frame.setLocationRelativeTo(null); + this.frame.setVisible(true); + } else { + this.frame.dispose(); + this.frame = null; + } + } + + private static class MyDocument implements Document { + private final Document document = new PlainDocument(); + + @Override + public int getLength() { + return this.document.getLength(); + } + + @Override + public void addDocumentListener(DocumentListener listener) { + this.document.addDocumentListener(listener); + } + + @Override + public void removeDocumentListener(DocumentListener listener) { + this.document.removeDocumentListener(listener); + } + + @Override + public void addUndoableEditListener(UndoableEditListener listener) { + this.document.addUndoableEditListener(listener); + } + + @Override + public void removeUndoableEditListener(UndoableEditListener listener) { + this.document.removeUndoableEditListener(listener); + } + + @Override + public Object getProperty(Object key) { + return this.document.getProperty(key); + } + + @Override + public void putProperty(Object key, Object value) { + this.document.putProperty(key, value); + } + + @Override + public void remove(int offset, int length) throws BadLocationException { + this.document.remove(offset, length); + } + + @Override + public void insertString(int offset, String string, AttributeSet set) throws BadLocationException { + for (int i = 0; i < string.length(); i++) { + System.out.println("i: " + i + "; ch: " + Integer.toHexString(string.charAt(i))); + } + this.document.insertString(offset, string, set); + } + + @Override + public String getText(int offset, int length) throws BadLocationException { + return this.document.getText(offset, length); + } + + @Override + public void getText(int offset, int length, Segment segment) throws BadLocationException { + this.document.getText(offset, length, segment); + } + + @Override + public Position getStartPosition() { + return this.document.getStartPosition(); + } + + @Override + public Position getEndPosition() { + return this.document.getEndPosition(); + } + + @Override + public Position createPosition(int offset) throws BadLocationException { + return this.document.createPosition(offset); + } + + @Override + public Element[] getRootElements() { + Element[] elements = this.document.getRootElements(); + Element[] wrappers = new Element[elements.length]; + for (int i = 0; i < elements.length; i++) { + wrappers[i] = new MyElement(elements[i]); + } + return wrappers; + } + + @Override + public Element getDefaultRootElement() { + return new MyElement(this.document.getDefaultRootElement()); + } + + @Override + public void render(Runnable task) { + this.document.render(task); + } + + private class MyElement implements Element { + private final Element element; + + private MyElement(Element element) { + this.element = element; + } + + @Override + public Document getDocument() { + return MyDocument.this; + } + + @Override + public Element getParentElement() { + return new MyElement(this.element.getParentElement()); + } + + @Override + public String getName() { + return this.element.getName(); + } + + @Override + public AttributeSet getAttributes() { + return this.element.getAttributes(); + } + + @Override + public int getStartOffset() { + return this.element.getStartOffset(); + } + + @Override + public int getEndOffset() { + return this.element.getEndOffset(); + } + + @Override + public int getElementIndex(int offset) { + return this.element.getElementIndex(offset); + } + + @Override + public int getElementCount() { + return this.element.getElementCount(); + } + + @Override + public Element getElement(int index) { + return new MyElement(this.element.getElement(index)); + } + + @Override + public boolean isLeaf() { + return this.element.isLeaf(); + } + } + } +} diff --git a/jdk/test/javax/swing/text/DefaultCaret/7083457/bug7083457.java b/jdk/test/javax/swing/text/DefaultCaret/7083457/bug7083457.java new file mode 100644 index 00000000000..7176ade9e67 --- /dev/null +++ b/jdk/test/javax/swing/text/DefaultCaret/7083457/bug7083457.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import javax.swing.text.DefaultCaret; + +/** + * @test + * @bug 7083457 + * @author Alexander Scherbatiy + * @summary Incomplete specification for javax/swing/text/DefaultCaret.html#setVisible(boolean) + * @run main bug7083457 + */ +public class bug7083457 { + + public static void main(String[] args) { + DefaultCaret caret = new DefaultCaret(); + + for (int i = 0; i < 10; i++) { + boolean active = (i % 2 == 0); + caret.setVisible(active); + if (caret.isActive() != active) { + throw new RuntimeException("caret.isActive() does not equal: " + active); + } + } + } +} diff --git a/jdk/test/javax/swing/text/View/8014863/bug8014863.java b/jdk/test/javax/swing/text/View/8014863/bug8014863.java index ba78b4bbbbb..8618ec4eba7 100644 --- a/jdk/test/javax/swing/text/View/8014863/bug8014863.java +++ b/jdk/test/javax/swing/text/View/8014863/bug8014863.java @@ -24,6 +24,7 @@ /* * @test * @bug 8014863 + * @bug 8024395 * @summary Tests the calculation of the line breaks when a text is inserted * @author Dmitry Markov * @library ../../../regtesthelpers @@ -34,91 +35,107 @@ import sun.awt.SunToolkit; import javax.swing.*; +import javax.swing.text.GlyphView; +import javax.swing.text.View; import javax.swing.text.html.HTMLEditorKit; import java.awt.*; import java.awt.event.KeyEvent; +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; public class bug8014863 { private static JEditorPane editorPane; + private static JFrame frame; private static Robot robot; private static SunToolkit toolkit; + private static String text1 = "

        one two qqqq this is a test sentence qqqq pp qqqq pp " + + "qqqq pp qqqq pp qqqq pp qqqq pp qqqq pp qqqq pp qqqq

        "; + private static String text2 = "

        qqqq this is a test sentence qqqq pp qqqq pp " + + "qqqq pp qqqq pp qqqq pp qqqq pp qqqq pp qqqq pp qqqq

        "; + + private static ArrayList glyphViews; + public static void main(String[] args) throws Exception { toolkit = (SunToolkit) Toolkit.getDefaultToolkit(); robot = new Robot(); + robot.setAutoDelay(50); + glyphViews = new ArrayList(); - createAndShowGUI(); + createAndShowGUI(text1); + + toolkit.realSync(); + + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + retrieveGlyphViews(editorPane.getUI().getRootView(editorPane)); + } + }); + GlyphView [] arr1 = glyphViews.toArray(new GlyphView[glyphViews.size()]); + + frame.dispose(); + glyphViews.clear(); + + createAndShowGUI(text2); toolkit.realSync(); Util.hitKeys(robot, KeyEvent.VK_HOME); + toolkit.realSync(); + Util.hitKeys(robot, KeyEvent.VK_O); - - toolkit.realSync(); - - if (3 != getNumberOfTextLines()) { - throw new RuntimeException("The number of texts lines does not meet the expectation"); - } - Util.hitKeys(robot, KeyEvent.VK_N); - - toolkit.realSync(); - - if (3 != getNumberOfTextLines()) { - throw new RuntimeException("The number of texts lines does not meet the expectation"); - } - Util.hitKeys(robot, KeyEvent.VK_E); Util.hitKeys(robot, KeyEvent.VK_SPACE); Util.hitKeys(robot, KeyEvent.VK_T); Util.hitKeys(robot, KeyEvent.VK_W); + Util.hitKeys(robot, KeyEvent.VK_O); + Util.hitKeys(robot, KeyEvent.VK_SPACE); toolkit.realSync(); - if (3 != getNumberOfTextLines()) { - throw new RuntimeException("The number of texts lines does not meet the expectation"); + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + retrieveGlyphViews(editorPane.getUI().getRootView(editorPane)); + } + }); + GlyphView [] arr2 = glyphViews.toArray(new GlyphView[glyphViews.size()]); + + if (arr1.length != arr2.length) { + throw new RuntimeException("Test Failed!"); + } + + for (int i=0; iqqqq pp qqqq pp " + - "qqqq pp qqqq pp qqqq pp qqqq pp" + - " qqqq pp qqqq pp qqqq pp qqqq

        "); + editorPane.setText(text); editorPane.setCaretPosition(1); - // An actual font size depends on OS and might be differnet on various OSs. - // It is necessary to calculate the width to meet the expected number of lines. - int width = SwingUtilities.computeStringWidth(editorPane.getFontMetrics(editorPane.getFont()), - "qqqq pp qqqq pp qqqq pp qqqqqqqq"); + frame.add(editorPane); - frame.setSize(width, 200); + frame.setSize(200, 200); frame.setVisible(true); } }); diff --git a/jdk/test/jdk/lambda/MethodReferenceTestCallerSensitive.java b/jdk/test/jdk/lambda/MethodReferenceTestCallerSensitive.java new file mode 100644 index 00000000000..805a6a203cb --- /dev/null +++ b/jdk/test/jdk/lambda/MethodReferenceTestCallerSensitive.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import org.testng.annotations.Test; + +import java.lang.reflect.Field; +import java.util.function.Function; + + +/** + * @author Robert Field + */ + +@Test +public class MethodReferenceTestCallerSensitive { + + private static void getF(T arg) { + Function,Field[]> firstFunction = Class::getFields; + } + + public void testConstructorReferenceVarArgs() { + getF("Hello World"); + } + +} diff --git a/jdk/test/lib/security/CheckBlacklistedCerts.java b/jdk/test/lib/security/CheckBlacklistedCerts.java new file mode 100644 index 00000000000..1f162b3e499 --- /dev/null +++ b/jdk/test/lib/security/CheckBlacklistedCerts.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8011402 + * @summary Move blacklisting certificate logic from hard code to data + */ + +import sun.security.util.UntrustedCertificates; + +import java.io.*; +import java.security.KeyStore; +import java.security.cert.*; +import java.util.*; + +public class CheckBlacklistedCerts { + public static void main(String[] args) throws Exception { + + String home = System.getProperty("java.home"); + boolean failed = false; + + // Root CAs should always be trusted + File file = new File(home, "lib/security/cacerts"); + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + try (FileInputStream fis = new FileInputStream(file)) { + ks.load(new FileInputStream(file), null); + } + System.out.println("Check for cacerts: " + ks.size()); + for (String alias: Collections.list(ks.aliases())) { + X509Certificate cert = (X509Certificate)ks.getCertificate(alias); + if (UntrustedCertificates.isUntrusted(cert)) { + System.out.print(alias + " is untrusted"); + failed = true; + } + } + + // All certs in the pem files + Set blacklisted = new HashSet<>(); + + // Hopefully src comes with test, but it might be missing if doing + // a -testonly JPRT job. + File[] blacklists = { + new File(System.getProperty("test.src"), + "../../../src/share/lib/security/blacklisted.certs.pem"), + new File(System.getProperty("test.src"), + "../../../src/closed/share/lib/security/blacklisted.certs.pem") + }; + + // Is this an OPENJDK build? + if (!new File(home, "lib/security/local_policy.jar").exists()) { + blacklists = Arrays.copyOf(blacklists, 1); + } + + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + for (File blacklist: blacklists) { + System.out.print("Check for " + blacklist + ": "); + if (!blacklist.exists()) { + System.out.println("does not exist"); + } else { + try (FileInputStream fis = new FileInputStream(blacklist)) { + Collection certs + = cf.generateCertificates(fis); + System.out.println(certs.size()); + for (Certificate c: certs) { + blacklisted.add(c); + X509Certificate cert = ((X509Certificate)c); + if (!UntrustedCertificates.isUntrusted(cert)) { + System.out.println(cert.getSubjectDN() + " is trusted"); + failed = true; + } + } + } + } + } + + // Check the blacklisted.certs file itself + file = new File(home, "lib/security/blacklisted.certs"); + System.out.print("Check for " + file + ": "); + try (BufferedReader reader = new BufferedReader( + new InputStreamReader(new FileInputStream(file)))) { + int acount = 0; + int ccount = 0; + while (true) { + String line = reader.readLine(); + if (line == null) break; + if (line.startsWith("Algorithm")) { + acount++; + } else if (!line.isEmpty() && !line.startsWith("#")) { + ccount++; + } + } + System.out.println(acount + " algs, " + ccount + " certs" ); + if (acount != 1) { + System.out.println("There are " + acount + " algorithms"); + failed = true; + } + if (ccount != blacklisted.size() + && !blacklisted.isEmpty()) { + System.out.println("Wrong blacklisted.certs size: " + + ccount + " fingerprints, " + + blacklisted.size() + " certs"); + failed = true; + } + } + + if (failed) { + throw new Exception("Failed"); + } + } +} diff --git a/jdk/test/sun/java2d/cmm/ProfileOp/DisposalCrashTest.java b/jdk/test/sun/java2d/cmm/ProfileOp/DisposalCrashTest.java new file mode 100644 index 00000000000..ab8527d76da --- /dev/null +++ b/jdk/test/sun/java2d/cmm/ProfileOp/DisposalCrashTest.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8024511 + * @summary Verifies that instances of color profiles are destroyed correctly. + * A crash during profile destruction indicates failure. + * + * @run main DisposalCrashTest + */ + +import static java.awt.color.ColorSpace.*; +import java.awt.color.ICC_Profile; +import java.lang.ref.Reference; +import java.lang.ref.ReferenceQueue; +import java.lang.ref.WeakReference; +import java.util.Vector; + +public class DisposalCrashTest { + + static final ReferenceQueue queue = new ReferenceQueue<>(); + static final Vector> v = new Vector<>(); + + public static void main(String[] args) { + int[] ids = new int[]{ + CS_sRGB, CS_CIEXYZ, CS_GRAY, CS_LINEAR_RGB, CS_PYCC + }; + + for (int id : ids) { + ICC_Profile p = getCopyOf(id); + } + + while (!v.isEmpty()) { + System.gc(); + System.out.println("."); + try { + Thread.sleep(500); + } catch (InterruptedException e) {}; + + final Reference ref = queue.poll(); + System.out.println("Got reference: " + ref); + + v.remove(ref); + } + + System.out.println("Test PASSED."); + } + + private static ICC_Profile getCopyOf(int id) { + ICC_Profile std = ICC_Profile.getInstance(id); + + byte[] data = std.getData(); + + ICC_Profile p = ICC_Profile.getInstance(data); + + WeakReference ref = new WeakReference<>(p, queue); + + v.add(ref); + + return p; + } +} diff --git a/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java b/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java index bc14128fcee..f3fa0791d46 100644 --- a/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java +++ b/jdk/test/sun/java2d/cmm/ProfileOp/ReadWriteProfileTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 6476665 6523403 6733501 7042594 + * @bug 6476665 6523403 6733501 7042594 7043064 * @summary Verifies reading and writing profiles and tags of the standard color * spaces * @run main ReadWriteProfileTest @@ -82,6 +82,7 @@ public class ReadWriteProfileTest implements Runnable { public void run() { for (int i = 0; i < cspaces.length; i++) { + System.out.println("Profile: " + csNames[i]); ICC_Profile pf = ICC_Profile.getInstance(cspaces[i]); byte [] data = pf.getData(); pf = ICC_Profile.getInstance(data); @@ -92,6 +93,10 @@ public class ReadWriteProfileTest implements Runnable { } for (int tagSig : tags[i].keySet()) { + String signature = SigToString(tagSig); + System.out.printf("Tag: %s\n", signature); + System.out.flush(); + byte [] tagData = pf.getData(tagSig); byte [] empty = new byte[tagData.length]; boolean emptyDataRejected = false; @@ -104,15 +109,23 @@ public class ReadWriteProfileTest implements Runnable { throw new RuntimeException("Test failed: empty tag data was not rejected."); } - pf.setData(tagSig, tagData); - + try { + pf.setData(tagSig, tagData); + } catch (IllegalArgumentException e) { + // let's ignore this exception for Kodak proprietary tags + if (isKodakExtention(signature)) { + System.out.println("Ignore Kodak tag: " + signature); + } else { + throw new RuntimeException("Test failed!", e); + } + } byte [] tagData1 = pf.getData(tagSig); if (!Arrays.equals(tagData1, tags[i].get(tagSig))) { System.err.println("Incorrect result of getData(int) with" + " tag " + - Integer.toHexString(tagSig) + + SigToString(tagSig) + " of " + csNames[i] + " profile"); throw new RuntimeException("Incorrect result of " + @@ -122,6 +135,19 @@ public class ReadWriteProfileTest implements Runnable { } } + private static boolean isKodakExtention(String signature) { + return signature.matches("K\\d\\d\\d"); + } + + private static String SigToString(int tagSig ) { + return String.format("%c%c%c%c", + (char)(0xff & (tagSig >> 24)), + (char)(0xff & (tagSig >> 16)), + (char)(0xff & (tagSig >> 8)), + (char)(0xff & (tagSig))); + + } + public static void main(String [] args) { ReadWriteProfileTest test = new ReadWriteProfileTest(); test.run(); diff --git a/jdk/test/sun/security/krb5/ParseCAPaths.java b/jdk/test/sun/security/krb5/ParseCAPaths.java index f8c30bd7b7d..18b43470842 100644 --- a/jdk/test/sun/security/krb5/ParseCAPaths.java +++ b/jdk/test/sun/security/krb5/ParseCAPaths.java @@ -22,7 +22,7 @@ */ /* * @test - * @bug 6789935 + * @bug 6789935 8012615 * @run main/othervm ParseCAPaths * @summary cross-realm capath search error */ @@ -35,37 +35,75 @@ public class ParseCAPaths { public static void main(String[] args) throws Exception { System.setProperty("java.security.krb5.conf", System.getProperty("test.src", ".") +"/krb5-capaths.conf"); - //System.setProperty("sun.security.krb5.debug", "true"); - // Standard example + // MIT check("ANL.GOV", "TEST.ANL.GOV", "ANL.GOV"); check("ANL.GOV", "ES.NET", "ANL.GOV"); check("ANL.GOV", "PNL.GOV", "ANL.GOV", "ES.NET"); check("ANL.GOV", "NERSC.GOV", "ANL.GOV", "ES.NET"); + check("NERSC.GOV", "TEST.ANL.GOV", "NERSC.GOV", "ES.NET", "ANL.GOV"); + + // RedHat + // 3.6.2.1. Configuring a Shared Hierarchy of Names + check("AA.EXAMPLE.COM", "BB.EXAMPLE.COM", + "AA.EXAMPLE.COM", "EXAMPLE.COM"); + check("SITE1.SALES.EXAMPLE.COM", "EVERYWHERE.EXAMPLE.COM", + "SITE1.SALES.EXAMPLE.COM", "SALES.EXAMPLE.COM", + "EXAMPLE.COM"); + check("DEVEL.EXAMPLE.COM", "PROD.EXAMPLE.ORG", + "DEVEL.EXAMPLE.COM", "EXAMPLE.COM", "COM", + "ORG", "EXAMPLE.ORG"); + // 3.6.2.2. Configuring Paths in krb5.conf + check("A.EXAMPLE.COM", "B.EXAMPLE.COM", "A.EXAMPLE.COM"); + check("A.EXAMPLE.COM", "C.EXAMPLE.COM", + "A.EXAMPLE.COM", "B.EXAMPLE.COM"); + check("A.EXAMPLE.COM", "D.EXAMPLE.COM", + "A.EXAMPLE.COM", "B.EXAMPLE.COM", "C.EXAMPLE.COM"); + + // The original JDK example + check("TIVOLI.COM", "IBM.COM", "TIVOLI.COM", "LDAPCENTRAL.NET", + "IBM_LDAPCENTRAL.COM", "MOONLITE.ORG"); + // Hierachical - check("N1.N.COM", "N2.N.COM", "N1.N.COM", "N.COM"); // 2 common - check("N1.N.COM", "N2.N3.COM", "N1.N.COM", "N.COM", // 1 common + check("N1.N.COM", "N2.N.COM", "N1.N.COM", "N.COM"); + check("N1.N.COM", "N2.N3.COM", "N1.N.COM", "N.COM", "COM", "N3.COM"); - check("N1.COM", "N2.COM", "N1.COM", "COM"); // 1 common - check("N1", "N2", "N1"); // 0 common - // Extra garbages - check("A1.COM", "A4.COM", "A1.COM", "A2.COM"); + check("N1.COM", "N2.COM", "N1.COM", "COM"); + check("N1", "N2", "N1"); + check("N1.COM", "N2.ORG", "N1.COM", "COM", "ORG"); + check("N1.N.COM", "N.COM", "N1.N.COM"); + check("X.N1.N.COM", "N.COM", "X.N1.N.COM", "N1.N.COM"); + check("N.COM", "N1.N.COM", "N.COM"); + check("N.COM", "X.N1.N.COM", "N.COM", "N1.N.COM"); + check("A.B.C", "D.E.F", "A.B.C", "B.C", "C", "F", "E.F"); + + // Full path + check("A1.COM", "A2.COM", "A1.COM"); + check("A1.COM", "A3.COM", "A1.COM", "A2.COM"); + check("A1.COM", "A4.COM", "A1.COM", "A2.COM", "A3.COM"); + + // Shortest path + check("B1.COM", "B2.COM", "B1.COM"); check("B1.COM", "B3.COM", "B1.COM", "B2.COM"); + check("B1.COM", "B4.COM", "B1.COM", "B2.COM", "B3.COM"); + // Missing is "." + check("C1.COM", "C2.COM", "C1.COM", "COM"); check("C1.COM", "C3.COM", "C1.COM", "C2.COM"); - // Multiple path - check("D1.COM", "D4.COM", "D1.COM", "D2.COM"); - check("E1.COM", "E4.COM", "E1.COM", "E2.COM"); - check("F1.COM", "F4.COM", "F1.COM", "F9.COM"); - // Infinite loop - check("G1.COM", "G3.COM", "G1.COM", "COM"); - check("H1.COM", "H3.COM", "H1.COM"); + + // cRealm = . + check("D1.COM", "D2.COM", "D1.COM"); + + // Bad cases + check("E1.COM", "E2.COM", "E1.COM"); + check("E1.COM", "E3.COM", "E1.COM", "E4.COM"); + check("G1.COM", "G3.COM", "G1.COM", "G2.COM"); check("I1.COM", "I4.COM", "I1.COM", "I5.COM"); - // J2=J1 is the same as J2=. - check("J1.COM", "J2.COM", "J1.COM"); + // 7019384 check("A9.PRAGUE.XXX.CZ", "SERVIS.XXX.CZ", "A9.PRAGUE.XXX.CZ", "PRAGUE.XXX.CZ", "ROOT.XXX.CZ"); + if (failed != null) { throw failed; } @@ -75,6 +113,7 @@ public class ParseCAPaths { try { check2(from, to, paths); } catch (Exception e) { + System.out.println(" " + e.getMessage()); failed = e; } } @@ -84,18 +123,14 @@ public class ParseCAPaths { System.out.println(from + " -> " + to); System.out.println(" expected: " + Arrays.toString(paths)); String[] result = Realm.getRealmsList(from, to); - System.out.println(" result: " + Arrays.toString(result)); - if (result == null) { - if (paths.length == 0) { - // OK - } else { - throw new Exception("Shouldn't have a valid path."); - } + if (result == null || result.length == 0) { + throw new Exception("There is always a valid path."); } else if(result.length != paths.length) { throw new Exception("Length of path not correct"); } else { for (int i=0; i /dev/null + if [ $? != 0 ]; then + # Fedora has a different path + /usr/kerberos/bin/krb5-config --libs gssapi 2> /dev/null + if [ $? != 0 ]; then + NATIVE=false + fi + fi ;; CYGWIN* ) PATHSEP=";" diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java index c6dd8ce9720..b64d424fe88 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseEngineException.java @@ -21,17 +21,24 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 4969799 * @summary javax.net.ssl.SSLSocket.SSLSocket(InetAddress,int) shouldn't * throw exception - * - * This is making sure that starting a new handshake throws the right - * exception. There is a similar test for SSLSocket. - * + * @run main/othervm CloseEngineException */ +// +// This is making sure that starting a new handshake throws the right +// exception. There is a similar test for SSLSocket. +// + import javax.net.ssl.*; import javax.net.ssl.SSLEngineResult.*; import java.io.*; diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java index 7d9274af36e..1c6103bb353 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseInboundException.java @@ -21,11 +21,17 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 4931274 * @summary closeInbound does not signal when a close_notify has not * been received. + * @run main/othervm CloseInboundException * @author Brad Wetmore */ diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java index 57224816b71..3c3e2e22b3d 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/CloseStart.java @@ -21,15 +21,22 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 5019096 * @summary Add scatter/gather APIs for SSLEngine - * - * Check to see if the args are being parsed properly. - * + * @run main/othervm CloseStart */ +// +// Check to see if the args are being parsed properly. +// + import javax.net.ssl.*; import javax.net.ssl.SSLEngineResult.*; import java.io.*; diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java index f9548d60be5..e912ff69b95 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/DelegatedTaskWrongException.java @@ -21,11 +21,16 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 4969459 * @summary Delegated tasks are not reflecting the subclasses of SSLException - * + * @run main/othervm DelegatedTaskWrongException */ import javax.net.ssl.*; diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java index f77938869f3..49387e3589b 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EmptyExtensionData.java @@ -21,10 +21,16 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 6728126 * @summary Parsing Extensions in Client Hello message is done in a wrong way + * @run main/othervm EmptyExtensionData */ import javax.net.ssl.*; diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java index ed1f84caeef..b7a1a9c509a 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/EngineEnforceUseClientMode.java @@ -21,11 +21,16 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 4980882 * @summary SSLEngine should enforce setUseClientMode - * + * @run main/othervm EngineEnforceUseClientMode * @author Brad R. Wetmore */ diff --git a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java index da8e591d922..fbe2f2e7854 100644 --- a/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java +++ b/jdk/test/sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLEngineImpl/RehandshakeFinished.java @@ -21,16 +21,21 @@ * questions. */ +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + /* * @test * @bug 6207322 * @summary SSLEngine is returning a premature FINISHED message when doing - * an abbreviated handshake. + * an abbreviated handshake. * @run main/othervm RehandshakeFinished - * - * SunJSSE does not support dynamic system properties, no way to re-use - * system properties in samevm/agentvm mode. - * + * @author Brad Wetmore + */ + +/* * This test may need some updating if the messages change order. * Currently I'm expecting that there is a simple renegotiation, with * each message being contained in a single SSL packet. @@ -41,8 +46,6 @@ * FINISHED * CCS * FINISHED - * - * @author Brad Wetmore */ /** diff --git a/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java b/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java new file mode 100644 index 00000000000..c25d74c7d2c --- /dev/null +++ b/jdk/test/sun/security/ssl/javax/net/ssl/SSLParameters/UseCipherSuitesOrder.java @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. +// + +/* + * @test + * @bug 7188657 + * @summary There should be a way to reorder the JSSE ciphers + * @run main/othervm UseCipherSuitesOrder + * TLS_RSA_WITH_AES_128_CBC_SHA,SSL_RSA_WITH_RC4_128_SHA + */ + +import java.io.*; +import java.net.*; +import javax.net.ssl.*; +import java.util.Arrays; + +public class UseCipherSuitesOrder { + + /* + * ============================================================= + * 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 = "../../../../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(); + + // use local cipher suites preference + SSLParameters params = sslServerSocket.getSSLParameters(); + params.setUseCipherSuitesOrder(true); + params.setCipherSuites(srvEnabledCipherSuites); + sslServerSocket.setSSLParameters(params); + + /* + * Signal Client, we're ready for his connect. + */ + serverReady = true; + + SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslIS.read(); + sslOS.write(85); + sslOS.flush(); + + SSLSession session = sslSocket.getSession(); + if (!srvEnabledCipherSuites[0].equals(session.getCipherSuite())) { + throw new Exception( + "Expected to negotiate " + srvEnabledCipherSuites[0] + + " , but not " + session.getCipherSuite()); + } + + sslSocket.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); + sslSocket.setEnabledCipherSuites(cliEnabledCipherSuites); + + InputStream sslIS = sslSocket.getInputStream(); + OutputStream sslOS = sslSocket.getOutputStream(); + + sslOS.write(280); + sslOS.flush(); + sslIS.read(); + + sslSocket.close(); + } + + // client enabled cipher suites + private static String[] cliEnabledCipherSuites; + + // server enabled cipher suites + private static String[] srvEnabledCipherSuites; + + private static void parseArguments(String[] args) throws Exception { + if (args.length != 1) { + System.out.println("Usage: java UseCipherSuitesOrder ciphersuites"); + System.out.println("\tciphersuites: " + + "a list of enabled cipher suites, separated with comma"); + throw new Exception("Incorrect usage"); + } + + cliEnabledCipherSuites = args[0].split(","); + + if (cliEnabledCipherSuites.length < 2) { + throw new Exception("Need to enable at least two cipher suites"); + } + + // Only need to use 2 cipher suites in server side. + srvEnabledCipherSuites = Arrays.copyOf( + cliEnabledCipherSuites, 2); + + // Reverse the cipher suite preference in server side. + srvEnabledCipherSuites[0] = cliEnabledCipherSuites[1]; + srvEnabledCipherSuites[1] = cliEnabledCipherSuites[0]; + } + + /* + * ============================================================= + * 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 { + // parse the arguments + parseArguments(args); + + 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 UseCipherSuitesOrder(); + } + + Thread clientThread = null; + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + UseCipherSuitesOrder() 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() { + 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() { + 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/sun/security/ssl/javax/net/ssl/ServerName/IllegalSNIName.java b/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/IllegalSNIName.java index 4d5460739cd..a6a6912c0aa 100644 --- a/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/IllegalSNIName.java +++ b/jdk/test/sun/security/ssl/javax/net/ssl/ServerName/IllegalSNIName.java @@ -34,7 +34,7 @@ public class IllegalSNIName { public static void main(String[] args) throws Exception { String[] illegalNames = { - "example\u3003\u3002com", + "example\u3002\u3002com", "example..com", "com\u3002", "com.", diff --git a/jdk/test/sun/security/tools/keytool/autotest.sh b/jdk/test/sun/security/tools/keytool/autotest.sh index 9c797dd21e5..1d691076616 100644 --- a/jdk/test/sun/security/tools/keytool/autotest.sh +++ b/jdk/test/sun/security/tools/keytool/autotest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -58,7 +58,7 @@ OS=`uname -s` case "$OS" in SunOS ) FS="/" - LIBNAME="/usr/lib/mps/libsoftokn3.so" + LIBNAME="/usr/lib/mps/`isainfo -n`/libsoftokn3.so" ;; Linux ) FS="/" diff --git a/jdk/test/sun/tools/jconsole/ImmutableResourceTest.java b/jdk/test/sun/tools/jconsole/ImmutableResourceTest.java deleted file mode 100644 index 082776667a4..00000000000 --- a/jdk/test/sun/tools/jconsole/ImmutableResourceTest.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2005, 2007, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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 isn't the test case: ImmutableResourceTest.sh is. - * Refer to ImmutableResourceTest.sh when running this test. - * - * @bug 6287579 - * @summary SubClasses of ListResourceBundle should fix getContents() - */ -import java.util.ResourceBundle; - -public class ImmutableResourceTest { - - public static void main(String[] args) throws Exception { - - /* Reach under the covers and get the message strings */ - sun.tools.jconsole.resources.JConsoleResources jcr = - new sun.tools.jconsole.resources.JConsoleResources (); - Object [][] testData = jcr.getContents(); - - /* Shred our copy of the message strings */ - for (int ii = 0; ii < testData.length; ii++) { - testData[ii][0] = "xxx"; - testData[ii][1] = "yyy"; - } - - /* - * Try a lookup for the shredded key. - * If this is successful we have a problem. - */ - String ss = sun.tools.jconsole.Resources.getText("xxx"); - if ("yyy".equals(ss)) { - throw new Exception ("SubClasses of ListResourceBundle should fix getContents()"); - } - System.out.println("...Finished."); - } -} diff --git a/jdk/test/sun/tools/jconsole/ImmutableResourceTest.sh b/jdk/test/sun/tools/jconsole/ImmutableResourceTest.sh deleted file mode 100644 index dedf21271b0..00000000000 --- a/jdk/test/sun/tools/jconsole/ImmutableResourceTest.sh +++ /dev/null @@ -1,111 +0,0 @@ -# -# Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# 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 6287579 -# @summary SubClasses of ListResourceBundle should fix getContents() -# -# @run shell ImmutableResourceTest.sh - -# Beginning of subroutines: -status=1 - -#Call this from anywhere to fail the test with an error message -# usage: fail "reason why the test failed" -fail() - { echo "The test failed :-(" - echo "$*" 1>&2 - echo "exit status was $status" - exit $status - } #end of fail() - -#Call this from anywhere to pass the test with a message -# usage: pass "reason why the test passed if applicable" -pass() - { echo "The test passed!!!" - echo "$*" 1>&2 - exit 0 - } #end of pass() - -# end of subroutines - -# The beginning of the script proper - -OS=`uname -s` -case "$OS" in - SunOS | Linux | Darwin ) - PATHSEP=":" - ;; - - Windows* | CYGWIN*) - PATHSEP=";" - ;; - - # catch all other OSs - * ) - echo "Unrecognized system! $OS" - fail "Unrecognized system! $OS" - ;; -esac - -TARGETCLASS="ImmutableResourceTest" -if [ -z "${TESTJAVA}" ] ; then - # TESTJAVA is not set, so the test is running stand-alone. - # TESTJAVA holds the path to the root directory of the build of the JDK - # to be tested. That is, any java files run explicitly in this shell - # should use TESTJAVA in the path to the java interpreter. - # So, we'll set this to the JDK spec'd on the command line. If none - # is given on the command line, tell the user that and use a default. - # THIS IS THE JDK BEING TESTED. - if [ -n "$1" ] ; then - TESTJAVA=$1 - else - TESTJAVA=$JAVA_HOME - fi - TESTSRC=. - TESTCLASSES=. - #Deal with .class files: -fi -# -echo "JDK under test is: $TESTJAVA" -# -CP="-classpath ${TESTCLASSES}${PATHSEP}${TESTJAVA}/lib/jconsole.jar" -# Compile the test class using the classpath we need: -# -env -# -set -vx -# -#Compile. jconsole.jar is required on the classpath. -${TESTJAVA}/bin/javac -d "${TESTCLASSES}" ${CP} -g \ - "${TESTSRC}"/"${TARGETCLASS}".java -# -#Run the test class, again with the classpath we need: -${TESTJAVA}/bin/java ${CP} ${TARGETCLASS} -status=$? -echo "test status was: $status" -if [ $status -eq "0" ]; - then pass "" - - else fail "unspecified test failure" -fi diff --git a/jdk/test/sun/tools/jconsole/ResourceCheckTest.java b/jdk/test/sun/tools/jconsole/ResourceCheckTest.java index 6d4e27be860..1ed5bb642c7 100644 --- a/jdk/test/sun/tools/jconsole/ResourceCheckTest.java +++ b/jdk/test/sun/tools/jconsole/ResourceCheckTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,377 +27,134 @@ * This isn't the test case: ResourceCheckTest.sh is. * Refer to ResourceCheckTest.sh when running this test. * - * @bug 5008856 5023573 5024917 5062569 + * @bug 5008856 5023573 5024917 5062569 7172176 * @summary 'missing resource key' error for key = "Operating system" */ -import java.awt.event.KeyEvent; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.ResourceBundle; +import sun.tools.jconsole.Messages; import sun.tools.jconsole.Resources; +/* + * Ensures that there is a one-to-one mapping between constants in the + * Message class and the keys in the sun.tools.jconsole.resources.messages + * bundle. + * + * An error will be thrown if there is a: + * + * - key in the resource bundle that doesn't have a public static field with + * the same name in the Message class. + * + * - public static field in the Message class that doesn't have a key with + * the same name in the resource bundle. + * + * - message with a mnemonic identifier(&) for which a mnemonic can't + * be looked up using Resources#getMnemonicInt(). + * + */ public class ResourceCheckTest { + private static final String MISSING_RESOURCE_KEY_PREFIX = "missing message for"; + private static final String RESOURCE_BUNDLE = "sun.tools.jconsole.resources.messages"; + private static final String NEW_LINE = String.format("%n"); - public static void main(String[] args){ - Object [][] testData = { - {"<", "", "", "", ""}, - {"<<", "", "", "", ""}, - {">", "", "", "", ""}, - {" 1 day", "", "", "", ""}, - {" 1 hour", "", "", "", ""}, - {" 1 min", "", "", "", ""}, - {" 1 month", "", "", "", ""}, - {" 1 year", "", "", "", ""}, - {" 2 hours", "", "", "", ""}, - {" 3 hours", "", "", "", ""}, - {" 3 months", "", "", "", ""}, - {" 5 min", "", "", "", ""}, - {" 6 hours", "", "", "", ""}, - {" 6 months", "", "", "", ""}, - {" 7 days", "", "", "", ""}, - {"10 min", "", "", "", ""}, - {"12 hours", "", "", "", ""}, - {"30 min", "", "", "", ""}, - {"ACTION", "", "", "", ""}, - {"ACTION_INFO", "", "", "", ""}, - {"All", "", "", "", ""}, - {"Architecture", "", "", "", ""}, - {"Attribute", "", "", "", ""}, - {"Attribute value", "", "", "", ""}, - {"Attribute values", "", "", "", ""}, - {"Attributes", "", "", "", ""}, - {"Blank", "", "", "", ""}, - {"BlockedCount WaitedCount", "BlockedCount", "WaitedCount", "", ""}, - {"Boot class path", "", "", "", ""}, - {"BorderedComponent.moreOrLessButton.toolTip", "", "", "", ""}, - {"Close", "", "", "", ""}, - {"CPU Usage", "", "", "", ""}, - {"CPUUsageFormat","PhonyPercentage", "", "", ""}, - {"Cancel", "", "", "", ""}, - {"Cascade", "", "", "", ""}, - {"Cascade.mnemonic", "", "", "", ""}, - {"Chart:", "", "", "", ""}, - {"Chart:.mnemonic", "", "", "", ""}, - {"ClassTab.infoLabelFormat", "LoadedCount", "UnloadedCount", "TotalCount", ""}, - {"ClassTab.loadedClassesPlotter.accessibleName", "", "", "", ""}, - {"Class path", "", "", "", ""}, - {"Classes", "", "", "", ""}, - {"ClassName", "", "", "", ""}, - {"Column.Name", "", "", "", ""}, - {"Column.PID", "", "", "", ""}, - {"Committed", "", "", "", ""}, - {"Committed memory", "", "", "", ""}, - {"Committed virtual memory", "", "", "", ""}, - {"Compiler", "", "", "", ""}, - {"Connect...", "", "", "", ""}, - {"Connect", "", "", "", ""}, - {"Connect.mnemonic", "", "", "", ""}, - {"ConnectDialog.connectButton.toolTip", "", "", "", ""}, - {"ConnectDialog.accessibleDescription", "", "", "", ""}, - {"ConnectDialog.masthead.accessibleName", "", "", "", ""}, - {"ConnectDialog.masthead.title", "", "", "", ""}, - {"ConnectDialog.statusBar.accessibleName", "", "", "", ""}, - {"ConnectDialog.title", "", "", "", ""}, - {"Connected. Click to disconnect.", "", "", "", ""}, - {"connectingTo1", "PhonyConnectionName", "", "", ""}, - {"connectingTo2", "PhonyConnectionName", "", "", ""}, - {"connectionFailed1", "", "", "", ""}, - {"connectionFailed2", "PhonyConnectionName", "", "", ""}, - {"connectionLost1", "", "", "", ""}, - {"connectionLost2", "PhonyConnectionName", "", "", ""}, - {"Connection failed", "", "", "", ""}, - {"Connection", "", "", "", ""}, - {"Connection.mnemonic", "", "", "", ""}, - {"Connection name", "", "", "", ""}, - {"ConnectionName (disconnected)", "Phony", "Phony", "", ""}, - {"Constructor", "", "", "", ""}, - {"Create", "Phony", "Phony", "", ""}, - {"Current classes loaded", "", "", "", ""}, - {"Current heap size", "", "", "", ""}, - {"Current value", "PhonyValue", "", "", ""}, - {"Daemon threads", "", "", "", ""}, - {"deadlockAllTab", "", "", "", ""}, - {"deadlockTab", "", "", "", ""}, - {"deadlockTabN", "PhonyInt", "", "", ""}, - {"Description", "", "", "", ""}, - {"Descriptor", "", "", "", ""}, - {"Details", "", "", "", ""}, - {"Detect Deadlock", "", "", "", ""}, - {"Detect Deadlock.mnemonic", "", "", "", ""}, - {"Detect Deadlock.toolTip", "", "", "", ""}, - {"Dimension is not supported:", "", "", "", ""}, - {"Discard chart", "", "", "", ""}, - {"Disconnected. Click to connect.", "", "", "", ""}, - {"Double click to expand/collapse", "", "", "", ""}, - {"Double click to visualize", "", "", "", ""}, - {"DurationDaysHoursMinutes", 0, 13, 54, ""}, - {"DurationDaysHoursMinutes", 1, 13, 54, ""}, - {"DurationDaysHoursMinutes", 2, 13, 54, ""}, - {"DurationDaysHoursMinutes", 1024, 13, 45, ""}, - {"DurationHoursMinutes", 0, 13, "", ""}, - {"DurationHoursMinutes", 1, 0, "", ""}, - {"DurationHoursMinutes", 1, 1, "", ""}, - {"DurationHoursMinutes", 2, 42, "", ""}, - {"DurationMinutes", 0, "", "", ""}, - {"DurationMinutes", 1, "", "", ""}, - {"DurationMinutes", 2, "", "", ""}, - {"DurationSeconds", 0, "", "", ""}, - {"DurationSeconds", 1, "", "", ""}, - {"DurationSeconds", 2, "", "", ""}, - {"Empty array", "", "", "", ""}, - {"Error", "", "", "", ""}, - {"Error: MBeans already exist", "", "", "", ""}, - {"Error: MBeans do not exist", "", "", "", ""}, - {"Event", "", "", "", ""}, - {"Exit", "", "", "", ""}, - {"Exit.mnemonic", "", "", "", ""}, - {"expand", "", "", "", ""}, - {"Fail to load plugin", "", "", "", ""}, - {"FileChooser.fileExists.cancelOption", "", "", "", ""}, - {"FileChooser.fileExists.message", "PhonyFileName", "", "", ""}, - {"FileChooser.fileExists.okOption", "", "", "", ""}, - {"FileChooser.fileExists.title", "", "", "", ""}, - {"FileChooser.savedFile", "PhonyFilePath", "PhonyFileSize", "", ""}, - {"FileChooser.saveFailed.message", "PhonyFilePath", "PhonyMessage", "", ""}, - {"FileChooser.saveFailed.title", "", "", "", ""}, - {"Free physical memory", "", "", "", ""}, - {"Free swap space", "", "", "", ""}, - {"Garbage collector", "", "", "", ""}, - {"GC time", "", "", "", ""}, - {"GC time details", 54, "Phony", 11, ""}, - {"GcInfo", "Phony", -1, 768, ""}, - {"GcInfo", "Phony", 0, 768, ""}, - {"GcInfo", "Phony", 1, 768, ""}, - {"Heap", "", "", "", ""}, - {"Heap Memory Usage", "", "", "", ""}, - {"Help.AboutDialog.accessibleDescription", "", "", "", ""}, - {"Help.AboutDialog.jConsoleVersion", "DummyVersion", "", "", ""}, - {"Help.AboutDialog.javaVersion", "DummyVersion", "", "", ""}, - {"Help.AboutDialog.masthead.accessibleName", "", "", "", ""}, - {"Help.AboutDialog.masthead.title", "", "", "", ""}, - {"Help.AboutDialog.title", "", "", "", ""}, - {"Help.AboutDialog.userGuideLink", "DummyMessage", "", "", ""}, - {"Help.AboutDialog.userGuideLink.mnemonic", "", "", "", ""}, - {"Help.AboutDialog.userGuideLink.url", "DummyURL", "", "", ""}, - {"HelpMenu.About.title", "", "", "", ""}, - {"HelpMenu.About.title.mnemonic", "", "", "", ""}, - {"HelpMenu.UserGuide.title", "", "", "", ""}, - {"HelpMenu.UserGuide.title.mnemonic", "", "", "", ""}, - {"HelpMenu.title", "", "", "", ""}, - {"HelpMenu.title.mnemonic", "", "", "", ""}, - {"Hotspot MBeans...", "", "", "", ""}, - {"Hotspot MBeans....mnemonic", "", "", "", ""}, - {"Hotspot MBeans.dialog.accessibleDescription", "", "", "", ""}, - {"Impact", "", "", "", ""}, - {"Info", "", "", "", ""}, - {"INFO", "", "", "", ""}, - {"Invalid plugin path", "", "", "", ""}, - {"Invalid URL", "", "", "", ""}, - {"Is", "", "", "", ""}, - {"Java Monitoring & Management Console", "", "", "", ""}, - {"Java Virtual Machine", "", "", "", ""}, - {"JConsole: ", "", "", "", ""}, - {"JConsole.accessibleDescription", "", "", "", ""}, - {"JConsole version", "PhonyVersion", "", "", ""}, - {"JIT compiler", "", "", "", ""}, - {"Library path", "", "", "", ""}, - {"Live Threads", "", "", "", ""}, - {"Loaded", "", "", "", ""}, - {"Local Process:", "", "", "", ""}, - {"Local Process:.mnemonic", "", "", "", ""}, - {"Manage Hotspot MBeans in: ", "", "", "", ""}, - {"Management Not Enabled", "", "", "", ""}, - {"Management Will Be Enabled", "", "", "", ""}, - {"Masthead.font", "", "", "", ""}, - {"Max", "", "", "", ""}, - {"Max", "", "", "", ""}, - {"Maximum heap size", "", "", "", ""}, - {"MBeanAttributeInfo", "", "", "", ""}, - {"MBeanInfo", "", "", "", ""}, - {"MBeanNotificationInfo", "", "", "", ""}, - {"MBeanOperationInfo", "", "", "", ""}, - {"MBeans", "", "", "", ""}, - {"MBeansTab.clearNotificationsButton", "", "", "", ""}, - {"MBeansTab.clearNotificationsButton.mnemonic", "", "", "", ""}, - {"MBeansTab.clearNotificationsButton.toolTip", "", "", "", ""}, - {"MBeansTab.compositeNavigationMultiple", 0, 0, "", ""}, - {"MBeansTab.compositeNavigationSingle", "", "", "", ""}, - {"MBeansTab.refreshAttributesButton", "", "", "", ""}, - {"MBeansTab.refreshAttributesButton.mnemonic", "", "", "", ""}, - {"MBeansTab.refreshAttributesButton.toolTip", "", "", "", ""}, - {"MBeansTab.subscribeNotificationsButton", "", "", "", ""}, - {"MBeansTab.subscribeNotificationsButton.mnemonic", "", "", "", ""}, - {"MBeansTab.subscribeNotificationsButton.toolTip", "", "", "", ""}, - {"MBeansTab.tabularNavigationMultiple", 0, 0, "", ""}, - {"MBeansTab.tabularNavigationSingle", "", "", "", ""}, - {"MBeansTab.unsubscribeNotificationsButton", "", "", "", ""}, - {"MBeansTab.unsubscribeNotificationsButton.mnemonic", "", "", "", ""}, - {"MBeansTab.unsubscribeNotificationsButton.toolTip", "", "", "", ""}, - {"Memory", "", "", "", ""}, - {"MemoryPoolLabel", "PhonyMemoryPool", "", "", ""}, - {"MemoryTab.heapPlotter.accessibleName", "", "", "", ""}, - {"MemoryTab.infoLabelFormat", "UsedCount", "CommittedCount", "MaxCount", ""}, - {"MemoryTab.nonHeapPlotter.accessibleName", "", "", "", ""}, - {"MemoryTab.poolChart.aboveThreshold", "Threshold", "", "", ""}, - {"MemoryTab.poolChart.accessibleName", "", "", "", ""}, - {"MemoryTab.poolChart.belowThreshold", "Threshold", "", "", ""}, - {"MemoryTab.poolPlotter.accessibleName", "PhonyMemoryPool", "", "", ""}, - {"Message", "", "", "", ""}, - {"Method successfully invoked", "", "", "", ""}, - {"Monitor locked", "", "", "", ""}, - {"Minimize All", "", "", "", ""}, - {"Minimize All.mnemonic", "", "", "", ""}, - {"Name", "", "", "", ""}, - {"Name and Build", "PhonyName", "PhonyBuild", "", ""}, - {"Name Build and Mode", "PhonyName", "PhonyBuild", "PhonyMode", ""}, - {"Name State", "PhonyName", "PhonyState", "", ""}, - {"Name State LockName", "PhonyName", "PhonyState", "PhonyLock", ""}, - {"Name State LockName LockOwner", "PhonyName", "PhonyState", "PhonyLock", "PhonyOwner"}, - {"New Connection...", "", "", "", ""}, - {"New Connection....mnemonic", "", "", "", ""}, - {"No deadlock detected", "", "", "", ""}, - {"Non-Heap", "", "", "", ""}, - {"Non-Heap Memory Usage", "", "", "", ""}, - {"Notification", "", "", "", ""}, - {"Notification buffer", "", "", "", ""}, - {"Notifications", "", "", "", ""}, - {"NotifTypes", "", "", "", ""}, - {"Number of Loaded Classes", "", "", "", ""}, - {"Number of processors", "", "", "", ""}, - {"Number of Threads", "", "", "", ""}, - {"ObjectName", "", "", "", ""}, - {"Operating System", "", "", "", ""}, - {"Operation", "", "", "", ""}, - {"Operation invocation", "", "", "", ""}, - {"Operation return value", "", "", "", ""}, - {"Operations", "", "", "", ""}, - {"Overview", "", "", "", ""}, - {"OverviewPanel.plotter.accessibleName", "PhonyPlotter", "", "", ""}, - {"Parameter", "", "", "", ""}, - {"Password: ", "", "", "", ""}, - {"Password: .mnemonic", "", "", "", ""}, - {"Password.accessibleName", "", "", "", ""}, - {"Peak", "", "", "", ""}, - {"Perform GC", "", "", "", ""}, - {"Perform GC.mnemonic", "", "", "", ""}, - {"Perform GC.toolTip", "", "", "", ""}, - {"Plotter.accessibleName", "", "", "", ""}, - {"Plotter.accessibleName.keyAndValue", "Key", "Value", "", ""}, - {"Plotter.accessibleName.noData", "", "", "", ""}, - {"Plotter.saveAsMenuItem", "", "", "", ""}, - {"Plotter.saveAsMenuItem.mnemonic", "", "", "", ""}, - {"Plotter.timeRangeMenu", "", "", "", ""}, - {"Plotter.timeRangeMenu.mnemonic", "", "", "", ""}, - {"plot", "", "", "", ""}, - {"Problem adding listener", "", "", "", ""}, - {"Problem displaying MBean", "", "", "", ""}, - {"Problem invoking", "", "", "", ""}, - {"Problem removing listener", "", "", "", ""}, - {"Problem setting attribute", "", "", "", ""}, - {"Process CPU time", "", "", "", ""}, - {"Readable", "", "", "", ""}, - {"Reconnect", "", "", "", ""}, - {"Remote Process:", "", "", "", ""}, - {"Remote Process:.mnemonic", "", "", "", ""}, - {"Remote Process.textField.accessibleName", "", "", "", ""}, - {"remoteTF.usage", "", "", "", ""}, - {"Restore All", "", "", "", ""}, - {"Restore All.mnemonic", "", "", "", ""}, - {"ReturnType", "", "", "", ""}, - {"SeqNum", "", "", "", ""}, - {"Size Bytes", 512, "", "", ""}, - {"Size Gb", 512, "", "", ""}, - {"Size Kb", 512, "", "", ""}, - {"Size Mb", 512, "", "", ""}, - {"Source", "", "", "", ""}, - {"Stack trace", "", "", "", ""}, - {"SummaryTab.headerDateTimeFormat", "", "", "", ""}, - {"SummaryTab.pendingFinalization.label", "", "", "", ""}, - {"SummaryTab.pendingFinalization.value", "ObjectCount", "", "", ""}, - {"SummaryTab.tabName", "", "", "", ""}, - {"SummaryTab.vmVersion", "VMName", "VMVersion", "", ""}, - {"ThreadTab.infoLabelFormat", "LiveCount", "PeakCount", "TotalCount", ""}, - {"ThreadTab.threadInfo.accessibleName", "", "", "", ""}, - {"ThreadTab.threadPlotter.accessibleName", "", "", "", ""}, - {"Threads", "", "", "", ""}, - {"Threshold", "", "", "", ""}, - {"Tile", "", "", "", ""}, - {"Tile.mnemonic", "", "", "", ""}, - {"Time", "", "", "", ""}, - {"Time Range:", "", "", "", ""}, - {"Time Range:.mnemonic", "", "", "", ""}, - {"TimeStamp", "", "", "", ""}, - {"Total classes loaded", "", "", "", ""}, - {"Total classes unloaded", "", "", "", ""}, - {"Total compile time", "", "", "", ""}, - {"Total Loaded", "", "", "", ""}, - {"Total physical memory", "", "", "", ""}, - {"Total swap space", "", "", "", ""}, - {"Total threads started", "", "", "", ""}, - {"Type", "", "", "", ""}, - {"Unavailable", "", "", "", ""}, - {"UNKNOWN", "", "", "", ""}, - {"Unregister", "", "", "", ""}, - {"Uptime", "", "", "", ""}, - {"Usage Threshold", "", "", "", ""}, - {"Used", "", "", "", ""}, - {"Username: ", "", "", "", ""}, - {"Username: .mnemonic", "", "", "", ""}, - {"Username.accessibleName", "", "", "", ""}, - {"UserData", "", "", "", ""}, - {"Value", "", "", "", ""}, - {"Vendor", "", "", "", ""}, - {"Verbose Output", "", "", "", ""}, - {"Verbose Output.toolTip", "", "", "", ""}, - {"visualize", "", "", "", ""}, - {"VM", "", "", "", ""}, - {"VMInternalFrame.accessibleDescription", "", "", "", ""}, - {"VM arguments", "", "", "", ""}, - {"Virtual Machine", "", "", "", ""}, - {"Window", "", "", "", ""}, - {"Window.mnemonic", "", "", "", ""}, - {"Writable", "", "", "", ""}, - {"zz usage text", "PhonyName", "", "", ""}, - }; - //boolean verbose = false; - boolean verbose = true; - - long badLookups = 0; - System.out.println("Start..."); - for (int ii = 0; ii < testData.length; ii++) { - String key = (String)testData[ii][0]; - - if (key.endsWith(".mnemonic")) { - String baseKey = key.substring(0, key.length() - ".mnemonic".length()); - int mnemonic = Resources.getMnemonicInt(baseKey); - if (mnemonic == 0) { - badLookups++; - System.out.println("****lookup failed for key = " + key); + public static void main(String... args) { + List errors = new ArrayList<>(); + // Ensure that all Message fields have a corresponding key/value + // in the resource bundle and that mnemonics can be looked + // up where applicable. + ResourceBundle rb = ResourceBundle.getBundle(RESOURCE_BUNDLE); + for (Field field : Messages.class.getFields()) { + if (isResourceKeyField(field)) { + String resourceKey = field.getName(); + String message = readField(field); + if (message.startsWith(MISSING_RESOURCE_KEY_PREFIX)) { + errors.add("Can't find message (and perhaps mnemonic) for " + + Messages.class.getSimpleName() + "." + + resourceKey + " in resource bundle."); } else { - if (verbose) { - System.out.println(" mnemonic: " + KeyEvent.getKeyText(mnemonic)); + String resourceMessage = rb.getString(resourceKey); + if (hasMnemonicIdentifier(resourceMessage)) { + int mi = Resources.getMnemonicInt(message); + if (mi == 0) { + errors.add("Could not look up mnemonic for message '" + + message + "'."); + } } } - continue; } + } - String ss = Resources.getText(key, - testData[ii][1], - testData[ii][2], - testData[ii][3], - testData[ii][4]); - if (ss.startsWith("missing resource key")) { - badLookups++; - System.out.println("****lookup failed for key = " + key); - } else { - if (verbose) { - System.out.println(" " + ss); + // Ensure that there is Message class field for every resource key. + for (String key : Collections.list(rb.getKeys())) { + try { + Messages.class.getField(key); + } catch (NoSuchFieldException nfe) { + errors.add("Can't find static field (" + + Messages.class.getSimpleName() + "." + key + + ") matching '" + key + + "' in resource bundle. Unused message?"); + } + } + + if (errors.size() > 0) { + throwError(errors); + } + } + + private static String readField(Field field) { + try { + return (String) field.get(null); + } catch (IllegalArgumentException | IllegalAccessException e) { + throw new Error("Could not access field " + field.getName() + + " when trying to read resource message."); + } + } + + private static boolean isResourceKeyField(Field field) { + int modifiers = field.getModifiers(); + return Modifier.isPublic(modifiers) && Modifier.isStatic(modifiers); + } + + private static boolean hasMnemonicIdentifier(String s) { + for (int i = 0; i < s.length() - 1; i++) { + if (s.charAt(i) == '&') { + if (s.charAt(i + 1) != '&') { + return true; + } else { + i++; } } } - if (badLookups > 0) { - throw new Error ("Resource lookup failed " + badLookups + - " time(s); Test failed"); + return false; + } + + private static void throwError(List errors) { + StringBuffer buffer = new StringBuffer(); + buffer.append("Found "); + buffer.append(errors.size()); + buffer.append(" error(s) when checking one-to-one mapping "); + buffer.append("between Message and resource bundle keys in "); + buffer.append(RESOURCE_BUNDLE); + buffer.append(" with "); + buffer.append(Locale.getDefault()); + buffer.append(" locale."); + buffer.append(NEW_LINE); + int errorIndex = 1; + for (String error : errors) { + buffer.append("Error "); + buffer.append(errorIndex); + buffer.append(": "); + buffer.append(error); + buffer.append(NEW_LINE); + errorIndex++; } - System.out.println("...Finished."); + throw new Error(buffer.toString()); } } diff --git a/jdk/test/sun/tools/jconsole/ResourceCheckTest.sh b/jdk/test/sun/tools/jconsole/ResourceCheckTest.sh index bec63a7992f..01c2e4b6f01 100644 --- a/jdk/test/sun/tools/jconsole/ResourceCheckTest.sh +++ b/jdk/test/sun/tools/jconsole/ResourceCheckTest.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -54,7 +54,7 @@ pass() OS=`uname -s` case "$OS" in - SunOS | Linux ) + SunOS | Linux | Darwin) PATHSEP=":" ;; diff --git a/jdk/test/sun/tools/jhat/HatRun.java b/jdk/test/sun/tools/jhat/HatRun.java index e9765408d47..284083580ec 100644 --- a/jdk/test/sun/tools/jhat/HatRun.java +++ b/jdk/test/sun/tools/jhat/HatRun.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -167,28 +167,23 @@ public class HatRun { String cdir = System.getProperty("test.classes", "."); String os_arch = System.getProperty("os.arch"); String os_name = System.getProperty("os.name"); - boolean d64 = os_name.equals("SunOS") && ( - os_arch.equals("sparcv9") || - os_arch.equals("amd64")); - String isa_dir = d64?(File.separator+os_arch):""; String java = jre_home - + File.separator + "bin" + isa_dir + + File.separator + "bin" + File.separator + "java"; String jhat = sdk_home + File.separator + "bin" + File.separator + "jhat"; /* Array of strings to be passed in for exec: * 1. java * 2. -Dtest.classes=. - * 3. -d64 (optional) - * 4. -Xcheck:jni (Just because it finds bugs) - * 5. -Xverify:all (Make sure verification is on full blast) - * 6. -agent + * 3. -Xcheck:jni (Just because it finds bugs) + * 4. -Xverify:all (Make sure verification is on full blast) + * 5. -agent * vm_options - * 7+i. classname + * 6+i. classname */ int nvm_options = 0; if ( vm_options != null ) nvm_options = vm_options.length; - String cmd[] = new String[1 + (d64?1:0) + 7 + nvm_options]; + String cmd[] = new String[1 + 7 + nvm_options]; int i,j; i = 0; @@ -196,9 +191,6 @@ public class HatRun { cmd[i++] = "-cp"; cmd[i++] = cdir; cmd[i++] = "-Dtest.classes=" + cdir; - if ( d64 ) { - cmd[i++] = "-d64"; - } cmd[i++] = "-Xcheck:jni"; cmd[i++] = "-Xverify:all"; dumpfile= cdir + File.separator + class_name + ".hdump"; diff --git a/jdk/test/sun/tools/jstat/gcCapacityOutput1.awk b/jdk/test/sun/tools/jstat/gcCapacityOutput1.awk index c59de5f0bdb..ab630d143b6 100644 --- a/jdk/test/sun/tools/jstat/gcCapacityOutput1.awk +++ b/jdk/test/sun/tools/jstat/gcCapacityOutput1.awk @@ -3,19 +3,19 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC YGC FGC -# 2176.0 7232.0 2176.0 64.0 64.0 2048.0 6016.0 58304.0 6016.0 6016.0 8192.0 65536.0 8192.0 8192.0 0 +# NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC +# 4096.0 657408.0 8192.0 512.0 512.0 3072.0 6144.0 1312768.0 6144.0 6144.0 512.0 132096.0 5120.0 512.0 131072.0 512.0 1 0 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC YGC FGC $/ { +/^ NGCMN NGCMX NGC S0C S1C EC OGCMN OGCMX OGC OC MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/gcCauseOutput1.awk b/jdk/test/sun/tools/jstat/gcCauseOutput1.awk index 973d2c049e6..f6127e415f5 100644 --- a/jdk/test/sun/tools/jstat/gcCauseOutput1.awk +++ b/jdk/test/sun/tools/jstat/gcCauseOutput1.awk @@ -3,15 +3,15 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O P YGC YGCT FGC FGCT GCT LGCC GCC -# 0.00 100.00 14.01 3.06 23.20 1 0.032 0 0.000 0.032 Allocation Failure No GC +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC +# 0.00 0.00 0.00 9.97 90.94 87.70 2 0.013 0 0.000 0.013 Allocation Failure No GC BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M YGC YGCT FGC FGCT GCT LGCC GCC $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC $/ { headerlines++; } @@ -23,7 +23,7 @@ BEGIN { # or more letters and spaces. It also provides for the ".", "(", and ")" # characters to allow for the string "System.gc()". # -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[a-zA-Z]+[a-zA-Z \.\(\)]*[ ]*[a-zA-Z]+[a-zA-Z \.\(\)]*$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[a-zA-Z]+[a-zA-Z \.\(\)]*[ ]*[a-zA-Z]+[a-zA-Z \.\(\)]*$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/gcMetaCapacityOutput1.awk b/jdk/test/sun/tools/jstat/gcMetaCapacityOutput1.awk index c015dd69c94..12d9544542a 100644 --- a/jdk/test/sun/tools/jstat/gcMetaCapacityOutput1.awk +++ b/jdk/test/sun/tools/jstat/gcMetaCapacityOutput1.awk @@ -3,18 +3,18 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# MCMN MCMX MC YGC FGC FGCT GCT -# 8192.0 65536.0 8192.0 8192.0 1 0 0.000 0.029 +# MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT +# 512.0 132096.0 5120.0 512.0 131072.0 512.0 1 0 0.000 0.004 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ MCMN MCMX MC YGC FGC FGCT GCT $/ { +/^ MCMN MCMX MC CCSMN CCSMX CCSC YGC FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/gcOldOutput1.awk b/jdk/test/sun/tools/jstat/gcOldOutput1.awk index df7c6b582c5..c007f66b3be 100644 --- a/jdk/test/sun/tools/jstat/gcOldOutput1.awk +++ b/jdk/test/sun/tools/jstat/gcOldOutput1.awk @@ -3,19 +3,19 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# MC MU OC OU YGC FGC FGCT GCT -# 8192.0 1877.3 6016.0 180.8 1 0 0.000 0.030 +# MC MU CCSC CCSU OC OU YGC FGC FGCT GCT +# 5120.0 4152.0 512.0 397.9 6144.0 200.0 1 0 0.000 0.005 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ MC MU OC OU YGC FGC FGCT GCT $/ { +/^ MC MU CCSC CCSU OC OU YGC FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/gcOutput1.awk b/jdk/test/sun/tools/jstat/gcOutput1.awk index 5ac5b2837a2..d1d90a281e2 100644 --- a/jdk/test/sun/tools/jstat/gcOutput1.awk +++ b/jdk/test/sun/tools/jstat/gcOutput1.awk @@ -3,19 +3,19 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0C S1C S0U S1U EC EU OC OU MC MU YGC YGCT FGC FGCT GCT -# 64.0 64.0 0.0 0.0 2048.0 1711.2 6016.0 0.0 8192.0 1948.6 0 0.000 0 0.000 0.000 +# S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT +# 512.0 512.0 0.0 496.0 3072.0 615.5 6144.0 280.0 5120.0 4176.0 512.0 401.0 1 0.005 0 0.000 0.005 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0C S1C S0U S1U EC EU OC OU MC MU YGC YGCT FGC FGCT GCT $/ { +/^ S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/lineCounts1.awk b/jdk/test/sun/tools/jstat/lineCounts1.awk index 33b2f08cc61..b5cb1cdd0bd 100644 --- a/jdk/test/sun/tools/jstat/lineCounts1.awk +++ b/jdk/test/sun/tools/jstat/lineCounts1.awk @@ -3,22 +3,22 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M YGC YGCT FGC FGCT GCT -# 0.00 100.00 68.87 1.24 27.75 1 0.044 0 0.000 0.044 -# 0.00 100.00 68.87 1.24 27.84 1 0.044 0 0.000 0.044 -# 0.00 100.00 68.87 1.24 27.84 1 0.044 0 0.000 0.044 -# 0.00 100.00 70.89 1.24 27.84 1 0.044 0 0.000 0.044 -# 0.00 100.00 70.89 1.24 27.84 1 0.044 0 0.000 0.044 +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.00 93.76 28.80 1.82 77.74 68.02 1 0.005 0 0.000 0.005 +# 0.00 93.76 73.04 1.82 77.74 68.02 1 0.005 0 0.000 0.005 +# 0.00 93.76 73.04 1.82 77.74 68.02 1 0.005 0 0.000 0.005 +# 0.00 93.76 73.04 1.82 77.74 68.02 1 0.005 0 0.000 0.005 +# 0.00 93.76 75.00 1.82 77.74 68.02 1 0.005 0 0.000 0.005 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M YGC YGCT FGC FGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/lineCounts2.awk b/jdk/test/sun/tools/jstat/lineCounts2.awk index b1e80482241..1309d04f8cb 100644 --- a/jdk/test/sun/tools/jstat/lineCounts2.awk +++ b/jdk/test/sun/tools/jstat/lineCounts2.awk @@ -3,18 +3,18 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M YGC YGCT FGC FGCT GCT -# 0.00 100.00 68.87 1.24 27.75 1 0.044 0 0.000 0.044 +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.00 93.76 28.40 1.82 77.74 68.02 1 0.005 0 0.000 0.005 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M YGC YGCT FGC FGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/lineCounts3.awk b/jdk/test/sun/tools/jstat/lineCounts3.awk index e7c362fbd8f..2d8d4bf1368 100644 --- a/jdk/test/sun/tools/jstat/lineCounts3.awk +++ b/jdk/test/sun/tools/jstat/lineCounts3.awk @@ -3,27 +3,27 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M YGC YGCT FGC FGCT GCT -# 0.00 99.99 66.81 1.24 26.55 1 0.028 0 0.000 0.028 -# 0.00 99.99 68.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 70.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 70.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 70.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 72.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 72.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 74.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 74.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 76.81 1.24 27.85 1 0.028 0 0.000 0.028 +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.00 93.76 26.48 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 71.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 73.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 73.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 73.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 75.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 75.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 77.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 77.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 +# 0.00 93.76 77.58 1.95 77.78 68.02 1 0.006 0 0.000 0.006 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M YGC YGCT FGC FGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstat/lineCounts4.awk b/jdk/test/sun/tools/jstat/lineCounts4.awk index af9487edb27..5ec4ac7e9bf 100644 --- a/jdk/test/sun/tools/jstat/lineCounts4.awk +++ b/jdk/test/sun/tools/jstat/lineCounts4.awk @@ -3,30 +3,30 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M YGC YGCT FGC FGCT GCT -# 0.00 99.99 66.81 1.24 26.55 1 0.028 0 0.000 0.028 -# 0.00 99.99 68.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 70.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 70.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 70.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 72.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 72.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 74.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 74.81 1.24 27.84 1 0.028 0 0.000 0.028 -# 0.00 99.99 76.81 1.24 27.85 1 0.028 0 0.000 0.028 -# S0 S1 E O P YGC YGCT FGC FGCT GCT -# 0.00 99.99 76.81 1.24 27.85 1 0.028 0 0.000 0.028 +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.00 96.88 66.55 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 71.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 73.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 73.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 73.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 75.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 75.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 77.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 77.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# 0.00 96.88 77.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.00 96.88 79.58 2.34 77.78 68.02 1 0.003 0 0.000 0.003 BEGIN { headerlines=0; datalines=0; totallines=0 datalines2=0; } -/^ S0 S1 E O M YGC YGCT FGC FGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { if (headerlines == 2) { datalines2++; } diff --git a/jdk/test/sun/tools/jstat/timeStamp1.awk b/jdk/test/sun/tools/jstat/timeStamp1.awk index 825101b3ac4..1d90a18f748 100644 --- a/jdk/test/sun/tools/jstat/timeStamp1.awk +++ b/jdk/test/sun/tools/jstat/timeStamp1.awk @@ -3,18 +3,18 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M YGC YGCT FGC FGCT GCT -# 0.00 100.00 68.87 1.24 27.75 1 0.044 0 0.000 0.044 +#Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.3 0.00 100.00 68.74 1.95 77.73 68.02 1 0.004 0 0.000 0.004 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^Timestamp S0 S1 E O M YGC YGCT FGC FGCT GCT $/ { +/^Timestamp S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/tools/jstatd/jstatGcutilOutput1.awk b/jdk/test/sun/tools/jstatd/jstatGcutilOutput1.awk index 33b2f08cc61..76b355e6707 100644 --- a/jdk/test/sun/tools/jstatd/jstatGcutilOutput1.awk +++ b/jdk/test/sun/tools/jstatd/jstatGcutilOutput1.awk @@ -3,22 +3,22 @@ # that the numerical values conform to a specific pattern, rather than # specific values. # -# S0 S1 E O M YGC YGCT FGC FGCT GCT -# 0.00 100.00 68.87 1.24 27.75 1 0.044 0 0.000 0.044 -# 0.00 100.00 68.87 1.24 27.84 1 0.044 0 0.000 0.044 -# 0.00 100.00 68.87 1.24 27.84 1 0.044 0 0.000 0.044 -# 0.00 100.00 70.89 1.24 27.84 1 0.044 0 0.000 0.044 -# 0.00 100.00 70.89 1.24 27.84 1 0.044 0 0.000 0.044 +# S0 S1 E O M CCS YGC YGCT FGC FGCT GCT +# 0.00 100.00 56.99 7.81 95.03 87.56 1 0.009 0 0.000 0.009 +# 0.00 100.00 63.64 7.81 95.03 87.56 1 0.009 0 0.000 0.009 +# 0.00 100.00 64.68 7.81 95.03 87.56 1 0.009 0 0.000 0.009 +# 0.00 100.00 65.73 7.81 95.03 87.56 1 0.009 0 0.000 0.009 +# 0.00 100.00 67.22 7.81 95.03 87.56 1 0.009 0 0.000 0.009 BEGIN { headerlines=0; datalines=0; totallines=0 } -/^ S0 S1 E O M YGC YGCT FGC FGCT GCT $/ { +/^ S0 S1 E O M CCS YGC YGCT FGC FGCT GCT $/ { headerlines++; } -/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { +/^[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+[ ]*[0-9]+\.[0-9]+[ ]*[0-9]+\.[0-9]+$/ { datalines++; } diff --git a/jdk/test/sun/util/locale/provider/Bug8024141.java b/jdk/test/sun/util/locale/provider/Bug8024141.java new file mode 100644 index 00000000000..24bd0f3024a --- /dev/null +++ b/jdk/test/sun/util/locale/provider/Bug8024141.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8024141 + * @summary Test for cache support of sun.util.locale.provider.LocaleResources.getTimeZoneNames + */ + +import java.time.ZoneId; +import static java.util.Locale.ENGLISH; +import static java.time.format.TextStyle.FULL; +import static java.time.format.TextStyle.SHORT; + +public class Bug8024141 { + // This test assumes that the two time zones are in GMT. If + // they become different zones, need to pick up another zones. + private static final String[] ZONES = { + "Africa/Abidjan", + "Africa/Bamako" + }; + + public static void main(String[] args) { + ZoneId gmt = ZoneId.of("GMT"); + String gmtName = gmt.getDisplayName(FULL, ENGLISH); + String gmtAbbr = gmt.getDisplayName(SHORT, ENGLISH); + + for (String zone : ZONES) { + ZoneId id = ZoneId.of(zone); + String name = id.getDisplayName(FULL, ENGLISH); + String abbr = id.getDisplayName(SHORT, ENGLISH); + + if (!name.equals(gmtName) || !abbr.equals(gmtAbbr)) { + throw new RuntimeException("inconsistent name/abbr for " + zone + ":\n" + + "name=" + name + ", abbr=" + abbr); + } + } + } +} diff --git a/jdk/test/tools/jar/ChangeDir.java b/jdk/test/tools/jar/ChangeDir.java index f811618af46..6f65fa8542e 100644 --- a/jdk/test/tools/jar/ChangeDir.java +++ b/jdk/test/tools/jar/ChangeDir.java @@ -23,13 +23,15 @@ /** * @test - * @bug 4806786 + * @bug 4806786 8023113 * @summary jar -C doesn't ignore multiple // in path */ import java.io.*; +import java.nio.file.*; import java.util.*; import java.util.jar.*; +import java.util.stream.Stream; import sun.tools.jar.Main; public class ChangeDir { @@ -37,13 +39,16 @@ public class ChangeDir { private final static String fileName = "hello.txt"; /** Remove dirs & files needed for test. */ - private static void cleanup(File dir) throws Throwable { - if (dir != null && dir.exists()) { - for (File ff : dir.listFiles()) { - check(ff.delete()); + private static void cleanup(Path dir) { + try { + if (Files.isDirectory(dir)) { + try (Stream s = Files.list(dir)) { + s.forEach( p -> cleanup(p)); + } } - check(dir.delete()); - check(new File(jarName).delete()); + Files.delete(dir); + } catch (IOException x) { + fail(x.toString()); } } @@ -62,19 +67,16 @@ public class ChangeDir { } static void doTest(String sep) throws Throwable { - File testDir = null; - JarFile jf = null; + Path topDir = Files.createTempDirectory("delete"); try { + Files.deleteIfExists(Paths.get(jarName)); + // Create a subdirectory "a/b" - File f = File.createTempFile("delete", ".me"); - String dirName = f.getParent(); - testDir = new File(dirName + sep + "a" + sep + "b"); - cleanup(testDir); - check(testDir.mkdirs()); + Path testDir = Files.createDirectories(topDir.resolve("a").resolve("b")); // Create file in that subdirectory - File testFile = new File(testDir, fileName); - check(testFile.createNewFile()); + Path testFile = testDir.resolve(fileName); + Files.createFile(testFile); // Create a jar file from that subdirectory, but with a // in the // path name. @@ -82,33 +84,32 @@ public class ChangeDir { argList.add("cf"); argList.add(jarName); argList.add("-C"); - argList.add(dirName + sep + "a" + sep + sep + "b"); // Note double 'sep' is intentional + argList.add(topDir.toString() + sep + "a" + sep + sep + "b"); // Note double 'sep' is intentional argList.add(fileName); - String jarArgs[] = new String[argList.size()]; - jarArgs = argList.toArray(jarArgs); Main jarTool = new Main(System.out, System.err, "jar"); - if (!jarTool.run(jarArgs)) { + if (!jarTool.run(argList.toArray(new String[argList.size()]))) { fail("Could not create jar file."); } // Check that the entry for hello.txt does *not* have a pathname. - jf = new JarFile(jarName); - for (Enumeration i = jf.entries(); i.hasMoreElements();) { - JarEntry je = i.nextElement(); - String name = je.getName(); - if (name.indexOf(fileName) != -1) { - if (name.indexOf(fileName) != 0) { - fail(String.format( - "Expected '%s' but got '%s'%n", fileName, name)); + try (JarFile jf = new JarFile(jarName)) { + for (Enumeration i = jf.entries(); i.hasMoreElements();) { + JarEntry je = i.nextElement(); + String name = je.getName(); + if (name.indexOf(fileName) != -1) { + if (name.indexOf(fileName) != 0) { + fail(String.format( + "Expected '%s' but got '%s'%n", fileName, name)); + } else { + pass(); + } } } } } finally { - if (jf != null) { - jf.close(); - } - cleanup(testDir); + cleanup(topDir); + Files.deleteIfExists(Paths.get(jarName)); } } diff --git a/jdk/test/tools/launcher/6842838/Test6842838.sh b/jdk/test/tools/launcher/6842838/Test6842838.sh index b552152a9f3..011e2dd1789 100644 --- a/jdk/test/tools/launcher/6842838/Test6842838.sh +++ b/jdk/test/tools/launcher/6842838/Test6842838.sh @@ -1,5 +1,5 @@ # -# Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -48,16 +48,16 @@ case "$OS" in NULL=/dev/null PS=":" FS="/" - JAVA_EXE=${TESTJAVA}${FS}bin${FS}sparcv9${FS}java + JAVA_EXE=${TESTJAVA}${FS}bin${FS}java ;; * ) - printf "Only testing on sparcv9 (use libumem to reliably catch buffer overrun)\n" + printf "Only testing on solaris 64-bit (use libumem to reliably catch buffer overrun)\n" exit 0; ;; esac if [ ! -x ${JAVA_EXE} ]; then - printf "Warning: sparcv9 components not installed - skipping test.\n" + printf "Warning: 64-bit components not installed - skipping test.\n" exit 0 fi diff --git a/jdk/test/tools/launcher/ChangeDataModel.java b/jdk/test/tools/launcher/ChangeDataModel.java index 6b4b6bb19c4..86909eb2efb 100644 --- a/jdk/test/tools/launcher/ChangeDataModel.java +++ b/jdk/test/tools/launcher/ChangeDataModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,6 @@ * @author Joseph D. Darcy, ksrini */ import java.io.File; -import java.util.HashMap; -import java.util.Map; public class ChangeDataModel extends TestHelper { private static final File TestJar = new File("test" + JAR_FILE_EXT); @@ -54,48 +52,14 @@ public class ChangeDataModel extends TestHelper { throw new Error("unsupported data model"); } - // test dual mode systems - if (isDualMode) { - // albeit dual mode we may not have the 64 bit components present - if (dualModePresent()) { - // 32-bit -> 64-bit - checkExecCount(javaCmd, "-d64"); - // 64-bit -> 32-bit - checkExecCount(java64Cmd, "-d32"); - - checkAcceptance(javaCmd, "-d64"); - checkAcceptance(java64Cmd, "-d32"); - } else { - System.out.println("Warning: no 64-bit components found;" + - " only one data model tested."); - } + // Negative tests: ensure that non-dual mode systems reject the + // complementary (other) data model + if (is32Bit) { + checkRejection(javaCmd, "-d64"); + } else if (is64Bit) { + checkRejection(javaCmd, "-d32"); } else { - // Negative tests: ensure that non-dual mode systems reject the - // complementary (other) data model - if (is32Bit) { - checkRejection(javaCmd, "-d64"); - } else if (is64Bit) { - checkRejection(javaCmd, "-d32"); - } else { - throw new Error("unsupported data model"); - } - } - } - - static void checkExecCount(String cmd, String dmodel) { - Map envMap = new HashMap<>(); - envMap.put(JLDEBUG_KEY, "true"); - TestResult tr = doExec(envMap, javaCmd, "-d64", - "-jar", TestJar.getAbsolutePath()); - int count = 0; - for (String x : tr.testOutput) { - if (x.contains(EXPECTED_MARKER)) { - count++; - if (count > 1) { - System.out.println(tr); - throw new RuntimeException("Maximum exec count of 1 execeeded"); - } - } + throw new Error("unsupported data model"); } } diff --git a/jdk/test/tools/launcher/DiacriticTest.java b/jdk/test/tools/launcher/DiacriticTest.java new file mode 100644 index 00000000000..44107bae42f --- /dev/null +++ b/jdk/test/tools/launcher/DiacriticTest.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8017248 + * @summary Compiler Diacritics Issue + * @run main DiacriticTest + */ + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; + +public class DiacriticTest extends TestHelper { + + // NFD-normalized form of the class name + static String NAME_NFD="ClassA\u0301"; + // NFC-normalized form of the same class name + static String NAME_NFC="Class\u00C1"; + + public static void main(String[] args) throws IOException { + if (!isMacOSX) { + System.out.println("This test is for Mac OS X only. Passing."); + return; + } + + File sourceFile = new File(NAME_NFC + ".java"); + String source = "public class " + NAME_NFC + " { " + + " public static void main(String args[]) {\n" + + " System.out.println(\"Success!\");\n" + + " }\n" + + "}\n"; + ArrayList content = new ArrayList<>(); + content.add(source); + createFile(sourceFile, content); + + HashMap env = new HashMap<>(); + env.put("LC_CTYPE", "UTF-8"); + + TestResult tr; + tr = doExec(env, javacCmd, NAME_NFD + ".java"); + System.out.println(tr.testOutput); + if (!tr.isOK()) { + System.out.println(tr); + throw new RuntimeException("Compilation failed"); + } + tr = doExec(env, javaCmd, "-cp", ".", NAME_NFD); + System.out.println(tr.testOutput); + if (!tr.isOK()) { + System.out.println(tr); + throw new RuntimeException("Test execution failed"); + } + } +} diff --git a/jdk/test/tools/launcher/ExecutionEnvironment.java b/jdk/test/tools/launcher/ExecutionEnvironment.java index 3b8b7eb848e..3587a1c0abe 100644 --- a/jdk/test/tools/launcher/ExecutionEnvironment.java +++ b/jdk/test/tools/launcher/ExecutionEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,7 +26,7 @@ * @bug 4780570 4731671 6354700 6367077 6670965 4882974 * @summary Checks for LD_LIBRARY_PATH and execution on *nixes * @compile -XDignore.symbol.file ExecutionEnvironment.java - * @run main ExecutionEnvironment + * @run main/othervm ExecutionEnvironment */ /* @@ -46,6 +46,9 @@ * b. LD_LIBRARY_PATH32 is ignored if set * 5. no extra symlink exists on Solaris ie. * jre/lib/$arch/libjvm.so -> client/libjvm.so + * 6. Since 32-bit Solaris is no longer supported we continue to ensure that + * the appropriate paths are ignored or used, additionally we also test to + * ensure the 64-bit isadir exists and contains appropriate links. * TODO: * a. perhaps we need to add a test to audit all environment variables are * in pristine condition after the launch, there may be a few that the @@ -54,10 +57,16 @@ */ import java.io.File; import java.io.FileNotFoundException; +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; +import static java.nio.file.LinkOption.*; +import java.util.regex.Pattern; public class ExecutionEnvironment extends TestHelper { @@ -80,13 +89,14 @@ public class ExecutionEnvironment extends TestHelper { static final File testJarFile = new File("EcoFriendly.jar"); - static int errors = 0; - static int passes = 0; - static final String LIBJVM = TestHelper.isWindows ? "jvm.dll" : "libjvm" + (TestHelper.isMacOSX ? ".dylib" : ".so"); + public ExecutionEnvironment() { + createTestJar(); + } + static void createTestJar() { try { List codeList = new ArrayList<>(); @@ -111,13 +121,17 @@ public class ExecutionEnvironment extends TestHelper { throw new RuntimeException(fnfe); } } - + private void flagError(TestResult tr, String message) { + System.err.println(tr); + throw new RuntimeException(message); + } /* * tests if the launcher pollutes the LD_LIBRARY_PATH variables ie. there * should not be any new variables or pollution/mutations of any kind, the * environment should be pristine. */ - private static void ensureEcoFriendly() { + @Test + void testEcoFriendly() { TestResult tr = null; Map env = new HashMap<>(); @@ -129,17 +143,12 @@ public class ExecutionEnvironment extends TestHelper { tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); if (!tr.isNotZeroOutput()) { - System.out.println(tr); - throw new RuntimeException("Error: No output at all. Did the test execute ?"); + flagError(tr, "Error: No output at all. Did the test execute ?"); } for (String x : LD_PATH_STRINGS) { if (!tr.contains(x)) { - System.out.println("FAIL: did not get <" + x + ">"); - System.out.println(tr); - errors++; - } else { - passes++; + flagError(tr, "FAIL: did not get <" + x + ">"); } } } @@ -148,19 +157,15 @@ public class ExecutionEnvironment extends TestHelper { * ensures that there are no execs as long as we are in the same * data model */ - static void ensureNoExec() { + @Test + void testNoExec() { Map env = new HashMap<>(); env.put(JLDEBUG_KEY, "true"); TestResult tr = doExec(env, javaCmd, "-version"); if (tr.testOutput.contains(EXPECTED_MARKER)) { - System.out.println("FAIL: EnsureNoExecs: found expected warning <" + - EXPECTED_MARKER + + flagError(tr, "testNoExec: found warning <" + EXPECTED_MARKER + "> the process execing ?"); - errors++; - } else { - passes++; } - return; } /* @@ -173,8 +178,8 @@ public class ExecutionEnvironment extends TestHelper { * For Solaris 64-bit * * The LD_LIBRARY_PATH_64 should override LD_LIBRARY_PATH if specified */ - - static void verifyJavaLibraryPath() { + @Test + void testJavaLibraryPath() { TestResult tr = null; Map env = new HashMap<>(); @@ -200,88 +205,33 @@ public class ExecutionEnvironment extends TestHelper { env.put(pairs[0], pairs[1]); } - // verify the override occurs, since we know the invocation always - // uses by default is 32-bit, therefore we also set the test - // expectation to be the same. + // verify the override occurs for 64-bit system tr = doExec(env, javaCmd, "-jar", testJarFile.getAbsolutePath()); - verifyJavaLibraryPathOverride(tr, true); - - // try changing the model from 32 to 64 bit - if (dualModePresent() && is32Bit) { - // verify the override occurs - env.clear(); - for (String x : LD_PATH_STRINGS) { - String pairs[] = x.split("="); - env.put(pairs[0], pairs[1]); - } - tr = doExec(env, javaCmd, "-d64", "-jar", - testJarFile.getAbsolutePath()); - verifyJavaLibraryPathOverride(tr, false); - - // no override - env.clear(); - env.put(LD_LIBRARY_PATH, LD_LIBRARY_PATH_VALUE); - tr = doExec(env, javaCmd, "-jar", - testJarFile.getAbsolutePath()); - verifyJavaLibraryPathGeneric(tr); - } - - // try changing the model from 64 to 32 bit - if (java64Cmd != null && is64Bit) { - // verify the override occurs - env.clear(); - for (String x : LD_PATH_STRINGS) { - String pairs[] = x.split("="); - env.put(pairs[0], pairs[1]); - } - tr = doExec(env, java64Cmd, "-d32", "-jar", - testJarFile.getAbsolutePath()); - verifyJavaLibraryPathOverride(tr, true); - - // no override - env.clear(); - env.put(LD_LIBRARY_PATH, LD_LIBRARY_PATH_VALUE); - tr = doExec(env, java64Cmd, "-d32", "-jar", - testJarFile.getAbsolutePath()); - verifyJavaLibraryPathGeneric(tr); - } + verifyJavaLibraryPathOverride(tr, false); } } - private static void verifyJavaLibraryPathGeneric(TestResult tr) { + private void verifyJavaLibraryPathGeneric(TestResult tr) { if (!tr.matches("java.library.path=.*" + LD_LIBRARY_PATH_VALUE + ".*")) { - System.out.print("FAIL: verifyJavaLibraryPath: "); - System.out.println(" java.library.path does not contain " + + flagError(tr, "testJavaLibraryPath: java.library.path does not contain " + LD_LIBRARY_PATH_VALUE); - System.out.println(tr); - errors++; - } else { - passes++; } } - private static void verifyJavaLibraryPathOverride(TestResult tr, + private void verifyJavaLibraryPathOverride(TestResult tr, boolean is32Bit) { // make sure the 32/64 bit value exists if (!tr.matches("java.library.path=.*" + (is32Bit ? LD_LIBRARY_PATH_32_VALUE : LD_LIBRARY_PATH_64_VALUE) + ".*")) { - System.out.print("FAIL: verifyJavaLibraryPathOverride: "); - System.out.println(" java.library.path does not contain " + + flagError(tr, "verifyJavaLibraryPathOverride: " + + " java.library.path does not contain " + (is32Bit ? LD_LIBRARY_PATH_32_VALUE : LD_LIBRARY_PATH_64_VALUE)); - System.out.println(tr); - errors++; - } else { - passes++; + } // make sure the generic value is absent - if (tr.matches("java.library.path=.*" + LD_LIBRARY_PATH_VALUE + ".*")) { - System.out.print("FAIL: verifyJavaLibraryPathOverride: "); - System.out.println(" java.library.path contains " + - LD_LIBRARY_PATH_VALUE); - System.out.println(tr); - errors++; - } else { - passes++; + if (!tr.notMatches("java.library.path=.*" + LD_LIBRARY_PATH_VALUE + ".*")) { + flagError(tr, "verifyJavaLibraryPathOverride: " + + " java.library.path contains " + LD_LIBRARY_PATH_VALUE); } } @@ -289,34 +239,28 @@ public class ExecutionEnvironment extends TestHelper { * ensures we have indeed exec'ed the correct vm of choice, all VMs support * -server, however 32-bit VMs support -client and -server. */ - static void verifyVmSelection() { + @Test + void testVmSelection() { TestResult tr = null; if (is32Bit) { tr = doExec(javaCmd, "-client", "-version"); if (!tr.matches(".*Client VM.*")) { - System.out.println("FAIL: the expected vm -client did not launch"); - System.out.println(tr); - errors++; - } else { - passes++; + flagError(tr, "the expected vm -client did not launch"); } } tr = doExec(javaCmd, "-server", "-version"); if (!tr.matches(".*Server VM.*")) { - System.out.println("FAIL: the expected vm -server did not launch"); - System.out.println(tr); - errors++; - } else { - passes++; + flagError(tr, "the expected vm -server did not launch"); } } /* * checks to see there is no extra libjvm.so than needed */ - static void verifyNoSymLink() { + @Test + void testNoSymLink() { if (is64Bit) { return; } @@ -326,31 +270,65 @@ public class ExecutionEnvironment extends TestHelper { symLink = new File(JAVAHOME, libPathPrefix + getJreArch() + "/" + LIBJVM); if (symLink.exists()) { - System.out.println("FAIL: The symlink exists " + - symLink.getAbsolutePath()); - errors++; - } else { - passes++; + throw new RuntimeException("symlink exists " + symLink.getAbsolutePath()); } } + /* + * verify if all the symlinks in the images are created correctly, + * only on solaris, this test works only on images. + */ + @Test + void testSymLinks() throws Exception { + if (!isSolaris) + return; + verifySymLinks(JAVA_BIN); + verifySymLinks(JAVA_JRE_BIN); + } + // exclude non-consequential binaries or scripts co-packaged in other + // build phases + private final String excludeRE = + ".*jvisualvm.*" + + "|.*javaws.*" + + "|.*ControlPanel.*" + + "|.*java-rmi.cgi" + + "|.*jcontrol.*"; + private final Pattern symlinkExcludes = Pattern.compile(excludeRE); + + private void verifySymLinks(String bindir) throws IOException { + File binDir = new File(bindir); + System.err.println("verifying links in: " + bindir); + File isaDir = new File(binDir, getArch()).getAbsoluteFile(); + if (!isaDir.exists()) { + throw new RuntimeException("dir: " + isaDir + " does not exist"); + } + try (DirectoryStream ds = Files.newDirectoryStream(binDir.toPath())) { + for (Path p : ds) { + if (symlinkExcludes.matcher(p.toString()).matches() || + Files.isDirectory(p, NOFOLLOW_LINKS)) { + continue; + } + Path link = new File(isaDir, p.getFileName().toString()).toPath(); + if (Files.isSymbolicLink(link)) { + Path target = Files.readSymbolicLink(link); + if (target.startsWith("..") && p.endsWith(target.getFileName())) { + // System.out.println(target + " OK"); + continue; + } + System.err.println("target:" + target); + System.err.println("file:" + p); + } + throw new RuntimeException("could not find link to " + p); + } + } + + } public static void main(String... args) throws Exception { if (isWindows) { - System.out.println("Warning: noop on windows"); + System.err.println("Warning: test not applicable to windows"); return; } - // create our test jar first - createTestJar(); - ensureNoExec(); - verifyVmSelection(); - ensureEcoFriendly(); - verifyJavaLibraryPath(); - verifyNoSymLink(); - if (errors > 0) { - throw new Exception("ExecutionEnvironment: FAIL: with " + - errors + " errors and passes " + passes ); - } else { - System.out.println("ExecutionEnvironment: PASS " + passes); - } + ExecutionEnvironment ee = new ExecutionEnvironment(); + ee.run(args); } } diff --git a/jdk/test/tools/launcher/FXLauncherTest.java b/jdk/test/tools/launcher/FXLauncherTest.java index 1ed251bad19..32cd7c522a0 100644 --- a/jdk/test/tools/launcher/FXLauncherTest.java +++ b/jdk/test/tools/launcher/FXLauncherTest.java @@ -405,7 +405,7 @@ public class FXLauncherTest extends TestHelper { } } else { System.err.println("Warning: JavaFX components missing or not supported"); - System.err.println(" test passes vacuosly."); + System.err.println(" test passes vacuously."); } } } diff --git a/jdk/test/tools/launcher/RunpathTest.java b/jdk/test/tools/launcher/RunpathTest.java index 79b8b0ecca7..a04609934a5 100644 --- a/jdk/test/tools/launcher/RunpathTest.java +++ b/jdk/test/tools/launcher/RunpathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,13 +64,8 @@ public class RunpathTest extends TestHelper { } void testRpath() { - if (isDualMode && is64Bit) { - String expectedRpath = ".*RPATH.*\\$ORIGIN/../../lib/" + getJreArch() + ".*"; - elfCheck(java64Cmd, expectedRpath); - } else { - String expectedRpath = ".*RPATH.*\\$ORIGIN/../lib/" + getJreArch() + ".*"; - elfCheck(javaCmd, expectedRpath); - } + String expectedRpath = ".*RPATH.*\\$ORIGIN/../../lib/" + getJreArch() + ".*"; + elfCheck(java64Cmd, expectedRpath); } public static void main(String... args) throws Exception { diff --git a/jdk/test/tools/launcher/Test7029048.java b/jdk/test/tools/launcher/Test7029048.java index aafee368432..9437c3e1817 100644 --- a/jdk/test/tools/launcher/Test7029048.java +++ b/jdk/test/tools/launcher/Test7029048.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,8 +30,8 @@ */ /* - * 7029048: test for LD_LIBRARY_PATH set to different paths pointing which may - * contain a libjvm.so and may not, but we test to ensure that the launcher + * 7029048: test for LD_LIBRARY_PATH set to different paths which may or + * may not contain a libjvm.so, but we test to ensure that the launcher * behaves correctly in all cases. */ import java.io.File; @@ -50,8 +50,6 @@ public class Test7029048 extends TestHelper { private static final String LIBJVM = ExecutionEnvironment.LIBJVM; private static final String LD_LIBRARY_PATH = ExecutionEnvironment.LD_LIBRARY_PATH; - private static final String LD_LIBRARY_PATH_32 = - ExecutionEnvironment.LD_LIBRARY_PATH_32; private static final String LD_LIBRARY_PATH_64 = ExecutionEnvironment.LD_LIBRARY_PATH_64; @@ -70,24 +68,8 @@ public class Test7029048 extends TestHelper { private static final File dstClientDir = new File(dstLibArchDir, "client"); private static final File dstClientLibjvm = new File(dstClientDir, LIBJVM); - // used primarily to test the solaris variants in dual mode - private static final File dstOtherArchDir; - private static final File dstOtherServerDir; - private static final File dstOtherServerLibjvm; - private static final Map env = new HashMap<>(); - static { - if (isDualMode) { - dstOtherArchDir = new File(dstLibDir, getComplementaryJreArch()); - dstOtherServerDir = new File(dstOtherArchDir, "server"); - dstOtherServerLibjvm = new File(dstOtherServerDir, LIBJVM); - } else { - dstOtherArchDir = null; - dstOtherServerDir = null; - dstOtherServerLibjvm = null; - } - } static String getValue(String name, List in) { for (String x : in) { @@ -99,45 +81,20 @@ public class Test7029048 extends TestHelper { return null; } - static void run(boolean want32, String dflag, Map env, + static void run(Map env, int nLLPComponents, String caseID) { - final boolean want64 = want32 == false; env.put(ExecutionEnvironment.JLDEBUG_KEY, "true"); List cmdsList = new ArrayList<>(); - - // only for a dual-mode system - if (want64 && isDualMode) { - cmdsList.add(java64Cmd); - } else { - cmdsList.add(javaCmd); // a 32-bit java command for all - } - - /* - * empty or null strings can confuse the ProcessBuilder. A null flag - * indicates that the appropriate data model is enforced on the chosen - * launcher variant. - */ - - if (dflag != null) { - cmdsList.add(dflag); - } else { - cmdsList.add(want32 ? "-d32" : "-d64"); - } + cmdsList.add(javaCmd); cmdsList.add("-server"); cmdsList.add("-jar"); cmdsList.add(ExecutionEnvironment.testJarFile.getAbsolutePath()); String[] cmds = new String[cmdsList.size()]; TestResult tr = doExec(env, cmdsList.toArray(cmds)); + System.out.println(tr); analyze(tr, nLLPComponents, caseID); } - // no cross launch, ie. no change to the data model. - static void run(Map env, int nLLPComponents, String caseID) - throws IOException { - boolean want32 = is32Bit; - run(want32, null, env, nLLPComponents, caseID); - } - static void analyze(TestResult tr, int nLLPComponents, String caseID) { String envValue = getValue(LD_LIBRARY_PATH, tr.testOutput); /* @@ -192,10 +149,6 @@ public class Test7029048 extends TestHelper { copyFile(srcLibjvmSo, dstServerLibjvm); // does not matter if it is client or a server copyFile(srcLibjvmSo, dstClientLibjvm); - // does not matter if the arch do not match either - if (isDualMode) { - copyFile(srcLibjvmSo, dstOtherServerLibjvm); - } desc = "LD_LIBRARY_PATH should be set"; break; case LLP_SET_EMPTY_PATH: @@ -211,14 +164,6 @@ public class Test7029048 extends TestHelper { Files.deleteIfExists(dstServerLibjvm.toPath()); } - if (isDualMode) { - if (!dstOtherServerDir.exists()) { - Files.createDirectories(dstOtherServerDir.toPath()); - } else { - Files.deleteIfExists(dstOtherServerLibjvm.toPath()); - } - } - desc = "LD_LIBRARY_PATH should not be set"; break; case LLP_SET_NON_EXISTENT_PATH: @@ -245,40 +190,14 @@ public class Test7029048 extends TestHelper { env.put(LD_LIBRARY_PATH, dstClientDir.getAbsolutePath()); run(env, v.value + 1, "Case 2: " + desc); - if (!isDualMode) { - continue; // nothing more to do for Linux - } - - // Tests applicable only to solaris. - - // initialize test variables for dual mode operations - final File dst32ServerDir = is32Bit - ? dstServerDir - : dstOtherServerDir; - - final File dst64ServerDir = is64Bit - ? dstServerDir - : dstOtherServerDir; - - /* - * Case 3: set the appropriate LLP_XX flag, - * java32 -d32, LLP_32 is relevant, LLP_64 is ignored - * java64 -d64, LLP_64 is relevant, LLP_32 is ignored - */ - env.clear(); - env.put(LD_LIBRARY_PATH_32, dst32ServerDir.getAbsolutePath()); - env.put(LD_LIBRARY_PATH_64, dst64ServerDir.getAbsolutePath()); - run(is32Bit, null, env, v.value + 1, "Case 3: " + desc); - - /* - * Case 4: we are in dual mode environment, running 64-bit then - * we have the following scenarios: - * java32 -d64, LLP_64 is relevant, LLP_32 is ignored - * java64 -d32, LLP_32 is relevant, LLP_64 is ignored - */ - if (dualModePresent()) { - run(true, "-d64", env, v.value + 1, "Case 4A: " + desc); - run(false,"-d32", env, v.value + 1, "Case 4B: " + desc); + if (isSolaris) { + /* + * Case 3: set the appropriate LLP_XX flag, + * java64 -d64, LLP_64 is relevant, LLP_32 is ignored + */ + env.clear(); + env.put(LD_LIBRARY_PATH_64, dstServerDir.getAbsolutePath()); + run(env, v.value + 1, "Case 3: " + desc); } } return; @@ -297,9 +216,6 @@ public class Test7029048 extends TestHelper { if (errors > 0) { throw new Exception("Test7029048: FAIL: with " + errors + " errors and passes " + passes); - } else if (dualModePresent() && passes < 15) { - throw new Exception("Test7029048: FAIL: " + - "all tests did not run, expected " + 15 + " got " + passes); } else if (isSolaris && passes < 9) { throw new Exception("Test7029048: FAIL: " + "all tests did not run, expected " + 9 + " got " + passes); diff --git a/jdk/test/tools/launcher/TestHelper.java b/jdk/test/tools/launcher/TestHelper.java index 0115f057142..6f827f3ce0d 100644 --- a/jdk/test/tools/launcher/TestHelper.java +++ b/jdk/test/tools/launcher/TestHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -66,10 +66,10 @@ public class TestHelper { static final String JAVAHOME = System.getProperty("java.home"); static final String JAVA_BIN; + static final String JAVA_JRE_BIN; static final boolean isSDK = JAVAHOME.endsWith("jre"); static final String javaCmd; static final String javawCmd; - static final String java64Cmd; static final String javacCmd; static final String jarCmd; @@ -88,7 +88,7 @@ public class TestHelper { System.getProperty("os.name", "unknown").startsWith("SunOS"); static final boolean isLinux = System.getProperty("os.name", "unknown").startsWith("Linux"); - static final boolean isDualMode = isSolaris; + static final boolean isSparc = System.getProperty("os.arch").startsWith("sparc"); // make a note of the golden default locale @@ -124,9 +124,12 @@ public class TestHelper { throw new RuntimeException("arch model is not 32 or 64 bit ?"); } compiler = ToolProvider.getSystemJavaCompiler(); - File binDir = (isSDK) ? new File((new File(JAVAHOME)).getParentFile(), "bin") - : new File(JAVAHOME, "bin"); + File binDir = (isSDK) + ? new File((new File(JAVAHOME)).getParentFile(), "bin") + : new File(JAVAHOME, "bin"); JAVA_BIN = binDir.getAbsolutePath(); + JAVA_JRE_BIN = new File((new File(JAVAHOME)).getParentFile(), + (isSDK) ? "jre/bin" : "bin").getAbsolutePath(); File javaCmdFile = (isWindows) ? new File(binDir, "java.exe") : new File(binDir, "java"); @@ -165,17 +168,6 @@ public class TestHelper { throw new RuntimeException("java <" + javacCmd + "> must exist and should be executable"); } - if (isSolaris) { - File sparc64BinDir = new File(binDir,isSparc ? "sparcv9" : "amd64"); - File java64CmdFile= new File(sparc64BinDir, "java"); - if (java64CmdFile.exists() && java64CmdFile.canExecute()) { - java64Cmd = java64CmdFile.getAbsolutePath(); - } else { - java64Cmd = null; - } - } else { - java64Cmd = null; - } } void run(String[] args) throws Exception { int passed = 0, failed = 0; @@ -194,7 +186,13 @@ public class TestHelper { System.out.printf("Passed: %d, Failed: %d, ExitValue: %d%n", passed, failed, testExitValue); } catch (Throwable ex) { - System.out.printf("Test %s failed: %s %n", m, ex.getCause()); + System.out.printf("Test %s failed: %s %n", m, ex); + System.out.println("----begin detailed exceptions----"); + ex.printStackTrace(System.out); + for (Throwable t : ex.getSuppressed()) { + t.printStackTrace(System.out); + } + System.out.println("----end detailed exceptions----"); failed++; } } @@ -209,13 +207,6 @@ public class TestHelper { } } - /* - * is a dual mode available in the test jdk - */ - static boolean dualModePresent() { - return isDualMode && java64Cmd != null; - } - /* * usually the jre/lib/arch-name is the same as os.arch, except for x86. */ @@ -223,28 +214,9 @@ public class TestHelper { String arch = System.getProperty("os.arch"); return arch.equals("x86") ? "i386" : arch; } - - /* - * get the complementary jre arch ie. if sparc then return sparcv9 and - * vice-versa. - */ - static String getComplementaryJreArch() { - String arch = System.getProperty("os.arch"); - if (arch != null) { - switch (arch) { - case "sparc": - return "sparcv9"; - case "sparcv9": - return "sparc"; - case "x86": - return "amd64"; - case "amd64": - return "i386"; - } - } - return null; + static String getArch() { + return System.getProperty("os.arch"); } - static File getClassFile(File javaFile) { String s = javaFile.getAbsolutePath().replace(JAVA_FILE_EXT, CLASS_FILE_EXT); return new File(s); @@ -623,6 +595,16 @@ public class TestHelper { appendError("string <" + stringToMatch + "> not found"); return false; } + + boolean notMatches(String stringToMatch) { + for (String x : testOutput) { + if (!x.matches(stringToMatch)) { + return true; + } + } + appendError("string <" + stringToMatch + "> found"); + return false; + } } /** * Indicates that the annotated method is a test method. diff --git a/langtools/.hgtags b/langtools/.hgtags index d15910c1e57..cd1913f9ccb 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -228,3 +228,6 @@ ce5a90df517bdceb2739d7dd3e6764b070def802 jdk8-b98 dd4a00c220c6e14d9b2ce93a2bd436a1d04f0d03 jdk8-b104 375834b5cf086dd7ce9e49f602d81bb51d3e0fa9 jdk8-b105 fcd768844b9926c5f994292ec6350c20cc7c0f76 jdk8-b106 +3f274927ec1863544b8214262ab02b7de2970da6 jdk8-b107 +252f872b8a2f81a416f9127e77924ca56a4578b0 jdk8-b108 +985abf1cd327169a317d4ff4f318a8162a5cd47d jdk8-b109 diff --git a/langtools/README b/langtools/README index bc8873178ef..94beb071e92 100644 --- a/langtools/README +++ b/langtools/README @@ -32,7 +32,7 @@ tests that the compiler performs according to the specifications in JLS and JVMS. In addition, there is a substantial collection of regression and unit -tests for all the tools in the maain langtools test/ directory. +tests for all the tools in the main langtools test/ directory. Finally, there is a small set of tests to do basic validation of a build of the langtools workspace for use by JDK. These tests check the contents diff --git a/langtools/make/jprt.properties b/langtools/make/jprt.properties index c0399ed7083..734fa8cd89d 100644 --- a/langtools/make/jprt.properties +++ b/langtools/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -40,8 +40,8 @@ jprt.build.targets= \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ macosx_x64_10.7-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # Test target list (no fastdebug & limited c2 testing) jprt.my.test.target.set= \ @@ -52,8 +52,8 @@ jprt.my.test.target.set= \ linux_i586_2.6-product-{c1|c2}-TESTNAME, \ linux_x64_2.6-product-c2-TESTNAME, \ macosx_x64_10.7-product-c2-TESTNAME, \ - windows_i586_5.1-product-c1-TESTNAME, \ - windows_x64_5.2-product-c2-TESTNAME + windows_i586_6.1-product-c1-TESTNAME, \ + windows_x64_6.1-product-c2-TESTNAME # Default test targets jprt.make.rule.test.targets= \ @@ -71,8 +71,8 @@ jprt.my.test.target.set= \ linux_i586_2.6-product-{c1|c2}-TESTNAME, \ linux_x64_2.6-product-c2-TESTNAME, \ macosx_x64_10.7-product-c2-TESTNAME, \ - windows_i586_5.1-product-c1-TESTNAME, \ - windows_x64_5.2-product-c2-TESTNAME + windows_i586_6.1-product-c1-TESTNAME, \ + windows_x64_6.1-product-c2-TESTNAME # Default test targets jprt.make.rule.test.targets= \ diff --git a/langtools/make/netbeans/langtools/build.xml b/langtools/make/netbeans/langtools/build.xml index dd2caf9e3bc..c0b6ae26c29 100644 --- a/langtools/make/netbeans/langtools/build.xml +++ b/langtools/make/netbeans/langtools/build.xml @@ -1,6 +1,6 @@ @@ -136,9 +144,9 @@ - + - + @@ -207,6 +215,7 @@ @@ -216,6 +225,7 @@ @@ -226,10 +236,12 @@ + + - + diff --git a/langtools/make/tools/anttasks/SelectToolTask.java b/langtools/make/tools/anttasks/SelectToolTask.java index fb2cf49e312..8cad36f6059 100644 --- a/langtools/make/tools/anttasks/SelectToolTask.java +++ b/langtools/make/tools/anttasks/SelectToolTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,6 +43,7 @@ import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.Arrays; +import java.util.EnumSet; import java.util.List; import java.util.Properties; import javax.swing.JButton; @@ -71,6 +72,32 @@ import org.apache.tools.ant.Task; * is invoked to allow the user to set or reset values for use in property mode. */ public class SelectToolTask extends Task { + + enum ToolChoices { + NONE(""), + JAVAC("javac"), + JAVADOC("javadoc"), + JAVAH("javah"), + JAVAP("javap"); + + String toolName; + boolean bootstrap; + + ToolChoices(String toolName) { + this(toolName, false); + } + + ToolChoices(String toolName, boolean bootstrap) { + this.toolName = toolName; + this.bootstrap = bootstrap; + } + + @Override + public String toString() { + return toolName; + } + } + /** * Set the location of the private properties file used to keep the retain * user preferences for this repository. @@ -96,6 +123,14 @@ public class SelectToolTask extends Task { this.argsProperty = argsProperty; } + /** + * Set the name of the property which will be set to the execution args of the + * selected tool, if any. The args default to an empty string. + */ + public void setBootstrapProperty(String bootstrapProperty) { + this.bootstrapProperty = bootstrapProperty; + } + /** * Specify whether or not to pop up a dialog if the user has not specified * a default value for a property. @@ -110,6 +145,7 @@ public class SelectToolTask extends Task { Properties props = readProperties(propertyFile); toolName = props.getProperty("tool.name"); + toolBootstrap = props.getProperty("tool.bootstrap") != null; if (toolName != null) { toolArgs = props.getProperty(toolName + ".args", ""); } @@ -123,6 +159,8 @@ public class SelectToolTask extends Task { // finally, return required values, if any if (toolProperty != null && !(toolName == null || toolName.equals(""))) { p.setProperty(toolProperty, toolName); + if (toolBootstrap) + p.setProperty(bootstrapProperty, "true"); if (argsProperty != null && toolArgs != null) p.setProperty(argsProperty, toolArgs); @@ -134,14 +172,20 @@ public class SelectToolTask extends Task { JOptionPane p = createPane(guiProps); p.createDialog("Select Tool").setVisible(true); - toolName = (String) toolChoice.getSelectedItem(); + toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName; toolArgs = argsField.getText(); - + toolBootstrap = bootstrapCheckbox.isSelected(); if (defaultCheck.isSelected()) { if (toolName.equals("")) { fileProps.remove("tool.name"); + fileProps.remove("tool.bootstrap"); } else { fileProps.put("tool.name", toolName); + if (toolBootstrap) { + fileProps.put("tool.bootstrap", "true"); + } else { + fileProps.remove("tool.bootstrap"); + } fileProps.put(toolName + ".args", toolArgs); } writeProperties(propertyFile, fileProps); @@ -154,32 +198,38 @@ public class SelectToolTask extends Task { lc.insets.right = 10; lc.insets.bottom = 3; GridBagConstraints fc = new GridBagConstraints(); - fc.anchor = GridBagConstraints.WEST; fc.gridx = 1; - fc.gridwidth = GridBagConstraints.REMAINDER; + fc.gridwidth = GridBagConstraints.NONE; fc.insets.bottom = 3; + JPanel toolPane = new JPanel(new GridBagLayout()); + JLabel toolLabel = new JLabel("Tool:"); body.add(toolLabel, lc); - String[] toolChoices = { "apt", "javac", "javadoc", "javah", "javap" }; - if (true || toolProperty == null) { - // include empty value in setup mode - List l = new ArrayList(Arrays.asList(toolChoices)); - l.add(0, ""); - toolChoices = l.toArray(new String[l.size()]); - } - toolChoice = new JComboBox(toolChoices); + EnumSet toolChoices = toolProperty == null ? + EnumSet.allOf(ToolChoices.class) : EnumSet.range(ToolChoices.JAVAC, ToolChoices.JAVAP); + toolChoice = new JComboBox(toolChoices.toArray()); if (toolName != null) - toolChoice.setSelectedItem(toolName); + toolChoice.setSelectedItem(ToolChoices.valueOf(toolName.toUpperCase())); toolChoice.addItemListener(new ItemListener() { public void itemStateChanged(ItemEvent e) { - String tn = (String) e.getItem(); + String tn = ((ToolChoices)e.getItem()).toolName; argsField.setText(getDefaultArgsForTool(props, tn)); if (toolProperty != null) okButton.setEnabled(!tn.equals("")); } }); - body.add(toolChoice, fc); + GridBagConstraints checkConstraint = new GridBagConstraints(); + fc.anchor = GridBagConstraints.EAST; + + GridBagConstraints toolConstraint = new GridBagConstraints(); + fc.anchor = GridBagConstraints.WEST; + + toolPane.add(toolChoice, toolConstraint); + bootstrapCheckbox = new JCheckBox("bootstrap", toolBootstrap); + toolPane.add(bootstrapCheckbox, checkConstraint); + + body.add(toolPane, fc); argsField = new JTextField(getDefaultArgsForTool(props, toolName), 40); if (toolProperty == null || argsProperty != null) { @@ -190,7 +240,7 @@ public class SelectToolTask extends Task { public void focusGained(FocusEvent e) { } public void focusLost(FocusEvent e) { - String toolName = (String) toolChoice.getSelectedItem(); + String toolName = ((ToolChoices)toolChoice.getSelectedItem()).toolName; if (toolName.length() > 0) props.put(toolName + ".args", argsField.getText()); } @@ -271,16 +321,19 @@ public class SelectToolTask extends Task { // Ant task parameters private boolean askIfUnset; private String toolProperty; + private String bootstrapProperty; private String argsProperty; private File propertyFile; // GUI components private JComboBox toolChoice; + private JCheckBox bootstrapCheckbox; private JTextField argsField; private JCheckBox defaultCheck; private JButton okButton; // Result values for the client private String toolName; + private boolean toolBootstrap; private String toolArgs; } diff --git a/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java b/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java index 5d7c81474f2..6d5b7e6bef8 100644 --- a/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java +++ b/langtools/src/share/classes/com/sun/tools/classfile/Code_attribute.java @@ -61,9 +61,9 @@ public class Code_attribute extends Attribute { code_length = cr.readInt(); code = new byte[code_length]; cr.readFully(code); - exception_table_langth = cr.readUnsignedShort(); - exception_table = new Exception_data[exception_table_langth]; - for (int i = 0; i < exception_table_langth; i++) + exception_table_length = cr.readUnsignedShort(); + exception_table = new Exception_data[exception_table_length]; + for (int i = 0; i < exception_table_length; i++) exception_table[i] = new Exception_data(cr); attributes = new Attributes(cr); } @@ -139,7 +139,7 @@ public class Code_attribute extends Attribute { public final int max_locals; public final int code_length; public final byte[] code; - public final int exception_table_langth; + public final int exception_table_length; public final Exception_data[] exception_table; public final Attributes attributes; diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java index bd84d2caf2d..91877d1cdfa 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AbstractPackageIndexWriter.java @@ -157,7 +157,7 @@ public abstract class AbstractPackageIndexWriter extends HtmlDocletWriter { addAllProfilesLink(div); } body.addContent(div); - if (configuration.showProfiles) { + if (configuration.showProfiles && configuration.profilePackages.size() > 0) { Content profileSummary = configuration.getResource("doclet.Profiles"); addProfilesList(profileSummary, body); } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java new file mode 100644 index 00000000000..f4c7c68f565 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeFieldWriterImpl.java @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.doclets.formats.html; + +import java.io.*; + +import com.sun.javadoc.*; +import com.sun.tools.doclets.formats.html.markup.*; +import com.sun.tools.doclets.internal.toolkit.*; + +/** + * Writes annotation type field documentation in HTML format. + * + *

        This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + */ +public class AnnotationTypeFieldWriterImpl extends AbstractMemberWriter + implements AnnotationTypeFieldWriter, MemberSummaryWriter { + + /** + * Construct a new AnnotationTypeFieldWriterImpl. + * + * @param writer the writer that will write the output. + * @param annotationType the AnnotationType that holds this member. + */ + public AnnotationTypeFieldWriterImpl(SubWriterHolderWriter writer, + AnnotationTypeDoc annotationType) { + super(writer, annotationType); + } + + /** + * {@inheritDoc} + */ + public Content getMemberSummaryHeader(ClassDoc classDoc, + Content memberSummaryTree) { + memberSummaryTree.addContent( + HtmlConstants.START_OF_ANNOTATION_TYPE_FIELD_SUMMARY); + Content memberTree = writer.getMemberTreeHeader(); + writer.addSummaryHeader(this, classDoc, memberTree); + return memberTree; + } + + /** + * {@inheritDoc} + */ + public Content getMemberTreeHeader() { + return writer.getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationFieldDetailsMarker(Content memberDetails) { + memberDetails.addContent(HtmlConstants.START_OF_ANNOTATION_TYPE_FIELD_DETAILS); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree) { + if (!writer.printedAnnotationFieldHeading) { + memberDetailsTree.addContent(writer.getMarkerAnchor( + "annotation_type_field_detail")); + Content heading = HtmlTree.HEADING(HtmlConstants.DETAILS_HEADING, + writer.fieldDetailsLabel); + memberDetailsTree.addContent(heading); + writer.printedAnnotationFieldHeading = true; + } + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDocTreeHeader(MemberDoc member, + Content annotationDetailsTree) { + annotationDetailsTree.addContent( + writer.getMarkerAnchor(member.name())); + Content annotationDocTree = writer.getMemberTreeHeader(); + Content heading = new HtmlTree(HtmlConstants.MEMBER_HEADING); + heading.addContent(member.name()); + annotationDocTree.addContent(heading); + return annotationDocTree; + } + + /** + * {@inheritDoc} + */ + public Content getSignature(MemberDoc member) { + Content pre = new HtmlTree(HtmlTag.PRE); + writer.addAnnotationInfo(member, pre); + addModifiers(member, pre); + Content link = + writer.getLink(new LinkInfoImpl(configuration, + LinkInfoImpl.Kind.MEMBER, getType(member))); + pre.addContent(link); + pre.addContent(writer.getSpace()); + if (configuration.linksource) { + Content memberName = new StringContent(member.name()); + writer.addSrcLink(member, memberName, pre); + } else { + addName(member.name(), pre); + } + return pre; + } + + /** + * {@inheritDoc} + */ + public void addDeprecated(MemberDoc member, Content annotationDocTree) { + addDeprecatedInfo(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public void addComments(MemberDoc member, Content annotationDocTree) { + addComment(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public void addTags(MemberDoc member, Content annotationDocTree) { + writer.addTagsInfo(member, annotationDocTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDetails(Content annotationDetailsTree) { + return getMemberTree(annotationDetailsTree); + } + + /** + * {@inheritDoc} + */ + public Content getAnnotationDoc(Content annotationDocTree, + boolean isLastContent) { + return getMemberTree(annotationDocTree, isLastContent); + } + + /** + * Close the writer. + */ + public void close() throws IOException { + writer.close(); + } + + /** + * {@inheritDoc} + */ + public void addSummaryLabel(Content memberTree) { + Content label = HtmlTree.HEADING(HtmlConstants.SUMMARY_HEADING, + writer.getResource("doclet.Field_Summary")); + memberTree.addContent(label); + } + + /** + * {@inheritDoc} + */ + public String getTableSummary() { + return configuration.getText("doclet.Member_Table_Summary", + configuration.getText("doclet.Field_Summary"), + configuration.getText("doclet.fields")); + } + + /** + * {@inheritDoc} + */ + public Content getCaption() { + return configuration.getResource("doclet.Fields"); + } + + /** + * {@inheritDoc} + */ + public String[] getSummaryTableHeader(ProgramElementDoc member) { + String[] header = new String[] { + writer.getModifierTypeHeader(), + configuration.getText("doclet.0_and_1", + configuration.getText("doclet.Fields"), + configuration.getText("doclet.Description")) + }; + return header; + } + + /** + * {@inheritDoc} + */ + public void addSummaryAnchor(ClassDoc cd, Content memberTree) { + memberTree.addContent(writer.getMarkerAnchor( + "annotation_type_field_summary")); + } + + /** + * {@inheritDoc} + */ + public void addInheritedSummaryAnchor(ClassDoc cd, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + public void addInheritedSummaryLabel(ClassDoc cd, Content inheritedTree) { + } + + /** + * {@inheritDoc} + */ + protected void addSummaryLink(LinkInfoImpl.Kind context, ClassDoc cd, ProgramElementDoc member, + Content tdSummary) { + Content strong = HtmlTree.SPAN(HtmlStyle.strong, + writer.getDocLink(context, (MemberDoc) member, member.name(), false)); + Content code = HtmlTree.CODE(strong); + tdSummary.addContent(code); + } + + /** + * {@inheritDoc} + */ + protected void addInheritedSummaryLink(ClassDoc cd, + ProgramElementDoc member, Content linksTree) { + //Not applicable. + } + + /** + * {@inheritDoc} + */ + protected void addSummaryType(ProgramElementDoc member, Content tdSummaryType) { + MemberDoc m = (MemberDoc)member; + addModifierAndType(m, getType(m), tdSummaryType); + } + + /** + * {@inheritDoc} + */ + protected Content getDeprecatedLink(ProgramElementDoc member) { + return writer.getDocLink(LinkInfoImpl.Kind.MEMBER, + (MemberDoc) member, ((MemberDoc)member).qualifiedName()); + } + + /** + * {@inheritDoc} + */ + protected Content getNavSummaryLink(ClassDoc cd, boolean link) { + if (link) { + return writer.getHyperLink("annotation_type_field_summary", + writer.getResource("doclet.navField")); + } else { + return writer.getResource("doclet.navField"); + } + } + + /** + * {@inheritDoc} + */ + protected void addNavDetailLink(boolean link, Content liNav) { + if (link) { + liNav.addContent(writer.getHyperLink("annotation_type_field_detail", + writer.getResource("doclet.navField"))); + } else { + liNav.addContent(writer.getResource("doclet.navField")); + } + } + + private Type getType(MemberDoc member) { + if (member instanceof FieldDoc) { + return ((FieldDoc) member).type(); + } else { + return ((MethodDoc) member).returnType(); + } + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java index a2fa33b68a5..1833d262db3 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeRequiredMemberWriterImpl.java @@ -68,6 +68,20 @@ public class AnnotationTypeRequiredMemberWriterImpl extends AbstractMemberWriter return memberTree; } + /** + * {@inheritDoc} + */ + public Content getMemberTreeHeader() { + return writer.getMemberTreeHeader(); + } + + /** + * {@inheritDoc} + */ + public void addAnnotationDetailsMarker(Content memberDetails) { + memberDetails.addContent(HtmlConstants.START_OF_ANNOTATION_TYPE_DETAILS); + } + /** * {@inheritDoc} */ diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java index 869bc75f89c..c90ae08c27e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java @@ -118,7 +118,7 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter if (prev != null) { Content prevLink = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS, prev.asClassDoc()) - .label(configuration.getText("doclet.Prev_Class")).strong(true)); + .label(prevclassLabel).strong(true)); li = HtmlTree.LI(prevLink); } else @@ -136,7 +136,7 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter if (next != null) { Content nextLink = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS, next.asClassDoc()) - .label(configuration.getText("doclet.Next_Class")).strong(true)); + .label(nextclassLabel).strong(true)); li = HtmlTree.LI(nextLink); } else @@ -275,13 +275,6 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter } } - /** - * {@inheritDoc} - */ - public void addAnnotationDetailsMarker(Content memberDetails) { - memberDetails.addContent(HtmlConstants.START_OF_ANNOTATION_TYPE_DETAILS); - } - /** * {@inheritDoc} */ @@ -319,6 +312,12 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) configuration.getBuilderFactory().getMemberSummaryBuilder(this); + Content liNavField = new HtmlTree(HtmlTag.LI); + addNavSummaryLink(memberSummaryBuilder, + "doclet.navField", + VisibleMemberMap.ANNOTATION_TYPE_FIELDS, liNavField); + addNavGap(liNavField); + ulNav.addContent(liNavField); Content liNavReq = new HtmlTree(HtmlTag.LI); addNavSummaryLink(memberSummaryBuilder, "doclet.navAnnotationTypeRequiredMember", @@ -364,12 +363,23 @@ public class AnnotationTypeWriterImpl extends SubWriterHolderWriter Content ulNav = HtmlTree.UL(HtmlStyle.subNavList, li); MemberSummaryBuilder memberSummaryBuilder = (MemberSummaryBuilder) configuration.getBuilderFactory().getMemberSummaryBuilder(this); + AbstractMemberWriter writerField = + ((AbstractMemberWriter) memberSummaryBuilder. + getMemberSummaryWriter(VisibleMemberMap.ANNOTATION_TYPE_FIELDS)); AbstractMemberWriter writerOptional = ((AbstractMemberWriter) memberSummaryBuilder. getMemberSummaryWriter(VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL)); AbstractMemberWriter writerRequired = ((AbstractMemberWriter) memberSummaryBuilder. getMemberSummaryWriter(VisibleMemberMap.ANNOTATION_TYPE_MEMBER_REQUIRED)); + Content liNavField = new HtmlTree(HtmlTag.LI); + if (writerField != null){ + writerField.addNavDetailLink(annotationType.fields().length > 0, liNavField); + } else { + liNavField.addContent(getResource("doclet.navField")); + } + addNavGap(liNavField); + ulNav.addContent(liNavField); if (writerOptional != null){ Content liNavOpt = new HtmlTree(HtmlTag.LI); writerOptional.addNavDetailLink(annotationType.elements().length > 0, liNavOpt); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java index 25f0f618af9..7899445dd4a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ClassWriterImpl.java @@ -126,7 +126,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter if (prev != null) { Content prevLink = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS, prev) - .label(configuration.getText("doclet.Prev_Class")).strong(true)); + .label(prevclassLabel).strong(true)); li = HtmlTree.LI(prevLink); } else @@ -144,7 +144,7 @@ public class ClassWriterImpl extends SubWriterHolderWriter if (next != null) { Content nextLink = getLink(new LinkInfoImpl(configuration, LinkInfoImpl.Kind.CLASS, next) - .label(configuration.getText("doclet.Next_Class")).strong(true)); + .label(nextclassLabel).strong(true)); li = HtmlTree.LI(nextLink); } else diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java index 24c95876e6f..bf61cd1fae5 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDoclet.java @@ -205,13 +205,20 @@ public class HtmlDoclet extends AbstractDoclet { * {@inheritDoc} */ protected void generateProfileFiles() throws Exception { - if (configuration.showProfiles) { + if (configuration.showProfiles && configuration.profilePackages.size() > 0) { ProfileIndexFrameWriter.generate(configuration); Profile prevProfile = null, nextProfile; + String profileName; for (int i = 1; i < configuration.profiles.getProfileCount(); i++) { - ProfilePackageIndexFrameWriter.generate(configuration, Profile.lookup(i).name); + profileName = Profile.lookup(i).name; + // Generate profile package pages only if there are any packages + // in a profile to be documented. The profilePackages map will not + // contain an entry for the profile if there are no packages to be documented. + if (!configuration.shouldDocumentProfile(profileName)) + continue; + ProfilePackageIndexFrameWriter.generate(configuration, profileName); PackageDoc[] packages = configuration.profilePackages.get( - Profile.lookup(i).name); + profileName); PackageDoc prev = null, next; for (int j = 0; j < packages.length; j++) { // if -nodeprecated option is set and the package is marked as diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java index 8dcf113e3f3..b3bfdcb1c3c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java @@ -84,6 +84,11 @@ public class HtmlDocletWriter extends HtmlDocWriter { */ protected boolean printedAnnotationHeading = false; + /** + * To check whether annotation field heading is printed or not. + */ + protected boolean printedAnnotationFieldHeading = false; + /** * To check whether the repeated annotations is documented or not. */ @@ -406,10 +411,7 @@ public class HtmlDocletWriter extends HtmlDocWriter { Content htmlDocType = DocType.TRANSITIONAL; Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); Content head = new HtmlTree(HtmlTag.HEAD); - if (!configuration.notimestamp) { - Content headComment = new Comment(getGeneratedByString()); - head.addContent(headComment); - } + head.addContent(getGeneratedBy(!configuration.notimestamp)); if (configuration.charset.length() > 0) { Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset); @@ -502,16 +504,17 @@ public class HtmlDocletWriter extends HtmlDocWriter { if (!configuration.nonavbar) { String allClassesId = "allclasses_"; HtmlTree navDiv = new HtmlTree(HtmlTag.DIV); + Content skipNavLinks = configuration.getResource("doclet.Skip_navigation_links"); if (header) { body.addContent(HtmlConstants.START_OF_TOP_NAVBAR); navDiv.addStyle(HtmlStyle.topNav); allClassesId += "navbar_top"; Content a = getMarkerAnchor("navbar_top"); + //WCAG - Hyperlinks should contain text or an image with alt text - for AT tools navDiv.addContent(a); - Content skipLinkContent = getHyperLink(DocLink.fragment("skip-navbar_top"), - HtmlTree.EMPTY, - configuration.getText("doclet.Skip_navigation_links"), - ""); + Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink( + DocLink.fragment("skip-navbar_top"), skipNavLinks, + skipNavLinks.toString(), "")); navDiv.addContent(skipLinkContent); } else { body.addContent(HtmlConstants.START_OF_BOTTOM_NAVBAR); @@ -519,10 +522,9 @@ public class HtmlDocletWriter extends HtmlDocWriter { allClassesId += "navbar_bottom"; Content a = getMarkerAnchor("navbar_bottom"); navDiv.addContent(a); - Content skipLinkContent = getHyperLink(DocLink.fragment("skip-navbar_bottom"), - HtmlTree.EMPTY, - configuration.getText("doclet.Skip_navigation_links"), - ""); + Content skipLinkContent = HtmlTree.DIV(HtmlStyle.skipNav, getHyperLink( + DocLink.fragment("skip-navbar_bottom"), skipNavLinks, + skipNavLinks.toString(), "")); navDiv.addContent(skipLinkContent); } if (header) { diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java index 7a67b38d102..caf0e0976a6 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/PackageIndexWriter.java @@ -130,10 +130,14 @@ public class PackageIndexWriter extends AbstractPackageIndexWriter { String profileName; for (int i = 1; i < configuration.profiles.getProfileCount(); i++) { profileName = Profile.lookup(i).name; - Content profileLinkContent = getTargetProfileLink("classFrame", - new StringContent(profileName), profileName); - Content li = HtmlTree.LI(profileLinkContent); - ul.addContent(li); + // If the profile has valid packages to be documented, add it to the + // profiles list on overview-summary.html page. + if (configuration.shouldDocumentProfile(profileName)) { + Content profileLinkContent = getTargetProfileLink("classFrame", + new StringContent(profileName), profileName); + Content li = HtmlTree.LI(profileLinkContent); + ul.addContent(li); + } } profilesDiv.addContent(ul); Content div = HtmlTree.DIV(HtmlStyle.contentContainer, profilesDiv); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java index c7217cd5037..c5caa90a10c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileIndexFrameWriter.java @@ -88,8 +88,13 @@ public class ProfileIndexFrameWriter extends AbstractProfileIndexWriter { Content div = HtmlTree.DIV(HtmlStyle.indexContainer, heading); HtmlTree ul = new HtmlTree(HtmlTag.UL); ul.setTitle(profilesLabel); + String profileName; for (int i = 1; i < profiles.getProfileCount(); i++) { - ul.addContent(getProfile(i)); + profileName = (Profile.lookup(i)).name; + // If the profile has valid packages to be documented, add it to the + // left-frame generated for profile index. + if (configuration.shouldDocumentProfile(profileName)) + ul.addContent(getProfile(profileName)); } div.addContent(ul); body.addContent(div); @@ -98,13 +103,12 @@ public class ProfileIndexFrameWriter extends AbstractProfileIndexWriter { /** * Gets each profile name as a separate link. * - * @param profile the profile being documented + * @param profileName the profile being documented * @return content for the profile link */ - protected Content getProfile(int profile) { + protected Content getProfile(String profileName) { Content profileLinkContent; Content profileLabel; - String profileName = (Profile.lookup(profile)).name; profileLabel = new StringContent(profileName); profileLinkContent = getHyperLink(DocPaths.profileFrame(profileName), profileLabel, "", "packageListFrame"); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java index 5dae2e944a4..ebe8b0d1e69 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/ProfileWriterImpl.java @@ -138,6 +138,7 @@ public class ProfileWriterImpl extends HtmlDocletWriter "classFrame", new StringContent(pkg.name()), profile.name); Content heading = HtmlTree.HEADING(HtmlTag.H3, pkgName); HtmlTree li = HtmlTree.LI(HtmlStyle.blockList, heading); + addPackageDeprecationInfo(li, pkg); return li; } @@ -174,6 +175,30 @@ public class ProfileWriterImpl extends HtmlDocletWriter true, contentTree); } + /** + * Add the profile package deprecation information to the documentation tree. + * + * @param li the content tree to which the deprecation information will be added + * @param pkg the PackageDoc that is added + */ + public void addPackageDeprecationInfo(Content li, PackageDoc pkg) { + Tag[] deprs; + if (Util.isDeprecated(pkg)) { + deprs = pkg.tags("deprecated"); + HtmlTree deprDiv = new HtmlTree(HtmlTag.DIV); + deprDiv.addStyle(HtmlStyle.deprecatedContent); + Content deprPhrase = HtmlTree.SPAN(HtmlStyle.strong, deprecatedPhrase); + deprDiv.addContent(deprPhrase); + if (deprs.length > 0) { + Tag[] commentTags = deprs[0].inlineTags(); + if (commentTags.length > 0) { + addInlineDeprecatedComment(pkg, deprs[0], deprDiv); + } + } + li.addContent(deprDiv); + } + } + /** * Get "PREV PROFILE" link in the navigation bar. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java index b8a1775c7be..70bace904ab 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/WriterFactoryImpl.java @@ -104,6 +104,16 @@ public class WriterFactoryImpl implements WriterFactory { annotationType, prevType, nextType); } + /** + * {@inheritDoc} + */ + public AnnotationTypeFieldWriter + getAnnotationTypeFieldWriter(AnnotationTypeWriter annotationTypeWriter) throws Exception { + return new AnnotationTypeFieldWriterImpl( + (SubWriterHolderWriter) annotationTypeWriter, + annotationTypeWriter.getAnnotationTypeDoc()); + } + /** * {@inheritDoc} */ @@ -202,6 +212,9 @@ public class WriterFactoryImpl implements WriterFactory { AnnotationTypeWriter annotationTypeWriter, int memberType) throws Exception { switch (memberType) { + case VisibleMemberMap.ANNOTATION_TYPE_FIELDS: + return (AnnotationTypeFieldWriterImpl) + getAnnotationTypeFieldWriter(annotationTypeWriter); case VisibleMemberMap.ANNOTATION_TYPE_MEMBER_OPTIONAL: return (AnnotationTypeOptionalMemberWriterImpl) getAnnotationTypeOptionalMemberWriter(annotationTypeWriter); diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java index 7c32503e625..98651468f95 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlConstants.java @@ -93,6 +93,12 @@ public class HtmlConstants { public static final Content START_OF_ANNOTATION_TYPE_REQUIRED_MEMBER_SUMMARY = new Comment("=========== ANNOTATION TYPE REQUIRED MEMBER SUMMARY ==========="); + /** + * Marker to identify start of annotation type required member summary. + */ + public static final Content START_OF_ANNOTATION_TYPE_FIELD_SUMMARY = + new Comment("=========== ANNOTATION TYPE FIELD SUMMARY ==========="); + /** * Marker to identify start of constructor summary. */ @@ -129,6 +135,12 @@ public class HtmlConstants { public static final Content START_OF_ANNOTATION_TYPE_DETAILS = new Comment("============ ANNOTATION TYPE MEMBER DETAIL ==========="); + /** + * Marker to identify start of annotation type field details. + */ + public static final Content START_OF_ANNOTATION_TYPE_FIELD_DETAILS = + new Comment("============ ANNOTATION TYPE FIELD DETAIL ==========="); + /** * Marker to identify start of method details. */ diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java index 0eb40080295..c780e962cac 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlDocWriter.java @@ -191,10 +191,7 @@ public abstract class HtmlDocWriter extends HtmlWriter { Content htmlDocType = DocType.FRAMESET; Content htmlComment = new Comment(configuration.getText("doclet.New_Page")); Content head = new HtmlTree(HtmlTag.HEAD); - if (! noTimeStamp) { - Content headComment = new Comment(getGeneratedByString()); - head.addContent(headComment); - } + head.addContent(getGeneratedBy(!noTimeStamp)); if (configuration.charset.length() > 0) { Content meta = HtmlTree.META("Content-Type", CONTENT_TYPE, configuration.charset); @@ -210,9 +207,13 @@ public abstract class HtmlDocWriter extends HtmlWriter { write(htmlDocument); } - protected String getGeneratedByString() { - Calendar calendar = new GregorianCalendar(TimeZone.getDefault()); - Date today = calendar.getTime(); - return "Generated by javadoc ("+ ConfigurationImpl.BUILD_DATE + ") on " + today; + protected Comment getGeneratedBy(boolean timestamp) { + String text = "Generated by javadoc"; // marker string, deliberately not localized + if (timestamp) { + Calendar calendar = new GregorianCalendar(TimeZone.getDefault()); + Date today = calendar.getTime(); + text += " ("+ ConfigurationImpl.BUILD_DATE + ") on " + today; + } + return new Comment(text); } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java index c20ac4c5d5f..5bf1c3259fe 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlStyle.java @@ -68,6 +68,7 @@ public enum HtmlStyle { packageSummary, rowColor, serializedFormContainer, + skipNav, sourceContainer, sourceLineNo, strong, diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java index dc59eb0f4a0..ce38afe7451 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlTree.java @@ -28,6 +28,7 @@ package com.sun.tools.doclets.formats.html.markup; import java.io.IOException; import java.io.Writer; import java.util.*; +import java.nio.charset.*; import com.sun.tools.doclets.internal.toolkit.Content; import com.sun.tools.doclets.internal.toolkit.util.*; @@ -163,6 +164,46 @@ public class HtmlTree extends Content { return s; } + /** + * A set of ASCII URI characters to be left unencoded. + */ + public static final BitSet NONENCODING_CHARS = new BitSet(256); + + static { + // alphabetic characters + for (int i = 'a'; i <= 'z'; i++) { + NONENCODING_CHARS.set(i); + } + for (int i = 'A'; i <= 'Z'; i++) { + NONENCODING_CHARS.set(i); + } + // numeric characters + for (int i = '0'; i <= '9'; i++) { + NONENCODING_CHARS.set(i); + } + // Reserved characters as per RFC 3986. These are set of delimiting characters. + String noEnc = ":/?#[]@!$&'()*+,;="; + // Unreserved characters as per RFC 3986 which should not be percent encoded. + noEnc += "-._~"; + for (int i = 0; i < noEnc.length(); i++) { + NONENCODING_CHARS.set(noEnc.charAt(i)); + } + } + + private static String encodeURL(String url) { + byte[] urlBytes = url.getBytes(Charset.forName("UTF-8")); + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < urlBytes.length; i++) { + int c = urlBytes[i]; + if (NONENCODING_CHARS.get(c & 0xFF)) { + sb.append((char) c); + } else { + sb.append(String.format("%%%02X", c & 0xFF)); + } + } + return sb.toString(); + } + /** * Generates an HTML anchor tag. * @@ -172,7 +213,7 @@ public class HtmlTree extends Content { */ public static HtmlTree A(String ref, Content body) { HtmlTree htmltree = new HtmlTree(HtmlTag.A, nullCheck(body)); - htmltree.addAttr(HtmlAttr.HREF, ref); + htmltree.addAttr(HtmlAttr.HREF, encodeURL(ref)); return htmltree; } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 5369733893b..e1da06598a6 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java @@ -203,27 +203,27 @@ public class HtmlWriter { useLabel = getResource("doclet.navClassUse"); prevLabel = getResource("doclet.Prev"); nextLabel = getResource("doclet.Next"); - prevclassLabel = getResource("doclet.Prev_Class"); - nextclassLabel = getResource("doclet.Next_Class"); + prevclassLabel = getNonBreakResource("doclet.Prev_Class"); + nextclassLabel = getNonBreakResource("doclet.Next_Class"); summaryLabel = getResource("doclet.Summary"); detailLabel = getResource("doclet.Detail"); framesLabel = getResource("doclet.Frames"); - noframesLabel = getResource("doclet.No_Frames"); + noframesLabel = getNonBreakResource("doclet.No_Frames"); treeLabel = getResource("doclet.Tree"); classLabel = getResource("doclet.Class"); deprecatedLabel = getResource("doclet.navDeprecated"); deprecatedPhrase = getResource("doclet.Deprecated"); - allclassesLabel = getResource("doclet.All_Classes"); - allpackagesLabel = getResource("doclet.All_Packages"); - allprofilesLabel = getResource("doclet.All_Profiles"); + allclassesLabel = getNonBreakResource("doclet.All_Classes"); + allpackagesLabel = getNonBreakResource("doclet.All_Packages"); + allprofilesLabel = getNonBreakResource("doclet.All_Profiles"); indexLabel = getResource("doclet.Index"); helpLabel = getResource("doclet.Help"); seeLabel = getResource("doclet.See"); descriptionLabel = getResource("doclet.Description"); - prevpackageLabel = getResource("doclet.Prev_Package"); - nextpackageLabel = getResource("doclet.Next_Package"); - prevprofileLabel = getResource("doclet.Prev_Profile"); - nextprofileLabel = getResource("doclet.Next_Profile"); + prevpackageLabel = getNonBreakResource("doclet.Prev_Package"); + nextpackageLabel = getNonBreakResource("doclet.Next_Package"); + prevprofileLabel = getNonBreakResource("doclet.Prev_Profile"); + nextprofileLabel = getNonBreakResource("doclet.Next_Profile"); packagesLabel = getResource("doclet.Packages"); profilesLabel = getResource("doclet.Profiles"); methodDetailsLabel = getResource("doclet.Method_Detail"); @@ -256,6 +256,27 @@ public class HtmlWriter { return configuration.getResource(key); } + /** + * Get the configuration string as a content, replacing spaces + * with non-breaking spaces. + * + * @param key the key to look for in the configuration file + * @return a content tree for the text + */ + public Content getNonBreakResource(String key) { + String text = configuration.getText(key); + Content c = configuration.newContent(); + int start = 0; + int p; + while ((p = text.indexOf(" ", start)) != -1) { + c.addContent(text.substring(start, p)); + c.addContent(RawHtml.nbsp); + start = p + 1; + } + c.addContent(text.substring(start)); + return c; + } + /** * Get the configuration string as a content. * @@ -314,6 +335,12 @@ public class HtmlWriter { " if (targetPage.indexOf(\":\") != -1 || (targetPage != \"\" && !validURL(targetPage)))" + DocletConstants.NL + " targetPage = \"undefined\";" + DocletConstants.NL + " function validURL(url) {" + DocletConstants.NL + + " try {" + DocletConstants.NL + + " url = decodeURIComponent(url);" + DocletConstants.NL + + " }" + DocletConstants.NL + + " catch (error) {" + DocletConstants.NL + + " return false;" + DocletConstants.NL + + " }" + DocletConstants.NL + " var pos = url.indexOf(\".html\");" + DocletConstants.NL + " if (pos == -1 || pos != url.length - 5)" + DocletConstants.NL + " return false;" + DocletConstants.NL + @@ -325,7 +352,8 @@ public class HtmlWriter { " if ('a' <= ch && ch <= 'z' ||" + DocletConstants.NL + " 'A' <= ch && ch <= 'Z' ||" + DocletConstants.NL + " ch == '$' ||" + DocletConstants.NL + - " ch == '_') {" + DocletConstants.NL + + " ch == '_' ||" + DocletConstants.NL + + " ch.charCodeAt(0) > 127) {" + DocletConstants.NL + " allowNumber = true;" + DocletConstants.NL + " allowSep = true;" + DocletConstants.NL + " } else if ('0' <= ch && ch <= '9'" + DocletConstants.NL + diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_ja.properties b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_ja.properties index 373b5334c42..5592f1032d6 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_ja.properties @@ -185,9 +185,9 @@ doclet.Error_in_packagelist=-group\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u4F7F\u75 doclet.Groupname_already_used=-group\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u304A\u3044\u3066\u3001\u3059\u3067\u306B\u30B0\u30EB\u30FC\u30D7\u540D\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059: {0} doclet.Same_package_name_used=\u30D1\u30C3\u30B1\u30FC\u30B8\u540D\u5F62\u5F0F\u304C2\u56DE\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059: {0} doclet.exception_encountered={1}\u306E\u51E6\u7406\u4E2D\u306B\u4F8B\u5916\u304C\u767A\u751F\u3057\u307E\u3057\u305F\u3002\n{0} -doclet.usage=\u6A19\u6E96\u306Edoclet\u306B\u3088\u308A\u63D0\u4F9B\u3055\u308C\u308B\u3082\u306E:\n-d \u51FA\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u8EE2\u9001\u5148\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n-use \u30AF\u30E9\u30B9\u3068\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4F7F\u7528\u30DA\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\n-version @version\u30D1\u30E9\u30B0\u30E9\u30D5\u3092\u542B\u3081\u308B\n-author @author\u30D1\u30E9\u30B0\u30E9\u30D5\u3092\u542B\u3081\u308B\n-docfilessubdirs doc-file\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u518D\u5E30\u7684\u306B\u30B3\u30D4\u30FC\u3059\u308B\n-splitindex 1\u5B57\u3054\u3068\u306B1\u30D5\u30A1\u30A4\u30EB\u306B\u7D22\u5F15\u3092\u5206\u5272\u3059\u308B\n-windowtitle \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u7528\u306E\u30D6\u30E9\u30A6\u30B6\u30FB\u30A6\u30A3\u30F3\u30C9\u30A6\u30FB\u30BF\u30A4\u30C8\u30EB\n-doctitle \u6982\u8981\u30DA\u30FC\u30B8\u306B\u30BF\u30A4\u30C8\u30EB\u3092\u542B\u3081\u308B\n-header \u5404\u30DA\u30FC\u30B8\u306B\u30D8\u30C3\u30C0\u30FC\u3092\u542B\u3081\u308B\n-footer \u5404\u30DA\u30FC\u30B8\u306B\u30D5\u30C3\u30BF\u30FC\u3092\u542B\u3081\u308B\n-top \u5404\u30DA\u30FC\u30B8\u306B\u4E0A\u90E8\u30C6\u30AD\u30B9\u30C8\u3092\u542B\u3081\u308B\n-bottom \u5404\u30DA\u30FC\u30B8\u306B\u4E0B\u90E8\u30C6\u30AD\u30B9\u30C8\u3092\u542B\u3081\u308B\n-link \u306Bjavadoc\u51FA\u529B\u3078\u306E\u30EA\u30F3\u30AF\u3092\u4F5C\u6210\u3059\u308B\n-linkoffline \u306B\u3042\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30B9\u30C8\u3092\u4F7F\u7528\u3057\u3066\u306Edocs\u306B\u30EA\u30F3\u30AF\u3059\u308B\n-excludedocfilessubdir :.. \u6307\u5B9A\u3055\u308C\u305F\u540D\u524D\u306Edoc-files\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u3059\u3079\u3066\u9664\u5916\u3059\u308B\n-group :.. \u6307\u5B9A\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u6982\u8981\u30DA\u30FC\u30B8\u306B\u304A\u3044\u3066\u30B0\u30EB\u30FC\u30D7\u5316\u3059\u308B\n-nocomment \u8A18\u8FF0\u304A\u3088\u3073\u30BF\u30B0\u3092\u6291\u5236\u3057\u3066\u5BA3\u8A00\u306E\u307F\u3092\u751F\u6210\u3059\u308B\n-nodeprecated @deprecated\u60C5\u5831\u3092\u9664\u5916\u3059\u308B\n-noqualifier ::... \u51FA\u529B\u304B\u3089\u4FEE\u98FE\u5B50\u306E\u30EA\u30B9\u30C8\u3092\u9664\u5916\u3059\u308B\n-nosince @since\u60C5\u5831\u3092\u9664\u5916\u3059\u308B\n-notimestamp \u975E\u8868\u793A\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u3092\u9664\u5916\u3059\u308B\n-nodeprecatedlist \u975E\u63A8\u5968\u306E\u30EA\u30B9\u30C8\u3092\u751F\u6210\u3057\u306A\u3044\n-notree \u30AF\u30E9\u30B9\u968E\u5C64\u3092\u751F\u6210\u3057\u306A\u3044\n-noindex \u7D22\u5F15\u3092\u751F\u6210\u3057\u306A\u3044\n-nohelp \u30D8\u30EB\u30D7\u30FB\u30EA\u30F3\u30AF\u3092\u751F\u6210\u3057\u306A\u3044\n-nonavbar \u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30FC\u3092\u751F\u6210\u3057\u306A\u3044\n-serialwarn @serial\u30BF\u30B0\u306B\u95A2\u3059\u308B\u8B66\u544A\u3092\u751F\u6210\u3059\u308B\n-tag ::

        \u5358\u4E00\u306E\u5F15\u6570\u3092\u6301\u3064\u30AB\u30B9\u30BF\u30E0\u30FB\u30BF\u30B0\u3092\u6307\u5B9A\u3059\u308B\n-taglet \u30BF\u30B0\u30EC\u30C3\u30C8\u306E\u5B8C\u5168\u4FEE\u98FE\u540D\u3092\u767B\u9332\u3059\u308B\n-tagletpath \u30BF\u30B0\u30EC\u30C3\u30C8\u306E\u30D1\u30B9\n-Xdocrootparent \ - \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30B3\u30E1\u30F3\u30C8\u5185\u306E@docRoot(\u3053\u306E\u5F8C\u306B\u306F/..\u304C\u7D9A\u304F)\u306E\u3059\u3079\u3066\u306E\u51FA\u73FE\u7B87\u6240\u3092\u3067\u7F6E\u63DB\u3059\u308B\n-charset \u751F\u6210\u3055\u308C\u308B\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30AF\u30ED\u30B9\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3067\u306E\u6587\u5B57\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\n-helpfile \u30D8\u30EB\u30D7\u30FB\u30EA\u30F3\u30AF\u306E\u30EA\u30F3\u30AF\u5148\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3081\u308B\n-linksource HTML\u5F62\u5F0F\u3067\u30BD\u30FC\u30B9\u3092\u751F\u6210\u3059\u308B\n-sourcetab \u30BD\u30FC\u30B9\u5185\u306E\u30BF\u30D6\u306E\u7A7A\u767D\u6587\u5B57\u306E\u6570\u3092\u6307\u5B9A\u3059\u308B\n-keywords HTML\u306Emeta\u30BF\u30B0\u306B\u3001\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30E1\u30F3\u30D0\u30FC\u306E\u60C5\u5831\u3092\u542B\u3081\u308B\n-stylesheetfile \u751F\u6210\u3055\u308C\u305F\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30B9\u30BF\u30A4\u30EB\u5909\u66F4\u7528\u30D5\u30A1\u30A4\u30EB\n-docencoding \u51FA\u529B\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u540D - - +doclet.usage=\u6A19\u6E96\u306Edoclet\u306B\u3088\u308A\u63D0\u4F9B\u3055\u308C\u308B\u3082\u306E:\n-d \u51FA\u529B\u30D5\u30A1\u30A4\u30EB\u306E\u8EE2\u9001\u5148\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n-use \u30AF\u30E9\u30B9\u3068\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u4F7F\u7528\u30DA\u30FC\u30B8\u3092\u4F5C\u6210\u3059\u308B\n-version @version\u30D1\u30E9\u30B0\u30E9\u30D5\u3092\u542B\u3081\u308B\n-author @author\u30D1\u30E9\u30B0\u30E9\u30D5\u3092\u542B\u3081\u308B\n-docfilessubdirs doc-file\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u518D\u5E30\u7684\u306B\u30B3\u30D4\u30FC\u3059\u308B\n-splitindex 1\u5B57\u3054\u3068\u306B1\u30D5\u30A1\u30A4\u30EB\u306B\u7D22\u5F15\u3092\u5206\u5272\u3059\u308B\n-windowtitle \u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u7528\u306E\u30D6\u30E9\u30A6\u30B6\u30FB\u30A6\u30A3\u30F3\u30C9\u30A6\u30FB\u30BF\u30A4\u30C8\u30EB\n-doctitle \u6982\u8981\u30DA\u30FC\u30B8\u306B\u30BF\u30A4\u30C8\u30EB\u3092\u542B\u3081\u308B\n-header \u5404\u30DA\u30FC\u30B8\u306B\u30D8\u30C3\u30C0\u30FC\u3092\u542B\u3081\u308B\n-footer \u5404\u30DA\u30FC\u30B8\u306B\u30D5\u30C3\u30BF\u30FC\u3092\u542B\u3081\u308B\n-top \u5404\u30DA\u30FC\u30B8\u306B\u4E0A\u90E8\u30C6\u30AD\u30B9\u30C8\u3092\u542B\u3081\u308B\n-bottom \u5404\u30DA\u30FC\u30B8\u306B\u4E0B\u90E8\u30C6\u30AD\u30B9\u30C8\u3092\u542B\u3081\u308B\n-link \u306Bjavadoc\u51FA\u529B\u3078\u306E\u30EA\u30F3\u30AF\u3092\u4F5C\u6210\u3059\u308B\n-linkoffline \u306B\u3042\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30B9\u30C8\u3092\u4F7F\u7528\u3057\u3066\u306Edocs\u306B\u30EA\u30F3\u30AF\u3059\u308B\n-excludedocfilessubdir :.. \u6307\u5B9A\u3055\u308C\u305F\u540D\u524D\u306Edoc-files\u30B5\u30D6\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3092\u3059\u3079\u3066\u9664\u5916\u3059\u308B\n-group :.. \u6307\u5B9A\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u6982\u8981\u30DA\u30FC\u30B8\u306B\u304A\u3044\u3066\u30B0\u30EB\u30FC\u30D7\u5316\u3059\u308B\n-nocomment \u8A18\u8FF0\u304A\u3088\u3073\u30BF\u30B0\u3092\u6291\u5236\u3057\u3066\u5BA3\u8A00\u306E\u307F\u3092\u751F\u6210\u3059\u308B\n-nodeprecated @deprecated\u60C5\u5831\u3092\u9664\u5916\u3059\u308B\n-noqualifier ::... \u51FA\u529B\u304B\u3089\u4FEE\u98FE\u5B50\u306E\u30EA\u30B9\u30C8\u3092\u9664\u5916\u3059\u308B\n-nosince @since\u60C5\u5831\u3092\u9664\u5916\u3059\u308B\n-notimestamp \u975E\u8868\u793A\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u3092\u9664\u5916\u3059\u308B\n-nodeprecatedlist \u975E\u63A8\u5968\u306E\u30EA\u30B9\u30C8\u3092\u751F\u6210\u3057\u306A\u3044\n-notree \u30AF\u30E9\u30B9\u968E\u5C64\u3092\u751F\u6210\u3057\u306A\u3044\n-noindex \u7D22\u5F15\u3092\u751F\u6210\u3057\u306A\u3044\n-nohelp \u30D8\u30EB\u30D7\u30FB\u30EA\u30F3\u30AF\u3092\u751F\u6210\u3057\u306A\u3044\n-nonavbar \u30CA\u30D3\u30B2\u30FC\u30B7\u30E7\u30F3\u30FB\u30D0\u30FC\u3092\u751F\u6210\u3057\u306A\u3044\n-serialwarn @serial\u30BF\u30B0\u306B\u95A2\u3059\u308B\u8B66\u544A\u3092\u751F\u6210\u3059\u308B\n-tag ::
        \u5358\u4E00\u306E\u5F15\u6570\u3092\u6301\u3064\u30AB\u30B9\u30BF\u30E0\u30FB\u30BF\u30B0\u3092\u6307\u5B9A\u3059\u308B\n-taglet \u30BF\u30B0\u30EC\u30C3\u30C8\u306E\u5B8C\u5168\u4FEE\u98FE\u540D\u3092\u767B\u9332\u3059\u308B\n-tagletpath \u30BF\u30B0\u30EC\u30C3\u30C8\u306E\u30D1\u30B9\n-charset \ + \u751F\u6210\u3055\u308C\u308B\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30AF\u30ED\u30B9\u30D7\u30E9\u30C3\u30C8\u30D5\u30A9\u30FC\u30E0\u3067\u306E\u6587\u5B57\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\n-helpfile \u30D8\u30EB\u30D7\u30FB\u30EA\u30F3\u30AF\u306E\u30EA\u30F3\u30AF\u5148\u30D5\u30A1\u30A4\u30EB\u3092\u542B\u3081\u308B\n-linksource HTML\u5F62\u5F0F\u3067\u30BD\u30FC\u30B9\u3092\u751F\u6210\u3059\u308B\n-sourcetab \u30BD\u30FC\u30B9\u5185\u306E\u30BF\u30D6\u306E\u7A7A\u767D\u6587\u5B57\u306E\u6570\u3092\u6307\u5B9A\u3059\u308B\n-keywords HTML\u306Emeta\u30BF\u30B0\u306B\u3001\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30E1\u30F3\u30D0\u30FC\u306E\u60C5\u5831\u3092\u542B\u3081\u308B\n-stylesheetfile \u751F\u6210\u3055\u308C\u305F\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u30B9\u30BF\u30A4\u30EB\u5909\u66F4\u7528\u30D5\u30A1\u30A4\u30EB\n-docencoding \u51FA\u529B\u306E\u6587\u5B57\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u3092\u6307\u5B9A\u3059\u308B +# L10N: do not localize these words: all none accessibility html missing reference syntax +doclet.X.usage=\u6A19\u6E96\u306Edoclet\u306B\u3088\u308A\u63D0\u4F9B\u3055\u308C\u308B\u3082\u306E:\n -Xdocrootparent doc\u30B3\u30E1\u30F3\u30C8\u5185\u306E/..\u304C\u5F8C\u306B\u7D9A\u304F@docRoot\u306E\u3059\u3079\u3066\u3092\n \u3067\u7F6E\u63DB\u3057\u307E\u3059\n -Xdoclint javadoc\u30B3\u30E1\u30F3\u30C8\u5185\u306E\u554F\u984C\u306B\u5BFE\u3059\u308B\u63A8\u5968\u3055\u308C\u308B\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n -Xdoclint:(all|none|[-]) \n javadoc\u30B3\u30E1\u30F3\u30C8\u5185\u306E\u554F\u984C\u306B\u5BFE\u3059\u308B\u7279\u5B9A\u306E\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3057\u307E\u3059\u3002\n \u3053\u3053\u3067\u3001\u306Fhtml\u3001missing\u3001reference\u307E\u305F\u306Fsyntax\u306E\u3044\u305A\u308C\u304B\u3067\u3059\u3002\n diff --git a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_zh_CN.properties index 61fd72cbe10..23d1b9b46d1 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/resources/standard_zh_CN.properties @@ -185,8 +185,8 @@ doclet.Error_in_packagelist=\u4F7F\u7528 -group \u9009\u9879\u65F6\u51FA\u9519: doclet.Groupname_already_used=\u5728 -group \u9009\u9879\u4E2D, groupname \u5DF2\u4F7F\u7528: {0} doclet.Same_package_name_used=\u7A0B\u5E8F\u5305\u540D\u79F0\u5F62\u5F0F\u4F7F\u7528\u4E86\u4E24\u6B21: {0} doclet.exception_encountered=\u5904\u7406{1}\u65F6\u51FA\u73B0\u5F02\u5E38\u9519\u8BEF\n{0} -doclet.usage=\u901A\u8FC7\u6807\u51C6 doclet \u63D0\u4F9B:\n-d \u8F93\u51FA\u6587\u4EF6\u7684\u76EE\u6807\u76EE\u5F55\n-use \u521B\u5EFA\u7C7B\u548C\u7A0B\u5E8F\u5305\u7528\u6CD5\u9875\u9762\n-version \u5305\u542B @version \u6BB5\n-author \u5305\u542B @author \u6BB5\n-docfilessubdirs \u9012\u5F52\u590D\u5236\u6587\u6863\u6587\u4EF6\u5B50\u76EE\u5F55\n-splitindex \u5C06\u7D22\u5F15\u5206\u4E3A\u6BCF\u4E2A\u5B57\u6BCD\u5BF9\u5E94\u4E00\u4E2A\u6587\u4EF6\n-windowtitle \u6587\u6863\u7684\u6D4F\u89C8\u5668\u7A97\u53E3\u6807\u9898\n-doctitle \u5305\u542B\u6982\u89C8\u9875\u9762\u7684\u6807\u9898\n-header \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u9875\u7709\u6587\u672C\n-footer \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u9875\u811A\u6587\u672C\n-top \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u9876\u90E8\u6587\u672C\n-bottom \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u5E95\u90E8\u6587\u672C\n-link \u521B\u5EFA\u6307\u5411\u4F4D\u4E8E \u7684 javadoc \u8F93\u51FA\u7684\u94FE\u63A5\n-linkoffline \u5229\u7528\u4F4D\u4E8E \u7684\u7A0B\u5E8F\u5305\u5217\u8868\u94FE\u63A5\u81F3\u4F4D\u4E8E \u7684\u6587\u6863\n-excludedocfilessubdir :.. \u6392\u9664\u5177\u6709\u7ED9\u5B9A\u540D\u79F0\u7684\u6240\u6709\u6587\u6863\u6587\u4EF6\u5B50\u76EE\u5F55\u3002\n-group :.. \u5728\u6982\u89C8\u9875\u9762\u4E2D, \u5C06\u6307\u5B9A\u7684\u7A0B\u5E8F\u5305\u5206\u7EC4\n-nocomment \u4E0D\u751F\u6210\u8BF4\u660E\u548C\u6807\u8BB0, \u53EA\u751F\u6210\u58F0\u660E\u3002\n-nodeprecated \u4E0D\u5305\u542B @deprecated \u4FE1\u606F\n-noqualifier ::... \u8F93\u51FA\u4E2D\u4E0D\u5305\u62EC\u9650\u5B9A\u7B26\u7684\u5217\u8868\u3002\n-nosince \u4E0D\u5305\u542B @since \u4FE1\u606F\n-notimestamp \u4E0D\u5305\u542B\u9690\u85CF\u65F6\u95F4\u6233\n-nodeprecatedlist \u4E0D\u751F\u6210\u5DF2\u8FC7\u65F6\u7684\u5217\u8868\n-notree \u4E0D\u751F\u6210\u7C7B\u5206\u5C42\u7ED3\u6784\n-noindex \u4E0D\u751F\u6210\u7D22\u5F15\n-nohelp \u4E0D\u751F\u6210\u5E2E\u52A9\u94FE\u63A5\n-nonavbar \u4E0D\u751F\u6210\u5BFC\u822A\u680F\n-serialwarn \u751F\u6210\u6709\u5173 @serial \u6807\u8BB0\u7684\u8B66\u544A\n-tag ::
        \u6307\u5B9A\u5355\u4E2A\u53C2\u6570\u5B9A\u5236\u6807\u8BB0\n-taglet \u8981\u6CE8\u518C\u7684 Taglet \u7684\u5168\u9650\u5B9A\u540D\u79F0\n-tagletpath Taglet \u7684\u8DEF\u5F84\n-Xdocrootparent \u5C06\u6587\u6863\u6CE8\u91CA\u4E2D\u51FA\u73B0\u7684\u6240\u6709\u540E\u8DDF /.. \u7684 @docRoot \u66FF\u6362\u4E3A \n-charset \u7528\u4E8E\u8DE8\u5E73\u53F0\u67E5\u770B\u751F\u6210\u7684\u6587\u6863\u7684\u5B57\u7B26\u96C6\u3002\n-helpfile \u5305\u542B\u5E2E\u52A9\u94FE\u63A5\u6240\u94FE\u63A5\u5230\u7684\u6587\u4EF6\n-linksource \u4EE5 HTML \u683C\u5F0F\u751F\u6210\u6E90\u6587\u4EF6\n-sourcetab \u6307\u5B9A\u6E90\u4E2D\u6BCF\u4E2A\u5236\u8868\u7B26\u5360\u636E\u7684\u7A7A\u683C\u6570\n-keywords \u4F7F\u7A0B\u5E8F\u5305, \u7C7B\u548C\u6210\u5458\u4FE1\u606F\u9644\u5E26 HTML \u5143\u6807\u8BB0\n-stylesheetfile \u7528\u4E8E\u66F4\u6539\u751F\u6210\u6587\u6863\u7684\u6837\u5F0F\u7684\u6587\u4EF6\n-docencoding \u8F93\u51FA\u7F16\u7801\u540D\u79F0 - - +doclet.usage=\u901A\u8FC7\u6807\u51C6 doclet \u63D0\u4F9B:\n -d \u8F93\u51FA\u6587\u4EF6\u7684\u76EE\u6807\u76EE\u5F55\n -use \u521B\u5EFA\u7C7B\u548C\u7A0B\u5E8F\u5305\u7528\u6CD5\u9875\u9762\n -version \u5305\u542B @version \u6BB5\n -author \u5305\u542B @author \u6BB5\n -docfilessubdirs \u9012\u5F52\u590D\u5236\u6587\u6863\u6587\u4EF6\u5B50\u76EE\u5F55\n -splitindex \u5C06\u7D22\u5F15\u5206\u4E3A\u6BCF\u4E2A\u5B57\u6BCD\u5BF9\u5E94\u4E00\u4E2A\u6587\u4EF6\n -windowtitle \u6587\u6863\u7684\u6D4F\u89C8\u5668\u7A97\u53E3\u6807\u9898\n -doctitle \u5305\u542B\u6982\u89C8\u9875\u9762\u7684\u6807\u9898\n -header \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u9875\u7709\u6587\u672C\n -footer \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u9875\u811A\u6587\u672C\n -top \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u9876\u90E8\u6587\u672C\n -bottom \u5305\u542B\u6BCF\u4E2A\u9875\u9762\u7684\u5E95\u90E8\u6587\u672C\n -link \u521B\u5EFA\u6307\u5411\u4F4D\u4E8E \u7684 javadoc \u8F93\u51FA\u7684\u94FE\u63A5\n -linkoffline \u5229\u7528\u4F4D\u4E8E \u7684\u7A0B\u5E8F\u5305\u5217\u8868\u94FE\u63A5\u81F3\u4F4D\u4E8E \u7684\u6587\u6863\n -excludedocfilessubdir :.. \u6392\u9664\u5177\u6709\u7ED9\u5B9A\u540D\u79F0\u7684\u6240\u6709\u6587\u6863\u6587\u4EF6\u5B50\u76EE\u5F55\u3002\n -group :.. \u5728\u6982\u89C8\u9875\u9762\u4E2D, \u5C06\u6307\u5B9A\u7684\u7A0B\u5E8F\u5305\u5206\u7EC4\n -nocomment \u4E0D\u751F\u6210\u8BF4\u660E\u548C\u6807\u8BB0, \u53EA\u751F\u6210\u58F0\u660E\u3002\n -nodeprecated \u4E0D\u5305\u542B @deprecated \u4FE1\u606F\n -noqualifier ::... \u8F93\u51FA\u4E2D\u4E0D\u5305\u62EC\u6307\u5B9A\u9650\u5B9A\u7B26\u7684\u5217\u8868\u3002\n -nosince \u4E0D\u5305\u542B @since \u4FE1\u606F\n -notimestamp \u4E0D\u5305\u542B\u9690\u85CF\u65F6\u95F4\u6233\n -nodeprecatedlist \u4E0D\u751F\u6210\u5DF2\u8FC7\u65F6\u7684\u5217\u8868\n -notree \u4E0D\u751F\u6210\u7C7B\u5206\u5C42\u7ED3\u6784\n -noindex \u4E0D\u751F\u6210\u7D22\u5F15\n -nohelp \u4E0D\u751F\u6210\u5E2E\u52A9\u94FE\u63A5\n -nonavbar \u4E0D\u751F\u6210\u5BFC\u822A\u680F\n -serialwarn \u751F\u6210\u6709\u5173 @serial \u6807\u8BB0\u7684\u8B66\u544A\n -tag ::
        \u6307\u5B9A\u5355\u4E2A\u53C2\u6570\u5B9A\u5236\u6807\u8BB0\n -taglet \u8981\u6CE8\u518C\u7684 Taglet \u7684\u5168\u9650\u5B9A\u540D\u79F0\n -tagletpath Taglet \u7684\u8DEF\u5F84\n -charset \u7528\u4E8E\u8DE8\u5E73\u53F0\u67E5\u770B\u751F\u6210\u7684\u6587\u6863\u7684\u5B57\u7B26\u96C6\u3002\n -helpfile \u5305\u542B\u5E2E\u52A9\u94FE\u63A5\u6240\u94FE\u63A5\u5230\u7684\u6587\u4EF6\n -linksource \u4EE5 HTML \u683C\u5F0F\u751F\u6210\u6E90\u6587\u4EF6\n -sourcetab \u6307\u5B9A\u6E90\u4E2D\u6BCF\u4E2A\u5236\u8868\u7B26\u5360\u636E\u7684\u7A7A\u683C\u6570\n -keywords \u4F7F\u7A0B\u5E8F\u5305, \u7C7B\u548C\u6210\u5458\u4FE1\u606F\u9644\u5E26 HTML \u5143\u6807\u8BB0\n -stylesheetfile \u7528\u4E8E\u66F4\u6539\u751F\u6210\u6587\u6863\u7684\u6837\u5F0F\u7684\u6587\u4EF6\n -docencoding \u6307\u5B9A\u8F93\u51FA\u7684\u5B57\u7B26\u7F16\u7801 +# L10N: do not localize these words: all none accessibility html missing reference syntax +doclet.X.usage=\u901A\u8FC7\u6807\u51C6 doclet \u63D0\u4F9B:\n -Xdocrootparent \u4F7F\u7528 \u66FF\u6362\u6587\u6863\u6CE8\u91CA\u4E2D\u51FA\u73B0\u7684\n \u6240\u6709\u5176\u540E\u8DDF\u968F /.. \u7684 @docRoot\n -Xdoclint \u4E3A javadoc \u6CE8\u91CA\u4E2D\u7684\u95EE\u9898\u542F\u7528\u5EFA\u8BAE\u7684\u68C0\u67E5\n -Xdoclint:(all|none|[-]) \n \u5BF9 javadoc \u6CE8\u91CA\u4E2D\u7684\u95EE\u9898\u542F\u7528\u6216\u7981\u7528\u7279\u5B9A\u68C0\u67E5\u3002\n \u5176\u4E2D \u662F accessibility, html, missing, reference \u6216 syntax \u4E4B\u4E00\u3002\n diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java new file mode 100644 index 00000000000..b556ccc7c86 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeFieldWriter.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.doclets.internal.toolkit; + +import java.io.*; +import com.sun.javadoc.*; + +/** + * The interface for writing annotation type field output. + * + *

        This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * + * @author Bhavesh Patel + * @since 1.8 + */ + +public interface AnnotationTypeFieldWriter { + + /** + * Add the annotation type member tree header. + * + * @return content tree for the member tree header + */ + public Content getMemberTreeHeader(); + + /** + * Add the annotation type field details marker. + * + * @param memberDetails the content tree representing field details marker + */ + public void addAnnotationFieldDetailsMarker(Content memberDetails); + + /** + * Add the annotation type details tree header. + * + * @param classDoc the annotation type being documented + * @param memberDetailsTree the content tree representing member details + */ + public void addAnnotationDetailsTreeHeader(ClassDoc classDoc, + Content memberDetailsTree); + + /** + * Get the annotation type documentation tree header. + * + * @param member the annotation type being documented + * @param annotationDetailsTree the content tree representing annotation type details + * @return content tree for the annotation type documentation header + */ + public Content getAnnotationDocTreeHeader(MemberDoc member, + Content annotationDetailsTree); + + /** + * Get the annotation type details tree. + * + * @param annotationDetailsTree the content tree representing annotation type details + * @return content tree for the annotation type details + */ + public Content getAnnotationDetails(Content annotationDetailsTree); + + /** + * Get the annotation type documentation. + * + * @param annotationDocTree the content tree representing annotation type documentation + * @param isLastContent true if the content to be added is the last content + * @return content tree for the annotation type documentation + */ + public Content getAnnotationDoc(Content annotationDocTree, boolean isLastContent); + + /** + * Get the signature for the given member. + * + * @param member the member being documented + * @return content tree for the annotation type signature + */ + public Content getSignature(MemberDoc member); + + /** + * Add the deprecated output for the given member. + * + * @param member the member being documented + * @param annotationDocTree content tree to which the deprecated information will be added + */ + public void addDeprecated(MemberDoc member, Content annotationDocTree); + + /** + * Add the comments for the given member. + * + * @param member the member being documented + * @param annotationDocTree the content tree to which the comments will be added + */ + public void addComments(MemberDoc member, Content annotationDocTree); + + /** + * Add the tags for the given member. + * + * @param member the member being documented + * @param annotationDocTree the content tree to which the tags will be added + */ + public void addTags(MemberDoc member, Content annotationDocTree); + + /** + * Close the writer. + */ + public void close() throws IOException; +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java index 28a18f9eaad..294d3217195 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeRequiredMemberWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,20 @@ import com.sun.javadoc.*; public interface AnnotationTypeRequiredMemberWriter { + /** + * Add the annotation type member tree header. + * + * @return content tree for the member tree header + */ + public Content getMemberTreeHeader(); + + /** + * Add the annotation type details marker. + * + * @param memberDetails the content tree representing details marker + */ + public void addAnnotationDetailsMarker(Content memberDetails); + /** * Add the annotation type details tree header. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java index b65740edf87..c11dfd8527e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/AnnotationTypeWriter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -103,13 +103,6 @@ public interface AnnotationTypeWriter { */ public void addAnnotationTypeDeprecationInfo (Content annotationInfoTree); - /** - * Add the annotation type details marker. - * - * @param memberDetails the content tree representing member details marker - */ - public void addAnnotationDetailsMarker(Content memberDetails); - /** * Get the member tree header for the annotation type. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java index 32b7648e34b..940f1c91294 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/Configuration.java @@ -383,35 +383,52 @@ public abstract class Configuration { DocErrorReporter reporter); private void initProfiles() throws IOException { - profiles = Profiles.read(new File(profilespath)); - // Generate profiles documentation only is profilespath is set and if - // profiles is not null and profiles count is 1 or more. - showProfiles = (!profilespath.isEmpty() && profiles != null && - profiles.getProfileCount() > 0); - } + if (profilespath.isEmpty()) + return; - private void initProfilePackages() throws IOException { - profilePackages = new HashMap(); - ArrayList results; - Map packageIndex = new HashMap(); - for (int i = 0; i < packages.length; i++) { - PackageDoc pkg = packages[i]; - packageIndex.put(pkg.name(), pkg); - } - for (int i = 1; i < profiles.getProfileCount(); i++) { - Set profPkgs = profiles.getPackages(i); - results = new ArrayList(); - for (String packageName : profPkgs) { - packageName = packageName.replace("/", "."); - PackageDoc profPkg = packageIndex.get(packageName); - if (profPkg != null) { - results.add(profPkg); - } + profiles = Profiles.read(new File(profilespath)); + + // Group the packages to be documented by the lowest profile (if any) + // in which each appears + Map> interimResults = + new EnumMap>(Profile.class); + for (Profile p: Profile.values()) + interimResults.put(p, new ArrayList()); + + for (PackageDoc pkg: packages) { + if (nodeprecated && Util.isDeprecated(pkg)) { + continue; + } + // the getProfile method takes a type name, not a package name, + // but isn't particularly fussy about the simple name -- so just use * + int i = profiles.getProfile(pkg.name().replace(".", "/") + "/*"); + Profile p = Profile.lookup(i); + if (p != null) { + List pkgs = interimResults.get(p); + pkgs.add(pkg); } - Collections.sort(results); - PackageDoc[] profilePkgs = results.toArray(new PackageDoc[]{}); - profilePackages.put(Profile.lookup(i).name, profilePkgs); } + + // Build the profilePackages structure used by the doclet + profilePackages = new HashMap(); + List prev = Collections.emptyList(); + int size; + for (Map.Entry> e: interimResults.entrySet()) { + Profile p = e.getKey(); + List pkgs = e.getValue(); + pkgs.addAll(prev); // each profile contains all lower profiles + Collections.sort(pkgs); + size = pkgs.size(); + // For a profile, if there are no packages to be documented, do not add + // it to profilePackages map. + if (size > 0) + profilePackages.put(p.name, pkgs.toArray(new PackageDoc[pkgs.size()])); + prev = pkgs; + } + + // Generate profiles documentation if any profile contains any + // of the packages to be documented. + showProfiles = !prev.isEmpty(); } private void initPackageArray() { @@ -534,13 +551,10 @@ public abstract class Configuration { public void setOptions() throws Fault { initPackageArray(); setOptions(root.options()); - if (!profilespath.isEmpty()) { - try { - initProfiles(); - initProfilePackages(); - } catch (Exception e) { - throw new DocletAbortException(e); - } + try { + initProfiles(); + } catch (Exception e) { + throw new DocletAbortException(e); } setSpecificDocletOptions(root.options()); } @@ -712,6 +726,17 @@ public abstract class Configuration { return true; } + /** + * Check the validity of the given profile. Return false if there are no + * valid packages to be documented for the profile. + * + * @param profileName the profile that needs to be validated. + * @return true if the profile has valid packages to be documented. + */ + public boolean shouldDocumentProfile(String profileName) { + return profilePackages.containsKey(profileName); + } + /** * Check the validity of the given Source or Output File encoding on this * platform. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java index 1fa4c2f00e9..985fb646647 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/WriterFactory.java @@ -129,6 +129,18 @@ public interface WriterFactory { public abstract MethodWriter getMethodWriter(ClassWriter classWriter) throws Exception; + /** + * Return the annotation type field writer for a given annotation type. + * + * @param annotationTypeWriter the writer for the annotation type + * being documented. + * @return the member writer for the given annotation type. Return null if + * this writer is not supported by the doclet. + */ + public abstract AnnotationTypeFieldWriter + getAnnotationTypeFieldWriter( + AnnotationTypeWriter annotationTypeWriter) throws Exception; + /** * Return the annotation type optional member writer for a given annotation * type. diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java index 4de54026794..ae1de88d587 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeBuilder.java @@ -223,13 +223,22 @@ public class AnnotationTypeBuilder extends AbstractBuilder { Content memberDetailsTree = writer.getMemberTreeHeader(); buildChildren(node, memberDetailsTree); if (memberDetailsTree.isValid()) { - Content memberDetails = writer.getMemberTreeHeader(); - writer.addAnnotationDetailsMarker(memberDetails); - memberDetails.addContent(writer.getMemberTree(memberDetailsTree)); - annotationContentTree.addContent(writer.getMemberDetailsTree(memberDetails)); + annotationContentTree.addContent(writer.getMemberDetailsTree(memberDetailsTree)); } } + /** + * Build the annotation type field documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeFieldDetails(XMLNode node, Content memberDetailsTree) + throws Exception { + configuration.getBuilderFactory(). + getAnnotationTypeFieldsBuilder(writer).buildChildren(node, memberDetailsTree); + } + /** * Build the annotation type optional member documentation. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java new file mode 100644 index 00000000000..4cbd4a20213 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeFieldBuilder.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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.doclets.internal.toolkit.builders; + +import java.util.*; + +import com.sun.javadoc.*; +import com.sun.tools.doclets.internal.toolkit.*; +import com.sun.tools.doclets.internal.toolkit.util.*; + +/** + * Builds documentation for annotation type fields. + * + *

        This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + * + * @author Bhavesh Patel + * @since 1.8 + */ +public class AnnotationTypeFieldBuilder extends AbstractMemberBuilder { + + /** + * The annotation type whose members are being documented. + */ + protected ClassDoc classDoc; + + /** + * The visible members for the given class. + */ + protected VisibleMemberMap visibleMemberMap; + + /** + * The writer to output the member documentation. + */ + protected AnnotationTypeFieldWriter writer; + + /** + * The list of members being documented. + */ + protected List members; + + /** + * The index of the current member that is being documented at this point + * in time. + */ + protected int currentMemberIndex; + + /** + * Construct a new AnnotationTypeFieldsBuilder. + * + * @param context the build context. + * @param classDoc the class whose members are being documented. + * @param writer the doclet specific writer. + * @param memberType the type of member that is being documented. + */ + protected AnnotationTypeFieldBuilder(Context context, + ClassDoc classDoc, + AnnotationTypeFieldWriter writer, + int memberType) { + super(context); + this.classDoc = classDoc; + this.writer = writer; + this.visibleMemberMap = new VisibleMemberMap(classDoc, memberType, + configuration); + this.members = new ArrayList( + this.visibleMemberMap.getMembersFor(classDoc)); + if (configuration.getMemberComparator() != null) { + Collections.sort(this.members, configuration.getMemberComparator()); + } + } + + + /** + * Construct a new AnnotationTypeFieldBuilder. + * + * @param context the build context. + * @param classDoc the class whose members are being documented. + * @param writer the doclet specific writer. + */ + public static AnnotationTypeFieldBuilder getInstance( + Context context, ClassDoc classDoc, + AnnotationTypeFieldWriter writer) { + return new AnnotationTypeFieldBuilder(context, classDoc, + writer, VisibleMemberMap.ANNOTATION_TYPE_FIELDS); + } + + /** + * {@inheritDoc} + */ + public String getName() { + return "AnnotationTypeFieldDetails"; + } + + /** + * Returns a list of members that will be documented for the given class. + * This information can be used for doclet specific documentation + * generation. + * + * @param classDoc the {@link ClassDoc} we want to check. + * @return a list of members that will be documented. + */ + public List members(ClassDoc classDoc) { + return visibleMemberMap.getMembersFor(classDoc); + } + + /** + * Returns the visible member map for the members of this class. + * + * @return the visible member map for the members of this class. + */ + public VisibleMemberMap getVisibleMemberMap() { + return visibleMemberMap; + } + + /** + * summaryOrder.size() + */ + public boolean hasMembersToDocument() { + return members.size() > 0; + } + + /** + * Build the annotation type field documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeField(XMLNode node, Content memberDetailsTree) { + buildAnnotationTypeMember(node, memberDetailsTree); + } + + /** + * Build the member documentation. + * + * @param node the XML element that specifies which components to document + * @param memberDetailsTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeMember(XMLNode node, Content memberDetailsTree) { + if (writer == null) { + return; + } + int size = members.size(); + if (size > 0) { + writer.addAnnotationFieldDetailsMarker(memberDetailsTree); + for (currentMemberIndex = 0; currentMemberIndex < size; + currentMemberIndex++) { + Content detailsTree = writer.getMemberTreeHeader(); + writer.addAnnotationDetailsTreeHeader(classDoc, detailsTree); + Content annotationDocTree = writer.getAnnotationDocTreeHeader( + (MemberDoc) members.get(currentMemberIndex), + detailsTree); + buildChildren(node, annotationDocTree); + detailsTree.addContent(writer.getAnnotationDoc( + annotationDocTree, (currentMemberIndex == size - 1))); + memberDetailsTree.addContent(writer.getAnnotationDetails(detailsTree)); + } + } + } + + /** + * Build the signature. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added + */ + public void buildSignature(XMLNode node, Content annotationDocTree) { + annotationDocTree.addContent( + writer.getSignature((MemberDoc) members.get(currentMemberIndex))); + } + + /** + * Build the deprecation information. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added + */ + public void buildDeprecationInfo(XMLNode node, Content annotationDocTree) { + writer.addDeprecated((MemberDoc) members.get(currentMemberIndex), + annotationDocTree); + } + + /** + * Build the comments for the member. Do nothing if + * {@link Configuration#nocomment} is set to true. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added + */ + public void buildMemberComments(XMLNode node, Content annotationDocTree) { + if(! configuration.nocomment){ + writer.addComments((MemberDoc) members.get(currentMemberIndex), + annotationDocTree); + } + } + + /** + * Build the tag information. + * + * @param node the XML element that specifies which components to document + * @param annotationDocTree the content tree to which the documentation will be added + */ + public void buildTagInfo(XMLNode node, Content annotationDocTree) { + writer.addTags((MemberDoc) members.get(currentMemberIndex), + annotationDocTree); + } + + /** + * Return the annotation type field writer for this builder. + * + * @return the annotation type field writer for this builder. + */ + public AnnotationTypeFieldWriter getWriter() { + return writer; + } +} diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java index 84ded901668..29ad9df370d 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/AnnotationTypeRequiredMemberBuilder.java @@ -167,16 +167,17 @@ public class AnnotationTypeRequiredMemberBuilder extends AbstractMemberBuilder { } int size = members.size(); if (size > 0) { - writer.addAnnotationDetailsTreeHeader( - classDoc, memberDetailsTree); + writer.addAnnotationDetailsMarker(memberDetailsTree); for (currentMemberIndex = 0; currentMemberIndex < size; - currentMemberIndex++) { + currentMemberIndex++) { + Content detailsTree = writer.getMemberTreeHeader(); + writer.addAnnotationDetailsTreeHeader(classDoc, detailsTree); Content annotationDocTree = writer.getAnnotationDocTreeHeader( - (MemberDoc) members.get(currentMemberIndex), - memberDetailsTree); + (MemberDoc) members.get(currentMemberIndex), detailsTree); buildChildren(node, annotationDocTree); - memberDetailsTree.addContent(writer.getAnnotationDoc( + detailsTree.addContent(writer.getAnnotationDoc( annotationDocTree, (currentMemberIndex == size - 1))); + memberDetailsTree.addContent(writer.getAnnotationDetails(detailsTree)); } } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java index 7152f2bd4f2..3509a06eac9 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/BuilderFactory.java @@ -173,11 +173,27 @@ public class BuilderFactory { writerFactory.getMethodWriter(classWriter)); } + /** + * Return an instance of the annotation type fields builder for the given + * class. + * + * @return an instance of the annotation type field builder for the given + * annotation type. + */ + public AbstractBuilder getAnnotationTypeFieldsBuilder( + AnnotationTypeWriter annotationTypeWriter) + throws Exception { + return AnnotationTypeFieldBuilder.getInstance(context, + annotationTypeWriter.getAnnotationTypeDoc(), + writerFactory.getAnnotationTypeFieldWriter( + annotationTypeWriter)); + } + /** * Return an instance of the annotation type member builder for the given * class. * - * @return an instance of the annotation type memebr builder for the given + * @return an instance of the annotation type member builder for the given * annotation type. */ public AbstractBuilder getAnnotationTypeOptionalMemberBuilder( @@ -193,7 +209,7 @@ public class BuilderFactory { * Return an instance of the annotation type member builder for the given * class. * - * @return an instance of the annotation type memebr builder for the given + * @return an instance of the annotation type member builder for the given * annotation type. */ public AbstractBuilder getAnnotationTypeRequiredMemberBuilder( diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java index 8edb5dd2bad..fb4f14c8253 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/builders/MemberSummaryBuilder.java @@ -212,6 +212,20 @@ public class MemberSummaryBuilder extends AbstractMemberBuilder { addSummary(writer, visibleMemberMap, false, memberSummaryTree); } + /** + * Build the summary for fields. + * + * @param node the XML element that specifies which components to document + * @param memberSummaryTree the content tree to which the documentation will be added + */ + public void buildAnnotationTypeFieldsSummary(XMLNode node, Content memberSummaryTree) { + MemberSummaryWriter writer = + memberSummaryWriters[VisibleMemberMap.ANNOTATION_TYPE_FIELDS]; + VisibleMemberMap visibleMemberMap = + visibleMemberMaps[VisibleMemberMap.ANNOTATION_TYPE_FIELDS]; + addSummary(writer, visibleMemberMap, false, memberSummaryTree); + } + /** * Build the summary for the optional members. * diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml index aabaafff250..f7f2f9c7458 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclet.xml @@ -66,10 +66,19 @@ + + + + + + + + + diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties index 54dff68e55b..cf21120f517 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets.properties @@ -136,6 +136,7 @@ doclet.Deprecated=Deprecated. doclet.Groupname_already_used=In -group option, groupname already used: {0} doclet.value_tag_invalid_reference={0} (referenced by @value tag) is an unknown reference. doclet.value_tag_invalid_constant=@value tag (which references {0}) can only be used in constants. +doclet.value_tag_invalid_use=@value tag cannot be used here. doclet.dest_dir_create=Creating destination directory: "{0}" doclet.in={0} in {1} doclet.Use_Table_Summary=Use table, listing {0}, and an explanation diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties index 82509fc3a63..24909fe13c1 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_ja.properties @@ -174,6 +174,16 @@ doclet.Value=\u5024 doclet.0_and_1={0}\u3068{1} #Documentation for Enums -doclet.enum_values_doc=\n\u3053\u306E\u5217\u6319\u578B\u306E\u5B9A\u6570\u3092\u542B\u3080\u914D\u5217\u3092\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u9806\u5E8F\u3067\u8FD4\u3057\u307E\u3059\u3002\n\u3053\u306E\u30E1\u30BD\u30C3\u30C9\u306F\u6B21\u306E\u3088\u3046\u306B\u3057\u3066\u5B9A\u6570\u3092\u53CD\u5FA9\u3059\u308B\u305F\u3081\u306B\n\u4F7F\u7528\u3067\u304D\u307E\u3059:\n

        \nfor({0} c: {0}.values())\n  System.out.println(c);\n
        \n@return\u3053\u306E\u5217\u6319\u578B\u306E\u5B9A\u6570\u3092\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u9806\u5E8F\u3067\n\u542B\u3080\u914D\u5217 +doclet.enum_values_doc.main=\n\u3053\u306E\u5217\u6319\u578B\u306E\u5B9A\u6570\u3092\u542B\u3080\u914D\u5217\u3092\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u9806\u5E8F\u3067\u8FD4\u3057\u307E\u3059\u3002\n\u3053\u306E\u30E1\u30BD\u30C3\u30C9\u306F\u6B21\u306E\u3088\u3046\u306B\u3057\u3066\u5B9A\u6570\u3092\u53CD\u5FA9\u3059\u308B\u305F\u3081\u306B\n\u4F7F\u7528\u3067\u304D\u307E\u3059:\n
        \nfor({0} c: {0}.values())\n  System.out.println(c);\n
        \n -doclet.enum_valueof_doc=\n\u6307\u5B9A\u3057\u305F\u540D\u524D\u3092\u6301\u3064\u3053\u306E\u578B\u306E\u5217\u6319\u578B\u5B9A\u6570\u3092\u8FD4\u3057\u307E\u3059\u3002\n\u6587\u5B57\u5217\u306F\u3001\u3053\u306E\u578B\u306E\u5217\u6319\u578B\u5B9A\u6570\u3092\u5BA3\u8A00\u3059\u308B\u306E\u306B\u4F7F\u7528\u3057\u305F\u8B58\u5225\u5B50\u3068\u6B63\u78BA\u306B\n\u4E00\u81F4\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n(\u4F59\u5206\u306A\u7A7A\u767D\u6587\u5B57\u3092\u542B\u3081\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002)\n\n@param name\u8FD4\u3055\u308C\u308B\u5217\u6319\u578B\u5B9A\u6570\u306E\u540D\u524D\n@return\u6307\u5B9A\u3055\u308C\u305F\u540D\u524D\u3092\u6301\u3064\u5217\u6319\u578B\u5B9A\u6570\n@throws IllegalArgumentException\u6307\u5B9A\u3055\u308C\u305F\u540D\u524D\u3092\u6301\u3064\u5B9A\u6570\u3092\n\u3053\u306E\u5217\u6319\u578B\u304C\u6301\u3063\u3066\u3044\u306A\u3044\u5834\u5408\n@throws NullPointerException\u5F15\u6570\u304Cnull\u306E\u5834\u5408 +doclet.enum_values_doc.return=\n\u3053\u306E\u5217\u6319\u578B\u306E\u5B9A\u6570\u3092\u542B\u3080\u3001\u5BA3\u8A00\u3055\u308C\u3066\u3044\u308B\u9806\u5E8F\u3067\u306E\u914D\u5217 + +doclet.enum_valueof_doc.main=\n\u6307\u5B9A\u3057\u305F\u540D\u524D\u3092\u6301\u3064\u3053\u306E\u578B\u306E\u5217\u6319\u578B\u5B9A\u6570\u3092\u8FD4\u3057\u307E\u3059\u3002\n\u6587\u5B57\u5217\u306F\u3001\u3053\u306E\u578B\u306E\u5217\u6319\u578B\u5B9A\u6570\u3092\u5BA3\u8A00\u3059\u308B\u306E\u306B\u4F7F\u7528\u3057\u305F\u8B58\u5225\u5B50\u3068\u6B63\u78BA\u306B\n\u4E00\u81F4\u3057\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\n(\u4F59\u5206\u306A\u7A7A\u767D\u6587\u5B57\u3092\u542B\u3081\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002)\n + +doclet.enum_valueof_doc.param_name=\u8FD4\u3055\u308C\u308B\u5217\u6319\u578B\u5B9A\u6570\u306E\u540D\u524D\u3002 + +doclet.enum_valueof_doc.return=\u6307\u5B9A\u3057\u305F\u540D\u524D\u306E\u5217\u6319\u578B\u5B9A\u6570 + +doclet.enum_valueof_doc.throws_ila=\u3053\u306E\u5217\u6319\u578B\u306B\u3001\u6307\u5B9A\u3057\u305F\u540D\u524D\u306E\u5B9A\u6570\u304C\u306A\u3044\u5834\u5408 + +doclet.enum_valueof_doc.throws_npe=\u5F15\u6570\u304Cnull\u306E\u5834\u5408 diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties index 602682459a4..905a179fdb4 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/doclets_zh_CN.properties @@ -174,6 +174,16 @@ doclet.Value=\u503C doclet.0_and_1={0}\u548C{1} #Documentation for Enums -doclet.enum_values_doc=\n\u6309\u7167\u58F0\u660E\u8BE5\u679A\u4E3E\u7C7B\u578B\u7684\u5E38\u91CF\u7684\u987A\u5E8F, \u8FD4\u56DE\n\u5305\u542B\u8FD9\u4E9B\u5E38\u91CF\u7684\u6570\u7EC4\u3002\u8BE5\u65B9\u6CD5\u53EF\u7528\u4E8E\u8FED\u4EE3\n\u5E38\u91CF, \u5982\u4E0B\u6240\u793A:\n
        \nfor ({0} c : {0}.values())\n    System.out.println(c);\n
        \n@return \u6309\u7167\u58F0\u660E\u8BE5\u679A\u4E3E\u7C7B\u578B\u7684\u5E38\u91CF\u7684\u987A\u5E8F, \u8FD4\u56DE\n\u5305\u542B\u8FD9\u4E9B\u5E38\u91CF\u7684\u6570\u7EC4 +doclet.enum_values_doc.main=\n\u6309\u7167\u58F0\u660E\u8BE5\u679A\u4E3E\u7C7B\u578B\u7684\u5E38\u91CF\u7684\u987A\u5E8F, \u8FD4\u56DE\n\u5305\u542B\u8FD9\u4E9B\u5E38\u91CF\u7684\u6570\u7EC4\u3002\u8BE5\u65B9\u6CD5\u53EF\u7528\u4E8E\u8FED\u4EE3\n\u5E38\u91CF, \u5982\u4E0B\u6240\u793A:\n
        \nfor ({0} c : {0}.values())\n    System.out.println(c);\n
        -doclet.enum_valueof_doc=\n\u8FD4\u56DE\u5E26\u6709\u6307\u5B9A\u540D\u79F0\u7684\u8BE5\u7C7B\u578B\u7684\u679A\u4E3E\u5E38\u91CF\u3002\n\u5B57\u7B26\u4E32\u5FC5\u987B\u4E0E\u7528\u4E8E\u58F0\u660E\u8BE5\u7C7B\u578B\u7684\u679A\u4E3E\u5E38\u91CF\u7684\n\u6807\u8BC6\u7B26\u5B8C\u5168\u5339\u914D\u3002(\u4E0D\u5141\u8BB8\u6709\u591A\u4F59\n\u7684\u7A7A\u683C\u5B57\u7B26\u3002)\n\n@param name \u8981\u8FD4\u56DE\u7684\u679A\u4E3E\u5E38\u91CF\u7684\u540D\u79F0\u3002\n@return \u8FD4\u56DE\u5E26\u6709\u6307\u5B9A\u540D\u79F0\u7684\u679A\u4E3E\u5E38\u91CF\n@throws \u5982\u679C\u8BE5\u679A\u4E3E\u7C7B\u578B\u6CA1\u6709\u5E26\u6709\u6307\u5B9A\u540D\u79F0\u7684\u5E38\u91CF, \n\u5219\u629B\u51FA IllegalArgumentException\n@throws \u5982\u679C\u53C2\u6570\u4E3A\u7A7A\u503C, \u5219\u629B\u51FA NullPointerException +doclet.enum_values_doc.return=\n\u6309\u7167\u58F0\u660E\u8BE5\u679A\u4E3E\u7C7B\u578B\u7684\u5E38\u91CF\u7684\u987A\u5E8F\u8FD4\u56DE\u7684\u5305\u542B\u8FD9\u4E9B\u5E38\u91CF\u7684\u6570\u7EC4 + +doclet.enum_valueof_doc.main=\n\u8FD4\u56DE\u5E26\u6709\u6307\u5B9A\u540D\u79F0\u7684\u8BE5\u7C7B\u578B\u7684\u679A\u4E3E\u5E38\u91CF\u3002\n\u5B57\u7B26\u4E32\u5FC5\u987B\u4E0E\u7528\u4E8E\u58F0\u660E\u8BE5\u7C7B\u578B\u7684\u679A\u4E3E\u5E38\u91CF\u7684\n\u6807\u8BC6\u7B26\u5B8C\u5168\u5339\u914D\u3002(\u4E0D\u5141\u8BB8\u6709\u591A\u4F59\n\u7684\u7A7A\u683C\u5B57\u7B26\u3002) + +doclet.enum_valueof_doc.param_name=\u8981\u8FD4\u56DE\u7684\u679A\u4E3E\u5E38\u91CF\u7684\u540D\u79F0\u3002 + +doclet.enum_valueof_doc.return=\u8FD4\u56DE\u5E26\u6709\u6307\u5B9A\u540D\u79F0\u7684\u679A\u4E3E\u5E38\u91CF + +doclet.enum_valueof_doc.throws_ila=\u5982\u679C\u8BE5\u679A\u4E3E\u7C7B\u578B\u6CA1\u6709\u5E26\u6709\u6307\u5B9A\u540D\u79F0\u7684\u5E38\u91CF + +doclet.enum_valueof_doc.throws_npe=\u5982\u679C\u53C2\u6570\u4E3A\u7A7A\u503C diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css index b2adb742b81..bf1bc9441de 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/resources/stylesheet.css @@ -180,6 +180,12 @@ ul.subNavList li{ margin: auto 5px; border:1px solid #c9aa44; } +.skipNav { + position:absolute; + top:auto; + left:-9999px; + overflow:hidden; + } /* Page header and footer styles */ @@ -372,7 +378,6 @@ Table styles overflow:hidden; padding:0px; margin:0px; - white-space:pre; } caption a:link, caption a:hover, caption a:active, caption a:visited { color:#FFFFFF; @@ -381,35 +386,32 @@ caption a:link, caption a:hover, caption a:active, caption a:visited { white-space:nowrap; padding-top:8px; padding-left:8px; - display:block; + display:inline-block; float:left; background-image:url(resources/titlebar.gif); - height:18px; } .contentContainer ul.blockList li.blockList caption span.activeTableTab span { white-space:nowrap; padding-top:8px; padding-left:8px; - display:block; + display:inline-block; float:left; background-image:url(resources/activetitlebar.gif); - height:18px; } .contentContainer ul.blockList li.blockList caption span.tableTab span { white-space:nowrap; padding-top:8px; padding-left:8px; - display:block; + display:inline-block; float:left; background-image:url(resources/titlebar.gif); - height:18px; } .contentContainer ul.blockList li.blockList caption span.tableTab, .contentContainer ul.blockList li.blockList caption span.activeTableTab { padding-top:0px; padding-left:0px; background-image:none; float:none; - display:inline; + display:inline-block; } .overviewSummary .tabEnd, .packageSummary .tabEnd, .contentContainer ul.blockList li.blockList .tabEnd, .summary .tabEnd, .classUseContainer .tabEnd, .constantValuesContainer .tabEnd { width:10px; diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java index 2691c2b4ab3..2dfce45c157 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/LegacyTaglet.java @@ -130,7 +130,13 @@ public class LegacyTaglet implements Taglet { public Content getTagletOutput(Doc holder, TagletWriter writer) throws IllegalArgumentException { Content output = writer.getOutputInstance(); - output.addContent(new RawHtml(legacyTaglet.toString(holder.tags(getName())))); + Tag[] tags = holder.tags(getName()); + if (tags.length > 0) { + String tagString = legacyTaglet.toString(tags); + if (tagString != null) { + output.addContent(new RawHtml(tagString)); + } + } return output; } } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java index 4d7dd74da2c..b1d6f39b8b3 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/taglets/ValueTaglet.java @@ -105,7 +105,9 @@ public class ValueTaglet extends BaseInlineTaglet { } /** - * Given the name of the field, return the corresponding FieldDoc. + * Given the name of the field, return the corresponding FieldDoc. Return null + * due to invalid use of value tag if the name is null or empty string and if + * the value tag is not used on a field. * * @param config the current configuration of the doclet. * @param tag the value tag. @@ -114,10 +116,8 @@ public class ValueTaglet extends BaseInlineTaglet { * it is assumed that the field is in the current class. * * @return the corresponding FieldDoc. If the name is null or empty string, - * return field that the value tag was used in. - * - * @throws DocletAbortException if the value tag does not specify a name to - * a value field and it is not used within the comments of a valid field. + * return field that the value tag was used in. Return null if the name is null + * or empty string and if the value tag is not used on a field. */ private FieldDoc getFieldDoc(Configuration config, Tag tag, String name) { if (name == null || name.length() == 0) { @@ -125,8 +125,9 @@ public class ValueTaglet extends BaseInlineTaglet { if (tag.holder() instanceof FieldDoc) { return (FieldDoc) tag.holder(); } else { - //This should never ever happen. - throw new DocletAbortException("should not happen"); + // If the value tag does not specify a parameter which is a valid field and + // it is not used within the comments of a valid field, return null. + return null; } } StringTokenizer st = new StringTokenizer(name, "#"); @@ -165,9 +166,15 @@ public class ValueTaglet extends BaseInlineTaglet { FieldDoc field = getFieldDoc( writer.configuration(), tag, tag.text()); if (field == null) { - //Reference is unknown. - writer.getMsgRetriever().warning(tag.holder().position(), - "doclet.value_tag_invalid_reference", tag.text()); + if (tag.text().isEmpty()) { + //Invalid use of @value + writer.getMsgRetriever().warning(tag.holder().position(), + "doclet.value_tag_invalid_use"); + } else { + //Reference is unknown. + writer.getMsgRetriever().warning(tag.holder().position(), + "doclet.value_tag_invalid_reference", tag.text()); + } } else if (field.constantValue() != null) { return writer.valueTagOutput(field, field.constantValueExpression(), diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java index 7990a347c18..faeec757e7a 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/PathDocFileFactory.java @@ -34,6 +34,7 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.UnsupportedEncodingException; import java.io.Writer; +import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -221,8 +222,10 @@ class PathDocFileFactory extends DocFileFactory { /** If the file is a directory, list its contents. */ public Iterable list() throws IOException { List files = new ArrayList(); - for (Path f: Files.newDirectoryStream(file)) { - files.add(new StandardDocFile(f)); + try (DirectoryStream ds = Files.newDirectoryStream(file)) { + for (Path f: ds) { + files.add(new StandardDocFile(f)); + } } return files; } diff --git a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java index 6c9870405f3..15d41773b4e 100644 --- a/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java +++ b/langtools/src/share/classes/com/sun/tools/doclets/internal/toolkit/util/VisibleMemberMap.java @@ -55,14 +55,15 @@ public class VisibleMemberMap { public static final int FIELDS = 2; public static final int CONSTRUCTORS = 3; public static final int METHODS = 4; - public static final int ANNOTATION_TYPE_MEMBER_OPTIONAL = 5; - public static final int ANNOTATION_TYPE_MEMBER_REQUIRED = 6; - public static final int PROPERTIES = 7; + public static final int ANNOTATION_TYPE_FIELDS = 5; + public static final int ANNOTATION_TYPE_MEMBER_OPTIONAL = 6; + public static final int ANNOTATION_TYPE_MEMBER_REQUIRED = 7; + public static final int PROPERTIES = 8; /** * The total number of member types is {@value}. */ - public static final int NUM_MEMBER_TYPES = 8; + public static final int NUM_MEMBER_TYPES = 9; public static final String STARTLEVEL = "start"; @@ -433,6 +434,9 @@ public class VisibleMemberMap { } ProgramElementDoc[] members = null; switch (kind) { + case ANNOTATION_TYPE_FIELDS: + members = cd.fields(filter); + break; case ANNOTATION_TYPE_MEMBER_OPTIONAL: members = cd.isAnnotationType() ? filter((AnnotationTypeDoc) cd, false) : diff --git a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java index d7d8ada40f0..bc4b86b0a09 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/Checker.java +++ b/langtools/src/share/classes/com/sun/tools/doclint/Checker.java @@ -44,6 +44,7 @@ import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.Name; +import javax.lang.model.element.VariableElement; import javax.lang.model.type.TypeKind; import javax.lang.model.type.TypeMirror; import javax.tools.Diagnostic.Kind; @@ -93,7 +94,7 @@ public class Checker extends DocTreePathScanner { Set foundParams = new HashSet<>(); Set foundThrows = new HashSet<>(); - Map> foundAnchors = new HashMap<>(); + Map> foundAnchors = new HashMap<>(); boolean foundInheritDoc = false; boolean foundReturn = false; @@ -576,13 +577,30 @@ public class Checker extends DocTreePathScanner { } private boolean checkAnchor(String name) { - JavaFileObject fo = env.currPath.getCompilationUnit().getSourceFile(); - Set set = foundAnchors.get(fo); + Element e = getEnclosingPackageOrClass(env.currElement); + if (e == null) + return true; + Set set = foundAnchors.get(e); if (set == null) - foundAnchors.put(fo, set = new HashSet<>()); + foundAnchors.put(e, set = new HashSet<>()); return set.add(name); } + private Element getEnclosingPackageOrClass(Element e) { + while (e != null) { + switch (e.getKind()) { + case CLASS: + case ENUM: + case INTERFACE: + case PACKAGE: + return e; + default: + e = e.getEnclosingElement(); + } + } + return e; + } + // http://www.w3.org/TR/html401/types.html#type-name private static final Pattern validName = Pattern.compile("[A-Za-z][A-Za-z0-9-_:.]*"); @@ -712,6 +730,10 @@ public class Checker extends DocTreePathScanner { @Override public Void visitReference(ReferenceTree tree, Void ignore) { + String sig = tree.getSignature(); + if (sig.contains("<") || sig.contains(">")) + env.messages.error(REFERENCE, tree, "dc.type.arg.not.allowed"); + Element e = env.trees.getElement(getCurrentPath()); if (e == null) env.messages.error(REFERENCE, tree, "dc.ref.not.found"); @@ -805,10 +827,33 @@ public class Checker extends DocTreePathScanner { @Override public Void visitValue(ValueTree tree, Void ignore) { + ReferenceTree ref = tree.getReference(); + if (ref == null || ref.getSignature().isEmpty()) { + if (!isConstant(env.currElement)) + env.messages.error(REFERENCE, tree, "dc.value.not.allowed.here"); + } else { + Element e = env.trees.getElement(new DocTreePath(getCurrentPath(), ref)); + if (!isConstant(e)) + env.messages.error(REFERENCE, tree, "dc.value.not.a.constant"); + } + markEnclosingTag(Flag.HAS_INLINE_TAG); return super.visitValue(tree, ignore); } + private boolean isConstant(Element e) { + if (e == null) + return false; + + switch (e.getKind()) { + case FIELD: + Object value = ((VariableElement) e).getConstantValue(); + return (value != null); // can't distinguish "not a constant" from "constant is null" + default: + return false; + } + } + @Override public Void visitVersion(VersionTree tree, Void ignore) { warnIfEmpty(tree, tree.getBody()); diff --git a/langtools/src/share/classes/com/sun/tools/doclint/DocLint.java b/langtools/src/share/classes/com/sun/tools/doclint/DocLint.java index 20151d1f360..a7b6fb6a15c 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/DocLint.java +++ b/langtools/src/share/classes/com/sun/tools/doclint/DocLint.java @@ -29,9 +29,14 @@ import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.util.ArrayList; +import java.util.HashSet; +import java.util.LinkedList; import java.util.List; +import java.util.Queue; +import java.util.Set; import javax.lang.model.element.Name; +import javax.tools.JavaFileObject; import javax.tools.StandardLocation; import com.sun.source.doctree.DocCommentTree; @@ -278,15 +283,25 @@ public class DocLint implements Plugin { TaskListener tl = new TaskListener() { @Override public void started(TaskEvent e) { + switch (e.getKind()) { + case ANALYZE: + CompilationUnitTree tree; + while ((tree = todo.poll()) != null) + ds.scan(tree, null); + break; + } } @Override public void finished(TaskEvent e) { switch (e.getKind()) { - case ENTER: - ds.scan(e.getCompilationUnit(), null); + case PARSE: + todo.add(e.getCompilationUnit()); + break; } } + + Queue todo = new LinkedList(); }; task.addTaskListener(tl); diff --git a/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java b/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java index 3b8f8599e09..2ea92af9ac0 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java +++ b/langtools/src/share/classes/com/sun/tools/doclint/HtmlTag.java @@ -86,6 +86,9 @@ public enum HtmlTag { DD(BlockType.LIST_ITEM, EndKind.OPTIONAL, EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE, Flag.EXPECT_CONTENT)), + DFN(BlockType.INLINE, EndKind.REQUIRED, + EnumSet.of(Flag.EXPECT_CONTENT, Flag.NO_NEST)), + DIV(BlockType.BLOCK, EndKind.REQUIRED, EnumSet.of(Flag.ACCEPTS_BLOCK, Flag.ACCEPTS_INLINE)), diff --git a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties index 37470976141..b51af2a7358 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties +++ b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint.properties @@ -67,7 +67,10 @@ dc.tag.self.closing = self-closing element not allowed dc.tag.start.unmatched = end tag missing: dc.tag.unknown = unknown tag: {0} dc.text.not.allowed = text not allowed in <{0}> element +dc.type.arg.not.allowed = type arguments not allowed here dc.unexpected.comment=documentation comment not expected here +dc.value.not.allowed.here='{@value}' not allowed here +dc.value.not.a.constant=value does not refer to a constant dc.main.ioerror=IO error: {0} dc.main.no.files.given=No files given diff --git a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_ja.properties b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_ja.properties index 10282be9632..6089737db60 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_ja.properties @@ -26,6 +26,7 @@ dc.anchor.already.defined = \u30A2\u30F3\u30AB\u30FC\u304C\u3059\u3067\u306B\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u307E\u3059: {0} dc.anchor.value.missing = \u30A2\u30F3\u30AB\u30FC\u306B\u5024\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 dc.attr.lacks.value = \u5C5E\u6027\u306B\u5024\u304C\u3042\u308A\u307E\u305B\u3093 +dc.attr.not.number = \u5C5E\u6027\u5024\u304C\u6570\u5B57\u3067\u306F\u3042\u308A\u307E\u305B\u3093 dc.attr.obsolete = \u5C5E\u6027\u306F\u5EC3\u6B62\u3055\u308C\u3066\u3044\u307E\u3059: {0} dc.attr.obsolete.use.css = \u5C5E\u6027\u306F\u5EC3\u6B62\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u304B\u308F\u308A\u306BCSS\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044: {0} dc.attr.repeated = \u7E70\u308A\u8FD4\u3055\u308C\u305F\u5C5E\u6027: {0} @@ -46,7 +47,7 @@ dc.missing.return = @return\u304C\u3042\u308A\u307E\u305B\u3093 dc.missing.throws = {0}\u306E@throws\u304C\u3042\u308A\u307E\u305B\u3093 dc.no.alt.attr.for.image = \u30A4\u30E1\u30FC\u30B8\u306E"alt"\u5C5E\u6027\u304C\u3042\u308A\u307E\u305B\u3093 dc.no.summary.or.caption.for.table=\u8868\u306E\u8981\u7D04\u307E\u305F\u306F\u30AD\u30E3\u30D7\u30B7\u30E7\u30F3\u304C\u3042\u308A\u307E\u305B\u3093 -dc.param.name.not.found = @param\u540D\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 +dc.param.name.not.found = @param name\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 dc.ref.not.found = \u53C2\u7167\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093 dc.tag.code.within.code = \u5185\u306E'{@code'} dc.tag.empty = \u7A7A\u306E<{0}>\u30BF\u30B0 @@ -66,3 +67,9 @@ dc.tag.self.closing = \u81EA\u5DF1\u7D42\u4E86\u8981\u7D20\u306F\u4F7F\u7528\u30 dc.tag.start.unmatched = \u7D42\u4E86\u30BF\u30B0\u304C\u3042\u308A\u307E\u305B\u3093: dc.tag.unknown = \u4E0D\u660E\u306A\u30BF\u30B0: {0} dc.text.not.allowed = <{0}>\u8981\u7D20\u3067\u306F\u30C6\u30AD\u30B9\u30C8\u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 +dc.unexpected.comment=\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u30FB\u30B3\u30E1\u30F3\u30C8\u306F\u3053\u3053\u3067\u306F\u5FC5\u8981\u3042\u308A\u307E\u305B\u3093 + +dc.main.ioerror=IO\u30A8\u30E9\u30FC: {0} +dc.main.no.files.given=\u30D5\u30A1\u30A4\u30EB\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 +dc.main.usage=\u4F7F\u7528\u65B9\u6CD5:\n doclint [options] source-files...\n\n\u30AA\u30D7\u30B7\u30E7\u30F3:\n -Xmsgs \n -Xmsgs:all\u3068\u540C\u3058\n -Xmsgs:values\n \u30C1\u30A7\u30C3\u30AF\u3059\u308B\u554F\u984C\u306E\u30AB\u30C6\u30B4\u30EA\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002\u3053\u3053\u3067\u306E''values''\u306F\u3001\n \u30AB\u30F3\u30DE\u3067\u533A\u5207\u3089\u308C\u305F\u6B21\u306E\u5024\u306E\u30EA\u30B9\u30C8\u3067\u3059:\n reference Java\u30BD\u30FC\u30B9\u30FB\u30B3\u30FC\u30C9\u8981\u7D20\u3078\u306E\u4E0D\u6B63\u306A\u53C2\u7167\u3092\u542B\u3080\u30B3\u30E1\u30F3\u30C8\u306E\n \u5834\u6240\u3092\u8868\u793A\u3057\u307E\u3059\n syntax \u30B3\u30E1\u30F3\u30C8\u5185\u306E\u57FA\u672C\u69CB\u6587\u30A8\u30E9\u30FC\u3092\u8868\u793A\u3057\u307E\u3059\n html HTML\u30BF\u30D6\u304A\u3088\u3073\u5C5E\u6027\u306E\u554F\u984C\u3092\u8868\u793A\u3057\u307E\u3059\n accessibility \u30A2\u30AF\u30BB\u30B7\u30D3\u30EA\u30C6\u30A3\u306E\u554F\u984C\u3092\u8868\u793A\u3057\u307E\u3059\n missing \u6B20\u843D\u3057\u3066\u3044\u308B\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306E\u554F\u984C\u3092\u8868\u793A\u3057\u307E\u3059\n all \u524D\u8FF0\u306E\u3059\u3079\u3066\n \u3053\u308C\u3092\u5426\u5B9A\u3059\u308B\u306B\u306F\u3001\u5024\u306E\u524D\u306B''-''\u3092\u6307\u5B9A\u3057\u307E\u3059\n \u30AB\u30C6\u30B4\u30EA\u306F\u3001\u6B21\u306E\u3044\u305A\u308C\u304B\u3067\u4FEE\u98FE\u3067\u304D\u307E\u3059:\n /public /protected /package /private\n \u6B63\u306E\u30AB\u30C6\u30B4\u30EA(''-''\u3067\u59CB\u307E\u3089\u306A\u3044)\u306E\u5834\u5408\n \u4FEE\u98FE\u5B50\u306F\u3001\u305D\u306E\u30A2\u30AF\u30BB\u30B9\u30FB\u30EC\u30D9\u30EB\u4EE5\u4E0A\u306B\u9069\u7528\u3055\u308C\u307E\u3059\u3002\n \u8CA0\u306E\u30AB\u30C6\u30B4\u30EA(''-''\u3067\u59CB\u307E\u308B)\u306E\u5834\u5408\n \u4FEE\u98FE\u5B50\u306F\u3001\u305D\u306E\u30A2\u30AF\u30BB\u30B9\u30FB\u30EC\u30D9\u30EB\u4EE5\u4E0B\u306B\u9069\u7528\u3055\u308C\u307E\u3059\u3002\n \u4FEE\u98FE\u5B50\u304C\u306A\u3044\u5834\u5408\u3001\u30AB\u30C6\u30B4\u30EA\u306F\u3059\u3079\u3066\u306E\u30A2\u30AF\u30BB\u30B9\u30FB\u30EC\u30D9\u30EB\u306B\n \u9069\u7528\u3055\u308C\u307E\u3059\u3002\n \u4F8B: -Xmsgs:all,-syntax/private\n \u3053\u306E\u5834\u5408\u3001private\u30E1\u30BD\u30C3\u30C9\u306Edoc\u30B3\u30E1\u30F3\u30C8\u5185\u306E\u69CB\u6587\u30A8\u30E9\u30FC\u3092\u9664\u304D\u3001\n \u3059\u3079\u3066\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u6709\u52B9\u5316\u3055\u308C\u307E\u3059\u3002\n -Xmsgs\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u306A\u3044\u5834\u5408\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u3001\n -Xmsgs:all/protected\u3068\u540C\u7B49\u306B\u306A\u308A\u3001\u3053\u308C\u306F\n \u3059\u3079\u3066\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u3001protected\u304A\u3088\u3073public\u306E\u5BA3\u8A00\u306E\u307F\u306B\u5831\u544A\u3055\u308C\u308B\u3053\u3068\u3092\n \u610F\u5473\u3057\u307E\u3059\u3002\n -stats\n \u5831\u544A\u3055\u308C\u305F\u554F\u984C\u306B\u5BFE\u3057\u3066\u7D71\u8A08\u3092\u5831\u544A\u3057\u307E\u3059\u3002\n -h -help --help -usage -?\n \u3053\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u8868\u793A\u3055\u308C\u307E\u3059\u3002\n\n\u6B21\u306Ejavac\u30AA\u30D7\u30B7\u30E7\u30F3\u3082\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u3059\n \ +-bootclasspath\u3001-classpath\u3001-cp\u3001-sourcepath\u3001-Xmaxerrs\u3001-Xmaxwarns\n\n\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u4E00\u90E8\u306B\u5BFE\u3057\u3066doclint\u3092\u5B9F\u884C\u3059\u308B\u306B\u306F\u3001\u30D7\u30ED\u30B8\u30A7\u30AF\u30C8\u306E\u30B3\u30F3\u30D1\u30A4\u30EB\u3055\u308C\u305F\u30AF\u30E9\u30B9\u3092\n\u30AF\u30E9\u30B9\u30D1\u30B9(\u307E\u305F\u306F\u30D6\u30FC\u30C8\u30FB\u30AF\u30E9\u30B9\u30D1\u30B9)\u306B\u6307\u5B9A\u3057\u3001\u30B3\u30DE\u30F3\u30C9\u30FB\u30E9\u30A4\u30F3\u3067\n\u30C1\u30A7\u30C3\u30AF\u3059\u308B\u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002 diff --git a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_zh_CN.properties index b3a9c7041bc..4d25a4d5c71 100644 --- a/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/doclint/resources/doclint_zh_CN.properties @@ -26,6 +26,7 @@ dc.anchor.already.defined = \u951A\u5B9A\u70B9\u5DF2\u5B9A\u4E49: {0} dc.anchor.value.missing = \u6CA1\u6709\u4E3A\u951A\u5B9A\u70B9\u6307\u5B9A\u503C dc.attr.lacks.value = \u5C5E\u6027\u7F3A\u5C11\u503C +dc.attr.not.number = \u5C5E\u6027\u503C\u4E0D\u662F\u6570\u5B57 dc.attr.obsolete = \u5C5E\u6027\u5DF2\u8FC7\u65F6: {0} dc.attr.obsolete.use.css = \u5C5E\u6027\u5DF2\u8FC7\u65F6, \u8BF7\u6539\u7528 CSS: {0} dc.attr.repeated = \u5C5E\u6027\u91CD\u590D: {0} @@ -46,7 +47,7 @@ dc.missing.return = \u6CA1\u6709 @return dc.missing.throws = {0}\u6CA1\u6709 @throws dc.no.alt.attr.for.image = \u56FE\u50CF\u6CA1\u6709 "alt" \u5C5E\u6027 dc.no.summary.or.caption.for.table=\u8868\u6CA1\u6709\u6982\u8981\u6216\u6807\u9898 -dc.param.name.not.found = \u627E\u4E0D\u5230 @param \u540D\u79F0 +dc.param.name.not.found = @param name \u672A\u627E\u5230 dc.ref.not.found = \u627E\u4E0D\u5230\u5F15\u7528 dc.tag.code.within.code = '{@code'} \u5728 \u4E2D dc.tag.empty = <{0}> \u6807\u8BB0\u4E3A\u7A7A @@ -66,3 +67,8 @@ dc.tag.self.closing = \u4E0D\u5141\u8BB8\u4F7F\u7528\u81EA\u5173\u95ED\u5143\u7D dc.tag.start.unmatched = \u7F3A\u5C11\u7ED3\u675F\u6807\u8BB0: dc.tag.unknown = \u672A\u77E5\u6807\u8BB0: {0} dc.text.not.allowed = <{0}> \u5143\u7D20\u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528\u6587\u672C +dc.unexpected.comment=\u6B64\u5904\u672A\u9884\u671F\u6587\u6863\u6CE8\u91CA + +dc.main.ioerror=IO \u9519\u8BEF: {0} +dc.main.no.files.given=\u672A\u6307\u5B9A\u6587\u4EF6 +dc.main.usage=\u7528\u6CD5:\n doclint [options] source-files...\n\n\u9009\u9879:\n -Xmsgs \n \u4E0E -Xmsgs:all \u76F8\u540C\n -Xmsgs:values\n \u6307\u5B9A\u8981\u68C0\u67E5\u7684\u95EE\u9898\u7684\u7C7B\u522B, \u5176\u4E2D ''values''\n \u662F\u4EFB\u610F\u4EE5\u4E0B\u5185\u5BB9\u7684\u4EE5\u9017\u53F7\u5206\u9694\u7684\u5217\u8868:\n reference \u663E\u793A\u5305\u542B\u5BF9 Java \u6E90\u4EE3\u7801\u5143\u7D20\n \u9519\u8BEF\u5F15\u7528\u7684\u6CE8\u91CA\u7684\u4F4D\u7F6E\n syntax \u663E\u793A\u6CE8\u91CA\u4E2D\u7684\u57FA\u672C\u8BED\u6CD5\u9519\u8BEF\n html \u663E\u793A HTML \u6807\u8BB0\u548C\u5C5E\u6027\u95EE\u9898\n accessibility \u663E\u793A\u53EF\u8BBF\u95EE\u6027\u7684\u95EE\u9898\n missing \u663E\u793A\u7F3A\u5C11\u6587\u6863\u7684\u95EE\u9898\n all \u6240\u6709\u4EE5\u4E0A\u5185\u5BB9\n \u5728\u503C\u4E4B\u524D\u4F7F\u7528 ''-'' \u53EF\u4F7F\u7528\u5176\u53CD\u503C\n \u53EF\u4EE5\u4F7F\u7528\u4EE5\u4E0B\u4E00\u9879\u6765\u9650\u5B9A\u7C7B\u522B:\n /public /protected /package /private\n \u5BF9\u4E8E\u6B63\u7C7B\u522B (\u4E0D\u4EE5 ''-'' \u5F00\u5934)\n \u9650\u5B9A\u7B26\u9002\u7528\u4E8E\u8BE5\u8BBF\u95EE\u7EA7\u522B\u53CA\u66F4\u9AD8\u7EA7\u522B\u3002\n \u5BF9\u4E8E\u8D1F\u7C7B\u522B (\u4EE5 ''-'' \u5F00\u5934)\n \u9650\u5B9A\u7B26\u9002\u7528\u4E8E\u8BE5\u8BBF\u95EE\u7EA7\u522B\u53CA\u66F4\u4F4E\u7EA7\u522B\u3002\n \u5982\u679C\u6CA1\u6709\u9650\u5B9A\u7B26, \u5219\u8BE5\u7C7B\u522B\u9002\u7528\u4E8E\n \u6240\u6709\u8BBF\u95EE\u7EA7\u522B\u3002\n \u4F8B\u5982, -Xmsgs:all,-syntax/private\n \u8FD9\u5C06\u5728\u4E13\u7528\u65B9\u6CD5\u7684\u6587\u6863\u6CE8\u91CA\u4E2D\n \u542F\u7528\u9664\u8BED\u6CD5\u9519\u8BEF\u4E4B\u5916\u7684\u6240\u6709\u6D88\u606F\u3002\n \u5982\u679C\u672A\u63D0\u4F9B -Xmsgs \u9009\u9879, \u5219\u9ED8\u8BA4\u503C\n \u7B49\u540C\u4E8E -Xmsgs:all/protected, \u8868\u793A\n \u4EC5\u62A5\u544A\u53D7\u4FDD\u62A4\u548C\u516C\u5171\u58F0\u660E\u4E2D\u7684\n \u6240\u6709\u6D88\u606F\n -stats\n \u62A5\u544A\u6240\u62A5\u544A\u95EE\u9898\u7684\u7EDF\u8BA1\u4FE1\u606F\u3002\n -h -help --help -usage -?\n \u663E\u793A\u6B64\u6D88\u606F\u3002\n\n\u8FD8\u652F\u6301\u4EE5\u4E0B javac \u9009\u9879\n -bootclasspath, -classpath, -cp, -sourcepath, -Xmaxerrs, -Xmaxwarns\n\n\u8981\u5728\u9879\u76EE\u7684\u4E00\u90E8\u5206\u4E0A\u8FD0\u884C doclint, \u8BF7\u5C06\u9879\u76EE\u4E2D\u5DF2\u7F16\u8BD1\u7684\u7C7B\n\u653E\u5728\u7C7B\u8DEF\u5F84 (\u6216\u5F15\u5BFC\u7C7B\u8DEF\u5F84) \u4E0A, \u7136\u540E\u5728\u547D\u4EE4\u884C\u4E0A\u6307\u5B9A\n\u8981\u68C0\u67E5\u7684\u6E90\u6587\u4EF6\u3002 diff --git a/langtools/src/share/classes/com/sun/tools/javac/Main.java b/langtools/src/share/classes/com/sun/tools/javac/Main.java index 2587d198972..43300b6c3c5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/Main.java +++ b/langtools/src/share/classes/com/sun/tools/javac/Main.java @@ -30,14 +30,6 @@ import java.io.PrintWriter; /** * The programmatic interface for the Java Programming Language * compiler, javac. - * - *

        Except for the two methods - * {@link #compile(java.lang.String[])} - * {@link #compile(java.lang.String[],java.io.PrintWriter)}, - * nothing described in this source file is part of any supported - * API. If you write code that depends on this, you do so at your own - * risk. This code and its internal interfaces are subject to change - * or deletion without notice. */ @jdk.Supported public class Main { diff --git a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java index f5f5a4b120e..e0dde3de7b2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javac/api/JavacTaskImpl.java @@ -472,7 +472,7 @@ public class JavacTaskImpl extends BasicJavacTask { for (TypeElement item: classes) set.add(item); - ListBuffer> defer = ListBuffer.>lb(); + ListBuffer> defer = new ListBuffer<>(); while (list.peek() != null) { Env env = list.remove(); ClassSymbol csym = env.enclClass.sym; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java b/langtools/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java index 022681bd8f6..0691498aeb5 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,6 +28,8 @@ package com.sun.tools.javac.code; import java.util.HashMap; import java.util.Map; +import com.sun.tools.javac.tree.EndPosTable; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.util.Assert; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -53,10 +55,13 @@ public class DeferredLintHandler { protected DeferredLintHandler(Context context) { context.put(deferredLintHandlerKey, this); + this.currentPos = IMMEDIATE_POSITION; } - private DeferredLintHandler() {} - + /**An interface for deferred lint reporting - loggers passed to + * {@link #report(LintLogger) } will be called when + * {@link #flush(DiagnosticPosition) } is invoked. + */ public interface LintLogger { void report(); } @@ -64,12 +69,26 @@ public class DeferredLintHandler { private DiagnosticPosition currentPos; private Map> loggersQueue = new HashMap>(); + /**Associate the given logger with the current position as set by {@link #setPos(DiagnosticPosition) }. + * Will be invoked when {@link #flush(DiagnosticPosition) } will be invoked with the same position. + *
        + * Will invoke the logger synchronously if {@link #immediate() } was called + * instead of {@link #setPos(DiagnosticPosition) }. + */ public void report(LintLogger logger) { - ListBuffer loggers = loggersQueue.get(currentPos); - Assert.checkNonNull(loggers); - loggers.append(logger); + if (currentPos == IMMEDIATE_POSITION) { + logger.report(); + } else { + ListBuffer loggers = loggersQueue.get(currentPos); + if (loggers == null) { + loggersQueue.put(currentPos, loggers = new ListBuffer<>()); + } + loggers.append(logger); + } } + /**Invoke all {@link LintLogger}s that were associated with the provided {@code pos}. + */ public void flush(DiagnosticPosition pos) { ListBuffer loggers = loggersQueue.get(pos); if (loggers != null) { @@ -80,16 +99,46 @@ public class DeferredLintHandler { } } - public DeferredLintHandler setPos(DiagnosticPosition currentPos) { + /**Sets the current position to the provided {@code currentPos}. {@link LintLogger}s + * passed to subsequent invocations of {@link #report(LintLogger) } will be associated + * with the given position. + */ + public DiagnosticPosition setPos(DiagnosticPosition currentPos) { + DiagnosticPosition prevPosition = this.currentPos; this.currentPos = currentPos; - loggersQueue.put(currentPos, ListBuffer.lb()); - return this; + return prevPosition; } - public static final DeferredLintHandler immediateHandler = new DeferredLintHandler() { + /**{@link LintLogger}s passed to subsequent invocations of + * {@link #report(LintLogger) } will be invoked immediately. + */ + public DiagnosticPosition immediate() { + return setPos(IMMEDIATE_POSITION); + } + + private static final DiagnosticPosition IMMEDIATE_POSITION = new DiagnosticPosition() { @Override - public void report(LintLogger logger) { - logger.report(); + public JCTree getTree() { + Assert.error(); + return null; + } + + @Override + public int getStartPosition() { + Assert.error(); + return -1; + } + + @Override + public int getPreferredPosition() { + Assert.error(); + return -1; + } + + @Override + public int getEndPosition(EndPosTable endPosTable) { + Assert.error(); + return -1; } }; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java index 12acc8dc27e..2f59cfab7fd 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Flags.java @@ -97,7 +97,6 @@ public class Flags { public static final int MANDATED = 1<<15; public static final int StandardFlags = 0x0fff; - public static final int ModifierFlags = StandardFlags & ~INTERFACE; // Because the following access flags are overloaded with other // bit positions, we translate them when reading and writing class @@ -262,10 +261,15 @@ public class Flags { public static final long SIGNATURE_POLYMORPHIC = 1L<<46; /** - * Flag that marks inference variables used in a 'throws' clause + * Flag that indicates that an inference variable is used in a 'throws' clause. */ public static final long THROWS = 1L<<47; + /** + * Flag that marks potentially ambiguous overloads + */ + public static final long POTENTIALLY_AMBIGUOUS = 1L<<48; + /** Modifier masks. */ public static final int @@ -282,7 +286,9 @@ public class Flags { SYNCHRONIZED | FINAL | STRICTFP; public static final long ExtendedStandardFlags = (long)StandardFlags | DEFAULT, + ModifierFlags = ((long)StandardFlags & ~INTERFACE) | DEFAULT, InterfaceMethodMask = ABSTRACT | STATIC | PUBLIC | STRICTFP | DEFAULT, + AnnotationTypeElementMask = FINAL | ABSTRACT | PUBLIC | STRICTFP, LocalVarFlags = FINAL | PARAMETER; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java index a6956f341ec..9e1c4424fa8 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java @@ -33,9 +33,6 @@ import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.Options; import com.sun.tools.javac.util.Pair; -import static com.sun.tools.javac.code.Flags.*; - - /** * A class for handling -Xlint suboptions and @SuppresssWarnings. * @@ -81,7 +78,6 @@ public class Lint return l; } - private final AugmentVisitor augmentor; private final EnumSet values; @@ -90,7 +86,6 @@ public class Lint private static final Map map = new java.util.concurrent.ConcurrentHashMap(20); - protected Lint(Context context) { // initialize values according to the lint options Options options = Options.instance(context); @@ -174,6 +169,11 @@ public class Lint */ OPTIONS("options"), + /** + * Warn about issues regarding method overloads. + */ + OVERLOADS("overloads"), + /** * Warn about issues regarding method overrides. */ diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java index aa05cc29204..d46631504b2 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Printer.java @@ -103,7 +103,7 @@ public abstract class Printer implements Type.Visitor, Symbol.Vi * @return localized string representation */ public String visitTypes(List ts, Locale locale) { - ListBuffer sbuf = ListBuffer.lb(); + ListBuffer sbuf = new ListBuffer<>(); for (Type t : ts) { sbuf.append(visit(t, locale)); } @@ -118,7 +118,7 @@ public abstract class Printer implements Type.Visitor, Symbol.Vi * @return localized string representation */ public String visitSymbols(List ts, Locale locale) { - ListBuffer sbuf = ListBuffer.lb(); + ListBuffer sbuf = new ListBuffer<>(); for (Symbol t : ts) { sbuf.append(visit(t, locale)); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 64c117cb2bc..7a65bd04b10 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java @@ -46,6 +46,7 @@ import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.code.TypeTag.FORALL; import static com.sun.tools.javac.code.TypeTag.TYPEVAR; +import com.sun.tools.javac.tree.JCTree.JCVariableDecl; /** Root class for Java symbols. It contains subclasses * for specific sorts of symbols, such as variables, methods and operators, @@ -98,9 +99,9 @@ public abstract class Symbol implements Element { // /** The attributes of this symbol are contained in this - * Annotations. The Annotations instance is NOT immutable. + * SymbolMetadata. The SymbolMetadata instance is NOT immutable. */ - protected Annotations annotations; + protected SymbolMetadata annotations; /** An accessor method for the attributes of this symbol. * Attributes of class symbols should be accessed through the accessor @@ -217,19 +218,19 @@ public abstract class Symbol implements Element { public void setTypeAttributes(List a) { if (annotations != null || a.nonEmpty()) { if (annotations == null) - annotations = new Annotations(this); + annotations = new SymbolMetadata(this); annotations.setTypeAttributes(a); } } - private Annotations initedAnnos() { + private SymbolMetadata initedAnnos() { if (annotations == null) - annotations = new Annotations(this); + annotations = new SymbolMetadata(this); return annotations; } /** This method is intended for debugging only. */ - public Annotations getAnnotations() { + public SymbolMetadata getAnnotations() { return annotations; } @@ -613,7 +614,7 @@ public abstract class Symbol implements Element { } public List getTypeParameters() { - ListBuffer l = ListBuffer.lb(); + ListBuffer l = new ListBuffer<>(); for (Type t : type.getTypeArguments()) { Assert.check(t.tsym.getKind() == ElementKind.TYPE_PARAMETER); l.append((TypeVariableSymbol)t.tsym); @@ -852,7 +853,7 @@ public abstract class Symbol implements Element { private void mergeAttributes() { if (annotations == null && package_info.annotations != null) { - annotations = new Annotations(this); + annotations = new SymbolMetadata(this); annotations.setAttributes(package_info.annotations); } } @@ -1167,11 +1168,11 @@ public abstract class Symbol implements Element { public void setLazyConstValue(final Env env, final Attr attr, - final JCTree.JCExpression initializer) + final JCVariableDecl variable) { setData(new Callable() { public Object call() { - return attr.attribLazyConstantValue(env, initializer, type); + return attr.attribLazyConstantValue(env, variable, type); } }); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/SymbolMetadata.java similarity index 94% rename from langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java rename to langtools/src/share/classes/com/sun/tools/javac/code/SymbolMetadata.java index 5be0865c042..42564f67ed3 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Annotations.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/SymbolMetadata.java @@ -57,7 +57,7 @@ import static com.sun.tools.javac.code.Kinds.PCK; * later. You can reset to IN_PROGRESS. While IN_PROGRESS you can set the list * of attributes (and this moves out of the IN_PROGRESS state). * - * "unnamed" this Annotations contains some attributes, possibly the final set. + * "unnamed" this SymbolMetadata contains some attributes, possibly the final set. * While in this state you can only prepend or append to the attributes not set * it directly. You can also move back to the IN_PROGRESS state using reset(). * @@ -65,7 +65,7 @@ import static com.sun.tools.javac.code.Kinds.PCK; * on this, you do so at your own risk. This code and its internal interfaces * are subject to change or deletion without notice. */ -public class Annotations { +public class SymbolMetadata { private static final List DECL_NOT_STARTED = List.of(null); private static final List DECL_IN_PROGRESS = List.of(null); @@ -94,11 +94,11 @@ public class Annotations { private List clinit_type_attributes = List.nil(); /* - * The Symbol this Annotations instance belongs to + * The Symbol this SymbolMetadata instance belongs to */ private final Symbol sym; - public Annotations(Symbol sym) { + public SymbolMetadata(Symbol sym) { this.sym = sym; } @@ -147,7 +147,7 @@ public class Annotations { clinit_type_attributes = a; } - public void setAttributes(Annotations other) { + public void setAttributes(SymbolMetadata other) { if (other == null) { throw new NullPointerException(); } @@ -221,7 +221,7 @@ public class Annotations { return buf.reverse(); } - public Annotations reset() { + public SymbolMetadata reset() { attributes = DECL_IN_PROGRESS; return this; } @@ -240,7 +240,7 @@ public class Annotations { return attributes == DECL_IN_PROGRESS; } - public Annotations append(List l) { + public SymbolMetadata append(List l) { attributes = filterDeclSentinels(attributes); if (l.isEmpty()) { @@ -253,7 +253,7 @@ public class Annotations { return this; } - public Annotations appendUniqueTypes(List l) { + public SymbolMetadata appendUniqueTypes(List l) { if (l.isEmpty()) { ; // no-op } else if (type_attributes.isEmpty()) { @@ -269,7 +269,7 @@ public class Annotations { return this; } - public Annotations appendInitTypeAttributes(List l) { + public SymbolMetadata appendInitTypeAttributes(List l) { if (l.isEmpty()) { ; // no-op } else if (init_type_attributes.isEmpty()) { @@ -280,7 +280,7 @@ public class Annotations { return this; } - public Annotations appendClassInitTypeAttributes(List l) { + public SymbolMetadata appendClassInitTypeAttributes(List l) { if (l.isEmpty()) { ; // no-op } else if (clinit_type_attributes.isEmpty()) { @@ -291,7 +291,7 @@ public class Annotations { return this; } - public Annotations prepend(List l) { + public SymbolMetadata prepend(List l) { attributes = filterDeclSentinels(attributes); if (l.isEmpty()) { @@ -367,7 +367,7 @@ public class Annotations { type_attributes = result.reverse(); - Assert.check(Annotations.this.getTypePlaceholders().isEmpty()); + Assert.check(SymbolMetadata.this.getTypePlaceholders().isEmpty()); } else { Assert.check(!pendingCompletion()); @@ -391,7 +391,7 @@ public class Annotations { attributes = result.reverse(); - Assert.check(Annotations.this.getPlaceholders().isEmpty()); + Assert.check(SymbolMetadata.this.getPlaceholders().isEmpty()); } } finally { log.useSource(oldSource); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java index fb6308ba9bd..699ac7ebedc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Type.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Type.java @@ -433,7 +433,7 @@ public abstract class Type implements TypeMirror { } public static List filter(List ts, Filter tf) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type t : ts) { if (tf.accepts(t)) { buf.append(t); @@ -977,7 +977,7 @@ public abstract class Type implements TypeMirror { } public java.util.List getBounds() { - return Collections.unmodifiableList(getComponents()); + return Collections.unmodifiableList(getExplicitComponents()); } public List getComponents() { @@ -1496,7 +1496,7 @@ public abstract class Type implements TypeMirror { /** get all bounds of a given kind */ public List getBounds(InferenceBound... ibs) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (InferenceBound ib : ibs) { buf.appendList(bounds.get(ib)); } @@ -1505,7 +1505,7 @@ public abstract class Type implements TypeMirror { /** get the list of declared (upper) bounds */ public List getDeclaredBounds() { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); int count = 0; for (Type b : getBounds(InferenceBound.UPPER)) { if (count++ == declaredCount) break; @@ -1565,8 +1565,8 @@ public abstract class Type implements TypeMirror { for (Map.Entry> _entry : bounds.entrySet()) { InferenceBound ib = _entry.getKey(); List prevBounds = _entry.getValue(); - ListBuffer newBounds = ListBuffer.lb(); - ListBuffer deps = ListBuffer.lb(); + ListBuffer newBounds = new ListBuffer<>(); + ListBuffer deps = new ListBuffer<>(); //step 1 - re-add bounds that are not dependent on ivars for (Type t : prevBounds) { if (!t.containsAny(instVars)) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java index 89f6ea40799..c481ea5d3e0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotationPosition.java @@ -304,7 +304,7 @@ public class TypeAnnotationPosition { * @param list The bytecode representation of the type path. */ public static List getTypePathFromBinary(java.util.List list) { - ListBuffer loc = ListBuffer.lb(); + ListBuffer loc = new ListBuffer<>(); Iterator iter = list.iterator(); while (iter.hasNext()) { Integer fst = iter.next(); @@ -316,7 +316,7 @@ public class TypeAnnotationPosition { } public static List getBinaryFromTypePath(java.util.List locs) { - ListBuffer loc = ListBuffer.lb(); + ListBuffer loc = new ListBuffer<>(); for (TypePathEntry tpe : locs) { loc = loc.append(tpe.tag.tag); loc = loc.append(tpe.arg); diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java index 642de5d4c4a..677319f1db6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -31,10 +31,7 @@ import javax.lang.model.type.TypeKind; import javax.tools.JavaFileObject; -import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Attribute.TypeCompound; -import com.sun.tools.javac.code.Flags; -import com.sun.tools.javac.code.Kinds; import com.sun.tools.javac.code.Type.AnnotatedType; import com.sun.tools.javac.code.Type.ArrayType; import com.sun.tools.javac.code.Type.CapturedType; @@ -49,7 +46,6 @@ import com.sun.tools.javac.code.Type.Visitor; import com.sun.tools.javac.code.Type.WildcardType; import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntry; import com.sun.tools.javac.code.TypeAnnotationPosition.TypePathEntryKind; -import com.sun.tools.javac.code.TypeTag; import com.sun.tools.javac.code.Symbol.VarSymbol; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.comp.Annotate; @@ -70,6 +66,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.tree.JCTree.*; import com.sun.tools.javac.util.Assert; +import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Log; @@ -83,8 +80,28 @@ import com.sun.tools.javac.util.Names; * and determine the TypeAnnotationPositions for all type annotations. */ public class TypeAnnotations { - // Class cannot be instantiated. - private TypeAnnotations() {} + protected static final Context.Key typeAnnosKey = + new Context.Key(); + + public static TypeAnnotations instance(Context context) { + TypeAnnotations instance = context.get(typeAnnosKey); + if (instance == null) + instance = new TypeAnnotations(context); + return instance; + } + + final Log log; + final Names names; + final Symtab syms; + final Annotate annotate; + + protected TypeAnnotations(Context context) { + context.put(typeAnnosKey, this); + names = Names.instance(context); + log = Log.instance(context); + syms = Symtab.instance(context); + annotate = Annotate.instance(context); + } /** * Separate type annotations from declaration annotations and @@ -95,15 +112,14 @@ public class TypeAnnotations { * adds an Annotator to the correct Annotate queue for * later processing. */ - public static void organizeTypeAnnotationsSignatures(final Symtab syms, final Names names, - final Log log, final Env env, final JCClassDecl tree, final Annotate annotate) { + public void organizeTypeAnnotationsSignatures(final Env env, final JCClassDecl tree) { annotate.afterRepeated( new Annotator() { @Override public void enterAnnotation() { JavaFileObject oldSource = log.useSource(env.toplevel.sourcefile); try { - new TypeAnnotationPositions(syms, names, log, true).scan(tree); + new TypeAnnotationPositions(true).scan(tree); } finally { log.useSource(oldSource); } @@ -115,8 +131,8 @@ public class TypeAnnotations { * This version only visits types in bodies, that is, field initializers, * top-level blocks, and method bodies, and should be called from Attr. */ - public static void organizeTypeAnnotationsBodies(Symtab syms, Names names, Log log, JCClassDecl tree) { - new TypeAnnotationPositions(syms, names, log, false).scan(tree); + public void organizeTypeAnnotationsBodies(JCClassDecl tree) { + new TypeAnnotationPositions(false).scan(tree); } public enum AnnotationType { DECLARATION, TYPE, BOTH }; @@ -125,8 +141,7 @@ public class TypeAnnotations { * Determine whether an annotation is a declaration annotation, * a type annotation, or both. */ - public static AnnotationType annotationType(Symtab syms, Names names, - Attribute.Compound a, Symbol s) { + public AnnotationType annotationType(Attribute.Compound a, Symbol s) { Attribute.Compound atTarget = a.type.tsym.attribute(syms.annotationTargetType.tsym); if (atTarget == null) { @@ -215,17 +230,11 @@ public class TypeAnnotations { } - private static class TypeAnnotationPositions extends TreeScanner { + private class TypeAnnotationPositions extends TreeScanner { - private final Symtab syms; - private final Names names; - private final Log log; private final boolean sigOnly; - private TypeAnnotationPositions(Symtab syms, Names names, Log log, boolean sigOnly) { - this.syms = syms; - this.names = names; - this.log = log; + TypeAnnotationPositions(boolean sigOnly) { this.sigOnly = sigOnly; } @@ -233,7 +242,7 @@ public class TypeAnnotations { * When traversing the AST we keep the "frames" of visited * trees in order to determine the position of annotations. */ - private ListBuffer frames = ListBuffer.lb(); + private ListBuffer frames = new ListBuffer<>(); protected void push(JCTree t) { frames = frames.prepend(t); } protected JCTree pop() { return frames.next(); } @@ -265,7 +274,7 @@ public class TypeAnnotations { ListBuffer typeAnnos = new ListBuffer(); for (Attribute.Compound a : annotations) { - switch (annotationType(syms, names, a, sym)) { + switch (annotationType(a, sym)) { case DECLARATION: declAnnos.append(a); break; @@ -301,7 +310,7 @@ public class TypeAnnotations { } // type is non-null and annotations are added to that type - type = typeWithAnnotations(typetree, type, typeAnnotations, log); + type = typeWithAnnotations(typetree, type, typeAnnotations); if (sym.getKind() == ElementKind.METHOD) { sym.type.asMethodType().restype = type; @@ -352,8 +361,8 @@ public class TypeAnnotations { // // As a side effect the method sets the type annotation position of "annotations". // Note that it is assumed that all annotations share the same position. - private static Type typeWithAnnotations(final JCTree typetree, final Type type, - final List annotations, Log log) { + private Type typeWithAnnotations(final JCTree typetree, final Type type, + final List annotations) { // System.out.printf("typeWithAnnotations(typetree: %s, type: %s, annotations: %s)%n", // typetree, type, annotations); if (annotations.isEmpty()) { @@ -381,7 +390,7 @@ public class TypeAnnotations { } JCArrayTypeTree arTree = arrayTypeTree(typetree); - ListBuffer depth = ListBuffer.lb(); + ListBuffer depth = new ListBuffer<>(); depth = depth.append(TypePathEntry.ARRAY); while (arType.elemtype.hasTag(TypeTag.ARRAY)) { if (arType.elemtype.isAnnotated()) { @@ -400,7 +409,7 @@ public class TypeAnnotations { arTree = arrayTypeTree(arTree.elemtype); depth = depth.append(TypePathEntry.ARRAY); } - Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations, log); + Type arelemType = typeWithAnnotations(arTree.elemtype, arType.elemtype, annotations); tomodify.elemtype = arelemType; { // All annotations share the same position; modify the first one. @@ -417,7 +426,7 @@ public class TypeAnnotations { // There is a TypeKind, but no TypeTag. JCTypeUnion tutree = (JCTypeUnion) typetree; JCExpression fst = tutree.alternatives.get(0); - Type res = typeWithAnnotations(fst, fst.type, annotations, log); + Type res = typeWithAnnotations(fst, fst.type, annotations); fst.type = res; // TODO: do we want to set res as first element in uct.alternatives? // UnionClassType uct = (com.sun.tools.javac.code.Type.UnionClassType)type; @@ -473,7 +482,7 @@ public class TypeAnnotations { // the correct nesting. // The genericLocation for the annotation. - ListBuffer depth = ListBuffer.lb(); + ListBuffer depth = new ListBuffer<>(); Type topTy = enclTy; while (enclEl != null && @@ -505,7 +514,7 @@ public class TypeAnnotations { } } - private static JCArrayTypeTree arrayTypeTree(JCTree typetree) { + private JCArrayTypeTree arrayTypeTree(JCTree typetree) { if (typetree.getKind() == JCTree.Kind.ARRAY_TYPE) { return (JCArrayTypeTree) typetree; } else if (typetree.getKind() == JCTree.Kind.ANNOTATED_TYPE) { @@ -532,7 +541,7 @@ public class TypeAnnotations { * @param annotations The annotations to insert. * @return A copy of type that contains the annotations. */ - private static Type typeWithAnnotations(final Type type, + private Type typeWithAnnotations(final Type type, final Type stopAt, final List annotations) { Visitor> visitor = @@ -619,7 +628,7 @@ public class TypeAnnotations { return type.accept(visitor, annotations); } - private static Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) { + private Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotationPosition p) { // It is safe to alias the position. return new Attribute.TypeCompound(a, p); } @@ -793,7 +802,7 @@ public class TypeAnnotations { } case ARRAY_TYPE: { - ListBuffer index = ListBuffer.lb(); + ListBuffer index = new ListBuffer<>(); index = index.append(TypePathEntry.ARRAY); List newPath = path.tail; while (true) { @@ -953,10 +962,10 @@ public class TypeAnnotations { } } - private static void locateNestedTypes(Type type, TypeAnnotationPosition p) { + private void locateNestedTypes(Type type, TypeAnnotationPosition p) { // The number of "steps" to get from the full type to the // left-most outer type. - ListBuffer depth = ListBuffer.lb(); + ListBuffer depth = new ListBuffer<>(); Type encl = type.getEnclosingType(); while (encl != null && @@ -970,7 +979,7 @@ public class TypeAnnotations { } } - private static int methodParamIndex(List path, JCTree param) { + private int methodParamIndex(List path, JCTree param) { List curr = path; while (curr.head.getTag() != Tag.METHODDEF && curr.head.getTag() != Tag.LAMBDA) { @@ -1226,7 +1235,7 @@ public class TypeAnnotations { public void visitNewArray(JCNewArray tree) { findPosition(tree, tree, tree.annotations); int dimAnnosCount = tree.dimAnnotations.size(); - ListBuffer depth = ListBuffer.lb(); + ListBuffer depth = new ListBuffer<>(); // handle annotations associated with dimensions for (int i = 0; i < dimAnnosCount; ++i) { @@ -1284,7 +1293,7 @@ public class TypeAnnotations { } } - private static void setTypeAnnotationPos(List annotations, + private void setTypeAnnotationPos(List annotations, TypeAnnotationPosition position) { for (JCAnnotation anno : annotations) { // attribute might be null during DeferredAttr; diff --git a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 06744bf6d06..84eaf4a431e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/code/Types.java +++ b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java @@ -51,7 +51,6 @@ import static com.sun.tools.javac.code.Symbol.*; import static com.sun.tools.javac.code.Type.*; import static com.sun.tools.javac.code.TypeTag.*; import static com.sun.tools.javac.jvm.ClassFile.externalize; -import static com.sun.tools.javac.util.ListBuffer.lb; /** * Utility class containing various operations on types. @@ -411,7 +410,7 @@ public class Types { throw failure("not.a.functional.intf", origin); } - final ListBuffer abstracts = ListBuffer.lb(); + final ListBuffer abstracts = new ListBuffer<>(); for (Symbol sym : membersCache.getElements(new DescriptorFilter(origin))) { Type mtype = memberType(origin.type, sym); if (abstracts.isEmpty() || @@ -434,7 +433,7 @@ public class Types { FunctionDescriptor descRes = mergeDescriptors(origin, abstracts.toList()); if (descRes == null) { //we can get here if the functional interface is ill-formed - ListBuffer descriptors = ListBuffer.lb(); + ListBuffer descriptors = new ListBuffer<>(); for (Symbol desc : abstracts) { String key = desc.type.getThrownTypes().nonEmpty() ? "descriptor.throws" : "descriptor"; @@ -596,7 +595,7 @@ public class Types { Type capturedSite = capture(site); if (capturedSite != site) { Type formalInterface = site.tsym.type; - ListBuffer typeargs = ListBuffer.lb(); + ListBuffer typeargs = new ListBuffer<>(); List actualTypeargs = site.getTypeArguments(); List capturedTypeargs = capturedSite.getTypeArguments(); //simply replace the wildcards with its bound @@ -662,7 +661,7 @@ public class Types { Assert.check(isFunctionalInterface(origin)); Symbol descSym = findDescriptorSymbol(origin); CompoundScope members = membersClosure(origin.type, false); - ListBuffer overridden = ListBuffer.lb(); + ListBuffer overridden = new ListBuffer<>(); outer: for (Symbol m2 : members.getElementsByName(descSym.name, bridgeFilter)) { if (m2 == descSym) continue; else if (descSym.overrides(m2, origin, Types.this, false)) { @@ -885,12 +884,12 @@ public class Types { private Type rewriteSupers(Type t) { if (!t.isParameterized()) return t; - ListBuffer from = lb(); - ListBuffer to = lb(); + ListBuffer from = new ListBuffer<>(); + ListBuffer to = new ListBuffer<>(); adaptSelf(t, from, to); if (from.isEmpty()) return t; - ListBuffer rewrite = lb(); + ListBuffer rewrite = new ListBuffer<>(); boolean changed = false; for (Type orig : to.toList()) { Type s = rewriteSupers(orig); @@ -2415,6 +2414,29 @@ public class Types { } }; + public List directSupertypes(Type t) { + return directSupertypes.visit(t); + } + // where + private final UnaryVisitor> directSupertypes = new UnaryVisitor>() { + + public List visitType(final Type type, final Void ignored) { + if (!type.isCompound()) { + final Type sup = supertype(type); + return (sup == Type.noType || sup == type || sup == null) + ? interfaces(type) + : interfaces(type).prepend(sup); + } else { + return visitIntersectionType((IntersectionClassType) type); + } + } + + private List visitIntersectionType(final IntersectionClassType it) { + return it.getExplicitComponents(); + } + + }; + public boolean isDirectSuperInterface(TypeSymbol isym, TypeSymbol origin) { for (Type i2 : interfaces(origin.type)) { if (isym == i2.tsym) return true; @@ -2744,7 +2766,7 @@ public class Types { } public List prune(List methods) { - ListBuffer methodsMin = ListBuffer.lb(); + ListBuffer methodsMin = new ListBuffer<>(); for (MethodSymbol m1 : methods) { boolean isMin_m1 = true; for (MethodSymbol m2 : methods) { @@ -3001,7 +3023,7 @@ public class Types { List to) { if (tvars.isEmpty()) return tvars; - ListBuffer newBoundsBuf = lb(); + ListBuffer newBoundsBuf = new ListBuffer<>(); boolean changed = false; // calculate new bounds for (Type t : tvars) { @@ -3013,7 +3035,7 @@ public class Types { } if (!changed) return tvars; - ListBuffer newTvars = lb(); + ListBuffer newTvars = new ListBuffer<>(); // create new type variables without bounds for (Type t : tvars) { newTvars.append(new TypeVar(t.tsym, null, syms.botType)); @@ -3055,7 +3077,7 @@ public class Types { /** * Does t have the same bounds for quantified variables as s? */ - boolean hasSameBounds(ForAll t, ForAll s) { + public boolean hasSameBounds(ForAll t, ForAll s) { List l1 = t.tvars; List l2 = s.tvars; while (l1.nonEmpty() && l2.nonEmpty() && @@ -3440,15 +3462,15 @@ public class Types { * compoundMin or glb. */ private List closureMin(List cl) { - ListBuffer classes = lb(); - ListBuffer interfaces = lb(); + ListBuffer classes = new ListBuffer<>(); + ListBuffer interfaces = new ListBuffer<>(); while (!cl.isEmpty()) { Type current = cl.head; if (current.isInterface()) interfaces.append(current); else classes.append(current); - ListBuffer candidates = lb(); + ListBuffer candidates = new ListBuffer<>(); for (Type t : cl.tail) { if (!isSubtypeNoCapture(current, t)) candidates.append(t); @@ -3564,7 +3586,7 @@ public class Types { } // where List erasedSupertypes(Type t) { - ListBuffer buf = lb(); + ListBuffer buf = new ListBuffer<>(); for (Type sup : closure(t)) { if (sup.hasTag(TYPEVAR)) { buf.append(sup); @@ -3914,7 +3936,7 @@ public class Types { } // where public List freshTypeVariables(List types) { - ListBuffer result = lb(); + ListBuffer result = new ListBuffer<>(); for (Type t : types) { if (t.hasTag(WILDCARD)) { t = t.unannotatedType(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java index 6ef409d9339..f9673deaa6a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java @@ -93,6 +93,7 @@ public class Attr extends JCTree.Visitor { final Types types; final JCDiagnostic.Factory diags; final Annotate annotate; + final TypeAnnotations typeAnnotations; final DeferredLintHandler deferredLintHandler; public static Attr instance(Context context) { @@ -121,6 +122,7 @@ public class Attr extends JCTree.Visitor { types = Types.instance(context); diags = JCDiagnostic.Factory.instance(context); annotate = Annotate.instance(context); + typeAnnotations = TypeAnnotations.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); Options options = Options.instance(context); @@ -748,19 +750,11 @@ public class Attr extends JCTree.Visitor { * @see VarSymbol#setLazyConstValue */ public Object attribLazyConstantValue(Env env, - JCTree.JCExpression initializer, + JCVariableDecl variable, Type type) { - /* When this env was created, it didn't have the correct lint nor had - * annotations has been processed. - * But now at this phase we have already processed annotations and the - * correct lint must have been set in chk, so we should use that one to - * attribute the initializer. - */ - Lint prevLint = env.info.lint; - env.info.lint = chk.getLint(); - - JavaFileObject prevSource = log.useSource(env.toplevel.sourcefile); + DiagnosticPosition prevLintPos + = deferredLintHandler.setPos(variable.pos()); try { // Use null as symbol to not attach the type annotation to any symbol. @@ -768,17 +762,16 @@ public class Attr extends JCTree.Visitor { // to the symbol. // This prevents having multiple type annotations, just because of // lazy constant value evaluation. - memberEnter.typeAnnotate(initializer, env, null); + memberEnter.typeAnnotate(variable.init, env, null, variable.pos()); annotate.flush(); - Type itype = attribExpr(initializer, env, type); + Type itype = attribExpr(variable.init, env, type); if (itype.constValue() != null) { return coerce(itype, type).constValue(); } else { return null; } } finally { - env.info.lint = prevLint; - log.useSource(prevSource); + deferredLintHandler.setPos(prevLintPos); } } @@ -1012,7 +1005,7 @@ public class Attr extends JCTree.Visitor { } // Attribute all type annotations in the body - memberEnter.typeAnnotate(tree.body, localEnv, m); + memberEnter.typeAnnotate(tree.body, localEnv, m, null); annotate.flush(); // Attribute method body. @@ -1042,7 +1035,7 @@ public class Attr extends JCTree.Visitor { } else { if (tree.init != null) { // Field initializer expression need to be entered. - memberEnter.typeAnnotate(tree.init, env, tree.sym); + memberEnter.typeAnnotate(tree.init, env, tree.sym, tree.pos()); annotate.flush(); } } @@ -1056,18 +1049,16 @@ public class Attr extends JCTree.Visitor { ((JCLambda)env.tree).paramKind == JCLambda.ParameterKind.IMPLICIT && (tree.sym.flags() & PARAMETER) != 0; chk.validate(tree.vartype, env, !isImplicitLambdaParameter); - deferredLintHandler.flush(tree.pos()); try { + v.getConstValue(); // ensure compile-time constant initializer is evaluated + deferredLintHandler.flush(tree.pos()); chk.checkDeprecatedAnnotation(tree.pos(), v); if (tree.init != null) { - if ((v.flags_field & FINAL) != 0 && - memberEnter.needsLazyConstValue(tree.init)) { - // In this case, `v' is final. Ensure that it's initializer is - // evaluated. - v.getConstValue(); // ensure initializer is evaluated - } else { + if ((v.flags_field & FINAL) == 0 || + !memberEnter.needsLazyConstValue(tree.init)) { + // Not a compile-time constant // Attribute initializer in a new environment // with the declared variable as owner. // Check that initializer conforms to variable's declared type. @@ -1106,7 +1097,7 @@ public class Attr extends JCTree.Visitor { if ((tree.flags & STATIC) != 0) localEnv.info.staticLevel++; // Attribute all type annotations in the block - memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner); + memberEnter.typeAnnotate(tree, localEnv, localEnv.info.scope.owner, null); annotate.flush(); { @@ -1735,7 +1726,7 @@ public class Attr extends JCTree.Visitor { boolean isConstructorCall = methName == names._this || methName == names._super; - ListBuffer argtypesBuf = ListBuffer.lb(); + ListBuffer argtypesBuf = new ListBuffer<>(); if (isConstructorCall) { // We are seeing a ...this(...) or ...super(...) call. // Check that this is the first statement in a constructor. @@ -2000,7 +1991,7 @@ public class Attr extends JCTree.Visitor { } // Attribute constructor arguments. - ListBuffer argtypesBuf = ListBuffer.lb(); + ListBuffer argtypesBuf = new ListBuffer<>(); int pkind = attribArgs(tree.args, localEnv, argtypesBuf); List argtypes = argtypesBuf.toList(); List typeargtypes = attribTypes(tree.typeargs, localEnv); @@ -2239,7 +2230,7 @@ public class Attr extends JCTree.Visitor { // empty annotations, if only declaration annotations were given. // This method will raise an error for such a type. for (JCAnnotation ai : annotations) { - if (TypeAnnotations.annotationType(syms, names, ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) { + if (typeAnnotations.annotationType(ai.attribute, sym) == TypeAnnotations.AnnotationType.DECLARATION) { log.error(ai.pos(), "annotation.type.not.applicable"); } } @@ -2319,30 +2310,37 @@ public class Attr extends JCTree.Visitor { boolean needsRecovery = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.CHECK; try { - Type target = pt(); + Type currentTarget = pt(); List explicitParamTypes = null; if (that.paramKind == JCLambda.ParameterKind.EXPLICIT) { //attribute lambda parameters attribStats(that.params, localEnv); explicitParamTypes = TreeInfo.types(that.params); - target = infer.instantiateFunctionalInterface(that, target, explicitParamTypes, resultInfo.checkContext); } Type lambdaType; if (pt() != Type.recoveryType) { - target = targetChecker.visit(target, that); - lambdaType = types.findDescriptorType(target); + /* We need to adjust the target. If the target is an + * intersection type, for example: SAM & I1 & I2 ... + * the target will be updated to SAM + */ + currentTarget = targetChecker.visit(currentTarget, that); + if (explicitParamTypes != null) { + currentTarget = infer.instantiateFunctionalInterface(that, + currentTarget, explicitParamTypes, resultInfo.checkContext); + } + lambdaType = types.findDescriptorType(currentTarget); } else { - target = Type.recoveryType; + currentTarget = Type.recoveryType; lambdaType = fallbackDescriptorType(that); } - setFunctionalInfo(localEnv, that, pt(), lambdaType, target, resultInfo.checkContext); + setFunctionalInfo(localEnv, that, pt(), lambdaType, currentTarget, resultInfo.checkContext); if (lambdaType.hasTag(FORALL)) { //lambda expression target desc cannot be a generic method resultInfo.checkContext.report(that, diags.fragment("invalid.generic.lambda.target", - lambdaType, kindName(target.tsym), target.tsym)); + lambdaType, kindName(currentTarget.tsym), currentTarget.tsym)); result = that.type = types.createErrorType(pt()); return; } @@ -2376,7 +2374,7 @@ public class Attr extends JCTree.Visitor { if (arityMismatch) { resultInfo.checkContext.report(that, diags.fragment("incompatible.arg.types.in.lambda")); - result = that.type = types.createErrorType(target); + result = that.type = types.createErrorType(currentTarget); return; } } @@ -2396,38 +2394,14 @@ public class Attr extends JCTree.Visitor { new ResultInfo(VAL, lambdaType.getReturnType(), funcContext); localEnv.info.returnResult = bodyResultInfo; - Log.DeferredDiagnosticHandler lambdaDeferredHandler = new Log.DeferredDiagnosticHandler(log); - try { - if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { - attribTree(that.getBody(), localEnv, bodyResultInfo); - } else { - JCBlock body = (JCBlock)that.body; - attribStats(body.stats, localEnv); - } - - if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) { - //check for errors in lambda body - for (JCDiagnostic deferredDiag : lambdaDeferredHandler.getDiagnostics()) { - if (deferredDiag.getKind() == JCDiagnostic.Kind.ERROR) { - resultInfo.checkContext - .report(that, diags.fragment("bad.arg.types.in.lambda", TreeInfo.types(that.params), - deferredDiag)); //hidden diag parameter - //we mark the lambda as erroneous - this is crucial in the recovery step - //as parameter-dependent type error won't be reported in that stage, - //meaning that a lambda will be deemed erroeneous only if there is - //a target-independent error (which will cause method diagnostic - //to be skipped). - result = that.type = types.createErrorType(target); - return; - } - } - } - } finally { - lambdaDeferredHandler.reportDeferredDiagnostics(); - log.popDiagnosticHandler(lambdaDeferredHandler); + if (that.getBodyKind() == JCLambda.BodyKind.EXPRESSION) { + attribTree(that.getBody(), localEnv, bodyResultInfo); + } else { + JCBlock body = (JCBlock)that.body; + attribStats(body.stats, localEnv); } - result = check(that, target, VAL, resultInfo); + result = check(that, currentTarget, VAL, resultInfo); boolean isSpeculativeRound = resultInfo.checkContext.deferredAttrContext().mode == DeferredAttr.AttrMode.SPECULATIVE; @@ -2435,12 +2409,20 @@ public class Attr extends JCTree.Visitor { preFlow(that); flow.analyzeLambda(env, that, make, isSpeculativeRound); - checkLambdaCompatible(that, lambdaType, resultInfo.checkContext, isSpeculativeRound); + checkLambdaCompatible(that, lambdaType, resultInfo.checkContext); if (!isSpeculativeRound) { - checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, target); + //add thrown types as bounds to the thrown types free variables if needed: + if (resultInfo.checkContext.inferenceContext().free(lambdaType.getThrownTypes())) { + List inferredThrownTypes = flow.analyzeLambdaThrownTypes(env, that, make); + List thrownTypes = resultInfo.checkContext.inferenceContext().asFree(lambdaType.getThrownTypes()); + + chk.unhandled(inferredThrownTypes, thrownTypes); + } + + checkAccessibleTypes(that, localEnv, resultInfo.checkContext.inferenceContext(), lambdaType, currentTarget); } - result = check(that, target, VAL, resultInfo); + result = check(that, currentTarget, VAL, resultInfo); } catch (Types.FunctionDescriptorLookupError ex) { JCDiagnostic cause = ex.getDiagnostic(); resultInfo.checkContext.report(that, cause); @@ -2496,8 +2478,8 @@ public class Attr extends JCTree.Visitor { } private TypeSymbol makeNotionalInterface(IntersectionClassType ict) { - ListBuffer targs = ListBuffer.lb(); - ListBuffer supertypes = ListBuffer.lb(); + ListBuffer targs = new ListBuffer<>(); + ListBuffer supertypes = new ListBuffer<>(); for (Type i : ict.interfaces_field) { if (i.isParameterized()) { targs.appendList(i.tsym.type.allparams()); @@ -2604,10 +2586,9 @@ public class Attr extends JCTree.Visitor { * Lambda compatibility. Check that given return types, thrown types, parameter types * are compatible with the expected functional interface descriptor. This means that: * (i) parameter types must be identical to those of the target descriptor; (ii) return - * types must be compatible with the return type of the expected descriptor; - * (iii) finish inference of thrown types if required. + * types must be compatible with the return type of the expected descriptor. */ - private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext, boolean speculativeAttr) { + private void checkLambdaCompatible(JCLambda tree, Type descriptor, CheckContext checkContext) { Type returnType = checkContext.inferenceContext().asFree(descriptor.getReturnType()); //return values have already been checked - but if lambda has no return @@ -2624,11 +2605,6 @@ public class Attr extends JCTree.Visitor { if (!types.isSameTypes(argTypes, TreeInfo.types(tree.params))) { checkContext.report(tree, diags.fragment("incompatible.arg.types.in.lambda")); } - - if (!speculativeAttr) { - List thrownTypes = checkContext.inferenceContext().asFree(descriptor.getThrownTypes()); - chk.unhandled(tree.inferredThrownTypes == null ? List.nil() : tree.inferredThrownTypes, thrownTypes); - } } private Env lambdaEnv(JCLambda that, Env env) { @@ -2664,6 +2640,13 @@ public class Attr extends JCTree.Visitor { if (that.getMode() == JCMemberReference.ReferenceMode.NEW) { exprType = chk.checkConstructorRefType(that.expr, exprType); + if (!exprType.isErroneous() && + exprType.isRaw() && + that.typeargs != null) { + log.error(that.expr.pos(), "invalid.mref", Kinds.kindName(that.getMode()), + diags.fragment("mref.infer.and.explicit.params")); + exprType = types.createErrorType(exprType); + } } if (exprType.isErroneous()) { @@ -2926,7 +2909,7 @@ public class Attr extends JCTree.Visitor { } }); } else { - ListBuffer targets = ListBuffer.lb(); + ListBuffer targets = new ListBuffer<>(); if (pt.hasTag(CLASS)) { if (pt.isCompound()) { targets.append(types.removeWildcards(primaryTarget)); //this goes first @@ -3121,8 +3104,14 @@ public class Attr extends JCTree.Visitor { public void visitTypeTest(JCInstanceOf tree) { Type exprtype = chk.checkNullOrRefType( tree.expr.pos(), attribExpr(tree.expr, env)); - Type clazztype = chk.checkReifiableReferenceType( - tree.clazz.pos(), attribType(tree.clazz, env)); + Type clazztype = attribType(tree.clazz, env); + if (!clazztype.hasTag(TYPEVAR)) { + clazztype = chk.checkClassOrArrayType(tree.clazz.pos(), clazztype); + } + if (!clazztype.isErroneous() && !types.isReifiable(clazztype)) { + log.error(tree.clazz.pos(), "illegal.generic.type.for.instof"); + clazztype = types.createErrorType(clazztype); + } chk.validate(tree.clazz, env, false); chk.checkCastable(tree.expr.pos(), exprtype, clazztype); result = check(tree, syms.booleanType, VAL, resultInfo); @@ -3731,7 +3720,7 @@ public class Attr extends JCTree.Visitor { * Check that method arguments conform to its instantiation. **/ public Type checkMethod(Type site, - Symbol sym, + final Symbol sym, ResultInfo resultInfo, Env env, final List argtrees, @@ -3820,8 +3809,19 @@ public class Attr extends JCTree.Visitor { resultInfo.checkContext.report(env.tree.pos(), ex.getDiagnostic()); return types.createErrorType(site); } catch (Resolve.InapplicableMethodException ex) { - Assert.error(ex.getDiagnostic().getMessage(Locale.getDefault())); - return null; + final JCDiagnostic diag = ex.getDiagnostic(); + Resolve.InapplicableSymbolError errSym = rs.new InapplicableSymbolError(null) { + @Override + protected Pair errCandidate() { + return new Pair(sym, diag); + } + }; + List argtypes2 = Type.map(argtypes, + rs.new ResolveDeferredRecoveryMap(AttrMode.CHECK, sym, env.info.pendingResolutionPhase)); + JCDiagnostic errDiag = errSym.getDiagnostic(JCDiagnostic.DiagnosticType.ERROR, + env.tree, sym, site, sym.name, argtypes2, typeargtypes); + log.report(errDiag); + return types.createErrorType(site); } } @@ -3911,7 +3911,7 @@ public class Attr extends JCTree.Visitor { } public void visitTypeUnion(JCTypeUnion tree) { - ListBuffer multicatchTypes = ListBuffer.lb(); + ListBuffer multicatchTypes = new ListBuffer<>(); ListBuffer all_multicatchTypes = null; // lazy, only if needed for (JCExpression typeTree : tree.alternatives) { Type ctype = attribType(typeTree, env); @@ -3938,7 +3938,7 @@ public class Attr extends JCTree.Visitor { all_multicatchTypes.append(ctype); } else { if (all_multicatchTypes == null) { - all_multicatchTypes = ListBuffer.lb(); + all_multicatchTypes = new ListBuffer<>(); all_multicatchTypes.appendList(multicatchTypes); } all_multicatchTypes.append(ctype); @@ -4093,7 +4093,7 @@ public class Attr extends JCTree.Visitor { if (annotations.isEmpty()) return List.nil(); - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (JCAnnotation anno : annotations) { if (anno.attribute != null) { // TODO: this null-check is only needed for an obscure @@ -4206,6 +4206,7 @@ public class Attr extends JCTree.Visitor { ResultInfo prevReturnRes = env.info.returnResult; try { + deferredLintHandler.flush(env.tree); env.info.returnResult = null; // java.lang.Enum may not be subclassed by a non-enum if (st.tsym == syms.enumSym && @@ -4340,7 +4341,7 @@ public class Attr extends JCTree.Visitor { } if (allowTypeAnnos) { // Correctly organize the postions of the type annotations - TypeAnnotations.organizeTypeAnnotationsBodies(this.syms, this.names, this.log, tree); + typeAnnotations.organizeTypeAnnotationsBodies(tree); // Check type annotations applicability rules validateTypeAnnotations(tree); diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java index 1bb051b1461..453bc70edda 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java @@ -148,7 +148,7 @@ public class Check { sunApiHandler = new MandatoryWarningHandler(log, verboseSunApi, enforceMandatoryWarnings, "sunapi", null); - deferredLintHandler = DeferredLintHandler.immediateHandler; + deferredLintHandler = DeferredLintHandler.instance(context); } /** Switch: generics enabled? @@ -218,20 +218,6 @@ public class Check { return prev; } - /* This idiom should be used only in cases when it is needed to set the lint - * of an environment that has been created in a phase previous to annotations - * processing. - */ - Lint getLint() { - return lint; - } - - DeferredLintHandler setDeferredLintHandler(DeferredLintHandler newDeferredLintHandler) { - DeferredLintHandler prev = deferredLintHandler; - deferredLintHandler = newDeferredLintHandler; - return prev; - } - MethodSymbol setMethod(MethodSymbol newMethod) { MethodSymbol prev = method; method = newMethod; @@ -582,14 +568,19 @@ public class Check { /** Check for redundant casts (i.e. where source type is a subtype of target type) * The problem should only be reported for non-292 cast */ - public void checkRedundantCast(Env env, JCTypeCast tree) { - if (!tree.type.isErroneous() && - (env.info.lint == null || env.info.lint.isEnabled(Lint.LintCategory.CAST)) + public void checkRedundantCast(Env env, final JCTypeCast tree) { + if (!tree.type.isErroneous() && types.isSameType(tree.expr.type, tree.clazz.type) && !(ignoreAnnotatedCasts && TreeInfo.containsTypeAnnotation(tree.clazz)) && !is292targetTypeCast(tree)) { - log.warning(Lint.LintCategory.CAST, - tree.pos(), "redundant.cast", tree.expr.type); + deferredLintHandler.report(new DeferredLintHandler.LintLogger() { + @Override + public void report() { + if (lint.isEnabled(Lint.LintCategory.CAST)) + log.warning(Lint.LintCategory.CAST, + tree.pos(), "redundant.cast", tree.expr.type); + } + }); } } //where @@ -715,20 +706,6 @@ public class Check { return t; } - /** Check that type is a reifiable class, interface or array type. - * @param pos Position to be used for error reporting. - * @param t The type to be checked. - */ - Type checkReifiableReferenceType(DiagnosticPosition pos, Type t) { - t = checkClassOrArrayType(pos, t); - if (!t.isErroneous() && !types.isReifiable(t)) { - log.error(pos, "illegal.generic.type.for.instof"); - return types.createErrorType(t); - } else { - return t; - } - } - /** Check that type is a reference type, i.e. a class, interface or array type * or a type variable. * @param pos Position to be used for error reporting. @@ -1050,6 +1027,7 @@ public class Check { long checkFlags(DiagnosticPosition pos, long flags, Symbol sym, JCTree tree) { long mask; long implicit = 0; + switch (sym.kind) { case VAR: if (sym.owner.kind != TYP) @@ -1070,7 +1048,10 @@ public class Check { } else mask = ConstructorFlags; } else if ((sym.owner.flags_field & INTERFACE) != 0) { - if ((flags & (DEFAULT | STATIC)) != 0) { + if ((sym.owner.flags_field & ANNOTATION) != 0) { + mask = AnnotationTypeElementMask; + implicit = PUBLIC | ABSTRACT; + } else if ((flags & (DEFAULT | STATIC)) != 0) { mask = InterfaceMethodMask; implicit = PUBLIC; if ((flags & DEFAULT) != 0) { @@ -1079,8 +1060,7 @@ public class Check { } else { mask = implicit = InterfaceMethodFlags; } - } - else { + } else { mask = MethodFlags; } // Imply STRICTFP if owner has STRICTFP set. @@ -1251,6 +1231,7 @@ public class Check { */ class Validator extends JCTree.Visitor { + boolean checkRaw; boolean isOuter; Env env; @@ -1260,7 +1241,7 @@ public class Check { @Override public void visitTypeArray(JCArrayTypeTree tree) { - tree.elemtype.accept(this); + validateTree(tree.elemtype, checkRaw, isOuter); } @Override @@ -1351,15 +1332,20 @@ public class Check { } public void validateTree(JCTree tree, boolean checkRaw, boolean isOuter) { - try { - if (tree != null) { - this.isOuter = isOuter; + if (tree != null) { + boolean prevCheckRaw = this.checkRaw; + this.checkRaw = checkRaw; + this.isOuter = isOuter; + + try { tree.accept(this); if (checkRaw) checkRaw(tree, env); + } catch (CompletionFailure ex) { + completionError(tree.pos(), ex); + } finally { + this.checkRaw = prevCheckRaw; } - } catch (CompletionFailure ex) { - completionError(tree.pos(), ex); } } @@ -2368,7 +2354,10 @@ public class Check { //for each method m1 that is overridden (directly or indirectly) //by method 'sym' in 'site'... for (Symbol m1 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) { - if (!sym.overrides(m1, site.tsym, types, false)) continue; + if (!sym.overrides(m1, site.tsym, types, false)) { + checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)m1); + continue; + } //...check each method m2 that is a member of 'site' for (Symbol m2 : types.membersClosure(site, false).getElementsByName(sym.name, cf)) { if (m2 == m1) continue; @@ -2406,14 +2395,17 @@ public class Check { for (Symbol s : types.membersClosure(site, true).getElementsByName(sym.name, cf)) { //if (i) the signature of 'sym' is not a subsignature of m1 (seen as //a member of 'site') and (ii) 'sym' has the same erasure as m1, issue an error - if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck) && - types.hasSameArgs(s.erasure(types), sym.erasure(types))) { - log.error(pos, - "name.clash.same.erasure.no.hide", - sym, sym.location(), - s, s.location()); - return; - } + if (!types.isSubSignature(sym.type, types.memberType(site, s), allowStrictMethodClashCheck)) { + if (types.hasSameArgs(s.erasure(types), sym.erasure(types))) { + log.error(pos, + "name.clash.same.erasure.no.hide", + sym, sym.location(), + s, s.location()); + return; + } else { + checkPotentiallyAmbiguousOverloads(pos, site, sym, (MethodSymbol)s); + } + } } } @@ -2446,8 +2438,8 @@ public class Check { Assert.check(m.kind == MTH); List prov = types.interfaceCandidates(site, (MethodSymbol)m); if (prov.size() > 1) { - ListBuffer abstracts = ListBuffer.lb(); - ListBuffer defaults = ListBuffer.lb(); + ListBuffer abstracts = new ListBuffer<>(); + ListBuffer defaults = new ListBuffer<>(); for (MethodSymbol provSym : prov) { if ((provSym.flags() & DEFAULT) != 0) { defaults = defaults.append(provSym); @@ -2496,6 +2488,62 @@ public class Check { } } + /** + * Report warnings for potentially ambiguous method declarations. Two declarations + * are potentially ambiguous if they feature two unrelated functional interface + * in same argument position (in which case, a call site passing an implicit + * lambda would be ambiguous). + */ + void checkPotentiallyAmbiguousOverloads(DiagnosticPosition pos, Type site, + MethodSymbol msym1, MethodSymbol msym2) { + if (msym1 != msym2 && + allowDefaultMethods && + lint.isEnabled(LintCategory.OVERLOADS) && + (msym1.flags() & POTENTIALLY_AMBIGUOUS) == 0 && + (msym2.flags() & POTENTIALLY_AMBIGUOUS) == 0) { + Type mt1 = types.memberType(site, msym1); + Type mt2 = types.memberType(site, msym2); + //if both generic methods, adjust type variables + if (mt1.hasTag(FORALL) && mt2.hasTag(FORALL) && + types.hasSameBounds((ForAll)mt1, (ForAll)mt2)) { + mt2 = types.subst(mt2, ((ForAll)mt2).tvars, ((ForAll)mt1).tvars); + } + //expand varargs methods if needed + int maxLength = Math.max(mt1.getParameterTypes().length(), mt2.getParameterTypes().length()); + List args1 = rs.adjustArgs(mt1.getParameterTypes(), msym1, maxLength, true); + List args2 = rs.adjustArgs(mt2.getParameterTypes(), msym2, maxLength, true); + //if arities don't match, exit + if (args1.length() != args2.length()) return; + boolean potentiallyAmbiguous = false; + while (args1.nonEmpty() && args2.nonEmpty()) { + Type s = args1.head; + Type t = args2.head; + if (!types.isSubtype(t, s) && !types.isSubtype(s, t)) { + if (types.isFunctionalInterface(s) && types.isFunctionalInterface(t) && + types.findDescriptorType(s).getParameterTypes().length() > 0 && + types.findDescriptorType(s).getParameterTypes().length() == + types.findDescriptorType(t).getParameterTypes().length()) { + potentiallyAmbiguous = true; + } else { + break; + } + } + args1 = args1.tail; + args2 = args2.tail; + } + if (potentiallyAmbiguous) { + //we found two incompatible functional interfaces with same arity + //this means a call site passing an implicit lambda would be ambigiuous + msym1.flags_field |= POTENTIALLY_AMBIGUOUS; + msym2.flags_field |= POTENTIALLY_AMBIGUOUS; + log.warning(LintCategory.OVERLOADS, pos, "potentially.ambiguous.overload", + msym1, msym1.location(), + msym2, msym2.location()); + return; + } + } + } + /** Report a conflict between a user symbol and a synthetic symbol. */ private void syntheticError(DiagnosticPosition pos, Symbol sym) { @@ -3275,7 +3323,9 @@ public class Check { (e.sym.flags() & CLASH) == 0 && sym.kind == e.sym.kind && sym.name != names.error && - (sym.kind != MTH || types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) { + (sym.kind != MTH || + types.hasSameArgs(sym.type, e.sym.type) || + types.hasSameArgs(types.erasure(sym.type), types.erasure(e.sym.type)))) { if ((sym.flags() & VARARGS) != (e.sym.flags() & VARARGS)) { varargsDuplicateError(pos, sym, e.sym); return true; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java index 6b7cfdd37ee..6357419cf3d 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/DeferredAttr.java @@ -25,6 +25,7 @@ package com.sun.tools.javac.comp; +import com.sun.source.tree.MemberReferenceTree; import com.sun.tools.javac.code.*; import com.sun.tools.javac.tree.*; import com.sun.tools.javac.util.*; @@ -39,7 +40,9 @@ import com.sun.tools.javac.tree.JCTree.*; import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; +import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -98,7 +101,7 @@ public class DeferredAttr extends JCTree.Visitor { emptyDeferredAttrContext = new DeferredAttrContext(AttrMode.CHECK, null, MethodResolutionPhase.BOX, infer.emptyContext, null, null) { @Override - void addDeferredAttrNode(DeferredType dt, ResultInfo ri, List stuckVars) { + void addDeferredAttrNode(DeferredType dt, ResultInfo ri, DeferredStuckPolicy deferredStuckPolicy) { Assert.error("Empty deferred context!"); } @Override @@ -149,15 +152,15 @@ public class DeferredAttr extends JCTree.Visitor { class Entry { JCTree speculativeTree; - Resolve.MethodResolutionPhase phase; + ResultInfo resultInfo; - public Entry(JCTree speculativeTree, MethodResolutionPhase phase) { + public Entry(JCTree speculativeTree, ResultInfo resultInfo) { this.speculativeTree = speculativeTree; - this.phase = phase; + this.resultInfo = resultInfo; } - boolean matches(Resolve.MethodResolutionPhase phase) { - return this.phase == phase; + boolean matches(MethodResolutionPhase phase) { + return resultInfo.checkContext.deferredAttrContext().phase == phase; } } @@ -178,12 +181,13 @@ public class DeferredAttr extends JCTree.Visitor { * Stores a speculative cache entry corresponding to given symbol * and resolution phase */ - void put(Symbol msym, JCTree speculativeTree, MethodResolutionPhase phase) { + void put(JCTree speculativeTree, ResultInfo resultInfo) { + Symbol msym = resultInfo.checkContext.deferredAttrContext().msym; List entries = cache.get(msym); if (entries == null) { entries = List.nil(); } - cache.put(msym, entries.prepend(new Entry(speculativeTree, phase))); + cache.put(msym, entries.prepend(new Entry(speculativeTree, resultInfo))); } } @@ -203,15 +207,24 @@ public class DeferredAttr extends JCTree.Visitor { * attribution round must follow one or more speculative rounds. */ Type check(ResultInfo resultInfo) { - return check(resultInfo, stuckVars(tree, env, resultInfo), basicCompleter); + DeferredStuckPolicy deferredStuckPolicy; + if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) { + deferredStuckPolicy = dummyStuckPolicy; + } else if (resultInfo.checkContext.deferredAttrContext().mode == AttrMode.SPECULATIVE) { + deferredStuckPolicy = new OverloadStuckPolicy(resultInfo, this); + } else { + deferredStuckPolicy = new CheckStuckPolicy(resultInfo, this); + } + return check(resultInfo, deferredStuckPolicy, basicCompleter); } - Type check(ResultInfo resultInfo, List stuckVars, DeferredTypeCompleter deferredTypeCompleter) { + private Type check(ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy, + DeferredTypeCompleter deferredTypeCompleter) { DeferredAttrContext deferredAttrContext = resultInfo.checkContext.deferredAttrContext(); Assert.check(deferredAttrContext != emptyDeferredAttrContext); - if (stuckVars.nonEmpty()) { - deferredAttrContext.addDeferredAttrNode(this, resultInfo, stuckVars); + if (deferredStuckPolicy.isStuck()) { + deferredAttrContext.addDeferredAttrNode(this, resultInfo, deferredStuckPolicy); return Type.noType; } else { try { @@ -236,6 +249,7 @@ public class DeferredAttr extends JCTree.Visitor { Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext); } + /** * A basic completer for deferred types. This completer type-checks a deferred type * using attribution; depending on the attribution mode, this could be either standard @@ -249,7 +263,7 @@ public class DeferredAttr extends JCTree.Visitor { //speculative rounds... Assert.check(dt.mode == null || dt.mode == AttrMode.SPECULATIVE); JCTree speculativeTree = attribSpeculative(dt.tree, dt.env, resultInfo); - dt.speculativeCache.put(deferredAttrContext.msym, speculativeTree, deferredAttrContext.phase); + dt.speculativeCache.put(speculativeTree, resultInfo); return speculativeTree.type; case CHECK: Assert.check(dt.mode != null); @@ -267,6 +281,45 @@ public class DeferredAttr extends JCTree.Visitor { } }; + /** + * Policy for detecting stuck expressions. Different criteria might cause + * an expression to be judged as stuck, depending on whether the check + * is performed during overload resolution or after most specific. + */ + interface DeferredStuckPolicy { + /** + * Has the policy detected that a given expression should be considered stuck? + */ + boolean isStuck(); + /** + * Get the set of inference variables a given expression depends upon. + */ + Set stuckVars(); + /** + * Get the set of inference variables which might get new constraints + * if a given expression is being type-checked. + */ + Set depVars(); + } + + /** + * Basic stuck policy; an expression is never considered to be stuck. + */ + DeferredStuckPolicy dummyStuckPolicy = new DeferredStuckPolicy() { + @Override + public boolean isStuck() { + return false; + } + @Override + public Set stuckVars() { + return Collections.emptySet(); + } + @Override + public Set depVars() { + return Collections.emptySet(); + } + }; + /** * The 'mode' in which the deferred type is to be type-checked */ @@ -388,8 +441,9 @@ public class DeferredAttr extends JCTree.Visitor { * Adds a node to the list of deferred attribution nodes - used by Resolve.rawCheckArgumentsApplicable * Nodes added this way act as 'roots' for the out-of-order method checking process. */ - void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, List stuckVars) { - deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, stuckVars)); + void addDeferredAttrNode(final DeferredType dt, ResultInfo resultInfo, + DeferredStuckPolicy deferredStuckPolicy) { + deferredAttrNodes.add(new DeferredAttrNode(dt, resultInfo, deferredStuckPolicy)); } /** @@ -400,23 +454,52 @@ public class DeferredAttr extends JCTree.Visitor { */ void complete() { while (!deferredAttrNodes.isEmpty()) { - Set stuckVars = new LinkedHashSet(); + Map> depVarsMap = new LinkedHashMap>(); + List stuckVars = List.nil(); boolean progress = false; //scan a defensive copy of the node list - this is because a deferred //attribution round can add new nodes to the list for (DeferredAttrNode deferredAttrNode : List.from(deferredAttrNodes)) { if (!deferredAttrNode.process(this)) { - stuckVars.addAll(deferredAttrNode.stuckVars); + List restStuckVars = + List.from(deferredAttrNode.deferredStuckPolicy.stuckVars()) + .intersect(inferenceContext.restvars()); + stuckVars = stuckVars.prependList(restStuckVars); + //update dependency map + for (Type t : List.from(deferredAttrNode.deferredStuckPolicy.depVars()) + .intersect(inferenceContext.restvars())) { + Set prevDeps = depVarsMap.get(t); + if (prevDeps == null) { + prevDeps = new LinkedHashSet(); + depVarsMap.put(t, prevDeps); + } + prevDeps.addAll(restStuckVars); + } } else { deferredAttrNodes.remove(deferredAttrNode); progress = true; } } if (!progress) { + DeferredAttrContext dac = this; + while (dac != emptyDeferredAttrContext) { + if (dac.mode == AttrMode.SPECULATIVE) { + //unsticking does not take place during overload + break; + } + dac = dac.parent; + } //remove all variables that have already been instantiated //from the list of stuck variables - inferenceContext.solveAny(List.from(stuckVars), warn); - inferenceContext.notifyChange(); + try { + inferenceContext.solveAny(stuckVars, depVarsMap, warn); + inferenceContext.notifyChange(); + } catch (Infer.GraphStrategy.NodeNotFoundException ex) { + //this means that we are in speculative mode and the + //set of contraints are too tight for progess to be made. + //Just leave the remaining expressions as stuck. + break; + } } } } @@ -426,7 +509,7 @@ public class DeferredAttr extends JCTree.Visitor { * Class representing a deferred attribution node. It keeps track of * a deferred type, along with the expected target type information. */ - class DeferredAttrNode implements Infer.FreeTypeListener { + class DeferredAttrNode { /** underlying deferred type */ DeferredType dt; @@ -434,22 +517,13 @@ public class DeferredAttr extends JCTree.Visitor { /** underlying target type information */ ResultInfo resultInfo; - /** list of uninferred inference variables causing this node to be stuck */ - List stuckVars; + /** stuck policy associated with this node */ + DeferredStuckPolicy deferredStuckPolicy; - DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, List stuckVars) { + DeferredAttrNode(DeferredType dt, ResultInfo resultInfo, DeferredStuckPolicy deferredStuckPolicy) { this.dt = dt; this.resultInfo = resultInfo; - this.stuckVars = stuckVars; - if (!stuckVars.isEmpty()) { - resultInfo.checkContext.inferenceContext().addFreeTypeListener(stuckVars, this); - } - } - - @Override - public void typesInferred(InferenceContext inferenceContext) { - stuckVars = List.nil(); - resultInfo = resultInfo.dup(inferenceContext.asInstType(resultInfo.pt)); + this.deferredStuckPolicy = deferredStuckPolicy; } /** @@ -457,24 +531,41 @@ public class DeferredAttr extends JCTree.Visitor { * Invariant: a stuck node cannot be processed. */ @SuppressWarnings("fallthrough") - boolean process(DeferredAttrContext deferredAttrContext) { + boolean process(final DeferredAttrContext deferredAttrContext) { switch (deferredAttrContext.mode) { case SPECULATIVE: - dt.check(resultInfo, List.nil(), new StructuralStuckChecker()); - return true; + if (deferredStuckPolicy.isStuck()) { + dt.check(resultInfo, dummyStuckPolicy, new StructuralStuckChecker()); + return true; + } else { + Assert.error("Cannot get here"); + } case CHECK: - if (stuckVars.nonEmpty()) { + if (deferredStuckPolicy.isStuck()) { //stuck expression - see if we can propagate if (deferredAttrContext.parent != emptyDeferredAttrContext && - Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, List.from(stuckVars))) { - deferredAttrContext.parent.deferredAttrNodes.add(this); - dt.check(resultInfo, List.nil(), dummyCompleter); + Type.containsAny(deferredAttrContext.parent.inferenceContext.inferencevars, + List.from(deferredStuckPolicy.stuckVars()))) { + deferredAttrContext.parent.addDeferredAttrNode(dt, + resultInfo.dup(new Check.NestedCheckContext(resultInfo.checkContext) { + @Override + public InferenceContext inferenceContext() { + return deferredAttrContext.parent.inferenceContext; + } + @Override + public DeferredAttrContext deferredAttrContext() { + return deferredAttrContext.parent; + } + }), deferredStuckPolicy); + dt.tree.type = Type.stuckType; return true; } else { return false; } } else { - dt.check(resultInfo, stuckVars, basicCompleter); + ResultInfo instResultInfo = + resultInfo.dup(deferredAttrContext.inferenceContext.asInstType(resultInfo.pt)); + dt.check(instResultInfo, dummyStuckPolicy, basicCompleter); return true; } default: @@ -489,12 +580,14 @@ public class DeferredAttr extends JCTree.Visitor { ResultInfo resultInfo; InferenceContext inferenceContext; + Env env; public Type complete(DeferredType dt, ResultInfo resultInfo, DeferredAttrContext deferredAttrContext) { this.resultInfo = resultInfo; this.inferenceContext = deferredAttrContext.inferenceContext; + this.env = dt.env; dt.tree.accept(this); - dt.speculativeCache.put(deferredAttrContext.msym, stuckTree, deferredAttrContext.phase); + dt.speculativeCache.put(stuckTree, resultInfo); return Type.noType; } @@ -541,15 +634,25 @@ public class DeferredAttr extends JCTree.Visitor { } catch (Types.FunctionDescriptorLookupError ex) { checkContext.report(null, ex.getDiagnostic()); } - switch (tree.sym.kind) { + Env localEnv = env.dup(tree); + JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, + attr.memberReferenceQualifierResult(tree)); + ListBuffer argtypes = new ListBuffer<>(); + for (Type t : types.findDescriptorType(pt).getParameterTypes()) { + argtypes.append(Type.noType); + } + JCMemberReference mref2 = new TreeCopier(make).copy(tree); + mref2.expr = exprTree; + Pair lookupRes = + rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, + tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, inferenceContext); + switch (lookupRes.fst.kind) { //note: as argtypes are erroneous types, type-errors must //have been caused by arity mismatch case Kinds.ABSENT_MTH: case Kinds.WRONG_MTH: case Kinds.WRONG_MTHS: - case Kinds.STATICERR: - case Kinds.MISSING_ENCL: - checkContext.report(null, diags.fragment("incompatible.arg.types.in.mref")); + checkContext.report(tree, diags.fragment("incompatible.arg.types.in.mref")); } } } @@ -575,18 +678,12 @@ public class DeferredAttr extends JCTree.Visitor { infer.emptyContext, emptyDeferredAttrContext, types.noWarnings); } - protected boolean validState(DeferredType dt) { - return dt.mode != null && - deferredAttrContext.mode.ordinal() <= dt.mode.ordinal(); - } - @Override public Type apply(Type t) { if (!t.hasTag(DEFERRED)) { return t.map(this); } else { DeferredType dt = (DeferredType)t; - Assert.check(validState(dt)); return typeOf(dt); } } @@ -623,11 +720,6 @@ public class DeferredAttr extends JCTree.Visitor { recover(dt) : owntype; } - @Override - protected boolean validState(DeferredType dt) { - return true; - } - /** * Synthesize a type for a deferred type that hasn't been previously * reduced to an ordinary type. Functional deferred types and conditionals @@ -646,25 +738,6 @@ public class DeferredAttr extends JCTree.Visitor { } } - /** - * Retrieves the list of inference variables that need to be inferred before - * an AST node can be type-checked - */ - @SuppressWarnings("fallthrough") - List stuckVars(JCTree tree, Env env, ResultInfo resultInfo) { - if (resultInfo.pt.hasTag(NONE) || resultInfo.pt.isErroneous()) { - return List.nil(); - } else { - return stuckVarsInternal(tree, resultInfo.pt, env, resultInfo.checkContext.inferenceContext()); - } - } - //where - private List stuckVarsInternal(JCTree tree, Type pt, Env env, Infer.InferenceContext inferenceContext) { - StuckChecker sc = new StuckChecker(pt, env, inferenceContext); - sc.scan(tree); - return List.from(sc.stuckVars); - } - /** * A special tree scanner that would only visit portions of a given tree. * The set of nodes visited by the scanner can be customized at construction-time. @@ -737,17 +810,41 @@ public class DeferredAttr extends JCTree.Visitor { * inferring types that make some of the nested expressions incompatible * with their corresponding instantiated target */ - class StuckChecker extends PolyScanner { + class CheckStuckPolicy extends PolyScanner implements DeferredStuckPolicy, Infer.FreeTypeListener { Type pt; - Env env; Infer.InferenceContext inferenceContext; Set stuckVars = new LinkedHashSet(); + Set depVars = new LinkedHashSet(); - StuckChecker(Type pt, Env env, Infer.InferenceContext inferenceContext) { - this.pt = pt; - this.env = env; - this.inferenceContext = inferenceContext; + @Override + public boolean isStuck() { + return !stuckVars.isEmpty(); + } + + @Override + public Set stuckVars() { + return stuckVars; + } + + @Override + public Set depVars() { + return depVars; + } + + public CheckStuckPolicy(ResultInfo resultInfo, DeferredType dt) { + this.pt = resultInfo.pt; + this.inferenceContext = resultInfo.checkContext.inferenceContext(); + scan(dt.tree); + if (!stuckVars.isEmpty()) { + resultInfo.checkContext.inferenceContext() + .addFreeTypeListener(List.from(stuckVars), this); + } + } + + @Override + public void typesInferred(InferenceContext inferenceContext) { + stuckVars.clear(); } @Override @@ -763,6 +860,7 @@ public class DeferredAttr extends JCTree.Visitor { if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT && freeArgVars.nonEmpty()) { stuckVars.addAll(freeArgVars); + depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType())); } scanLambdaBody(tree, descType.getReturnType()); } @@ -780,41 +878,34 @@ public class DeferredAttr extends JCTree.Visitor { Type descType = types.findDescriptorType(pt); List freeArgVars = inferenceContext.freeVarsIn(descType.getParameterTypes()); - Env localEnv = env.dup(tree, env.info.dup()); - if (freeArgVars.nonEmpty()) { - //perform arity-based check - JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, - attr.memberReferenceQualifierResult(tree)); - ListBuffer argtypes = ListBuffer.lb(); - for (Type t : descType.getParameterTypes()) { - argtypes.append(Type.noType); - } - JCMemberReference mref2 = new TreeCopier(make).copy(tree); - mref2.expr = exprTree; - Pair lookupRes = - rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, - tree.name, argtypes.toList(), null, true, rs.arityMethodCheck, - inferenceContext); - Symbol res = tree.sym = lookupRes.fst; - if (res.kind >= Kinds.ERRONEOUS || - res.type.hasTag(FORALL) || - (res.flags() & Flags.VARARGS) != 0 || - (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && - exprTree.type.isRaw())) { - stuckVars.addAll(freeArgVars); - } + if (freeArgVars.nonEmpty() && + tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) { + stuckVars.addAll(freeArgVars); + depVars.addAll(inferenceContext.freeVarsIn(descType.getReturnType())); } } void scanLambdaBody(JCLambda lambda, final Type pt) { if (lambda.getBodyKind() == JCTree.JCLambda.BodyKind.EXPRESSION) { - stuckVars.addAll(stuckVarsInternal(lambda.body, pt, env, inferenceContext)); + Type prevPt = this.pt; + try { + this.pt = pt; + scan(lambda.body); + } finally { + this.pt = prevPt; + } } else { LambdaReturnScanner lambdaScanner = new LambdaReturnScanner() { @Override public void visitReturn(JCReturn tree) { if (tree.expr != null) { - stuckVars.addAll(stuckVarsInternal(tree.expr, pt, env, inferenceContext)); + Type prevPt = CheckStuckPolicy.this.pt; + try { + CheckStuckPolicy.this.pt = pt; + CheckStuckPolicy.this.scan(tree.expr); + } finally { + CheckStuckPolicy.this.pt = prevPt; + } } } }; @@ -823,6 +914,42 @@ public class DeferredAttr extends JCTree.Visitor { } } + /** + * This visitor is used to check that structural expressions conform + * to their target - this step is required as inference could end up + * inferring types that make some of the nested expressions incompatible + * with their corresponding instantiated target + */ + class OverloadStuckPolicy extends CheckStuckPolicy implements DeferredStuckPolicy { + + boolean stuck; + + @Override + public boolean isStuck() { + return super.isStuck() || stuck; + } + + public OverloadStuckPolicy(ResultInfo resultInfo, DeferredType dt) { + super(resultInfo, dt); + } + + @Override + public void visitLambda(JCLambda tree) { + super.visitLambda(tree); + if (tree.paramKind == JCLambda.ParameterKind.IMPLICIT) { + stuck = true; + } + } + + @Override + public void visitReference(JCMemberReference tree) { + super.visitReference(tree); + if (tree.overloadKind == JCMemberReference.OverloadKind.OVERLOADED) { + stuck = true; + } + } + } + /** * Does the argument expression {@code expr} need speculative type-checking? */ @@ -904,6 +1031,26 @@ public class DeferredAttr extends JCTree.Visitor { @Override public void visitReference(JCMemberReference tree) { + //perform arity-based check + Env localEnv = env.dup(tree); + JCExpression exprTree = (JCExpression)attribSpeculative(tree.getQualifierExpression(), localEnv, + attr.memberReferenceQualifierResult(tree)); + JCMemberReference mref2 = new TreeCopier(make).copy(tree); + mref2.expr = exprTree; + Pair lookupRes = + rs.resolveMemberReference(tree, localEnv, mref2, exprTree.type, + tree.name, List.nil(), null, true, rs.nilMethodCheck, + infer.emptyContext); + Symbol res = tree.sym = lookupRes.fst; + if (res.kind >= Kinds.ERRONEOUS || + res.type.hasTag(FORALL) || + (res.flags() & Flags.VARARGS) != 0 || + (TreeInfo.isStaticSelector(exprTree, tree.name.table.names) && + exprTree.type.isRaw())) { + tree.overloadKind = JCMemberReference.OverloadKind.OVERLOADED; + } else { + tree.overloadKind = JCMemberReference.OverloadKind.UNOVERLOADED; + } //a method reference is always a poly expression result = ArgumentExpressionKind.POLY; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java index 41c0792acf2..697a6921d01 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Enter.java @@ -288,7 +288,9 @@ public class Enter extends JCTree.Visitor { JavaFileObject.Kind.SOURCE); if (tree.pid != null) { tree.packge = reader.enterPackage(TreeInfo.fullName(tree.pid)); - if (tree.packageAnnotations.nonEmpty() || pkginfoOpt == PkgInfo.ALWAYS) { + if (tree.packageAnnotations.nonEmpty() + || pkginfoOpt == PkgInfo.ALWAYS + || tree.docComments != null) { if (isPkgInfo) { addEnv = true; } else if (tree.packageAnnotations.nonEmpty()){ diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index e488d45b0c0..8c69c814965 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java @@ -207,7 +207,7 @@ public class Flow { public void analyzeTree(Env env, TreeMaker make) { new AliveAnalyzer().analyzeTree(env, make); - new AssignAnalyzer().analyzeTree(env, make); + new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); new FlowAnalyzer().analyzeTree(env, make); new CaptureAnalyzer().analyzeTree(env, make); } @@ -224,7 +224,6 @@ public class Flow { } try { new AliveAnalyzer().analyzeTree(env, that, make); - new LambdaFlowAnalyzer().analyzeTree(env, that, make); } finally { if (!speculative) { log.popDiagnosticHandler(diagHandler); @@ -232,6 +231,23 @@ public class Flow { } } + public List analyzeLambdaThrownTypes(Env env, JCLambda that, TreeMaker make) { + //we need to disable diagnostics temporarily; the problem is that if + //a lambda expression contains e.g. an unreachable statement, an error + //message will be reported and will cause compilation to skip the flow analyis + //step - if we suppress diagnostics, we won't stop at Attr for flow-analysis + //related errors, which will allow for more errors to be detected + Log.DiagnosticHandler diagHandler = new Log.DiscardDiagnosticHandler(log); + try { + new AssignAnalyzer(log, syms, lint, names).analyzeTree(env); + LambdaFlowAnalyzer flowAnalyzer = new LambdaFlowAnalyzer(); + flowAnalyzer.analyzeTree(env, that, make); + return flowAnalyzer.inferredThrownTypes; + } finally { + log.popDiagnosticHandler(diagHandler); + } + } + /** * Definite assignment scan mode */ @@ -275,15 +291,6 @@ public class Flow { allowEffectivelyFinalInInnerClasses = source.allowEffectivelyFinalInInnerClasses(); } - /** - * Utility method to reset several Bits instances. - */ - private void resetBits(Bits... bits) { - for (Bits b : bits) { - b.reset(); - } - } - /** * Base visitor class for all visitors implementing dataflow analysis logic. * This class define the shared logic for handling jumps (break/continue statements). @@ -331,17 +338,17 @@ public class Flow { this.tree = tree; } - void resolveJump() { + void resolveJump(JCTree tree) { //do nothing } } - abstract void markDead(); + abstract void markDead(JCTree tree); /** Record an outward transfer of control. */ void recordExit(JCTree tree, P pe) { pendingExits.append(pe); - markDead(); + markDead(tree); } /** Resolve all jumps of this statement. */ @@ -355,7 +362,7 @@ public class Flow { P exit = exits.head; if (exit.tree.hasTag(jk.treeTag) && jk.getTarget(exit.tree) == tree) { - exit.resolveJump(); + exit.resolveJump(tree); resolved = true; } else { pendingExits.append(exit); @@ -364,12 +371,12 @@ public class Flow { return resolved; } - /** Resolve all breaks of this statement. */ + /** Resolve all continues of this statement. */ boolean resolveContinues(JCTree tree) { return resolveJump(tree, new ListBuffer

        (), JumpKind.CONTINUE); } - /** Resolve all continues of this statement. */ + /** Resolve all breaks of this statement. */ boolean resolveBreaks(JCTree tree, ListBuffer

        oldPendingExits) { return resolveJump(tree, oldPendingExits, JumpKind.BREAK); } @@ -398,7 +405,7 @@ public class Flow { private boolean alive; @Override - void markDead() { + void markDead(JCTree tree) { alive = false; } @@ -680,7 +687,7 @@ public class Flow { public void visitThrow(JCThrow tree) { scan(tree.expr); - markDead(); + markDead(tree); } public void visitApply(JCMethodInvocation tree) { @@ -706,7 +713,7 @@ public class Flow { ListBuffer prevPending = pendingExits; boolean prevAlive = alive; try { - pendingExits = ListBuffer.lb(); + pendingExits = new ListBuffer<>(); alive = true; scanStat(tree.body); tree.canCompleteNormally = alive; @@ -781,7 +788,7 @@ public class Flow { } @Override - void markDead() { + void markDead(JCTree tree) { //do nothing } @@ -1206,7 +1213,7 @@ public class Flow { else { markThrown(tree, tree.expr.type); } - markDead(); + markDead(tree); } public void visitApply(JCMethodInvocation tree) { @@ -1258,7 +1265,7 @@ public class Flow { List prevThrown = thrown; ListBuffer prevPending = pendingExits; try { - pendingExits = ListBuffer.lb(); + pendingExits = new ListBuffer<>(); caught = tree.getDescriptorType(types).getThrownTypes(); thrown = List.nil(); scan(tree.body); @@ -1318,27 +1325,35 @@ public class Flow { * Specialized pass that performs inference of thrown types for lambdas. */ class LambdaFlowAnalyzer extends FlowAnalyzer { + List inferredThrownTypes; + boolean inLambda; @Override public void visitLambda(JCLambda tree) { - if (tree.type != null && - tree.type.isErroneous()) { + if ((tree.type != null && + tree.type.isErroneous()) || inLambda) { return; } List prevCaught = caught; List prevThrown = thrown; ListBuffer prevPending = pendingExits; + inLambda = true; try { - pendingExits = ListBuffer.lb(); + pendingExits = new ListBuffer<>(); caught = List.of(syms.throwableType); thrown = List.nil(); scan(tree.body); - tree.inferredThrownTypes = thrown; + inferredThrownTypes = thrown; } finally { pendingExits = prevPending; caught = prevCaught; thrown = prevThrown; + inLambda = false; } } + @Override + public void visitClassDef(JCClassDecl tree) { + //skip + } } /** @@ -1348,11 +1363,13 @@ public class Flow { * depends on the results of the liveliness analyzer. This pass is also used to mark * effectively-final local variables/parameters. */ - class AssignAnalyzer extends BaseAnalyzer { + + public abstract static class AbstractAssignAnalyzer

        + extends BaseAnalyzer

        { /** The set of definitely assigned variables. */ - final Bits inits; + protected final Bits inits; /** The set of definitely unassigned variables. */ @@ -1378,7 +1395,7 @@ public class Flow { /** A mapping from addresses to variable symbols. */ - JCVariableDecl[] vardecls; + protected JCVariableDecl[] vardecls; /** The current class being defined. */ @@ -1390,11 +1407,11 @@ public class Flow { /** The next available variable sequence number. */ - int nextadr; + protected int nextadr; /** The first variable sequence number in a block that can return. */ - int returnadr; + protected int returnadr; /** The list of unreferenced automatic resources. */ @@ -1406,35 +1423,46 @@ public class Flow { /** The starting position of the analysed tree */ int startPos; - AssignAnalyzer() { - inits = new Bits(); + final Symtab syms; + + protected Names names; + + public static class AbstractAssignPendingExit extends BaseAnalyzer.PendingExit { + + final Bits inits; + final Bits uninits; + final Bits exit_inits = new Bits(true); + final Bits exit_uninits = new Bits(true); + + public AbstractAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { + super(tree); + this.inits = inits; + this.uninits = uninits; + this.exit_inits.assign(inits); + this.exit_uninits.assign(uninits); + } + + @Override + public void resolveJump(JCTree tree) { + inits.andSet(exit_inits); + uninits.andSet(exit_uninits); + } + } + + public AbstractAssignAnalyzer(Bits inits, Symtab syms, Names names) { + this.inits = inits; uninits = new Bits(); uninitsTry = new Bits(); initsWhenTrue = new Bits(true); initsWhenFalse = new Bits(true); uninitsWhenTrue = new Bits(true); uninitsWhenFalse = new Bits(true); - } - - class AssignPendingExit extends BaseAnalyzer.PendingExit { - - final Bits exit_inits = new Bits(true); - final Bits exit_uninits = new Bits(true); - - AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { - super(tree); - this.exit_inits.assign(inits); - this.exit_uninits.assign(uninits); - } - - void resolveJump() { - inits.andSet(exit_inits); - uninits.andSet(exit_uninits); - } + this.syms = syms; + this.names = names; } @Override - void markDead() { + protected void markDead(JCTree tree) { inits.inclRange(returnadr, nextadr); uninits.inclRange(returnadr, nextadr); } @@ -1444,7 +1472,7 @@ public class Flow { /** Do we need to track init/uninit state of this symbol? * I.e. is symbol either a local or a blank final variable? */ - boolean trackable(VarSymbol sym) { + protected boolean trackable(VarSymbol sym) { return sym.pos >= startPos && ((sym.owner.kind == MTH || @@ -1464,44 +1492,35 @@ public class Flow { } sym.adr = nextadr; vardecls[nextadr] = varDecl; - inits.excl(nextadr); + exclVarFromInits(varDecl, nextadr); uninits.incl(nextadr); nextadr++; } + protected void exclVarFromInits(JCTree tree, int adr) { + inits.excl(adr); + } + + protected void assignToInits(JCTree tree, Bits bits) { + inits.assign(bits); + } + + protected void andSetInits(JCTree tree, Bits bits) { + inits.andSet(bits); + } + + protected void orSetInits(JCTree tree, Bits bits) { + inits.orSet(bits); + } + /** Record an initialization of a trackable variable. */ void letInit(DiagnosticPosition pos, VarSymbol sym) { if (sym.adr >= firstadr && trackable(sym)) { - if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { - if (!uninits.isMember(sym.adr)) { - //assignment targeting an effectively final variable - //makes the variable lose its status of effectively final - //if the variable is _not_ definitively unassigned - sym.flags_field &= ~EFFECTIVELY_FINAL; - } else { - uninit(sym); - } - } - else if ((sym.flags() & FINAL) != 0) { - if ((sym.flags() & PARAMETER) != 0) { - if ((sym.flags() & UNION) != 0) { //multi-catch parameter - log.error(pos, "multicatch.parameter.may.not.be.assigned", - sym); - } - else { - log.error(pos, "final.parameter.may.not.be.assigned", - sym); - } - } else if (!uninits.isMember(sym.adr)) { - log.error(pos, flowKind.errKey, sym); - } else { - uninit(sym); - } + if (uninits.isMember(sym.adr)) { + uninit(sym); } inits.incl(sym.adr); - } else if ((sym.flags() & FINAL) != 0) { - log.error(pos, "var.might.already.be.assigned", sym); } } //where @@ -1535,12 +1554,14 @@ public class Flow { void checkInit(DiagnosticPosition pos, VarSymbol sym) { checkInit(pos, sym, "var.might.not.have.been.initialized"); } - void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { - if ((sym.adr >= firstadr || sym.owner.kind != TYP) && - trackable(sym) && - !inits.isMember(sym.adr)) { - log.error(pos, errkey, sym); - inits.incl(sym.adr); + + void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) {} + + /** Utility method to reset several Bits instances. + */ + private void resetBits(Bits... bits) { + for (Bits b : bits) { + b.reset(); } } @@ -1558,7 +1579,7 @@ public class Flow { /** Merge (intersect) inits/uninits from WhenTrue/WhenFalse sets. */ - void merge() { + protected void merge(JCTree tree) { inits.assign(initsWhenFalse.andSet(initsWhenTrue)); uninits.assign(uninitsWhenFalse.andSet(uninitsWhenTrue)); } @@ -1573,7 +1594,9 @@ public class Flow { void scanExpr(JCTree tree) { if (tree != null) { scan(tree); - if (inits.isReset()) merge(); + if (inits.isReset()) { + merge(tree); + } } } @@ -1590,7 +1613,7 @@ public class Flow { */ void scanCond(JCTree tree) { if (tree.type.isFalse()) { - if (inits.isReset()) merge(); + if (inits.isReset()) merge(tree); initsWhenTrue.assign(inits); initsWhenTrue.inclRange(firstadr, nextadr); uninitsWhenTrue.assign(uninits); @@ -1598,7 +1621,7 @@ public class Flow { initsWhenFalse.assign(inits); uninitsWhenFalse.assign(uninits); } else if (tree.type.isTrue()) { - if (inits.isReset()) merge(); + if (inits.isReset()) merge(tree); initsWhenFalse.assign(inits); initsWhenFalse.inclRange(firstadr, nextadr); uninitsWhenFalse.assign(uninits); @@ -1617,22 +1640,22 @@ public class Flow { /* ------------ Visitor methods for various sorts of trees -------------*/ + @Override public void visitClassDef(JCClassDecl tree) { - if (tree.sym == null) return; + if (tree.sym == null) { + return; + } JCClassDecl classDefPrev = classDef; int firstadrPrev = firstadr; int nextadrPrev = nextadr; - ListBuffer pendingExitsPrev = pendingExits; - Lint lintPrev = lint; + ListBuffer

        pendingExitsPrev = pendingExits; - pendingExits = new ListBuffer(); + pendingExits = new ListBuffer

        (); if (tree.name != names.empty) { firstadr = nextadr; } classDef = tree; - lint = lint.augment(tree.sym); - try { // define all the static fields for (List l = tree.defs; l.nonEmpty(); l = l.tail) { @@ -1640,8 +1663,9 @@ public class Flow { JCVariableDecl def = (JCVariableDecl)l.head; if ((def.mods.flags & STATIC) != 0) { VarSymbol sym = def.sym; - if (trackable(sym)) + if (trackable(sym)) { newVar(def); + } } } } @@ -1660,8 +1684,9 @@ public class Flow { JCVariableDecl def = (JCVariableDecl)l.head; if ((def.mods.flags & STATIC) == 0) { VarSymbol sym = def.sym; - if (trackable(sym)) + if (trackable(sym)) { newVar(def); + } } } } @@ -1685,21 +1710,25 @@ public class Flow { nextadr = nextadrPrev; firstadr = firstadrPrev; classDef = classDefPrev; - lint = lintPrev; } } + @Override public void visitMethodDef(JCMethodDecl tree) { - if (tree.body == null) return; + if (tree.body == null) { + return; + } + /* MemberEnter can generate synthetic methods, ignore them + */ + if ((tree.sym.flags() & SYNTHETIC) != 0) { + return; + } final Bits initsPrev = new Bits(inits); final Bits uninitsPrev = new Bits(uninits); int nextadrPrev = nextadr; int firstadrPrev = firstadr; int returnadrPrev = returnadr; - Lint lintPrev = lint; - - lint = lint.augment(tree.sym); Assert.check(pendingExits.isEmpty()); @@ -1707,13 +1736,17 @@ public class Flow { boolean isInitialConstructor = TreeInfo.isInitialConstructor(tree); - if (!isInitialConstructor) + if (!isInitialConstructor) { firstadr = nextadr; + } for (List l = tree.params; l.nonEmpty(); l = l.tail) { JCVariableDecl def = l.head; scan(def); - inits.incl(def.sym.adr); - uninits.excl(def.sym.adr); + Assert.check((def.sym.flags() & PARAMETER) != 0, "Method parameter without PARAMETER flag"); + /* If we are executing the code from Gen, then there can be + * synthetic or mandated variables, ignore them. + */ + initParam(def); } // else we are in an instance initializer block; // leave caught unchanged. @@ -1737,39 +1770,42 @@ public class Flow { } } } - List exits = pendingExits.toList(); - pendingExits = new ListBuffer(); + List

        exits = pendingExits.toList(); + pendingExits = new ListBuffer<>(); while (exits.nonEmpty()) { - AssignPendingExit exit = exits.head; + P exit = exits.head; exits = exits.tail; Assert.check(exit.tree.hasTag(RETURN), exit.tree); if (isInitialConstructor) { - inits.assign(exit.exit_inits); - for (int i = firstadr; i < nextadr; i++) + assignToInits(exit.tree, exit.exit_inits); + for (int i = firstadr; i < nextadr; i++) { checkInit(exit.tree.pos(), vardecls[i].sym); + } } } } finally { - inits.assign(initsPrev); + assignToInits(tree, initsPrev); uninits.assign(uninitsPrev); nextadr = nextadrPrev; firstadr = firstadrPrev; returnadr = returnadrPrev; - lint = lintPrev; } } + protected void initParam(JCVariableDecl def) { + inits.incl(def.sym.adr); + uninits.excl(def.sym.adr); + } + public void visitVarDef(JCVariableDecl tree) { boolean track = trackable(tree.sym); - if (track && tree.sym.owner.kind == MTH) newVar(tree); + if (track && tree.sym.owner.kind == MTH) { + newVar(tree); + } if (tree.init != null) { - Lint lintPrev = lint; - lint = lint.augment(tree.sym); - try{ - scanExpr(tree.init); - if (track) letInit(tree.pos(), tree.sym); - } finally { - lint = lintPrev; + scanExpr(tree.init); + if (track) { + letInit(tree.pos(), tree.sym); } } } @@ -1780,14 +1816,18 @@ public class Flow { nextadr = nextadrPrev; } + int getLogNumberOfErrors() { + return 0; + } + public void visitDoLoop(JCDoWhileLoop tree) { - ListBuffer prevPendingExits = pendingExits; + ListBuffer

        prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; final Bits initsSkip = new Bits(true); final Bits uninitsSkip = new Bits(true); - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; + pendingExits = new ListBuffer

        (); + int prevErrors = getLogNumberOfErrors(); do { final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); @@ -1798,28 +1838,28 @@ public class Flow { initsSkip.assign(initsWhenFalse); uninitsSkip.assign(uninitsWhenFalse); } - if (log.nerrors != prevErrors || + if (getLogNumberOfErrors() != prevErrors || flowKind.isFinal() || new Bits(uninitsEntry).diffSet(uninitsWhenTrue).nextBit(firstadr)==-1) break; - inits.assign(initsWhenTrue); + assignToInits(tree.cond, initsWhenTrue); uninits.assign(uninitsEntry.andSet(uninitsWhenTrue)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; - inits.assign(initsSkip); + assignToInits(tree, initsSkip); uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); } public void visitWhileLoop(JCWhileLoop tree) { - ListBuffer prevPendingExits = pendingExits; + ListBuffer

        prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; final Bits initsSkip = new Bits(true); final Bits uninitsSkip = new Bits(true); - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; + pendingExits = new ListBuffer<>(); + int prevErrors = getLogNumberOfErrors(); final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); do { @@ -1828,35 +1868,36 @@ public class Flow { initsSkip.assign(initsWhenFalse) ; uninitsSkip.assign(uninitsWhenFalse); } - inits.assign(initsWhenTrue); + assignToInits(tree, initsWhenTrue); uninits.assign(uninitsWhenTrue); scan(tree.body); resolveContinues(tree); - if (log.nerrors != prevErrors || + if (getLogNumberOfErrors() != prevErrors || flowKind.isFinal() || - new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) + new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) { break; + } uninits.assign(uninitsEntry.andSet(uninits)); flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; //a variable is DA/DU after the while statement, if it's DA/DU assuming the //branch is not taken AND if it's DA/DU before any break statement - inits.assign(initsSkip); + assignToInits(tree.body, initsSkip); uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); } public void visitForLoop(JCForLoop tree) { - ListBuffer prevPendingExits = pendingExits; + ListBuffer

        prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; int nextadrPrev = nextadr; scan(tree.init); final Bits initsSkip = new Bits(true); final Bits uninitsSkip = new Bits(true); - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; + pendingExits = new ListBuffer

        (); + int prevErrors = getLogNumberOfErrors(); do { final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); @@ -1866,7 +1907,7 @@ public class Flow { initsSkip.assign(initsWhenFalse); uninitsSkip.assign(uninitsWhenFalse); } - inits.assign(initsWhenTrue); + assignToInits(tree.body, initsWhenTrue); uninits.assign(uninitsWhenTrue); } else if (!flowKind.isFinal()) { initsSkip.assign(inits); @@ -1877,7 +1918,7 @@ public class Flow { scan(tree.body); resolveContinues(tree); scan(tree.step); - if (log.nerrors != prevErrors || + if (getLogNumberOfErrors() != prevErrors || flowKind.isFinal() || new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; @@ -1887,7 +1928,7 @@ public class Flow { flowKind = prevFlowKind; //a variable is DA/DU after a for loop, if it's DA/DU assuming the //branch is not taken AND if it's DA/DU before any break statement - inits.assign(initsSkip); + assignToInits(tree.body, initsSkip); uninits.assign(uninitsSkip); resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; @@ -1896,7 +1937,7 @@ public class Flow { public void visitForeachLoop(JCEnhancedForLoop tree) { visitVarDef(tree.var); - ListBuffer prevPendingExits = pendingExits; + ListBuffer

        prevPendingExits = pendingExits; FlowKind prevFlowKind = flowKind; flowKind = FlowKind.NORMAL; int nextadrPrev = nextadr; @@ -1905,14 +1946,14 @@ public class Flow { final Bits uninitsStart = new Bits(uninits); letInit(tree.pos(), tree.var.sym); - pendingExits = new ListBuffer(); - int prevErrors = log.nerrors; + pendingExits = new ListBuffer

        (); + int prevErrors = getLogNumberOfErrors(); do { final Bits uninitsEntry = new Bits(uninits); uninitsEntry.excludeFrom(nextadr); scan(tree.body); resolveContinues(tree); - if (log.nerrors != prevErrors || + if (getLogNumberOfErrors() != prevErrors || flowKind.isFinal() || new Bits(uninitsEntry).diffSet(uninits).nextBit(firstadr) == -1) break; @@ -1920,41 +1961,50 @@ public class Flow { flowKind = FlowKind.SPECULATIVE_LOOP; } while (true); flowKind = prevFlowKind; - inits.assign(initsStart); + assignToInits(tree.body, initsStart); uninits.assign(uninitsStart.andSet(uninits)); resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; } public void visitLabelled(JCLabeledStatement tree) { - ListBuffer prevPendingExits = pendingExits; - pendingExits = new ListBuffer(); + ListBuffer

        prevPendingExits = pendingExits; + pendingExits = new ListBuffer

        (); scan(tree.body); resolveBreaks(tree, prevPendingExits); } public void visitSwitch(JCSwitch tree) { - ListBuffer prevPendingExits = pendingExits; - pendingExits = new ListBuffer(); + ListBuffer

        prevPendingExits = pendingExits; + pendingExits = new ListBuffer<>(); int nextadrPrev = nextadr; scanExpr(tree.selector); final Bits initsSwitch = new Bits(inits); final Bits uninitsSwitch = new Bits(uninits); boolean hasDefault = false; for (List l = tree.cases; l.nonEmpty(); l = l.tail) { - inits.assign(initsSwitch); + assignToInits(l.head, initsSwitch); uninits.assign(uninits.andSet(uninitsSwitch)); JCCase c = l.head; - if (c.pat == null) + if (c.pat == null) { hasDefault = true; - else + } else { scanExpr(c.pat); + } + if (hasDefault) { + assignToInits(null, initsSwitch); + uninits.assign(uninits.andSet(uninitsSwitch)); + } scan(c.stats); addVars(c.stats, initsSwitch, uninitsSwitch); + if (!hasDefault) { + assignToInits(l.head.stats.last(), initsSwitch); + uninits.assign(uninits.andSet(uninitsSwitch)); + } // Warn about fall-through if lint switch fallthrough enabled. } if (!hasDefault) { - inits.andSet(initsSwitch); + andSetInits(null, initsSwitch); } resolveBreaks(tree, prevPendingExits); nextadr = nextadrPrev; @@ -1973,11 +2023,17 @@ public class Flow { } } + boolean isEnabled(Lint.LintCategory lc) { + return false; + } + + void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, String key, Object ... args) {} + public void visitTry(JCTry tree) { - ListBuffer resourceVarDecls = ListBuffer.lb(); + ListBuffer resourceVarDecls = new ListBuffer<>(); final Bits uninitsTryPrev = new Bits(uninitsTry); - ListBuffer prevPendingExits = pendingExits; - pendingExits = new ListBuffer(); + ListBuffer

        prevPendingExits = pendingExits; + pendingExits = new ListBuffer<>(); final Bits initsTry = new Bits(inits); uninitsTry.assign(uninits); for (JCTree resource : tree.resources) { @@ -1999,10 +2055,10 @@ public class Flow { int nextadrCatch = nextadr; if (!resourceVarDecls.isEmpty() && - lint.isEnabled(Lint.LintCategory.TRY)) { + isEnabled(Lint.LintCategory.TRY)) { for (JCVariableDecl resVar : resourceVarDecls) { if (unrefdResources.includes(resVar.sym)) { - log.warning(Lint.LintCategory.TRY, resVar.pos(), + reportWarning(Lint.LintCategory.TRY, resVar.pos(), "try.resource.not.referenced", resVar.sym); unrefdResources.remove(resVar.sym); } @@ -2018,20 +2074,22 @@ public class Flow { for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { JCVariableDecl param = l.head.param; - inits.assign(initsCatchPrev); + assignToInits(tree.body, initsCatchPrev); uninits.assign(uninitsCatchPrev); scan(param); - inits.incl(param.sym.adr); - uninits.excl(param.sym.adr); + /* If this is a TWR and we are executing the code from Gen, + * then there can be synthetic variables, ignore them. + */ + initParam(param); scan(l.head.body); initsEnd.andSet(inits); uninitsEnd.andSet(uninits); nextadr = nextadrCatch; } if (tree.finalizer != null) { - inits.assign(initsTry); + assignToInits(tree.finalizer, initsTry); uninits.assign(uninitsTry); - ListBuffer exits = pendingExits; + ListBuffer

        exits = pendingExits; pendingExits = prevPendingExits; scan(tree.finalizer); if (!tree.finallyCanCompleteNormally) { @@ -2041,19 +2099,19 @@ public class Flow { // FIX: this doesn't preserve source order of exits in catch // versus finally! while (exits.nonEmpty()) { - AssignPendingExit exit = exits.next(); + P exit = exits.next(); if (exit.exit_inits != null) { exit.exit_inits.orSet(inits); exit.exit_uninits.andSet(uninits); } pendingExits.append(exit); } - inits.orSet(initsEnd); + orSetInits(tree, initsEnd); } } else { - inits.assign(initsEnd); + assignToInits(tree, initsEnd); uninits.assign(uninitsEnd); - ListBuffer exits = pendingExits; + ListBuffer

        exits = pendingExits; pendingExits = prevPendingExits; while (exits.nonEmpty()) pendingExits.append(exits.next()); } @@ -2064,7 +2122,7 @@ public class Flow { scanCond(tree.cond); final Bits initsBeforeElse = new Bits(initsWhenFalse); final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); - inits.assign(initsWhenTrue); + assignToInits(tree.cond, initsWhenTrue); uninits.assign(uninitsWhenTrue); if (tree.truepart.type.hasTag(BOOLEAN) && tree.falsepart.type.hasTag(BOOLEAN)) { @@ -2077,7 +2135,7 @@ public class Flow { final Bits initsAfterThenWhenFalse = new Bits(initsWhenFalse); final Bits uninitsAfterThenWhenTrue = new Bits(uninitsWhenTrue); final Bits uninitsAfterThenWhenFalse = new Bits(uninitsWhenFalse); - inits.assign(initsBeforeElse); + assignToInits(tree.truepart, initsBeforeElse); uninits.assign(uninitsBeforeElse); scanCond(tree.falsepart); initsWhenTrue.andSet(initsAfterThenWhenTrue); @@ -2088,10 +2146,10 @@ public class Flow { scanExpr(tree.truepart); final Bits initsAfterThen = new Bits(inits); final Bits uninitsAfterThen = new Bits(uninits); - inits.assign(initsBeforeElse); + assignToInits(tree.truepart, initsBeforeElse); uninits.assign(uninitsBeforeElse); scanExpr(tree.falsepart); - inits.andSet(initsAfterThen); + andSetInits(tree.falsepart, initsAfterThen); uninits.andSet(uninitsAfterThen); } } @@ -2100,39 +2158,46 @@ public class Flow { scanCond(tree.cond); final Bits initsBeforeElse = new Bits(initsWhenFalse); final Bits uninitsBeforeElse = new Bits(uninitsWhenFalse); - inits.assign(initsWhenTrue); + assignToInits(tree.cond, initsWhenTrue); uninits.assign(uninitsWhenTrue); scan(tree.thenpart); if (tree.elsepart != null) { final Bits initsAfterThen = new Bits(inits); final Bits uninitsAfterThen = new Bits(uninits); - inits.assign(initsBeforeElse); + assignToInits(tree.thenpart, initsBeforeElse); uninits.assign(uninitsBeforeElse); scan(tree.elsepart); - inits.andSet(initsAfterThen); + andSetInits(tree.elsepart, initsAfterThen); uninits.andSet(uninitsAfterThen); } else { - inits.andSet(initsBeforeElse); + andSetInits(tree.thenpart, initsBeforeElse); uninits.andSet(uninitsBeforeElse); } } + protected P createNewPendingExit(JCTree tree, Bits inits, Bits uninits) { + return null; + } + + @Override public void visitBreak(JCBreak tree) { - recordExit(tree, new AssignPendingExit(tree, inits, uninits)); + recordExit(tree, createNewPendingExit(tree, inits, uninits)); } + @Override public void visitContinue(JCContinue tree) { - recordExit(tree, new AssignPendingExit(tree, inits, uninits)); + recordExit(tree, createNewPendingExit(tree, inits, uninits)); } + @Override public void visitReturn(JCReturn tree) { scanExpr(tree.expr); - recordExit(tree, new AssignPendingExit(tree, inits, uninits)); + recordExit(tree, createNewPendingExit(tree, inits, uninits)); } public void visitThrow(JCThrow tree) { scanExpr(tree.expr); - markDead(); + markDead(tree.expr); } public void visitApply(JCMethodInvocation tree) { @@ -2151,10 +2216,10 @@ public class Flow { final Bits prevUninits = new Bits(uninits); final Bits prevInits = new Bits(inits); int returnadrPrev = returnadr; - ListBuffer prevPending = pendingExits; + ListBuffer

        prevPending = pendingExits; try { returnadr = nextadr; - pendingExits = new ListBuffer(); + pendingExits = new ListBuffer

        (); for (List l = tree.params; l.nonEmpty(); l = l.tail) { JCVariableDecl def = l.head; scan(def); @@ -2170,7 +2235,7 @@ public class Flow { finally { returnadr = returnadrPrev; uninits.assign(prevUninits); - inits.assign(prevInits); + assignToInits(tree, prevInits); pendingExits = prevPending; } } @@ -2186,11 +2251,11 @@ public class Flow { scanCond(tree.cond); uninitsExit.andSet(uninitsWhenTrue); if (tree.detail != null) { - inits.assign(initsWhenFalse); + assignToInits(tree, initsWhenFalse); uninits.assign(uninitsWhenFalse); scanExpr(tree.detail); } - inits.assign(initsExit); + assignToInits(tree, initsExit); uninits.assign(uninitsExit); } @@ -2236,7 +2301,7 @@ public class Flow { scanCond(tree.lhs); final Bits initsWhenFalseLeft = new Bits(initsWhenFalse); final Bits uninitsWhenFalseLeft = new Bits(uninitsWhenFalse); - inits.assign(initsWhenTrue); + assignToInits(tree.lhs, initsWhenTrue); uninits.assign(uninitsWhenTrue); scanCond(tree.rhs); initsWhenFalse.andSet(initsWhenFalseLeft); @@ -2246,7 +2311,7 @@ public class Flow { scanCond(tree.lhs); final Bits initsWhenTrueLeft = new Bits(initsWhenTrue); final Bits uninitsWhenTrueLeft = new Bits(uninitsWhenTrue); - inits.assign(initsWhenFalse); + assignToInits(tree.lhs, initsWhenFalse); uninits.assign(uninitsWhenFalse); scanCond(tree.rhs); initsWhenTrue.andSet(initsWhenTrueLeft); @@ -2284,14 +2349,12 @@ public class Flow { /** Perform definite assignment/unassignment analysis on a tree. */ - public void analyzeTree(Env env, TreeMaker make) { - analyzeTree(env, env.tree, make); - } + public void analyzeTree(Env env) { + analyzeTree(env, env.tree); + } - public void analyzeTree(Env env, JCTree tree, TreeMaker make) { + public void analyzeTree(Env env, JCTree tree) { try { - attrEnv = env; - Flow.this.make = make; startPos = tree.pos().getStartPosition(); if (vardecls == null) @@ -2301,7 +2364,7 @@ public class Flow { vardecls[i] = null; firstadr = 0; nextadr = 0; - pendingExits = new ListBuffer(); + pendingExits = new ListBuffer<>(); this.classDef = null; unrefdResources = new Scope(env.enclClass.sym); scan(tree); @@ -2310,18 +2373,160 @@ public class Flow { startPos = -1; resetBits(inits, uninits, uninitsTry, initsWhenTrue, initsWhenFalse, uninitsWhenTrue, uninitsWhenFalse); - if (vardecls != null) for (int i=0; i { + + Log log; + Lint lint; + + public static class AssignPendingExit + extends AbstractAssignAnalyzer.AbstractAssignPendingExit { + + public AssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { + super(tree, inits, uninits); + } + } + + public AssignAnalyzer(Log log, Symtab syms, Lint lint, Names names) { + super(new Bits(), syms, names); + this.log = log; + this.lint = lint; + } + + @Override + protected AssignPendingExit createNewPendingExit(JCTree tree, + Bits inits, Bits uninits) { + return new AssignPendingExit(tree, inits, uninits); + } + + /** Record an initialization of a trackable variable. + */ + @Override + void letInit(DiagnosticPosition pos, VarSymbol sym) { + if (sym.adr >= firstadr && trackable(sym)) { + if ((sym.flags() & EFFECTIVELY_FINAL) != 0) { + if (!uninits.isMember(sym.adr)) { + //assignment targeting an effectively final variable + //makes the variable lose its status of effectively final + //if the variable is _not_ definitively unassigned + sym.flags_field &= ~EFFECTIVELY_FINAL; + } else { + uninit(sym); + } + } + else if ((sym.flags() & FINAL) != 0) { + if ((sym.flags() & PARAMETER) != 0) { + if ((sym.flags() & UNION) != 0) { //multi-catch parameter + log.error(pos, "multicatch.parameter.may.not.be.assigned", sym); + } + else { + log.error(pos, "final.parameter.may.not.be.assigned", + sym); + } + } else if (!uninits.isMember(sym.adr)) { + log.error(pos, flowKind.errKey, sym); + } else { + uninit(sym); + } + } + inits.incl(sym.adr); + } else if ((sym.flags() & FINAL) != 0) { + log.error(pos, "var.might.already.be.assigned", sym); + } + } + + @Override + void checkInit(DiagnosticPosition pos, VarSymbol sym, String errkey) { + if ((sym.adr >= firstadr || sym.owner.kind != TYP) && + trackable(sym) && + !inits.isMember(sym.adr)) { + log.error(pos, errkey, sym); + inits.incl(sym.adr); + } + } + + @Override + void reportWarning(Lint.LintCategory lc, DiagnosticPosition pos, + String key, Object ... args) { + log.warning(lc, pos, key, args); + } + + @Override + int getLogNumberOfErrors() { + return log.nerrors; + } + + @Override + boolean isEnabled(Lint.LintCategory lc) { + return lint.isEnabled(lc); + } + + @Override + public void visitClassDef(JCClassDecl tree) { + if (tree.sym == null) { + return; + } + + Lint lintPrev = lint; + lint = lint.augment(tree.sym); + try { + super.visitClassDef(tree); + } finally { + lint = lintPrev; + } + } + + @Override + public void visitMethodDef(JCMethodDecl tree) { + if (tree.body == null) { + return; + } + + /* MemberEnter can generate synthetic methods ignore them + */ + if ((tree.sym.flags() & SYNTHETIC) != 0) { + return; + } + + Lint lintPrev = lint; + lint = lint.augment(tree.sym); + try { + super.visitMethodDef(tree); + } finally { + lint = lintPrev; + } + } + + @Override + public void visitVarDef(JCVariableDecl tree) { + if (tree.init == null) { + super.visitVarDef(tree); + } else { + Lint lintPrev = lint; + lint = lint.augment(tree.sym); + try{ + super.visitVarDef(tree); + } finally { + lint = lintPrev; + } + } + } + + } + /** * This pass implements the last step of the dataflow analysis, namely * the effectively-final analysis check. This checks that every local variable @@ -2334,7 +2539,7 @@ public class Flow { JCTree currentTree; //local class or lambda @Override - void markDead() { + void markDead(JCTree tree) { //do nothing } diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java index a87156a6b07..61f75f068fa 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Infer.java @@ -40,17 +40,17 @@ import com.sun.tools.javac.comp.Infer.GraphSolver.InferenceGraph; 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.util.Comparator; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; +import com.sun.tools.javac.util.GraphUtils.TarjanNode; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumMap; import java.util.EnumSet; +import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; import static com.sun.tools.javac.code.TypeTag.*; @@ -113,6 +113,12 @@ public class Infer { super(diags); } + @Override + InapplicableMethodException setMessage() { + //no message to set + return this; + } + @Override InapplicableMethodException setMessage(JCDiagnostic diag) { messages = messages.append(diag); @@ -271,7 +277,7 @@ public class Infer { * Infer cyclic inference variables as described in 15.12.2.8. */ private void instantiateAsUninferredVars(List vars, InferenceContext inferenceContext) { - ListBuffer todo = ListBuffer.lb(); + ListBuffer todo = new ListBuffer<>(); //step 1 - create fresh tvars for (Type t : vars) { UndetVar uv = (UndetVar)inferenceContext.asFree(t); @@ -1006,10 +1012,24 @@ public class Infer { * and (ii) tell th engine when we are done fixing inference variables */ interface GraphStrategy { + + /** + * A NodeNotFoundException is thrown whenever an inference strategy fails + * to pick the next node to solve in the inference graph. + */ + public static class NodeNotFoundException extends RuntimeException { + private static final long serialVersionUID = 0; + + InferenceGraph graph; + + public NodeNotFoundException(InferenceGraph graph) { + this.graph = graph; + } + } /** * Pick the next node (leaf) to solve in the graph */ - Node pickNode(InferenceGraph g); + Node pickNode(InferenceGraph g) throws NodeNotFoundException; /** * Is this the last step? */ @@ -1022,7 +1042,10 @@ public class Infer { */ abstract class LeafSolver implements GraphStrategy { public Node pickNode(InferenceGraph g) { - Assert.check(!g.nodes.isEmpty(), "No nodes to solve!"); + if (g.nodes.isEmpty()) { + //should not happen + throw new NodeNotFoundException(g); + }; return g.nodes.get(0); } @@ -1069,6 +1092,7 @@ public class Infer { */ abstract class BestLeafSolver extends LeafSolver { + /** list of ivars of which at least one must be solved */ List varsToSolve; BestLeafSolver(List varsToSolve) { @@ -1076,54 +1100,66 @@ public class Infer { } /** - * Computes the minimum path that goes from a given node to any of the nodes - * containing a variable in {@code varsToSolve}. For any given path, the cost - * is computed as the total number of type-variables that should be eagerly - * instantiated across that path. + * Computes a path that goes from a given node to the leafs in the graph. + * Typically this will start from a node containing a variable in + * {@code varsToSolve}. For any given path, the cost is computed as the total + * number of type-variables that should be eagerly instantiated across that path. */ - int computeMinPath(InferenceGraph g, Node n) { - return computeMinPath(g, n, List.nil(), 0); + Pair, Integer> computeTreeToLeafs(Node n) { + Pair, Integer> cachedPath = treeCache.get(n); + if (cachedPath == null) { + //cache miss + if (n.isLeaf()) { + //if leaf, stop + cachedPath = new Pair, Integer>(List.of(n), n.data.length()); + } else { + //if non-leaf, proceed recursively + Pair, Integer> path = new Pair, Integer>(List.of(n), n.data.length()); + for (Node n2 : n.getAllDependencies()) { + if (n2 == n) continue; + Pair, Integer> subpath = computeTreeToLeafs(n2); + path = new Pair, Integer>( + path.fst.prependList(subpath.fst), + path.snd + subpath.snd); + } + cachedPath = path; + } + //save results in cache + treeCache.put(n, cachedPath); + } + return cachedPath; } - int computeMinPath(InferenceGraph g, Node n, List path, int cost) { - if (path.contains(n)) return Integer.MAX_VALUE; - List path2 = path.prepend(n); - int cost2 = cost + n.data.size(); - if (!Collections.disjoint(n.data, varsToSolve)) { - return cost2; - } else { - int bestPath = Integer.MAX_VALUE; - for (Node n2 : g.nodes) { - if (n2.deps.contains(n)) { - int res = computeMinPath(g, n2, path2, cost2); - if (res < bestPath) { - bestPath = res; - } - } - } - return bestPath; - } - } + /** cache used to avoid redundant computation of tree costs */ + final Map, Integer>> treeCache = + new HashMap, Integer>>(); + + /** constant value used to mark non-existent paths */ + final Pair, Integer> noPath = + new Pair, Integer>(null, Integer.MAX_VALUE); /** * Pick the leaf that minimize cost */ @Override public Node pickNode(final InferenceGraph g) { - final Map leavesMap = new HashMap(); + treeCache.clear(); //graph changes at every step - cache must be cleared + Pair, Integer> bestPath = noPath; for (Node n : g.nodes) { - if (n.isLeaf(n)) { - leavesMap.put(n, computeMinPath(g, n)); + if (!Collections.disjoint(n.data, varsToSolve)) { + Pair, Integer> path = computeTreeToLeafs(n); + //discard all paths containing at least a node in the + //closure computed above + if (path.snd < bestPath.snd) { + bestPath = path; + } } } - Assert.check(!leavesMap.isEmpty(), "No nodes to solve!"); - TreeSet orderedLeaves = new TreeSet(new Comparator() { - public int compare(Node n1, Node n2) { - return leavesMap.get(n1) - leavesMap.get(n2); - } - }); - orderedLeaves.addAll(leavesMap.keySet()); - return orderedLeaves.first(); + if (bestPath == noPath) { + //no path leads there + throw new NodeNotFoundException(g); + } + return bestPath.fst.head; } } @@ -1320,6 +1356,33 @@ public class Infer { } } + /** + * There are two kinds of dependencies between inference variables. The basic + * kind of dependency (or bound dependency) arises when a variable mention + * another variable in one of its bounds. There's also a more subtle kind + * of dependency that arises when a variable 'might' lead to better constraints + * on another variable (this is typically the case with variables holding up + * stuck expressions). + */ + enum DependencyKind implements GraphUtils.DependencyKind { + + /** bound dependency */ + BOUND("dotted"), + /** stuck dependency */ + STUCK("dashed"); + + final String dotSyle; + + private DependencyKind(String dotSyle) { + this.dotSyle = dotSyle; + } + + @Override + public String getDotStyle() { + return dotSyle; + } + } + /** * This is the graph inference solver - the solver organizes all inference variables in * a given inference context by bound dependencies - in the general case, such dependencies @@ -1331,10 +1394,12 @@ public class Infer { class GraphSolver { InferenceContext inferenceContext; + Map> stuckDeps; Warner warn; - GraphSolver(InferenceContext inferenceContext, Warner warn) { + GraphSolver(InferenceContext inferenceContext, Map> stuckDeps, Warner warn) { this.inferenceContext = inferenceContext; + this.stuckDeps = stuckDeps; this.warn = warn; } @@ -1345,7 +1410,7 @@ public class Infer { */ void solve(GraphStrategy sstrategy) { checkWithinBounds(inferenceContext, warn); //initial propagation of bounds - InferenceGraph inferenceGraph = new InferenceGraph(); + InferenceGraph inferenceGraph = new InferenceGraph(stuckDeps); while (!sstrategy.done()) { InferenceGraph.Node nodeToSolve = sstrategy.pickNode(inferenceGraph); List varsToSolve = List.from(nodeToSolve.data); @@ -1390,64 +1455,172 @@ public class Infer { */ class Node extends GraphUtils.TarjanNode> { - Set deps; + /** map listing all dependencies (grouped by kind) */ + EnumMap> deps; Node(Type ivar) { super(ListBuffer.of(ivar)); - this.deps = new HashSet(); + this.deps = new EnumMap>(DependencyKind.class); } @Override - public Iterable getDependencies() { - return deps; + public GraphUtils.DependencyKind[] getSupportedDependencyKinds() { + return DependencyKind.values(); } @Override - public String printDependency(GraphUtils.Node> to) { - StringBuilder buf = new StringBuilder(); - String sep = ""; - for (Type from : data) { - UndetVar uv = (UndetVar)inferenceContext.asFree(from); - for (Type bound : uv.getBounds(InferenceBound.values())) { - if (bound.containsAny(List.from(to.data))) { - buf.append(sep); - buf.append(bound); - sep = ","; + public String getDependencyName(GraphUtils.Node> to, GraphUtils.DependencyKind dk) { + if (dk == DependencyKind.STUCK) return ""; + else { + StringBuilder buf = new StringBuilder(); + String sep = ""; + for (Type from : data) { + UndetVar uv = (UndetVar)inferenceContext.asFree(from); + for (Type bound : uv.getBounds(InferenceBound.values())) { + if (bound.containsAny(List.from(to.data))) { + buf.append(sep); + buf.append(bound); + sep = ","; + } } } + return buf.toString(); } - return buf.toString(); } - boolean isLeaf(Node n) { + @Override + public Iterable getAllDependencies() { + return getDependencies(DependencyKind.values()); + } + + @Override + public Iterable>> getDependenciesByKind(GraphUtils.DependencyKind dk) { + return getDependencies((DependencyKind)dk); + } + + /** + * Retrieves all dependencies with given kind(s). + */ + protected Set getDependencies(DependencyKind... depKinds) { + Set buf = new LinkedHashSet(); + for (DependencyKind dk : depKinds) { + Set depsByKind = deps.get(dk); + if (depsByKind != null) { + buf.addAll(depsByKind); + } + } + return buf; + } + + /** + * Adds dependency with given kind. + */ + protected void addDependency(DependencyKind dk, Node depToAdd) { + Set depsByKind = deps.get(dk); + if (depsByKind == null) { + depsByKind = new LinkedHashSet(); + deps.put(dk, depsByKind); + } + depsByKind.add(depToAdd); + } + + /** + * Add multiple dependencies of same given kind. + */ + protected void addDependencies(DependencyKind dk, Set depsToAdd) { + for (Node n : depsToAdd) { + addDependency(dk, n); + } + } + + /** + * Remove a dependency, regardless of its kind. + */ + protected Set removeDependency(Node n) { + Set removedKinds = new HashSet<>(); + for (DependencyKind dk : DependencyKind.values()) { + Set depsByKind = deps.get(dk); + if (depsByKind == null) continue; + if (depsByKind.remove(n)) { + removedKinds.add(dk); + } + } + return removedKinds; + } + + /** + * Compute closure of a give node, by recursively walking + * through all its dependencies (of given kinds) + */ + protected Set closure(DependencyKind... depKinds) { + boolean progress = true; + Set closure = new HashSet(); + closure.add(this); + while (progress) { + progress = false; + for (Node n1 : new HashSet(closure)) { + progress = closure.addAll(n1.getDependencies(depKinds)); + } + } + return closure; + } + + /** + * Is this node a leaf? This means either the node has no dependencies, + * or it just has self-dependencies. + */ + protected boolean isLeaf() { //no deps, or only one self dep - return (n.deps.isEmpty() || - n.deps.size() == 1 && n.deps.contains(n)); + Set allDeps = getDependencies(DependencyKind.BOUND, DependencyKind.STUCK); + if (allDeps.isEmpty()) return true; + for (Node n : allDeps) { + if (n != this) { + return false; + } + } + return true; } - void mergeWith(List nodes) { + /** + * Merge this node with another node, acquiring its dependencies. + * This routine is used to merge all cyclic node together and + * form an acyclic graph. + */ + protected void mergeWith(List nodes) { for (Node n : nodes) { Assert.check(n.data.length() == 1, "Attempt to merge a compound node!"); data.appendList(n.data); - deps.addAll(n.deps); + for (DependencyKind dk : DependencyKind.values()) { + addDependencies(dk, n.getDependencies(dk)); + } } //update deps - Set deps2 = new HashSet(); - for (Node d : deps) { - if (data.contains(d.data.first())) { - deps2.add(this); - } else { - deps2.add(d); + EnumMap> deps2 = new EnumMap>(DependencyKind.class); + for (DependencyKind dk : DependencyKind.values()) { + for (Node d : getDependencies(dk)) { + Set depsByKind = deps2.get(dk); + if (depsByKind == null) { + depsByKind = new LinkedHashSet(); + deps2.put(dk, depsByKind); + } + if (data.contains(d.data.first())) { + depsByKind.add(this); + } else { + depsByKind.add(d); + } } } deps = deps2; } - void graphChanged(Node from, Node to) { - if (deps.contains(from)) { - deps.remove(from); + /** + * Notify all nodes that something has changed in the graph + * topology. + */ + private void graphChanged(Node from, Node to) { + for (DependencyKind dk : removeDependency(from)) { if (to != null) { - deps.add(to); + addDependency(dk, to); } } } @@ -1456,8 +1629,21 @@ public class Infer { /** the nodes in the inference graph */ ArrayList nodes; - InferenceGraph() { - initNodes(); + InferenceGraph(Map> optDeps) { + initNodes(optDeps); + } + + /** + * Basic lookup helper for retrieving a graph node given an inference + * variable type. + */ + public Node findNode(Type t) { + for (Node n : nodes) { + if (n.data.contains(t)) { + return n; + } + } + return null; } /** @@ -1484,24 +1670,32 @@ public class Infer { * Create the graph nodes. First a simple node is created for every inference * variables to be solved. Then Tarjan is used to found all connected components * in the graph. For each component containing more than one node, a super node is - * created, effectively replacing the original cyclic nodes. + * created, effectively replacing the original cyclic nodes. */ - void initNodes() { + void initNodes(Map> stuckDeps) { + //add nodes nodes = new ArrayList(); for (Type t : inferenceContext.restvars()) { nodes.add(new Node(t)); } + //add dependencies for (Node n_i : nodes) { Type i = n_i.data.first(); + Set optDepsByNode = stuckDeps.get(i); for (Node n_j : nodes) { Type j = n_j.data.first(); UndetVar uv_i = (UndetVar)inferenceContext.asFree(i); if (Type.containsAny(uv_i.getBounds(InferenceBound.values()), List.of(j))) { - //update i's deps - n_i.deps.add(n_j); + //update i's bound dependencies + n_i.addDependency(DependencyKind.BOUND, n_j); + } + if (optDepsByNode != null && optDepsByNode.contains(j)) { + //update i's stuck dependencies + n_i.addDependency(DependencyKind.STUCK, n_j); } } } + //merge cyclic nodes ArrayList acyclicNodes = new ArrayList(); for (List conSubGraph : GraphUtils.tarjan(nodes)) { if (conSubGraph.length() > 1) { @@ -1631,14 +1825,14 @@ public class Infer { return filterVars(new Filter() { public boolean accepts(UndetVar uv) { return uv.getBounds(InferenceBound.UPPER) - .diff(uv.getDeclaredBounds()) - .appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty(); + .diff(uv.getDeclaredBounds()) + .appendList(uv.getBounds(InferenceBound.EQ, InferenceBound.LOWER)).nonEmpty(); } }); } private List filterVars(Filter fu) { - ListBuffer res = ListBuffer.lb(); + ListBuffer res = new ListBuffer<>(); for (Type t : undetvars) { UndetVar uv = (UndetVar)t; if (fu.accepts(uv)) { @@ -1666,7 +1860,7 @@ public class Infer { * Returns a list of free variables in a given type */ final List freeVarsIn(Type t) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type iv : inferenceVars()) { if (t.contains(iv)) { buf.add(iv); @@ -1676,11 +1870,11 @@ public class Infer { } final List freeVarsIn(List ts) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type t : ts) { buf.appendList(freeVarsIn(t)); } - ListBuffer buf2 = ListBuffer.lb(); + ListBuffer buf2 = new ListBuffer<>(); for (Type t : buf) { if (!buf2.contains(t)) { buf2.add(t); @@ -1699,7 +1893,7 @@ public class Infer { } final List asFree(List ts) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type t : ts) { buf.append(asFree(t)); } @@ -1707,7 +1901,7 @@ public class Infer { } List instTypes() { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type t : undetvars) { UndetVar uv = (UndetVar)t; buf.append(uv.inst != null ? uv.inst : uv.qtype); @@ -1725,7 +1919,7 @@ public class Infer { } List asInstTypes(List ts) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type t : ts) { buf.append(asInstType(t)); } @@ -1773,7 +1967,7 @@ public class Infer { * Save the state of this inference context */ List save() { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Type t : undetvars) { UndetVar uv = (UndetVar)t; UndetVar uv2 = new UndetVar((TypeVar)uv.qtype, types); @@ -1822,11 +2016,15 @@ public class Infer { } } + private void solve(GraphStrategy ss, Warner warn) { + solve(ss, new HashMap>(), warn); + } + /** * Solve with given graph strategy. */ - private void solve(GraphStrategy ss, Warner warn) { - GraphSolver s = new GraphSolver(this, warn); + private void solve(GraphStrategy ss, Map> stuckDeps, Warner warn) { + GraphSolver s = new GraphSolver(this, stuckDeps, warn); s.solve(ss); } @@ -1855,18 +2053,12 @@ public class Infer { /** * Solve at least one variable in given list. */ - public void solveAny(List varsToSolve, Warner warn) { - checkWithinBounds(this, warn); //propagate bounds - List boundedVars = boundedVars().intersect(restvars()).intersect(varsToSolve); - if (boundedVars.isEmpty()) { - throw inferenceException.setMessage("cyclic.inference", - freeVarsIn(varsToSolve)); - } - solve(new BestLeafSolver(boundedVars) { + public void solveAny(List varsToSolve, Map> optDeps, Warner warn) { + solve(new BestLeafSolver(varsToSolve.intersect(restvars())) { public boolean done() { return instvars().intersect(varsToSolve).nonEmpty(); } - }, warn); + }, optDeps, warn); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index 7633f96d1df..eb15ef65c11 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -126,7 +126,7 @@ public class LambdaToMethod extends TreeTranslator { private final VarSymbol deserParamSym; private KlassInfo(Symbol kSym) { - appendedMethodList = ListBuffer.lb(); + appendedMethodList = new ListBuffer<>(); deserializeCases = new HashMap>(); long flags = PRIVATE | STATIC | SYNTHETIC; MethodType type = new MethodType(List.of(syms.serializedLambdaType), syms.objectType, @@ -153,6 +153,8 @@ public class LambdaToMethod extends TreeTranslator { return instance; } + private Attr attr; + private LambdaToMethod(Context context) { diags = JCDiagnostic.Factory.instance(context); log = Log.instance(context); @@ -166,6 +168,7 @@ public class LambdaToMethod extends TreeTranslator { analyzer = new LambdaAnalyzerPreprocessor(); Options options = Options.instance(context); dumpLambdaToMethodStats = options.isSet("dumpLambdaToMethodStats"); + attr = Attr.instance(context); } // @@ -188,7 +191,7 @@ public class LambdaToMethod extends TreeTranslator { } List translate(List trees, TranslationContext newContext) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (T tree : trees) { buf.append(translate(tree, newContext)); } @@ -301,7 +304,7 @@ public class LambdaToMethod extends TreeTranslator { // * the "this" argument if it is an instance method // * enclosing locals captured by the lambda expression - ListBuffer syntheticInits = ListBuffer.lb(); + ListBuffer syntheticInits = new ListBuffer<>(); if (!sym.isStatic()) { syntheticInits.append(makeThis( @@ -368,6 +371,7 @@ public class LambdaToMethod extends TreeTranslator { case BOUND: /** Expr :: instMethod */ init = tree.getQualifierExpression(); + init = attr.makeNullCheck(init); break; case UNBOUND: /** Type :: instMethod */ @@ -465,7 +469,7 @@ public class LambdaToMethod extends TreeTranslator { } else if (isLambda_void && isTarget_Void) { //void to Void conversion: // BODY; return null; - ListBuffer stats = ListBuffer.lb(); + ListBuffer stats = new ListBuffer<>(); stats.append(make.Exec(expr)); stats.append(make.Return(make.Literal(BOT, null).setType(syms.botType))); return make.Block(0, stats.toList()); @@ -527,8 +531,8 @@ public class LambdaToMethod extends TreeTranslator { } private JCMethodDecl makeDeserializeMethod(Symbol kSym) { - ListBuffer cases = ListBuffer.lb(); - ListBuffer breaks = ListBuffer.lb(); + ListBuffer cases = new ListBuffer<>(); + ListBuffer breaks = new ListBuffer<>(); for (Map.Entry> entry : kInfo.deserializeCases.entrySet()) { JCBreak br = make.Break(null); breaks.add(br); @@ -590,11 +594,11 @@ public class LambdaToMethod extends TreeTranslator { String implMethodSignature = methodSig(types.erasure(refSym.type)); JCExpression kindTest = eqTest(syms.intType, deserGetter("getImplMethodKind", syms.intType), make.Literal(implMethodKind)); - ListBuffer serArgs = ListBuffer.lb(); + ListBuffer serArgs = new ListBuffer<>(); int i = 0; for (Type t : indyType.getParameterTypes()) { - List indexAsArg = ListBuffer.lb().append(make.Literal(i)).toList(); - List argTypes = ListBuffer.lb().append(syms.intType).toList(); + List indexAsArg = new ListBuffer().append(make.Literal(i)).toList(); + List argTypes = new ListBuffer().append(syms.intType).toList(); serArgs.add(make.TypeCast(types.erasure(t), deserGetter("getCapturedArg", syms.objectType, argTypes, indexAsArg))); ++i; } @@ -614,7 +618,7 @@ public class LambdaToMethod extends TreeTranslator { null); ListBuffer stmts = kInfo.deserializeCases.get(implMethodName); if (stmts == null) { - stmts = ListBuffer.lb(); + stmts = new ListBuffer<>(); kInfo.deserializeCases.put(implMethodName, stmts); } /**** @@ -724,8 +728,8 @@ public class LambdaToMethod extends TreeTranslator { private final JCMemberReference tree; private final ReferenceTranslationContext localContext; - private final ListBuffer args = ListBuffer.lb(); - private final ListBuffer params = ListBuffer.lb(); + private final ListBuffer args = new ListBuffer<>(); + private final ListBuffer params = new ListBuffer<>(); MemberReferenceBridger(JCMemberReference tree, ReferenceTranslationContext localContext) { this.tree = tree; @@ -930,7 +934,7 @@ public class LambdaToMethod extends TreeTranslator { typeToMethodType(tree.getDescriptorType(types))); //computed indy arg types - ListBuffer indy_args_types = ListBuffer.lb(); + ListBuffer indy_args_types = new ListBuffer<>(); for (JCExpression arg : indy_args) { indy_args_types.append(arg.type); } @@ -945,7 +949,7 @@ public class LambdaToMethod extends TreeTranslator { names.altMetafactory : names.metafactory; if (context.needsAltMetafactory()) { - ListBuffer markers = ListBuffer.lb(); + ListBuffer markers = new ListBuffer<>(); for (Type t : tree.targets.tail) { if (t.tsym != syms.serializableType.tsym) { markers.append(t.tsym); @@ -1023,7 +1027,7 @@ public class LambdaToMethod extends TreeTranslator { } //where private List bsmStaticArgToTypes(List args) { - ListBuffer argtypes = ListBuffer.lb(); + ListBuffer argtypes = new ListBuffer<>(); for (Object arg : args) { argtypes.append(bsmStaticArgToType(arg)); } @@ -1745,6 +1749,11 @@ public class LambdaToMethod extends TreeTranslator { // Just erase the type var ret = new VarSymbol(sym.flags(), name, types.erasure(sym.type), sym.owner); + + /* this information should also be kept for LVT generation at Gen + * a Symbol with pos < startPos won't be tracked. + */ + ((VarSymbol)ret).pos = ((VarSymbol)sym).pos; break; case CAPTURED_VAR: ret = new VarSymbol(SYNTHETIC | FINAL, name, types.erasure(sym.type), translatedSym) { @@ -1842,7 +1851,7 @@ public class LambdaToMethod extends TreeTranslator { (thisReferenced? (inInterface? DEFAULT : 0) : STATIC); //compute synthetic params - ListBuffer params = ListBuffer.lb(); + ListBuffer params = new ListBuffer<>(); // The signature of the method is augmented with the following // synthetic parameters: diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java index 75e1d388666..51588257c9b 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Lower.java @@ -49,7 +49,6 @@ import static com.sun.tools.javac.code.Kinds.*; 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.*; -import javax.lang.model.type.TypeKind; /** This pass translates away some syntactic sugar: inner classes, * class literals, assertions, foreach loops, etc. @@ -1480,7 +1479,12 @@ public class Lower extends TreeTranslator { * @param owner The class in which the definitions go. */ List freevarDefs(int pos, List freevars, Symbol owner) { - long flags = FINAL | SYNTHETIC; + return freevarDefs(pos, freevars, owner, 0); + } + + List freevarDefs(int pos, List freevars, Symbol owner, + long additionalFlags) { + long flags = FINAL | SYNTHETIC | additionalFlags; if (owner.kind == TYP && target.usePrivateSyntheticFields()) flags |= PRIVATE; @@ -1543,7 +1547,7 @@ public class Lower extends TreeTranslator { (owner.isConstructor() && c.isInner() && !c.isPrivate() && !c.isStatic()); long flags = - FINAL | (isMandated ? MANDATED : SYNTHETIC); + FINAL | (isMandated ? MANDATED : SYNTHETIC) | PARAMETER; VarSymbol outerThis = makeOuterThisVarSymbol(owner, flags); owner.extraParams = owner.extraParams.prepend(outerThis); return makeOuterThisVarDecl(pos, outerThis); @@ -1627,7 +1631,8 @@ public class Lower extends TreeTranslator { JCTree makeTwrTry(JCTry tree) { make_at(tree.pos()); twrVars = twrVars.dup(); - JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, 0); + JCBlock twrBlock = makeTwrBlock(tree.resources, tree.body, + tree.finallyCanCompleteNormally, 0); if (tree.catchers.isEmpty() && tree.finalizer == null) result = translate(twrBlock); else @@ -1636,7 +1641,8 @@ public class Lower extends TreeTranslator { return result; } - private JCBlock makeTwrBlock(List resources, JCBlock block, int depth) { + private JCBlock makeTwrBlock(List resources, JCBlock block, + boolean finallyCanCompleteNormally, int depth) { if (resources.isEmpty()) return block; @@ -1692,17 +1698,20 @@ public class Lower extends TreeTranslator { make.at(TreeInfo.endPos(block)); JCBlock finallyClause = makeTwrFinallyClause(primaryException, expr); make.at(oldPos); - JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, depth + 1), + JCTry outerTry = make.Try(makeTwrBlock(resources.tail, block, + finallyCanCompleteNormally, depth + 1), List.of(catchClause), finallyClause); + outerTry.finallyCanCompleteNormally = finallyCanCompleteNormally; stats.add(outerTry); - return make.Block(0L, stats.toList()); + JCBlock newBlock = make.Block(0L, stats.toList()); + return newBlock; } private JCBlock makeTwrFinallyClause(Symbol primaryException, JCExpression resource) { // primaryException.addSuppressed(catchException); VarSymbol catchException = - new VarSymbol(0, make.paramName(2), + new VarSymbol(SYNTHETIC, make.paramName(2), syms.throwableType, currentMethodSym); JCStatement addSuppressionStatement = @@ -1717,6 +1726,7 @@ public class Lower extends TreeTranslator { JCBlock catchBlock = make.Block(0L, List.of(addSuppressionStatement)); List catchClauses = List.of(make.Catch(catchExceptionDecl, catchBlock)); JCTry tryTree = make.Try(tryBlock, catchClauses, null); + tryTree.finallyCanCompleteNormally = true; // if (primaryException != null) {try...} else resourceClose; JCIf closeIfStatement = make.If(makeNonNullCheck(make.Ident(primaryException)), @@ -2017,7 +2027,7 @@ public class Lower extends TreeTranslator { // catchParam := ClassNotFoundException e1 VarSymbol catchParam = - new VarSymbol(0, make.paramName(1), + new VarSymbol(SYNTHETIC, make.paramName(1), syms.classNotFoundExceptionType, classDollarSym); @@ -2705,7 +2715,7 @@ public class Lower extends TreeTranslator { JCVariableDecl otdef = null; if (currentClass.hasOuterInstance()) otdef = outerThisDef(tree.pos, m); - List fvdefs = freevarDefs(tree.pos, fvs, m); + List fvdefs = freevarDefs(tree.pos, fvs, m, PARAMETER); // Recursively translate result type, parameters and thrown list. tree.restype = translate(tree.restype); @@ -3364,18 +3374,18 @@ public class Lower extends TreeTranslator { */ private void visitArrayForeachLoop(JCEnhancedForLoop tree) { make_at(tree.expr.pos()); - VarSymbol arraycache = new VarSymbol(0, + VarSymbol arraycache = new VarSymbol(SYNTHETIC, names.fromString("arr" + target.syntheticNameChar()), tree.expr.type, currentMethodSym); JCStatement arraycachedef = make.VarDef(arraycache, tree.expr); - VarSymbol lencache = new VarSymbol(0, + VarSymbol lencache = new VarSymbol(SYNTHETIC, names.fromString("len" + target.syntheticNameChar()), syms.intType, currentMethodSym); JCStatement lencachedef = make. VarDef(lencache, make.Select(make.Ident(arraycache), syms.lengthVar)); - VarSymbol index = new VarSymbol(0, + VarSymbol index = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()), syms.intType, currentMethodSym); @@ -3457,7 +3467,7 @@ public class Lower extends TreeTranslator { names.iterator, eType, List.nil()); - VarSymbol itvar = new VarSymbol(0, names.fromString("i" + target.syntheticNameChar()), + VarSymbol itvar = new VarSymbol(SYNTHETIC, names.fromString("i" + target.syntheticNameChar()), types.erasure(types.asSuper(iterator.type.getReturnType(), syms.iteratorType.tsym)), currentMethodSym); @@ -3715,7 +3725,7 @@ public class Lower extends TreeTranslator { (JCVariableDecl)make.VarDef(dollar_tmp, make.Literal(INT, -1)).setType(dollar_tmp.type); dollar_tmp_def.init.type = dollar_tmp.type = syms.intType; stmtList.append(dollar_tmp_def); - ListBuffer caseBuffer = ListBuffer.lb(); + ListBuffer caseBuffer = new ListBuffer<>(); // hashCode will trigger nullcheck on original switch expression JCMethodInvocation hashCodeCall = makeCall(make.Ident(dollar_s), names.hashCode, @@ -3739,7 +3749,7 @@ public class Lower extends TreeTranslator { elsepart); } - ListBuffer lb = ListBuffer.lb(); + ListBuffer lb = new ListBuffer<>(); JCBreak breakStmt = make.Break(null); breakStmt.target = switch1; lb.append(elsepart).append(breakStmt); @@ -3754,7 +3764,7 @@ public class Lower extends TreeTranslator { // with corresponding integer ones from the label to // position map. - ListBuffer lb = ListBuffer.lb(); + ListBuffer lb = new ListBuffer<>(); JCSwitch switch2 = make.Switch(make.Ident(dollar_tmp), lb.toList()); for(JCCase oneCase : caseList ) { // Rewire up old unlabeled break statements to the @@ -3830,19 +3840,32 @@ public class Lower extends TreeTranslator { @Override public void visitTry(JCTry tree) { - /* special case of try without catchers and with finally emtpy. - * Don't give it a try, translate only the body. - */ - if (tree.resources.isEmpty()) { - if (tree.catchers.isEmpty() && - tree.finalizer.getStatements().isEmpty()) { - result = translate(tree.body); - } else { - super.visitTry(tree); - } - } else { + if (tree.resources.nonEmpty()) { result = makeTwrTry(tree); + return; } + + boolean hasBody = tree.body.getStatements().nonEmpty(); + boolean hasCatchers = tree.catchers.nonEmpty(); + boolean hasFinally = tree.finalizer != null && + tree.finalizer.getStatements().nonEmpty(); + + if (!hasCatchers && !hasFinally) { + result = translate(tree.body); + return; + } + + if (!hasBody) { + if (hasFinally) { + result = translate(tree.finalizer); + } else { + result = translate(tree.body); + } + return; + } + + // no optimizations possible + super.visitTry(tree); } /************************************************************************** diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java index 9f9dd4fb874..fbb8c326889 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/MemberEnter.java @@ -79,11 +79,13 @@ public class MemberEnter extends JCTree.Visitor implements Completer { private final ClassReader reader; private final Todo todo; private final Annotate annotate; + private final TypeAnnotations typeAnnotations; private final Types types; private final JCDiagnostic.Factory diags; private final Source source; private final Target target; private final DeferredLintHandler deferredLintHandler; + private final Lint lint; public static MemberEnter instance(Context context) { MemberEnter instance = context.get(memberEnterKey); @@ -104,11 +106,13 @@ public class MemberEnter extends JCTree.Visitor implements Completer { reader = ClassReader.instance(context); todo = Todo.instance(context); annotate = Annotate.instance(context); + typeAnnotations = TypeAnnotations.instance(context); types = Types.instance(context); diags = JCDiagnostic.Factory.instance(context); source = Source.instance(context); target = Target.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); + lint = Lint.instance(context); allowTypeAnnos = source.allowTypeAnnotations(); } @@ -506,9 +510,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } // process package annotations - annotateLater(tree.packageAnnotations, env, tree.packge); + annotateLater(tree.packageAnnotations, env, tree.packge, null); - DeferredLintHandler prevLintHandler = chk.setDeferredLintHandler(DeferredLintHandler.immediateHandler); + DiagnosticPosition prevLintPos = deferredLintHandler.immediate(); + Lint prevLint = chk.setLint(lint); try { // Import-on-demand java.lang. @@ -517,7 +522,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { // Process all import clauses. memberEnter(tree.defs, env); } finally { - chk.setDeferredLintHandler(prevLintHandler); + chk.setLint(prevLint); + deferredLintHandler.setPos(prevLintPos); } } @@ -564,8 +570,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { Env localEnv = methodEnv(tree, env); - DeferredLintHandler prevLintHandler = - chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos())); + DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); try { // Compute the method type m.type = signature(m, tree.typarams, tree.params, @@ -573,7 +578,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { tree.thrown, localEnv); } finally { - chk.setDeferredLintHandler(prevLintHandler); + deferredLintHandler.setPos(prevLintPos); } if (types.isSignaturePolymorphic(m)) { @@ -597,10 +602,10 @@ public class MemberEnter extends JCTree.Visitor implements Completer { if (chk.checkUnique(tree.pos(), m, enclScope)) { enclScope.enter(m); } - annotateLater(tree.mods.annotations, localEnv, m); + annotateLater(tree.mods.annotations, localEnv, m, tree.pos()); // Visit the signature of the method. Note that // TypeAnnotate doesn't descend into the body. - typeAnnotate(tree, localEnv, m); + typeAnnotate(tree, localEnv, m, tree.pos()); if (tree.defaultValue != null) annotateDefaultValueLater(tree.defaultValue, localEnv, m); @@ -630,15 +635,14 @@ public class MemberEnter extends JCTree.Visitor implements Completer { localEnv = env.dup(tree, env.info.dup()); localEnv.info.staticLevel++; } - DeferredLintHandler prevLintHandler = - chk.setDeferredLintHandler(deferredLintHandler.setPos(tree.pos())); + DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); try { if (TreeInfo.isEnumInit(tree)) { attr.attribIdentAsEnumType(localEnv, (JCIdent)tree.vartype); } else { // Make sure type annotations are processed. // But we don't have a symbol to attach them to yet - use null. - typeAnnotate(tree.vartype, env, null); + typeAnnotate(tree.vartype, env, null, tree.pos()); attr.attribType(tree.vartype, localEnv); if (tree.nameexpr != null) { attr.attribExpr(tree.nameexpr, localEnv); @@ -658,7 +662,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } } finally { - chk.setDeferredLintHandler(prevLintHandler); + deferredLintHandler.setPos(prevLintPos); } if ((tree.mods.flags & VARARGS) != 0) { @@ -680,15 +684,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer { needsLazyConstValue(tree.init)) { Env initEnv = getInitEnv(tree, env); initEnv.info.enclVar = v; - v.setLazyConstValue(initEnv(tree, initEnv), attr, tree.init); + v.setLazyConstValue(initEnv(tree, initEnv), attr, tree); } } if (chk.checkUnique(tree.pos(), v, enclScope)) { chk.checkTransparentVar(tree.pos(), v, enclScope); enclScope.enter(v); } - annotateLater(tree.mods.annotations, localEnv, v); - typeAnnotate(tree.vartype, env, v); + annotateLater(tree.mods.annotations, localEnv, v, tree.pos()); + typeAnnotate(tree.vartype, env, v, tree.pos()); annotate.flush(); v.pos = tree.pos; } @@ -719,6 +723,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer { result = false; } + @Override + public void visitNewArray(JCNewArray that) { + result = false; + } + @Override public void visitLambda(JCLambda that) { result = false; @@ -729,6 +738,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer { result = false; } + @Override + public void visitApply(JCMethodInvocation that) { + result = false; + } + @Override public void visitSelect(JCFieldAccess tree) { tree.selected.accept(this); @@ -820,7 +834,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { /** Queue annotations for later processing. */ void annotateLater(final List annotations, final Env localEnv, - final Symbol s) { + final Symbol s, + final DiagnosticPosition deferPos) { if (annotations.isEmpty()) { return; } @@ -837,6 +852,11 @@ public class MemberEnter extends JCTree.Visitor implements Completer { public void enterAnnotation() { Assert.check(s.kind == PCK || s.annotationsPendingCompletion()); JavaFileObject prev = log.useSource(localEnv.toplevel.sourcefile); + DiagnosticPosition prevLintPos = + deferPos != null + ? deferredLintHandler.setPos(deferPos) + : deferredLintHandler.immediate(); + Lint prevLint = deferPos != null ? null : chk.setLint(lint); try { if (s.hasAnnotations() && annotations.nonEmpty()) @@ -845,6 +865,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer { kindName(s), s); actualEnterAnnotations(annotations, localEnv, s); } finally { + if (prevLint != null) + chk.setLint(prevLint); + deferredLintHandler.setPos(prevLintPos); log.useSource(prev); } } @@ -964,6 +987,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { isFirst = false; JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + DiagnosticPosition prevLintPos = deferredLintHandler.setPos(tree.pos()); try { // Save class environment for later member enter (2) processing. halfcompleted.append(env); @@ -985,9 +1009,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer { Env baseEnv = baseEnv(tree, env); if (tree.extending != null) - typeAnnotate(tree.extending, baseEnv, sym); + typeAnnotate(tree.extending, baseEnv, sym, tree.pos()); for (JCExpression impl : tree.implementing) - typeAnnotate(impl, baseEnv, sym); + typeAnnotate(impl, baseEnv, sym, tree.pos()); annotate.flush(); // Determine supertype. @@ -1048,7 +1072,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { attr.attribAnnotationTypes(tree.mods.annotations, baseEnv); if (hasDeprecatedAnnotation(tree.mods.annotations)) c.flags_field |= DEPRECATED; - annotateLater(tree.mods.annotations, baseEnv, c); + annotateLater(tree.mods.annotations, baseEnv, c, tree.pos()); // class type parameters use baseEnv but everything uses env chk.checkNonCyclicDecl(tree); @@ -1056,7 +1080,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { attr.attribTypeVariables(tree.typarams, baseEnv); // Do this here, where we have the symbol. for (JCTypeParameter tp : tree.typarams) - typeAnnotate(tp, baseEnv, sym); + typeAnnotate(tp, baseEnv, sym, tree.pos()); annotate.flush(); // Add default constructor if needed. @@ -1126,6 +1150,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } catch (CompletionFailure ex) { chk.completionError(tree.pos(), ex); } finally { + deferredLintHandler.setPos(prevLintPos); log.useSource(prev); } @@ -1141,7 +1166,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } if (allowTypeAnnos) { - TypeAnnotations.organizeTypeAnnotationsSignatures(syms, names, log, env, tree, annotate); + typeAnnotations.organizeTypeAnnotationsSignatures(env, tree); } } @@ -1186,9 +1211,9 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } - public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym) { + public void typeAnnotate(final JCTree tree, final Env env, final Symbol sym, DiagnosticPosition deferPos) { if (allowTypeAnnos) { - tree.accept(new TypeAnnotate(env, sym)); + tree.accept(new TypeAnnotate(env, sym, deferPos)); } } @@ -1199,10 +1224,12 @@ public class MemberEnter extends JCTree.Visitor implements Completer { private class TypeAnnotate extends TreeScanner { private Env env; private Symbol sym; + private DiagnosticPosition deferPos; - public TypeAnnotate(final Env env, final Symbol sym) { + public TypeAnnotate(final Env env, final Symbol sym, DiagnosticPosition deferPos) { this.env = env; this.sym = sym; + this.deferPos = deferPos; } void annotateTypeLater(final List annotations) { @@ -1210,6 +1237,8 @@ public class MemberEnter extends JCTree.Visitor implements Completer { return; } + final DiagnosticPosition deferPos = this.deferPos; + annotate.normal(new Annotate.Annotator() { @Override public String toString() { @@ -1218,9 +1247,16 @@ public class MemberEnter extends JCTree.Visitor implements Completer { @Override public void enterAnnotation() { JavaFileObject prev = log.useSource(env.toplevel.sourcefile); + DiagnosticPosition prevLintPos = null; + + if (deferPos != null) { + prevLintPos = deferredLintHandler.setPos(deferPos); + } try { actualEnterTypeAnnotations(annotations, env, sym); } finally { + if (prevLintPos != null) + deferredLintHandler.setPos(prevLintPos); log.useSource(prev); } } @@ -1262,13 +1298,19 @@ public class MemberEnter extends JCTree.Visitor implements Completer { @Override public void visitVarDef(final JCVariableDecl tree) { - if (sym != null && sym.kind == Kinds.VAR) { - // Don't visit a parameter once when the sym is the method - // and once when the sym is the parameter. - scan(tree.mods); - scan(tree.vartype); + DiagnosticPosition prevPos = deferPos; + deferPos = tree.pos(); + try { + if (sym != null && sym.kind == Kinds.VAR) { + // Don't visit a parameter once when the sym is the method + // and once when the sym is the parameter. + scan(tree.mods); + scan(tree.vartype); + } + scan(tree.init); + } finally { + deferPos = prevPos; } - scan(tree.init); } @Override @@ -1532,7 +1574,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { * parameters from baseInit. */ initParams = List.nil(); - VarSymbol param = new VarSymbol(0, make.paramName(0), argtypes.head, init); + VarSymbol param = new VarSymbol(PARAMETER, make.paramName(0), argtypes.head, init); initParams = initParams.append(param); argTypesList = argTypesList.tail; } @@ -1541,7 +1583,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { initParams = (initParams == null) ? List.nil() : initParams; List baseInitParams = baseInit.params; while (baseInitParams.nonEmpty() && argTypesList.nonEmpty()) { - VarSymbol param = new VarSymbol(baseInitParams.head.flags(), + VarSymbol param = new VarSymbol(baseInitParams.head.flags() | PARAMETER, baseInitParams.head.name, argTypesList.head, init); initParams = initParams.append(param); baseInitParams = baseInitParams.tail; diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java index 0439e0d6132..87eb36668f4 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -213,7 +213,7 @@ public class Resolve { int pos = 0; int mostSpecificPos = -1; - ListBuffer subDiags = ListBuffer.lb(); + ListBuffer subDiags = new ListBuffer<>(); for (Candidate c : currentResolutionContext.candidates) { if (currentResolutionContext.step != c.step || (c.isApplicable() && !verboseResolutionMode.contains(VerboseResolutionMode.APPLICABLE)) || @@ -568,8 +568,10 @@ public class Resolve { currentResolutionContext, warn); - currentResolutionContext.methodCheck.argumentsAcceptable(env, currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn), + DeferredAttr.DeferredAttrContext dc = currentResolutionContext.deferredAttrContext(m, infer.emptyContext, resultInfo, warn); + currentResolutionContext.methodCheck.argumentsAcceptable(env, dc, argtypes, mt.getParameterTypes(), warn); + dc.complete(); return mt; } @@ -781,7 +783,7 @@ public class Resolve { }; List dummyArgs(int length) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (int i = 0 ; i < length ; i++) { buf.append(Type.noType); } @@ -1053,7 +1055,8 @@ public class Resolve { DeferredType dt = (DeferredType) actual; DeferredType.SpeculativeCache.Entry e = dt.speculativeCache.get(deferredAttrContext.msym, deferredAttrContext.phase); return (e == null || e.speculativeTree == deferredAttr.stuckTree) - ? false : mostSpecific(found, req, e.speculativeTree, warn); + ? super.compatible(found, req, warn) : + mostSpecific(found, req, e.speculativeTree, warn); default: return standaloneMostSpecific(found, req, actual, warn); } @@ -1125,13 +1128,15 @@ public class Resolve { @Override public void visitReference(JCMemberReference tree) { if (types.isFunctionalInterface(t.tsym) && - types.isFunctionalInterface(s.tsym) && - types.asSuper(t, s.tsym) == null && - types.asSuper(s, t.tsym) == null) { + types.isFunctionalInterface(s.tsym)) { Type desc_t = types.findDescriptorType(t); Type desc_s = types.findDescriptorType(s); - if (types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { - if (!desc_s.getReturnType().hasTag(VOID)) { + if (types.isSameTypes(desc_t.getParameterTypes(), + inferenceContext().asFree(desc_s.getParameterTypes()))) { + if (types.asSuper(t, s.tsym) != null || + types.asSuper(s, t.tsym) != null) { + result &= MostSpecificCheckContext.super.compatible(t, s, warn); + } else if (!desc_s.getReturnType().hasTag(VOID)) { //perform structural comparison Type ret_t = desc_t.getReturnType(); Type ret_s = desc_s.getReturnType(); @@ -1141,25 +1146,24 @@ public class Resolve { } else { return; } - } else { - result &= false; } } else { - result &= MostSpecificCheckContext.super.compatible(t, s, warn); + result &= false; } } @Override public void visitLambda(JCLambda tree) { if (types.isFunctionalInterface(t.tsym) && - types.isFunctionalInterface(s.tsym) && - types.asSuper(t, s.tsym) == null && - types.asSuper(s, t.tsym) == null) { + types.isFunctionalInterface(s.tsym)) { Type desc_t = types.findDescriptorType(t); Type desc_s = types.findDescriptorType(s); - if (tree.paramKind == JCLambda.ParameterKind.EXPLICIT - || types.isSameTypes(desc_t.getParameterTypes(), desc_s.getParameterTypes())) { - if (!desc_s.getReturnType().hasTag(VOID)) { + if (types.isSameTypes(desc_t.getParameterTypes(), + inferenceContext().asFree(desc_s.getParameterTypes()))) { + if (types.asSuper(t, s.tsym) != null || + types.asSuper(s, t.tsym) != null) { + result &= MostSpecificCheckContext.super.compatible(t, s, warn); + } else if (!desc_s.getReturnType().hasTag(VOID)) { //perform structural comparison Type ret_t = desc_t.getReturnType(); Type ret_s = desc_s.getReturnType(); @@ -1167,11 +1171,9 @@ public class Resolve { } else { return; } - } else { - result &= false; } } else { - result &= MostSpecificCheckContext.super.compatible(t, s, warn); + result &= false; } } //where @@ -1521,7 +1523,8 @@ public class Resolve { currentResolutionContext = prevResolutionContext; } } - private List adjustArgs(List args, Symbol msym, int length, boolean allowVarargs) { + + List adjustArgs(List args, Symbol msym, int length, boolean allowVarargs) { if ((msym.flags() & VARARGS) != 0 && allowVarargs) { Type varargsElem = types.elemtype(args.last()); if (varargsElem == null) { @@ -2241,33 +2244,33 @@ public class Resolve { public List getArgumentTypes(ResolveError errSym, Symbol accessedSym, Name name, List argtypes) { return (syms.operatorNames.contains(name)) ? argtypes : - Type.map(argtypes, new ResolveDeferredRecoveryMap(accessedSym)); - } - - class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap { - - public ResolveDeferredRecoveryMap(Symbol msym) { - deferredAttr.super(AttrMode.SPECULATIVE, msym, currentResolutionContext.step); - } - - @Override - protected Type typeOf(DeferredType dt) { - Type res = super.typeOf(dt); - if (!res.isErroneous()) { - switch (TreeInfo.skipParens(dt.tree).getTag()) { - case LAMBDA: - case REFERENCE: - return dt; - case CONDEXPR: - return res == Type.recoveryType ? - dt : res; - } - } - return res; - } + Type.map(argtypes, new ResolveDeferredRecoveryMap(AttrMode.SPECULATIVE, accessedSym, currentResolutionContext.step)); } }; + class ResolveDeferredRecoveryMap extends DeferredAttr.RecoveryDeferredTypeMap { + + public ResolveDeferredRecoveryMap(AttrMode mode, Symbol msym, MethodResolutionPhase step) { + deferredAttr.super(mode, msym, step); + } + + @Override + protected Type typeOf(DeferredType dt) { + Type res = super.typeOf(dt); + if (!res.isErroneous()) { + switch (TreeInfo.skipParens(dt.tree).getTag()) { + case LAMBDA: + case REFERENCE: + return dt; + case CONDEXPR: + return res == Type.recoveryType ? + dt : res; + } + } + return res; + } + } + /** Check that sym is not an abstract method. */ void checkNonAbstract(DiagnosticPosition pos, Symbol sym) { @@ -2543,22 +2546,26 @@ public class Resolve { @Override Symbol access(Env env, DiagnosticPosition pos, Symbol location, Symbol sym) { if (sym.kind >= AMBIGUOUS) { - final JCDiagnostic details = sym.kind == WRONG_MTH ? - ((InapplicableSymbolError)sym).errCandidate().snd : - null; - sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) { - @Override - JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, - Symbol location, Type site, Name name, List argtypes, List typeargtypes) { - String key = details == null ? - "cant.apply.diamond" : - "cant.apply.diamond.1"; - return diags.create(dkind, log.currentSource(), pos, key, - diags.fragment("diamond", site.tsym), details); - } - }; - sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); - env.info.pendingResolutionPhase = currentResolutionContext.step; + if (sym.kind != WRONG_MTH && sym.kind != WRONG_MTHS) { + sym = super.access(env, pos, location, sym); + } else { + final JCDiagnostic details = sym.kind == WRONG_MTH ? + ((InapplicableSymbolError)sym).errCandidate().snd : + null; + sym = new InapplicableSymbolError(sym.kind, "diamondError", currentResolutionContext) { + @Override + JCDiagnostic getDiagnostic(DiagnosticType dkind, DiagnosticPosition pos, + Symbol location, Type site, Name name, List argtypes, List typeargtypes) { + String key = details == null ? + "cant.apply.diamond" : + "cant.apply.diamond.1"; + return diags.create(dkind, log.currentSource(), pos, key, + diags.fragment("diamond", site.tsym), details); + } + }; + sym = accessMethod(sym, pos, site, names.init, true, argtypes, typeargtypes); + env.info.pendingResolutionPhase = currentResolutionContext.step; + } } return sym; }}); @@ -3166,7 +3173,7 @@ public class Resolve { } //where private List pruneInterfaces(Type t) { - ListBuffer result = ListBuffer.lb(); + ListBuffer result = new ListBuffer<>(); for (Type t1 : types.interfaces(t)) { boolean shouldAdd = true; for (Type t2 : types.interfaces(t)) { @@ -3279,7 +3286,7 @@ public class Resolve { if (argtypes == null || argtypes.isEmpty()) { return noArgs; } else { - ListBuffer diagArgs = ListBuffer.lb(); + ListBuffer diagArgs = new ListBuffer<>(); for (Type t : argtypes) { if (t.hasTag(DEFERRED)) { diagArgs.append(((DeferredAttr.DeferredType)t).tree); @@ -3969,16 +3976,6 @@ public class Resolve { static { String argMismatchRegex = MethodCheckDiag.ARG_MISMATCH.regex(); - rewriters.put(new Template(argMismatchRegex, new Template("(.*)(bad.arg.types.in.lambda)", skip, skip)), - new DiagnosticRewriter() { - @Override - public JCDiagnostic rewriteDiagnostic(JCDiagnostic.Factory diags, - DiagnosticPosition preferedPos, DiagnosticSource preferredSource, - DiagnosticType preferredKind, JCDiagnostic d) { - return (JCDiagnostic)((JCDiagnostic)d.getArgs()[0]).getArgs()[1]; - } - }); - rewriters.put(new Template(argMismatchRegex, skip), new DiagnosticRewriter() { @Override diff --git a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java index 47cc589e967..48bd03c7a66 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/comp/TransTypes.java @@ -310,7 +310,7 @@ public class TransTypes extends TreeTranslator { Type.MethodType mType = (Type.MethodType)bridgeType; List argTypes = mType.argtypes; while (implParams.nonEmpty() && argTypes.nonEmpty()) { - VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC, + VarSymbol param = new VarSymbol(implParams.head.flags() | SYNTHETIC | PARAMETER, implParams.head.name, argTypes.head, bridge); param.setAttributes(implParams.head); bridgeParams = bridgeParams.append(param); @@ -833,7 +833,7 @@ public class TransTypes extends TreeTranslator { } public void visitReference(JCMemberReference tree) { - tree.expr = translate(tree.expr, null); + tree.expr = translate(tree.expr, erasure(tree.expr.type)); tree.type = erasure(tree.type); result = tree; } @@ -887,7 +887,7 @@ public class TransTypes extends TreeTranslator { private List addOverrideBridgesIfNeeded(DiagnosticPosition pos, final ClassSymbol c) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); if (c.isInterface() || !boundsRestricted(c)) return buf.toList(); Type t = types.supertype(c.type); diff --git a/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java b/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java index d99d729ac2c..055977f172e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java +++ b/langtools/src/share/classes/com/sun/tools/javac/file/RegularFileObject.java @@ -40,6 +40,7 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.nio.charset.CharsetDecoder; import javax.tools.JavaFileObject; +import java.text.Normalizer; /** * A subclass of JavaFileObject representing regular files. @@ -57,6 +58,7 @@ class RegularFileObject extends BaseFileObject { private String name; final File file; private Reference absFileRef; + final static boolean isMacOS = System.getProperty("os.name", "").contains("OS X"); public RegularFileObject(JavacFileManager fileManager, File f) { this(fileManager, f.getName(), f); @@ -180,7 +182,19 @@ class RegularFileObject extends BaseFileObject { if (name.equals(n)) { return true; } - if (name.equalsIgnoreCase(n)) { + if (isMacOS && Normalizer.isNormalized(name, Normalizer.Form.NFD) + && Normalizer.isNormalized(n, Normalizer.Form.NFC)) { + // On Mac OS X it is quite possible to file name and class + // name normalized in a different way - in that case we have to normalize file name + // to the Normal Form Compised (NFC) + String normName = Normalizer.normalize(name, Normalizer.Form.NFC); + if (normName.equals(n)) { + this.name = normName; + return true; + } + } + + if (name.equalsIgnoreCase(n)) { try { // allow for Windows return file.getCanonicalFile().getName().equals(n); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java index 1717e50194f..397069589ff 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassReader.java @@ -56,6 +56,7 @@ import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import static com.sun.tools.javac.code.Flags.*; import static com.sun.tools.javac.code.Kinds.*; import static com.sun.tools.javac.code.TypeTag.CLASS; +import static com.sun.tools.javac.code.TypeTag.TYPEVAR; import static com.sun.tools.javac.jvm.ClassFile.*; import static com.sun.tools.javac.jvm.ClassFile.Version.*; @@ -72,7 +73,7 @@ import static com.sun.tools.javac.main.Option.*; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class ClassReader implements Completer { +public class ClassReader { /** The context key for the class reader. */ protected static final Context.Key classReaderKey = new Context.Key(); @@ -234,6 +235,17 @@ public class ClassReader implements Completer { */ Set warnedAttrs = new HashSet(); + /** + * Completer that delegates to the complete-method of this class. + */ + private final Completer thisCompleter = new Completer() { + @Override + public void complete(Symbol sym) throws CompletionFailure { + ClassReader.this.complete(sym); + } + }; + + /** Get the ClassReader instance for this invocation. */ public static ClassReader instance(Context context) { ClassReader instance = context.get(classReaderKey); @@ -264,8 +276,8 @@ public class ClassReader implements Completer { } packages.put(names.empty, syms.rootPackage); - syms.rootPackage.completer = this; - syms.unnamedPackage.completer = this; + syms.rootPackage.completer = thisCompleter; + syms.unnamedPackage.completer = thisCompleter; } /** Construct a new class reader, optionally treated as the @@ -692,6 +704,12 @@ public class ClassReader implements Completer { sigp++; thrown = thrown.prepend(sigToType()); } + // if there is a typevar in the throws clause we should state it. + for (List l = thrown; l.nonEmpty(); l = l.tail) { + if (l.head.hasTag(TYPEVAR)) { + l.head.tsym.flags_field |= THROWS; + } + } return new MethodType(argtypes, restype, thrown.reverse(), @@ -727,12 +745,14 @@ public class ClassReader implements Completer { ClassSymbol t = enterClass(names.fromUtf(signatureBuffer, startSbp, sbp - startSbp)); - if (outer == Type.noType) - outer = t.erasure(types); - else - outer = new ClassType(outer, List.nil(), t); - sbp = startSbp; - return outer; + + try { + return (outer == Type.noType) ? + t.erasure(types) : + new ClassType(outer, List.nil(), t); + } finally { + sbp = startSbp; + } } case '<': // generic arguments @@ -797,6 +817,13 @@ public class ClassReader implements Completer { continue; case '.': + //we have seen an enclosing non-generic class + if (outer != Type.noType) { + t = enterClass(names.fromUtf(signatureBuffer, + startSbp, + sbp - startSbp)); + outer = new ClassType(outer, List.nil(), t); + } signatureBuffer[sbp++] = (byte)'$'; continue; case '/': @@ -1419,8 +1446,7 @@ public class ClassReader implements Completer { void attachTypeAnnotations(final Symbol sym) { int numAttributes = nextChar(); if (numAttributes != 0) { - ListBuffer proxies = - ListBuffer.lb(); + ListBuffer proxies = new ListBuffer<>(); for (int i = 0; i < numAttributes; i++) proxies.append(readTypeAnnotation()); annotate.normal(new TypeAnnotationCompleter(sym, proxies.toList())); @@ -1569,7 +1595,7 @@ public class ClassReader implements Completer { { // See whether there is location info and read it int len = nextByte(); - ListBuffer loc = ListBuffer.lb(); + ListBuffer loc = new ListBuffer<>(); for (int i = 0; i < len * TypeAnnotationPosition.TypePathEntry.bytesPerEntry; ++i) loc = loc.append(nextByte()); position.location = TypeAnnotationPosition.getTypePathFromBinary(loc.toList()); @@ -1919,7 +1945,7 @@ public class ClassReader implements Completer { } List deproxyTypeCompoundList(List proxies) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (TypeAnnotationProxy proxy: proxies) { Attribute.Compound compound = deproxyCompound(proxy.compound); Attribute.TypeCompound typeCompound = new Attribute.TypeCompound(compound, proxy.position); @@ -2006,7 +2032,7 @@ public class ClassReader implements Completer { boolean isVarargs = (flags & VARARGS) != 0; if (isVarargs) { Type varargsElem = args.last(); - ListBuffer adjustedArgs = ListBuffer.lb(); + ListBuffer adjustedArgs = new ListBuffer<>(); for (Type t : args) { adjustedArgs.append(t != varargsElem ? t : @@ -2310,7 +2336,7 @@ public class ClassReader implements Completer { ClassSymbol c = new ClassSymbol(0, name, owner); if (owner.kind == PCK) Assert.checkNull(classes.get(c.flatname), c); - c.completer = this; + c.completer = thisCompleter; return c; } @@ -2380,7 +2406,7 @@ public class ClassReader implements Completer { /** Completion for classes to be loaded. Before a class is loaded * we make sure its enclosing class (if any) is loaded. */ - public void complete(Symbol sym) throws CompletionFailure { + private void complete(Symbol sym) throws CompletionFailure { if (sym.kind == TYP) { ClassSymbol c = (ClassSymbol)sym; c.members_field = new Scope.ErrorScope(c); // make sure it's always defined @@ -2601,7 +2627,7 @@ public class ClassReader implements Completer { p = new PackageSymbol( Convert.shortName(fullname), enterPackage(Convert.packagePart(fullname))); - p.completer = this; + p.completer = thisCompleter; packages.put(fullname, p); } return p; diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java index 73eb2d34acf..54122430380 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/ClassWriter.java @@ -37,7 +37,6 @@ import javax.tools.JavaFileObject; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Attribute.RetentionPolicy; -import com.sun.tools.javac.code.Attribute.TypeCompound; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Type.*; import com.sun.tools.javac.code.Types.UniqueType; @@ -55,7 +54,6 @@ import static com.sun.tools.javac.jvm.UninitializedType.*; import static com.sun.tools.javac.main.Option.*; import static javax.tools.StandardLocation.CLASS_OUTPUT; - /** This class provides operations to map an internal symbol table graph * rooted in a ClassSymbol into a classfile. * @@ -768,8 +766,8 @@ public class ClassWriter extends ClassFile { int writeTypeAnnotations(List typeAnnos, boolean inCode) { if (typeAnnos.isEmpty()) return 0; - ListBuffer visibles = ListBuffer.lb(); - ListBuffer invisibles = ListBuffer.lb(); + ListBuffer visibles = new ListBuffer<>(); + ListBuffer invisibles = new ListBuffer<>(); for (Attribute.TypeCompound tc : typeAnnos) { if (tc.hasUnknownPosition()) { @@ -1180,25 +1178,26 @@ public class ClassWriter extends ClassFile { if (code.varBufferSize > 0) { int alenIdx = writeAttr(names.LocalVariableTable); - databuf.appendChar(code.varBufferSize); - + databuf.appendChar(code.getLVTSize()); for (int i=0; i= 0 - && var.start_pc <= code.cp); - databuf.appendChar(var.start_pc); - Assert.check(var.length >= 0 - && (var.start_pc + var.length) <= code.cp); - databuf.appendChar(var.length); - VarSymbol sym = var.sym; - databuf.appendChar(pool.put(sym.name)); - Type vartype = sym.erasure(types); - if (needsLocalVariableTypeEntry(sym.type)) - nGenericVars++; - databuf.appendChar(pool.put(typeSig(vartype))); - databuf.appendChar(var.reg); + for (Code.LocalVar.Range r: var.aliveRanges) { + // write variable info + Assert.check(r.start_pc >= 0 + && r.start_pc <= code.cp); + databuf.appendChar(r.start_pc); + Assert.check(r.length >= 0 + && (r.start_pc + r.length) <= code.cp); + databuf.appendChar(r.length); + VarSymbol sym = var.sym; + databuf.appendChar(pool.put(sym.name)); + Type vartype = sym.erasure(types); + databuf.appendChar(pool.put(typeSig(vartype))); + databuf.appendChar(var.reg); + if (needsLocalVariableTypeEntry(var.sym.type)) + nGenericVars++; + } } endAttr(alenIdx); acount++; @@ -1214,13 +1213,15 @@ public class ClassWriter extends ClassFile { VarSymbol sym = var.sym; if (!needsLocalVariableTypeEntry(sym.type)) continue; - count++; - // write variable info - databuf.appendChar(var.start_pc); - databuf.appendChar(var.length); - databuf.appendChar(pool.put(sym.name)); - databuf.appendChar(pool.put(typeSig(sym.type))); - databuf.appendChar(var.reg); + for (Code.LocalVar.Range r : var.aliveRanges) { + // write variable info + databuf.appendChar(r.start_pc); + databuf.appendChar(r.length); + databuf.appendChar(pool.put(sym.name)); + databuf.appendChar(pool.put(typeSig(sym.type))); + databuf.appendChar(var.reg); + count++; + } } Assert.check(count == nGenericVars); endAttr(alenIdx); diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java index d151dd46172..6276a24ad2f 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Code.java @@ -28,6 +28,7 @@ package com.sun.tools.javac.jvm; import com.sun.tools.javac.code.*; import com.sun.tools.javac.code.Symbol.*; import com.sun.tools.javac.code.Types.UniqueType; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.util.*; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; @@ -181,6 +182,8 @@ public class Code { final MethodSymbol meth; + final LVTRanges lvtRanges; + /** Construct a code object, given the settings of the fatcode, * debugging info switches and the CharacterRangeTable. */ @@ -193,7 +196,8 @@ public class Code { CRTable crt, Symtab syms, Types types, - Pool pool) { + Pool pool, + LVTRanges lvtRanges) { this.meth = meth; this.fatcode = fatcode; this.lineMap = lineMap; @@ -215,6 +219,7 @@ public class Code { state = new State(); lvar = new LocalVar[20]; this.pool = pool; + this.lvtRanges = lvtRanges; } @@ -305,9 +310,19 @@ public class Code { /** The current output code pointer. */ - public int curPc() { - if (pendingJumps != null) resolvePending(); - if (pendingStatPos != Position.NOPOS) markStatBegin(); + public int curCP() { + /* + * This method has side-effects because calling it can indirectly provoke + * extra code generation, like goto instructions, depending on the context + * where it's called. + * Use with care or even better avoid using it. + */ + if (pendingJumps != null) { + resolvePending(); + } + if (pendingStatPos != Position.NOPOS) { + markStatBegin(); + } fixedPc = true; return cp; } @@ -1175,7 +1190,7 @@ public class Code { /** Declare an entry point; return current code pointer */ public int entryPoint() { - int pc = curPc(); + int pc = curCP(); alive = true; pendingStackMap = needStackMap; return pc; @@ -1185,7 +1200,7 @@ public class Code { * return current code pointer */ public int entryPoint(State state) { - int pc = curPc(); + int pc = curCP(); alive = true; this.state = state.dup(); Assert.check(state.stacksize <= max_stack); @@ -1198,7 +1213,7 @@ public class Code { * return current code pointer */ public int entryPoint(State state, Type pushed) { - int pc = curPc(); + int pc = curCP(); alive = true; this.state = state.dup(); Assert.check(state.stacksize <= max_stack); @@ -1238,7 +1253,7 @@ public class Code { /** Emit a stack map entry. */ public void emitStackMap() { - int pc = curPc(); + int pc = curCP(); if (!needStackMap) return; @@ -1482,6 +1497,9 @@ public class Code { chain.pc + 3 == target && target == cp && !fixedPc) { // If goto the next instruction, the jump is not needed: // compact the code. + if (varDebugInfo) { + adjustAliveRanges(cp, -3); + } cp = cp - 3; target = target - 3; if (chain.next == null) { @@ -1577,7 +1595,7 @@ public class Code { public void compressCatchTable() { - ListBuffer compressedCatchInfo = ListBuffer.lb(); + ListBuffer compressedCatchInfo = new ListBuffer<>(); List handlerPcs = List.nil(); for (char[] catchEntry : catchInfo) { handlerPcs = handlerPcs.prepend((int)catchEntry[2]); @@ -1781,8 +1799,7 @@ public class Code { sym = sym.clone(sym.owner); sym.type = newtype; LocalVar newlv = lvar[i] = new LocalVar(sym); - // should the following be initialized to cp? - newlv.start_pc = lv.start_pc; + newlv.aliveRanges = lv.aliveRanges; } } } @@ -1870,8 +1887,36 @@ public class Code { static class LocalVar { final VarSymbol sym; final char reg; - char start_pc = Character.MAX_VALUE; - char length = Character.MAX_VALUE; + + class Range { + char start_pc = Character.MAX_VALUE; + char length = Character.MAX_VALUE; + + Range() {} + + Range(char start) { + this.start_pc = start; + } + + Range(char start, char length) { + this.start_pc = start; + this.length = length; + } + + boolean closed() { + return start_pc != Character.MAX_VALUE && length != Character.MAX_VALUE; + } + + @Override + public String toString() { + int currentStartPC = start_pc; + int currentLength = length; + return "startpc = " + currentStartPC + " length " + currentLength; + } + } + + java.util.List aliveRanges = new java.util.ArrayList<>(); + LocalVar(VarSymbol v) { this.sym = v; this.reg = (char)v.adr; @@ -1879,9 +1924,78 @@ public class Code { public LocalVar dup() { return new LocalVar(sym); } - public String toString() { - return "" + sym + " in register " + ((int)reg) + " starts at pc=" + ((int)start_pc) + " length=" + ((int)length); + + Range firstRange() { + return aliveRanges.isEmpty() ? null : aliveRanges.get(0); } + + Range lastRange() { + return aliveRanges.isEmpty() ? null : aliveRanges.get(aliveRanges.size() - 1); + } + + @Override + public String toString() { + if (aliveRanges == null) { + return "empty local var"; + } + StringBuilder sb = new StringBuilder().append(sym) + .append(" in register ").append((int)reg).append(" \n"); + for (Range r : aliveRanges) { + sb.append(" starts at pc=").append(Integer.toString(((int)r.start_pc))) + .append(" length=").append(Integer.toString(((int)r.length))) + .append("\n"); + } + return sb.toString(); + } + + public void openRange(char start) { + if (!hasOpenRange()) { + aliveRanges.add(new Range(start)); + } + } + + public void closeRange(char end) { + if (isLastRangeInitialized()) { + Range range = lastRange(); + if (range != null) { + if (range.length == Character.MAX_VALUE) { + range.length = end; + } + } + } else { + if (!aliveRanges.isEmpty()) { + aliveRanges.remove(aliveRanges.size() - 1); + } + } + } + + public boolean hasOpenRange() { + if (aliveRanges.isEmpty()) { + return false; + } + Range range = lastRange(); + return range.length == Character.MAX_VALUE; + } + + public boolean isLastRangeInitialized() { + if (aliveRanges.isEmpty()) { + return false; + } + Range range = lastRange(); + return range.start_pc != Character.MAX_VALUE; + } + + public Range getWidestRange() { + if (aliveRanges.isEmpty()) { + return new Range(); + } else { + Range firstRange = firstRange(); + Range lastRange = lastRange(); + char length = (char)(lastRange.length + (lastRange.start_pc - firstRange.start_pc)); + return new Range(firstRange.start_pc, length); + } + } + }; /** Local variables, indexed by register. */ @@ -1892,11 +2006,60 @@ public class Code { int adr = v.adr; lvar = ArrayUtils.ensureCapacity(lvar, adr+1); Assert.checkNull(lvar[adr]); - if (pendingJumps != null) resolvePending(); + if (pendingJumps != null) { + resolvePending(); + } lvar[adr] = new LocalVar(v); state.defined.excl(adr); } + + public void closeAliveRanges(JCTree tree) { + closeAliveRanges(tree, cp); + } + + public void closeAliveRanges(JCTree tree, int closingCP) { + List locals = lvtRanges.getVars(meth, tree); + for (LocalVar localVar: lvar) { + for (VarSymbol aliveLocal : locals) { + if (localVar == null) { + return; + } + if (localVar.sym == aliveLocal && localVar.lastRange() != null) { + char length = (char)(closingCP - localVar.lastRange().start_pc); + if (length > 0 && length < Character.MAX_VALUE) { + localVar.closeRange(length); + } + } + } + } + } + + void adjustAliveRanges(int oldCP, int delta) { + for (LocalVar localVar: lvar) { + if (localVar == null) { + return; + } + for (LocalVar.Range range: localVar.aliveRanges) { + if (range.closed() && range.start_pc + range.length >= oldCP) { + range.length += delta; + } + } + } + } + + /** + * Calculates the size of the LocalVariableTable. + */ + public int getLVTSize() { + int result = varBufferSize; + for (int i = 0; i < varBufferSize; i++) { + LocalVar var = varBuffer[i]; + result += var.aliveRanges.size() - 1; + } + return result; + } + /** Set the current variable defined state. */ public void setDefined(Bits newDefined) { if (alive && newDefined != state.defined) { @@ -1922,8 +2085,7 @@ public class Code { } else { state.defined.incl(adr); if (cp < Character.MAX_VALUE) { - if (v.start_pc == Character.MAX_VALUE) - v.start_pc = (char)cp; + v.openRange((char)cp); } } } @@ -1933,15 +2095,15 @@ public class Code { state.defined.excl(adr); if (adr < lvar.length && lvar[adr] != null && - lvar[adr].start_pc != Character.MAX_VALUE) { + lvar[adr].isLastRangeInitialized()) { LocalVar v = lvar[adr]; - char length = (char)(curPc() - v.start_pc); + char length = (char)(curCP() - v.lastRange().start_pc); if (length > 0 && length < Character.MAX_VALUE) { lvar[adr] = v.dup(); - v.length = length; + v.closeRange(length); putVar(v); } else { - v.start_pc = Character.MAX_VALUE; + v.lastRange().start_pc = Character.MAX_VALUE; } } } @@ -1951,10 +2113,10 @@ public class Code { LocalVar v = lvar[adr]; if (v != null) { lvar[adr] = null; - if (v.start_pc != Character.MAX_VALUE) { - char length = (char)(curPc() - v.start_pc); + if (v.isLastRangeInitialized()) { + char length = (char)(curCP() - v.lastRange().start_pc); if (length < Character.MAX_VALUE) { - v.length = length; + v.closeRange(length); putVar(v); fillLocalVarPosition(v); } @@ -1968,8 +2130,9 @@ public class Code { return; for (Attribute.TypeCompound ta : lv.sym.getRawTypeAttributes()) { TypeAnnotationPosition p = ta.position; - p.lvarOffset = new int[] { (int)lv.start_pc }; - p.lvarLength = new int[] { (int)lv.length }; + LocalVar.Range widestRange = lv.getWidestRange(); + p.lvarOffset = new int[] { (int)widestRange.start_pc }; + p.lvarLength = new int[] { (int)widestRange.length }; p.lvarIndex = new int[] { (int)lv.reg }; p.isValidOffset = true; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java index cc438a73510..7e727f23955 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -24,6 +24,7 @@ */ package com.sun.tools.javac.jvm; + import java.util.*; import com.sun.tools.javac.util.*; @@ -95,10 +96,14 @@ public class Gen extends JCTree.Visitor { return instance; } - /* Constant pool, reset by genClass. + /** Constant pool, reset by genClass. */ private Pool pool; + /** LVTRanges info. + */ + private LVTRanges lvtRanges; + protected Gen(Context context) { context.put(genKey, this); @@ -128,6 +133,9 @@ public class Gen extends JCTree.Visitor { options.isUnset(G_CUSTOM) ? options.isSet(G) : options.isSet(G_CUSTOM, "vars"); + if (varDebugInfo) { + lvtRanges = LVTRanges.instance(context); + } genCrt = options.isSet(XJCOV); debugCode = options.isSet("debugcode"); allowInvokedynamic = target.hasInvokedynamic() || options.isSet("invokedynamic"); @@ -423,7 +431,7 @@ public class Gen extends JCTree.Visitor { */ void endFinalizerGap(Env env) { if (env.info.gaps != null && env.info.gaps.length() % 2 == 1) - env.info.gaps.append(code.curPc()); + env.info.gaps.append(code.curCP()); } /** Mark end of all gaps in catch-all ranges for finalizers of environments @@ -743,10 +751,10 @@ public class Gen extends JCTree.Visitor { genStat(tree, env); return; } - int startpc = code.curPc(); + int startpc = code.curCP(); genStat(tree, env); if (tree.hasTag(Tag.BLOCK)) crtFlags |= CRT_BLOCK; - code.crt.put(tree, crtFlags, startpc, code.curPc()); + code.crt.put(tree, crtFlags, startpc, code.curCP()); } /** Derived visitor method: generate code for a statement. @@ -781,9 +789,9 @@ public class Gen extends JCTree.Visitor { if (trees.length() == 1) { // mark one statement with the flags genStat(trees.head, env, crtFlags | CRT_STATEMENT); } else { - int startpc = code.curPc(); + int startpc = code.curCP(); genStats(trees, env); - code.crt.put(trees, crtFlags, startpc, code.curPc()); + code.crt.put(trees, crtFlags, startpc, code.curCP()); } } @@ -806,9 +814,9 @@ public class Gen extends JCTree.Visitor { */ public CondItem genCond(JCTree tree, int crtFlags) { if (!genCrt) return genCond(tree, false); - int startpc = code.curPc(); + int startpc = code.curCP(); CondItem item = genCond(tree, (crtFlags & CRT_FLOW_CONTROLLER) != 0); - code.crt.put(tree, crtFlags, startpc, code.curPc()); + code.crt.put(tree, crtFlags, startpc, code.curCP()); return item; } @@ -971,7 +979,6 @@ public class Gen extends JCTree.Visitor { // definition. Env localEnv = env.dup(tree); localEnv.enclMethod = tree; - // The expected type of every return statement in this method // is the method's return type. this.pt = tree.sym.erasure(types).getReturnType(); @@ -1045,7 +1052,7 @@ public class Gen extends JCTree.Visitor { code.crt.put(tree.body, CRT_BLOCK, startpcCrt, - code.curPc()); + code.curCP()); code.endScopes(0); @@ -1087,10 +1094,12 @@ public class Gen extends JCTree.Visitor { : null, syms, types, - pool); + pool, + varDebugInfo ? lvtRanges : null); items = new Items(pool, code, syms, types); - if (code.debugCode) + if (code.debugCode) { System.err.println(meth + " for body " + tree); + } // If method is not static, create a new local variable address // for `this'. @@ -1111,7 +1120,7 @@ public class Gen extends JCTree.Visitor { } // Get ready to generate code for method body. - int startpcCrt = genCrt ? code.curPc() : 0; + int startpcCrt = genCrt ? code.curCP() : 0; code.entryPoint(); // Suppress initial stackmap @@ -1189,14 +1198,30 @@ public class Gen extends JCTree.Visitor { Chain loopDone = c.jumpFalse(); code.resolve(c.trueJumps); genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); + if (varDebugInfo) { + checkLoopLocalVarRangeEnding(loop, body, + LoopLocalVarRangeEndingPoint.BEFORE_STEPS); + } code.resolve(loopEnv.info.cont); genStats(step, loopEnv); + if (varDebugInfo) { + checkLoopLocalVarRangeEnding(loop, body, + LoopLocalVarRangeEndingPoint.AFTER_STEPS); + } code.resolve(code.branch(goto_), startpc); code.resolve(loopDone); } else { genStat(body, loopEnv, CRT_STATEMENT | CRT_FLOW_TARGET); + if (varDebugInfo) { + checkLoopLocalVarRangeEnding(loop, body, + LoopLocalVarRangeEndingPoint.BEFORE_STEPS); + } code.resolve(loopEnv.info.cont); genStats(step, loopEnv); + if (varDebugInfo) { + checkLoopLocalVarRangeEnding(loop, body, + LoopLocalVarRangeEndingPoint.AFTER_STEPS); + } CondItem c; if (cond != null) { code.statBegin(cond.pos); @@ -1210,6 +1235,44 @@ public class Gen extends JCTree.Visitor { code.resolve(loopEnv.info.exit); } + private enum LoopLocalVarRangeEndingPoint { + BEFORE_STEPS, + AFTER_STEPS, + } + + /** + * Checks whether we have reached an alive range ending point for local + * variables after a loop. + * + * Local variables alive range ending point for loops varies depending + * on the loop type. The range can be closed before or after the code + * for the steps sentences has been generated. + * + * - While loops has no steps so in that case the range is closed just + * after the body of the loop. + * + * - For-like loops may have steps so as long as the steps sentences + * can possibly contain non-synthetic local variables, the alive range + * for local variables must be closed after the steps in this case. + */ + private void checkLoopLocalVarRangeEnding(JCTree loop, JCTree body, + LoopLocalVarRangeEndingPoint endingPoint) { + if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) { + switch (endingPoint) { + case BEFORE_STEPS: + if (!loop.hasTag(FORLOOP)) { + code.closeAliveRanges(body); + } + break; + case AFTER_STEPS: + if (loop.hasTag(FORLOOP)) { + code.closeAliveRanges(body); + } + break; + } + } + } + public void visitForeachLoop(JCEnhancedForLoop tree) { throw new AssertionError(); // should have been removed by Lower. } @@ -1223,7 +1286,7 @@ public class Gen extends JCTree.Visitor { public void visitSwitch(JCSwitch tree) { int limit = code.nextreg; Assert.check(!tree.selector.type.hasTag(CLASS)); - int startpcCrt = genCrt ? code.curPc() : 0; + int startpcCrt = genCrt ? code.curCP() : 0; Item sel = genExpr(tree.selector, syms.intType); List cases = tree.cases; if (cases.isEmpty()) { @@ -1231,13 +1294,13 @@ public class Gen extends JCTree.Visitor { sel.load().drop(); if (genCrt) code.crt.put(TreeInfo.skipParens(tree.selector), - CRT_FLOW_CONTROLLER, startpcCrt, code.curPc()); + CRT_FLOW_CONTROLLER, startpcCrt, code.curCP()); } else { // We are seeing a nonempty switch. sel.load(); if (genCrt) code.crt.put(TreeInfo.skipParens(tree.selector), - CRT_FLOW_CONTROLLER, startpcCrt, code.curPc()); + CRT_FLOW_CONTROLLER, startpcCrt, code.curCP()); Env switchEnv = env.dup(tree, new GenContext()); switchEnv.info.isSwitch = true; @@ -1278,10 +1341,10 @@ public class Gen extends JCTree.Visitor { ? tableswitch : lookupswitch; - int startpc = code.curPc(); // the position of the selector operation + int startpc = code.curCP(); // the position of the selector operation code.emitop0(opcode); code.align(4); - int tableBase = code.curPc(); // the start of the jump table + int tableBase = code.curCP(); // the start of the jump table int[] offsets = null; // a table of offsets for a lookupswitch code.emit4(-1); // leave space for default offset if (opcode == tableswitch) { @@ -1323,6 +1386,9 @@ public class Gen extends JCTree.Visitor { // Generate code for the statements in this case. genStats(c.stats, switchEnv, CRT_FLOW_TARGET); + if (varDebugInfo && lvtRanges.containsKey(code.meth, c.stats.last())) { + code.closeAliveRanges(c.stats.last()); + } } // Resolve all breaks. @@ -1402,7 +1468,7 @@ public class Gen extends JCTree.Visitor { void gen() { genLast(); Assert.check(syncEnv.info.gaps.length() % 2 == 0); - syncEnv.info.gaps.append(code.curPc()); + syncEnv.info.gaps.append(code.curCP()); } void genLast() { if (code.isAlive()) { @@ -1441,10 +1507,10 @@ public class Gen extends JCTree.Visitor { jsrState); } Assert.check(tryEnv.info.gaps.length() % 2 == 0); - tryEnv.info.gaps.append(code.curPc()); + tryEnv.info.gaps.append(code.curCP()); } else { Assert.check(tryEnv.info.gaps.length() % 2 == 0); - tryEnv.info.gaps.append(code.curPc()); + tryEnv.info.gaps.append(code.curCP()); genLast(); } } @@ -1467,10 +1533,10 @@ public class Gen extends JCTree.Visitor { */ void genTry(JCTree body, List catchers, Env env) { int limit = code.nextreg; - int startpc = code.curPc(); + int startpc = code.curCP(); Code.State stateTry = code.state.dup(); genStat(body, env, CRT_BLOCK); - int endpc = code.curPc(); + int endpc = code.curCP(); boolean hasFinalizer = env.info.finalize != null && env.info.finalize.hasFinalizer(); @@ -1478,82 +1544,77 @@ public class Gen extends JCTree.Visitor { code.statBegin(TreeInfo.endPos(body)); genFinalizer(env); code.statBegin(TreeInfo.endPos(env.tree)); - Chain exitChain; - if (startpc != endpc) { - exitChain = code.branch(goto_); - } else { - exitChain = code.branch(dontgoto); + Chain exitChain = code.branch(goto_); + if (varDebugInfo && lvtRanges.containsKey(code.meth, body)) { + code.closeAliveRanges(body); } endFinalizerGap(env); - if (startpc != endpc) { - for (List l = catchers; l.nonEmpty(); l = l.tail) { - // start off with exception on stack - code.entryPoint(stateTry, l.head.param.sym.type); - genCatch(l.head, env, startpc, endpc, gaps); - genFinalizer(env); - if (hasFinalizer || l.tail.nonEmpty()) { - code.statBegin(TreeInfo.endPos(env.tree)); - exitChain = Code.mergeChains(exitChain, - code.branch(goto_)); - } - endFinalizerGap(env); + if (startpc != endpc) for (List l = catchers; l.nonEmpty(); l = l.tail) { + // start off with exception on stack + code.entryPoint(stateTry, l.head.param.sym.type); + genCatch(l.head, env, startpc, endpc, gaps); + genFinalizer(env); + if (hasFinalizer || l.tail.nonEmpty()) { + code.statBegin(TreeInfo.endPos(env.tree)); + exitChain = Code.mergeChains(exitChain, + code.branch(goto_)); } + endFinalizerGap(env); + } + if (hasFinalizer) { + // Create a new register segement to avoid allocating + // the same variables in finalizers and other statements. + code.newRegSegment(); - if (hasFinalizer) { - // Create a new register segement to avoid allocating - // the same variables in finalizers and other statements. - code.newRegSegment(); + // Add a catch-all clause. - // Add a catch-all clause. + // start off with exception on stack + int catchallpc = code.entryPoint(stateTry, syms.throwableType); - // start off with exception on stack - int catchallpc = code.entryPoint(stateTry, syms.throwableType); + // Register all exception ranges for catch all clause. + // The range of the catch all clause is from the beginning + // of the try or synchronized block until the present + // code pointer excluding all gaps in the current + // environment's GenContext. + int startseg = startpc; + while (env.info.gaps.nonEmpty()) { + int endseg = env.info.gaps.next().intValue(); + registerCatch(body.pos(), startseg, endseg, + catchallpc, 0); + startseg = env.info.gaps.next().intValue(); + } + code.statBegin(TreeInfo.finalizerPos(env.tree)); + code.markStatBegin(); - // Register all exception ranges for catch all clause. - // The range of the catch all clause is from the beginning - // of the try or synchronized block until the present - // code pointer excluding all gaps in the current - // environment's GenContext. - int startseg = startpc; - while (env.info.gaps.nonEmpty()) { - int endseg = env.info.gaps.next().intValue(); - registerCatch(body.pos(), startseg, endseg, - catchallpc, 0); - startseg = env.info.gaps.next().intValue(); - } + Item excVar = makeTemp(syms.throwableType); + excVar.store(); + genFinalizer(env); + excVar.load(); + registerCatch(body.pos(), startseg, + env.info.gaps.next().intValue(), + catchallpc, 0); + code.emitop0(athrow); + code.markDead(); + + // If there are jsr's to this finalizer, ... + if (env.info.cont != null) { + // Resolve all jsr's. + code.resolve(env.info.cont); + + // Mark statement line number code.statBegin(TreeInfo.finalizerPos(env.tree)); code.markStatBegin(); - Item excVar = makeTemp(syms.throwableType); - excVar.store(); - genFinalizer(env); - excVar.load(); - registerCatch(body.pos(), startseg, - env.info.gaps.next().intValue(), - catchallpc, 0); - code.emitop0(athrow); + // Save return address. + LocalItem retVar = makeTemp(syms.throwableType); + retVar.store(); + + // Generate finalizer code. + env.info.finalize.genLast(); + + // Return. + code.emitop1w(ret, retVar.reg); code.markDead(); - - // If there are jsr's to this finalizer, ... - if (env.info.cont != null) { - // Resolve all jsr's. - code.resolve(env.info.cont); - - // Mark statement line number - code.statBegin(TreeInfo.finalizerPos(env.tree)); - code.markStatBegin(); - - // Save return address. - LocalItem retVar = makeTemp(syms.throwableType); - retVar.store(); - - // Generate finalizer code. - env.info.finalize.genLast(); - - // Return. - code.emitop1w(ret, retVar.reg); - code.markDead(); - } } } // Resolve all breaks. @@ -1581,7 +1642,7 @@ public class Gen extends JCTree.Visitor { int catchType = makeRef(tree.pos(), subCatch.type); int end = gaps.head.intValue(); registerCatch(tree.pos(), - startpc, end, code.curPc(), + startpc, end, code.curCP(), catchType); if (subCatch.type.isAnnotated()) { // All compounds share the same position, simply update the @@ -1597,7 +1658,7 @@ public class Gen extends JCTree.Visitor { for (JCExpression subCatch : subClauses) { int catchType = makeRef(tree.pos(), subCatch.type); registerCatch(tree.pos(), - startpc, endpc, code.curPc(), + startpc, endpc, code.curCP(), catchType); if (subCatch.type.isAnnotated()) { // All compounds share the same position, simply update the @@ -1740,11 +1801,19 @@ public class Gen extends JCTree.Visitor { code.resolve(c.trueJumps); genStat(tree.thenpart, env, CRT_STATEMENT | CRT_FLOW_TARGET); thenExit = code.branch(goto_); + if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.thenpart)) { + code.closeAliveRanges(tree.thenpart, + thenExit != null && tree.elsepart == null ? thenExit.pc : code.cp); + } } if (elseChain != null) { code.resolve(elseChain); - if (tree.elsepart != null) + if (tree.elsepart != null) { genStat(tree.elsepart, env,CRT_STATEMENT | CRT_FLOW_TARGET); + if (varDebugInfo && lvtRanges.containsKey(code.meth, tree.elsepart)) { + code.closeAliveRanges(tree.elsepart); + } + } } code.resolve(thenExit); code.endScopes(limit); @@ -1838,20 +1907,20 @@ public class Gen extends JCTree.Visitor { Chain elseChain = c.jumpFalse(); if (!c.isFalse()) { code.resolve(c.trueJumps); - int startpc = genCrt ? code.curPc() : 0; + int startpc = genCrt ? code.curCP() : 0; genExpr(tree.truepart, pt).load(); code.state.forceStackTop(tree.type); if (genCrt) code.crt.put(tree.truepart, CRT_FLOW_TARGET, - startpc, code.curPc()); + startpc, code.curCP()); thenExit = code.branch(goto_); } if (elseChain != null) { code.resolve(elseChain); - int startpc = genCrt ? code.curPc() : 0; + int startpc = genCrt ? code.curCP() : 0; genExpr(tree.falsepart, pt).load(); code.state.forceStackTop(tree.type); if (genCrt) code.crt.put(tree.falsepart, CRT_FLOW_TARGET, - startpc, code.curPc()); + startpc, code.curCP()); } code.resolve(thenExit); result = items.makeStackItem(pt); @@ -2431,6 +2500,19 @@ public class Gen extends JCTree.Visitor { new Env(cdef, new GenContext()); localEnv.toplevel = env.toplevel; localEnv.enclClass = cdef; + + /* We must not analyze synthetic methods + */ + if (varDebugInfo && (cdef.sym.flags() & SYNTHETIC) == 0) { + try { + LVTAssignAnalyzer lvtAssignAnalyzer = LVTAssignAnalyzer.make( + lvtRanges, syms, names); + lvtAssignAnalyzer.analyzeTree(localEnv); + } catch (Throwable e) { + throw e; + } + } + for (List l = cdef.defs; l.nonEmpty(); l = l.tail) { genDef(l.head, localEnv); } @@ -2515,4 +2597,311 @@ public class Gen extends JCTree.Visitor { cont = Code.mergeChains(c, cont); } } + + static class LVTAssignAnalyzer + extends Flow.AbstractAssignAnalyzer { + + final LVTBits lvtInits; + final LVTRanges lvtRanges; + + /* This class is anchored to a context dependent tree. The tree can + * vary inside the same instruction for example in the switch instruction + * the same FlowBits instance can be anchored to the whole tree, or + * to a given case. The aim is to always anchor the bits to the tree + * capable of closing a DA range. + */ + static class LVTBits extends Bits { + + enum BitsOpKind { + INIT, + CLEAR, + INCL_BIT, + EXCL_BIT, + ASSIGN, + AND_SET, + OR_SET, + DIFF_SET, + XOR_SET, + INCL_RANGE, + EXCL_RANGE, + } + + JCTree currentTree; + LVTAssignAnalyzer analyzer; + private int[] oldBits = null; + BitsState stateBeforeOp; + + LVTBits() { + super(false); + } + + LVTBits(int[] bits, BitsState initState) { + super(bits, initState); + } + + @Override + public void clear() { + generalOp(null, -1, BitsOpKind.CLEAR); + } + + @Override + protected void internalReset() { + super.internalReset(); + oldBits = null; + } + + @Override + public Bits assign(Bits someBits) { + // bits can be null + oldBits = bits; + stateBeforeOp = currentState; + super.assign(someBits); + changed(); + return this; + } + + @Override + public void excludeFrom(int start) { + generalOp(null, start, BitsOpKind.EXCL_RANGE); + } + + @Override + public void excl(int x) { + Assert.check(x >= 0); + generalOp(null, x, BitsOpKind.EXCL_BIT); + } + + @Override + public Bits andSet(Bits xs) { + return generalOp(xs, -1, BitsOpKind.AND_SET); + } + + @Override + public Bits orSet(Bits xs) { + return generalOp(xs, -1, BitsOpKind.OR_SET); + } + + @Override + public Bits diffSet(Bits xs) { + return generalOp(xs, -1, BitsOpKind.DIFF_SET); + } + + @Override + public Bits xorSet(Bits xs) { + return generalOp(xs, -1, BitsOpKind.XOR_SET); + } + + private Bits generalOp(Bits xs, int i, BitsOpKind opKind) { + Assert.check(currentState != BitsState.UNKNOWN); + oldBits = dupBits(); + stateBeforeOp = currentState; + switch (opKind) { + case AND_SET: + super.andSet(xs); + break; + case OR_SET: + super.orSet(xs); + break; + case XOR_SET: + super.xorSet(xs); + break; + case DIFF_SET: + super.diffSet(xs); + break; + case CLEAR: + super.clear(); + break; + case EXCL_BIT: + super.excl(i); + break; + case EXCL_RANGE: + super.excludeFrom(i); + break; + } + changed(); + return this; + } + + /* The tree we need to anchor the bits instance to. + */ + LVTBits at(JCTree tree) { + this.currentTree = tree; + return this; + } + + /* If the instance should be changed but the tree is not a closing + * tree then a reset is needed or the former tree can mistakingly be + * used. + */ + LVTBits resetTree() { + this.currentTree = null; + return this; + } + + /** This method will be called after any operation that causes a change to + * the bits. Subclasses can thus override it in order to extract information + * from the changes produced to the bits by the given operation. + */ + public void changed() { + if (currentTree != null && + stateBeforeOp != BitsState.UNKNOWN && + trackTree(currentTree)) { + List locals = + analyzer.lvtRanges + .getVars(analyzer.currentMethod, currentTree); + locals = locals != null ? + locals : List.nil(); + for (JCVariableDecl vardecl : analyzer.vardecls) { + //once the first is null, the rest will be so. + if (vardecl == null) { + break; + } + if (trackVar(vardecl.sym) && bitChanged(vardecl.sym.adr)) { + locals = locals.prepend(vardecl.sym); + } + } + if (!locals.isEmpty()) { + analyzer.lvtRanges.setEntry(analyzer.currentMethod, + currentTree, locals); + } + } + } + + boolean bitChanged(int x) { + boolean isMemberOfBits = isMember(x); + int[] tmp = bits; + bits = oldBits; + boolean isMemberOfOldBits = isMember(x); + bits = tmp; + return (!isMemberOfBits && isMemberOfOldBits); + } + + boolean trackVar(VarSymbol var) { + return (var.owner.kind == MTH && + (var.flags() & (PARAMETER | HASINIT)) == 0 && + analyzer.trackable(var)); + } + + boolean trackTree(JCTree tree) { + switch (tree.getTag()) { + // of course a method closes the alive range of a local variable. + case METHODDEF: + // for while loops we want only the body + case WHILELOOP: + return false; + } + return true; + } + + } + + public class LVTAssignPendingExit extends Flow.AssignAnalyzer.AssignPendingExit { + + LVTAssignPendingExit(JCTree tree, final Bits inits, final Bits uninits) { + super(tree, inits, uninits); + } + + @Override + public void resolveJump(JCTree tree) { + lvtInits.at(tree); + super.resolveJump(tree); + } + } + + private LVTAssignAnalyzer(LVTRanges lvtRanges, Symtab syms, Names names) { + super(new LVTBits(), syms, names); + lvtInits = (LVTBits)inits; + this.lvtRanges = lvtRanges; + } + + public static LVTAssignAnalyzer make(LVTRanges lvtRanges, Symtab syms, Names names) { + LVTAssignAnalyzer result = new LVTAssignAnalyzer(lvtRanges, syms, names); + result.lvtInits.analyzer = result; + return result; + } + + @Override + protected void markDead(JCTree tree) { + lvtInits.at(tree).inclRange(returnadr, nextadr); + super.markDead(tree); + } + + @Override + protected void merge(JCTree tree) { + lvtInits.at(tree); + super.merge(tree); + } + + boolean isSyntheticOrMandated(Symbol sym) { + return (sym.flags() & (SYNTHETIC | MANDATED)) != 0; + } + + @Override + protected boolean trackable(VarSymbol sym) { + if (isSyntheticOrMandated(sym)) { + //fast check to avoid tracking synthetic or mandated variables + return false; + } + return super.trackable(sym); + } + + @Override + protected void initParam(JCVariableDecl def) { + if (!isSyntheticOrMandated(def.sym)) { + super.initParam(def); + } + } + + @Override + protected void assignToInits(JCTree tree, Bits bits) { + lvtInits.at(tree); + lvtInits.assign(bits); + } + + @Override + protected void andSetInits(JCTree tree, Bits bits) { + lvtInits.at(tree); + lvtInits.andSet(bits); + } + + @Override + protected void orSetInits(JCTree tree, Bits bits) { + lvtInits.at(tree); + lvtInits.orSet(bits); + } + + @Override + protected void exclVarFromInits(JCTree tree, int adr) { + lvtInits.at(tree); + lvtInits.excl(adr); + } + + @Override + protected LVTAssignPendingExit createNewPendingExit(JCTree tree, Bits inits, Bits uninits) { + return new LVTAssignPendingExit(tree, inits, uninits); + } + + MethodSymbol currentMethod; + + @Override + public void visitMethodDef(JCMethodDecl tree) { + if ((tree.sym.flags() & (SYNTHETIC | GENERATEDCONSTR)) != 0) { + return; + } + if (tree.name.equals(names.clinit)) { + return; + } + boolean enumClass = (tree.sym.owner.flags() & ENUM) != 0; + if (enumClass && + (tree.name.equals(names.valueOf) || + tree.name.equals(names.values) || + tree.name.equals(names.init))) { + return; + } + currentMethod = tree.sym; + super.visitMethodDef(tree); + } + + } + } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java index 054facddaa6..3e1d7c68eb6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/Items.java @@ -789,18 +789,18 @@ public class Items { Chain jumpTrue() { if (tree == null) return Code.mergeChains(trueJumps, code.branch(opcode)); // we should proceed further in -Xjcov mode only - int startpc = code.curPc(); + int startpc = code.curCP(); Chain c = Code.mergeChains(trueJumps, code.branch(opcode)); - code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curPc()); + code.crt.put(tree, CRTable.CRT_BRANCH_TRUE, startpc, code.curCP()); return c; } Chain jumpFalse() { if (tree == null) return Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); // we should proceed further in -Xjcov mode only - int startpc = code.curPc(); + int startpc = code.curCP(); Chain c = Code.mergeChains(falseJumps, code.branch(Code.negate(opcode))); - code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curPc()); + code.crt.put(tree, CRTable.CRT_BRANCH_FALSE, startpc, code.curCP()); return c; } diff --git a/langtools/src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java b/langtools/src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java new file mode 100644 index 00000000000..71139ee78b6 --- /dev/null +++ b/langtools/src/share/classes/com/sun/tools/javac/jvm/LVTRanges.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.tools.javac.jvm; + +import java.util.Map; +import java.util.Map.Entry; +import java.util.WeakHashMap; + +import com.sun.tools.javac.code.Symbol.MethodSymbol; +import com.sun.tools.javac.code.Symbol.VarSymbol; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.List; + +/** This class contains a one to many relation between a tree and a set of variables. + * The relation implies that the given tree closes the DA (definite assignment) + * range for the set of variables. + * + *

        This is NOT part of any supported API. + * If you write code that depends on this, you do so at your own risk. + * This code and its internal interfaces are subject to change or + * deletion without notice. + */ +public class LVTRanges { + /** The context key for the LVT ranges. */ + protected static final Context.Key lvtRangesKey = new Context.Key<>(); + + /** Get the LVTRanges instance for this context. */ + public static LVTRanges instance(Context context) { + LVTRanges instance = context.get(lvtRangesKey); + if (instance == null) { + instance = new LVTRanges(context); + } + return instance; + } + + private static final long serialVersionUID = 1812267524140424433L; + + protected Context context; + + protected Map>> + aliveRangeClosingTrees = new WeakHashMap<>(); + + public LVTRanges(Context context) { + this.context = context; + context.put(lvtRangesKey, this); + } + + public List getVars(MethodSymbol method, JCTree tree) { + Map> varMap = aliveRangeClosingTrees.get(method); + return (varMap != null) ? varMap.get(tree) : null; + } + + public boolean containsKey(MethodSymbol method, JCTree tree) { + Map> varMap = aliveRangeClosingTrees.get(method); + if (varMap == null) { + return false; + } + return varMap.containsKey(tree); + } + + public void setEntry(MethodSymbol method, JCTree tree, List vars) { + Map> varMap = aliveRangeClosingTrees.get(method); + if (varMap != null) { + varMap.put(tree, vars); + } else { + varMap = new WeakHashMap<>(); + varMap.put(tree, vars); + aliveRangeClosingTrees.put(method, varMap); + } + } + + public List removeEntry(MethodSymbol method, JCTree tree) { + Map> varMap = aliveRangeClosingTrees.get(method); + if (varMap != null) { + List result = varMap.remove(tree); + if (varMap.isEmpty()) { + aliveRangeClosingTrees.remove(method); + } + return result; + } + return null; + } + + /* This method should be used for debugging LVT related issues. + */ + @Override + public String toString() { + String result = ""; + for (Entry>> mainEntry: aliveRangeClosingTrees.entrySet()) { + result += "Method: \n" + mainEntry.getKey().flatName() + "\n"; + int i = 1; + for (Entry> treeEntry: mainEntry.getValue().entrySet()) { + result += " Tree " + i + ": \n" + treeEntry.getKey().toString() + "\n"; + result += " Variables closed:\n"; + for (VarSymbol var: treeEntry.getValue()) { + result += " " + var.toString(); + } + result += "\n"; + i++; + } + } + return result; + } + +} diff --git a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 73d3b020bc1..39a59f662ff 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/langtools/src/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -67,7 +67,6 @@ import com.sun.tools.javac.util.Log.WriterKind; import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.main.Option.*; import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; -import static com.sun.tools.javac.util.ListBuffer.lb; /** This class could be the main entry point for GJC when GJC is used as a @@ -80,7 +79,7 @@ import static com.sun.tools.javac.util.ListBuffer.lb; * This code and its internal interfaces are subject to change or * deletion without notice. */ -public class JavaCompiler implements ClassReader.SourceCompleter { +public class JavaCompiler { /** The context key for the compiler. */ protected static final Context.Key compilerKey = new Context.Key(); @@ -310,6 +309,17 @@ public class JavaCompiler implements ClassReader.SourceCompleter { */ protected JavaCompiler delegateCompiler; + /** + * SourceCompleter that delegates to the complete-method of this class. + */ + protected final ClassReader.SourceCompleter thisCompleter = + new ClassReader.SourceCompleter() { + @Override + public void complete(ClassSymbol sym) throws CompletionFailure { + JavaCompiler.this.complete(sym); + } + }; + /** * Command line options. */ @@ -374,7 +384,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { types = Types.instance(context); taskListener = MultiTaskListener.instance(context); - reader.sourceCompleter = this; + reader.sourceCompleter = thisCompleter; options = Options.instance(context); @@ -575,7 +585,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { } protected final Queue stopIfError(CompileState cs, Queue queue) { - return shouldStop(cs) ? ListBuffer.lb() : queue; + return shouldStop(cs) ? new ListBuffer() : queue; } protected final List stopIfError(CompileState cs, List list) { @@ -941,7 +951,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { return List.nil(); //parse all files - ListBuffer trees = lb(); + ListBuffer trees = new ListBuffer<>(); Set filesSoFar = new HashSet(); for (JavaFileObject fileObject : fileObjects) { if (!filesSoFar.contains(fileObject)) { @@ -991,7 +1001,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { // then remember the classes declared in // the original compilation units listed on the command line. if (needRootClasses || sourceOutput || stubOutput) { - ListBuffer cdefs = lb(); + ListBuffer cdefs = new ListBuffer<>(); for (JCCompilationUnit unit : roots) { for (List defs = unit.defs; defs.nonEmpty(); @@ -1215,7 +1225,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * @returns a list of environments for attributd classes. */ public Queue> attribute(Queue> envs) { - ListBuffer> results = lb(); + ListBuffer> results = new ListBuffer<>(); while (!envs.isEmpty()) results.append(attribute(envs.remove())); return stopIfError(CompileState.ATTR, results); @@ -1280,7 +1290,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * @returns the list of attributed parse trees */ public Queue> flow(Queue> envs) { - ListBuffer> results = lb(); + ListBuffer> results = new ListBuffer<>(); for (Env env: envs) { flow(env, results); } @@ -1291,7 +1301,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * Perform dataflow checks on an attributed parse tree. */ public Queue> flow(Env env) { - ListBuffer> results = lb(); + ListBuffer> results = new ListBuffer<>(); flow(env, results); return stopIfError(CompileState.FLOW, results); } @@ -1345,7 +1355,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { * @returns a list containing the classes to be generated */ public Queue, JCClassDecl>> desugar(Queue> envs) { - ListBuffer, JCClassDecl>> results = lb(); + ListBuffer, JCClassDecl>> results = new ListBuffer<>(); for (Env env: envs) desugar(env, results); return stopIfError(CompileState.FLOW, results); @@ -1594,7 +1604,7 @@ public class JavaCompiler implements ClassReader.SourceCompleter { } @Override public void visitClassDef(JCClassDecl tree) { - ListBuffer newdefs = lb(); + ListBuffer newdefs = new ListBuffer<>(); for (List it = tree.defs; it.tail != null; it = it.tail) { JCTree t = it.head; switch (t.getTag()) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java index a2cd3c55de7..c05662cbcbb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacAnnoConstructs.java @@ -207,7 +207,7 @@ public class JavacAnnoConstructs { Attribute[] contained0 = null; if (container != null) contained0 = unpackAttributes(container); - ListBuffer compounds = ListBuffer.lb(); + ListBuffer compounds = new ListBuffer<>(); if (contained0 != null) { for (Attribute a : contained0) if (a instanceof Attribute.Compound) @@ -328,7 +328,7 @@ public class JavacAnnoConstructs { Attribute[] contained0 = null; if (container != null) contained0 = unpackAttributes(container); - ListBuffer compounds = ListBuffer.lb(); + ListBuffer compounds = new ListBuffer<>(); if (contained0 != null) { for (Attribute a : contained0) if (a instanceof Attribute.Compound) diff --git a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java index 14e377fb37f..726264bb79c 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java +++ b/langtools/src/share/classes/com/sun/tools/javac/model/JavacTypes.java @@ -116,11 +116,7 @@ public class JavacTypes implements javax.lang.model.util.Types { public List directSupertypes(TypeMirror t) { validateTypeNotIn(t, EXEC_OR_PKG); - Type type = (Type) t; - Type sup = types.supertype(type); - return (sup == Type.noType || sup == type || sup == null) - ? types.interfaces(type) - : types.interfaces(type).prepend(sup); + return types.directSupertypes((Type) t); } public TypeMirror erasure(TypeMirror t) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java index 182f21158ca..57a492f3a3a 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/JavacParser.java @@ -48,7 +48,6 @@ import static com.sun.tools.javac.parser.Tokens.TokenKind.GT; import static com.sun.tools.javac.parser.Tokens.TokenKind.IMPORT; import static com.sun.tools.javac.parser.Tokens.TokenKind.LT; import static com.sun.tools.javac.tree.JCTree.Tag.*; -import static com.sun.tools.javac.util.ListBuffer.lb; /** The parser maps a token sequence into an abstract syntax * tree. It operates by recursive descent, with code derived @@ -1767,7 +1766,7 @@ public class JavacParser implements Parser { /** Arguments = "(" [Expression { COMMA Expression }] ")" */ List arguments() { - ListBuffer args = lb(); + ListBuffer args = new ListBuffer<>(); if (token.kind == LPAREN) { nextToken(); if (token.kind != RPAREN) { @@ -1834,7 +1833,7 @@ public class JavacParser implements Parser { nextToken(); return List.nil(); } else { - ListBuffer args = ListBuffer.lb(); + ListBuffer args = new ListBuffer<>(); args.append(((mode & EXPR) == 0) ? typeArgument() : parseType()); while (token.kind == COMMA) { nextToken(); @@ -2175,7 +2174,7 @@ public class JavacParser implements Parser { ListBuffer dims = new ListBuffer(); // maintain array dimension type annotations - ListBuffer> dimAnnotations = ListBuffer.lb(); + ListBuffer> dimAnnotations = new ListBuffer<>(); dimAnnotations.append(annos); dims.append(parseExpression()); @@ -2626,7 +2625,7 @@ public class JavacParser implements Parser { } List catchTypes() { - ListBuffer catchTypes = ListBuffer.lb(); + ListBuffer catchTypes = new ListBuffer<>(); catchTypes.add(parseType()); while (token.kind == BAR) { checkMulticatch(); @@ -2708,7 +2707,7 @@ public class JavacParser implements Parser { * | { FINAL | '@' Annotation } Type VariableDeclarators */ List forInit() { - ListBuffer stats = lb(); + ListBuffer stats = new ListBuffer<>(); int pos = token.pos; if (token.kind == FINAL || token.kind == MONKEYS_AT) { return variableDeclarators(optFinal(0), parseType(), stats).toList(); diff --git a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java index d55defedf73..fcb19dcb5fb 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java +++ b/langtools/src/share/classes/com/sun/tools/javac/parser/Tokens.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -402,7 +402,7 @@ public class Tokens { if (comments == null) { return List.nil(); } else { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (Comment c : comments) { if (c.getStyle() == style) { buf.add(c); diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties index 5d1a22b84a1..a87abc35b70 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -742,11 +742,6 @@ compiler.misc.incompatible.arg.types.in.lambda=\ compiler.misc.incompatible.arg.types.in.mref=\ incompatible parameter types in method reference -# 0: list of type, 1: message segment -compiler.misc.bad.arg.types.in.lambda=\ - cannot type-check lambda expression with inferred parameter types\n\ - inferred types: {0} - compiler.err.new.not.allowed.in.annotation=\ ''new'' not allowed in an annotation @@ -1397,6 +1392,10 @@ compiler.warn.long.SVUID=\ compiler.warn.missing.SVUID=\ serializable class {0} has no definition of serialVersionUID +# 0: symbol, 1: symbol, 2: symbol, 3: symbol +compiler.warn.potentially.ambiguous.overload=\ + {0} in {1} is potentially ambiguous with {2} in {3} + # 0: message segment compiler.warn.override.varargs.missing=\ {0}; overridden method has no ''...'' @@ -1916,10 +1915,6 @@ compiler.misc.inferred.do.not.conform.to.eq.bounds=\ inferred: {0}\n\ equality constraints(s): {1} -# 0: list of type -compiler.misc.cyclic.inference=\ - Cannot instantiate inference variables {0} because of an inference loop - # 0: symbol compiler.misc.diamond=\ {0}<> @@ -1932,6 +1927,10 @@ compiler.misc.diamond.non.generic=\ compiler.misc.diamond.and.explicit.params=\ cannot use ''<>'' with explicit type parameters for constructor +# 0: unused +compiler.misc.mref.infer.and.explicit.params=\ + cannot use raw constructor reference with explicit type parameters for constructor + # 0: type, 1: list of type compiler.misc.explicit.param.do.not.conform.to.bounds=\ explicit type argument {0} does not conform to declared bound(s) {1} diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index bff4e9a217b..9702e684c78 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -524,9 +524,6 @@ compiler.misc.incompatible.ret.type.in.lambda=\u30E9\u30E0\u30C0\u5F0F\u306E\u62 # 0: type compiler.misc.incompatible.ret.type.in.mref=\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u306E\u623B\u308A\u578B\u304C\u4E0D\u6B63\u3067\u3059\n{0} -# 0: list of type -compiler.err.incompatible.thrown.types.in.lambda=\u30E9\u30E0\u30C0\u5F0F\u3067\u30B9\u30ED\u30FC\u3055\u308C\u305F\u30BF\u30A4\u30D7{0}\u306F\u4E0D\u9069\u5408\u3067\u3059 - # 0: list of type compiler.err.incompatible.thrown.types.in.mref=\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u306E\u30B9\u30ED\u30FC\u3055\u308C\u305F\u30BF\u30A4\u30D7{0}\u306F\u4E0D\u9069\u5408\u3067\u3059 @@ -642,12 +639,18 @@ compiler.err.repeated.modifier=\u4FEE\u98FE\u5B50\u304C\u7E70\u308A\u8FD4\u3055\ # 0: symbol, 1: set of modifier, 2: symbol compiler.err.report.access={0}\u306F{2}\u3067{1}\u30A2\u30AF\u30BB\u30B9\u3055\u308C\u307E\u3059 +# 0: symbol, 1: set of modifier, 2: symbol +compiler.misc.report.access={0}\u306F{2}\u3067{1}\u30A2\u30AF\u30BB\u30B9\u3055\u308C\u307E\u3059 + compiler.err.ret.outside.meth=\u30E1\u30BD\u30C3\u30C9\u306E\u5916\u306Ereturn\u6587\u3067\u3059 compiler.err.signature.doesnt.match.supertype=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C{0}\u306B\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u4E0D\u9069\u5408\u306A\u30B9\u30FC\u30D1\u30FC\u30BF\u30A4\u30D7\u3067\u3059 compiler.err.signature.doesnt.match.intf=\u30B7\u30B0\u30CD\u30C1\u30E3\u304C{0}\u306B\u4E00\u81F4\u3057\u307E\u305B\u3093\u3002\u4E0D\u9069\u5408\u306A\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u3067\u3059 +# 0: number, 1: number +compiler.err.method.invoked.with.incorrect.number.arguments=\u30E1\u30BD\u30C3\u30C9\u3092\u8D77\u52D5\u3057\u305F\u5F15\u6570\u306E\u6570\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093\u3002\u4E88\u671F\u3055\u308C\u308B\u6570\u306F{0}\u3067\u3059\u304C\u3001{1}\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F + # 0: symbol, 1: symbol, 2: symbol compiler.err.does.not.override.abstract={0}\u306Fabstract\u3067\u306A\u304F\u3001{2}\u5185\u306Eabstract\u30E1\u30BD\u30C3\u30C9{1}\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3057\u307E\u305B\u3093 @@ -755,6 +758,9 @@ compiler.err.var.might.already.be.assigned=\u5909\u6570{0}\u306F\u3059\u3067\u30 # 0: symbol compiler.err.var.might.not.have.been.initialized=\u5909\u6570{0}\u306F\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059 +# 0: symbol +compiler.err.var.not.initialized.in.default.constructor=\u5909\u6570{0}\u306F\u3001\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u3067\u521D\u671F\u5316\u3055\u308C\u3066\u3044\u307E\u305B\u3093 + # 0: symbol compiler.err.var.might.be.assigned.in.loop=\u5909\u6570{0}\u306F\u30EB\u30FC\u30D7\u5185\u3067\u4EE3\u5165\u3055\u308C\u3066\u3044\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059 @@ -829,6 +835,14 @@ compiler.note.compressed.diags=\u4E00\u90E8\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\ compiler.note.potential.lambda.found=\u3053\u306E\u533F\u540D\u5185\u90E8\u30AF\u30E9\u30B9\u3092\u30E9\u30E0\u30C0\u5F0F\u306B\u5909\u63DB\u3067\u304D\u307E\u3059\u3002 +# 0: boolean, 1: symbol +compiler.note.lambda.stat=\u30E9\u30E0\u30C0\u5F0F\u3092\u5909\u63DB\u3057\u3066\u3044\u307E\u3059\n\u4EE3\u66FFmetafactory = {0}\n\u5408\u6210\u30E1\u30BD\u30C3\u30C9 = {1} + +# 0: boolean, 1: unused +compiler.note.mref.stat=\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u3092\u5909\u63DB\u3057\u3066\u3044\u307E\u3059\n\u4EE3\u66FFmetafactory = {0}\n +# 0: boolean, 1: symbol +compiler.note.mref.stat.1=\u30E1\u30BD\u30C3\u30C9\u53C2\u7167\u3092\u5909\u63DB\u3057\u3066\u3044\u307E\u3059\n\u4EE3\u66FFmetafactory = {0}\n\u30D6\u30EA\u30C3\u30B8\u30FB\u30E1\u30BD\u30C3\u30C9 = {1} + compiler.note.note=\u6CE8\u610F: # 0: file name @@ -1015,6 +1029,14 @@ compiler.warn.static.not.qualified.by.type=static {0}\u306F\u5F0F\u3067\u306F\u3 # 0: string compiler.warn.source.no.bootclasspath=\u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u30D1\u30B9\u304C-source {0}\u3068\u4E00\u7DD2\u306B\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 +# 0: string +compiler.warn.option.obsolete.source=\u30BD\u30FC\u30B9\u5024{0}\u306F\u5EC3\u6B62\u3055\u308C\u3066\u3044\u3066\u3001\u4ECA\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059 + +# 0: string +compiler.warn.option.obsolete.target=\u30BF\u30FC\u30B2\u30C3\u30C8\u5024{0}\u306F\u5EC3\u6B62\u3055\u308C\u3066\u3044\u3066\u3001\u4ECA\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059 + +compiler.warn.option.obsolete.suppression=\u5EC3\u6B62\u3055\u308C\u305F\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u3064\u3044\u3066\u306E\u8B66\u544A\u3092\u8868\u793A\u3057\u306A\u3044\u3088\u3046\u306B\u3059\u308B\u306B\u306F\u3001-Xlint:\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3057\u307E\u3059\u3002 + # 0: name, 1: number, 2: number, 3: number, 4: number compiler.warn.future.attr=\u30D0\u30FC\u30B8\u30E7\u30F3{1}.{2}\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3067\u5C0E\u5165\u3055\u308C\u305F{0}\u5C5E\u6027\u306F\u3001\u30D0\u30FC\u30B8\u30E7\u30F3{3}.{4}\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3067\u306F\u7121\u8996\u3055\u308C\u307E\u3059 @@ -1550,7 +1572,7 @@ compiler.warn.enum.as.identifier=\u30EA\u30EA\u30FC\u30B95\u304B\u3089''enum''\u compiler.warn.assert.as.identifier=\u30EA\u30EA\u30FC\u30B91.4\u304B\u3089''assert''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u3001\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\n(''assert''\u3092\u30AD\u30FC\u30EF\u30FC\u30C9\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u306B\u306F\u3001-source 1.4\u4EE5\u964D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) -compiler.warn.underscore.as.identifier=\u8B58\u5225\u5B50\u3068\u3057\u3066''_''\u304C\u4F7F\u7528\u3055\u308C\u307E\u3057\u305F\n(\u8B58\u5225\u5B50\u3068\u3057\u3066\u306E''_''\u306E\u4F7F\u7528\u306F\u3001\u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059) +compiler.warn.underscore.as.identifier=\u8B58\u5225\u5B50\u3068\u3057\u3066''_''\u304C\u4F7F\u7528\u3055\u308C\u307E\u3057\u305F\n(\u8B58\u5225\u5B50\u3068\u3057\u3066\u306E''_''\u306E\u4F7F\u7528\u306F\u3001Java SE 8\u3088\u308A\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u306A\u3044\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059) compiler.err.enum.as.identifier=\u30EA\u30EA\u30FC\u30B95\u304B\u3089''enum''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\n(''enum''\u3092\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u306B\u306F-source 1.4\u4EE5\u524D\u3092\u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044) @@ -1567,7 +1589,7 @@ compiler.err.cant.annotate.static.class=\u5305\u542B\u3059\u308Bstatic\u306E\u30 # TODO 308: make a better error message # 0: unused -compiler.err.cant.annotate.nested.type=\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30BF\u30A4\u30D7\u306F\u6CE8\u91C8\u4ED8\u3051\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 +compiler.err.cant.annotate.nested.type=static\u306E\u30CD\u30B9\u30C8\u3055\u308C\u305F\u30BF\u30A4\u30D7\u306E\u30B9\u30B3\u30FC\u30D7\u30FB\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30C8\u306B\u306F\u6CE8\u91C8\u4ED8\u3051\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 # 0: type, 1: type compiler.err.incorrect.receiver.name=\u53D7\u53D6\u308A\u5074\u306E\u540D\u524D\u304C\u3001\u5305\u542B\u3059\u308B\u30AF\u30E9\u30B9\u30FB\u30BF\u30A4\u30D7\u3068\u4E00\u81F4\u3057\u307E\u305B\u3093\n\u5FC5\u9808: {0}\n\u691C\u51FA: {1} diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index b2e76c037f4..d4f1a214cd0 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -524,9 +524,6 @@ compiler.misc.incompatible.ret.type.in.lambda=lambda \u8868\u8FBE\u5F0F\u4E2D\u7 # 0: type compiler.misc.incompatible.ret.type.in.mref=\u65B9\u6CD5\u5F15\u7528\u4E2D\u7684\u8FD4\u56DE\u7C7B\u578B\u9519\u8BEF\n{0} -# 0: list of type -compiler.err.incompatible.thrown.types.in.lambda=lambda \u8868\u8FBE\u5F0F\u4E2D\u629B\u51FA\u7684\u7C7B\u578B{0}\u4E0D\u517C\u5BB9 - # 0: list of type compiler.err.incompatible.thrown.types.in.mref=\u65B9\u6CD5\u5F15\u7528\u4E2D\u629B\u51FA\u7684\u7C7B\u578B{0}\u4E0D\u517C\u5BB9 @@ -642,12 +639,18 @@ compiler.err.repeated.modifier=\u4FEE\u9970\u7B26\u91CD\u590D # 0: symbol, 1: set of modifier, 2: symbol compiler.err.report.access={0}\u53EF\u4EE5\u5728{2}\u4E2D\u8BBF\u95EE{1} +# 0: symbol, 1: set of modifier, 2: symbol +compiler.misc.report.access={0}\u53EF\u4EE5\u5728{2}\u4E2D\u8BBF\u95EE{1} + compiler.err.ret.outside.meth=\u8FD4\u56DE\u5916\u90E8\u65B9\u6CD5 compiler.err.signature.doesnt.match.supertype=\u7B7E\u540D\u4E0E{0}\u4E0D\u5339\u914D; \u4E0D\u517C\u5BB9\u7684\u8D85\u7C7B\u578B compiler.err.signature.doesnt.match.intf=\u7B7E\u540D\u4E0E{0}\u4E0D\u5339\u914D; \u4E0D\u517C\u5BB9\u7684\u63A5\u53E3 +# 0: number, 1: number +compiler.err.method.invoked.with.incorrect.number.arguments=\u4F7F\u7528\u4E0D\u6B63\u786E\u6570\u91CF\u7684\u53C2\u6570\u8C03\u7528\u4E86\u65B9\u6CD5; \u9884\u671F\u4E3A {0} \u4E2A, \u627E\u5230 {1} \u4E2A + # 0: symbol, 1: symbol, 2: symbol compiler.err.does.not.override.abstract={0}\u4E0D\u662F\u62BD\u8C61\u7684, \u5E76\u4E14\u672A\u8986\u76D6{2}\u4E2D\u7684\u62BD\u8C61\u65B9\u6CD5{1} @@ -755,6 +758,9 @@ compiler.err.var.might.already.be.assigned=\u53EF\u80FD\u5DF2\u5206\u914D\u53D8\ # 0: symbol compiler.err.var.might.not.have.been.initialized=\u53EF\u80FD\u5C1A\u672A\u521D\u59CB\u5316\u53D8\u91CF{0} +# 0: symbol +compiler.err.var.not.initialized.in.default.constructor=\u53D8\u91CF {0} \u672A\u5728\u9ED8\u8BA4\u6784\u9020\u5668\u4E2D\u521D\u59CB\u5316 + # 0: symbol compiler.err.var.might.be.assigned.in.loop=\u53EF\u80FD\u5728 loop \u4E2D\u5206\u914D\u4E86\u53D8\u91CF{0} @@ -829,6 +835,14 @@ compiler.note.compressed.diags=\u67D0\u4E9B\u6D88\u606F\u5DF2\u7ECF\u8FC7\u7B80\ compiler.note.potential.lambda.found=\u53EF\u5C06\u6B64\u533F\u540D\u5185\u90E8\u7C7B\u521B\u5EFA\u8F6C\u6362\u4E3A lambda \u8868\u8FBE\u5F0F\u3002 +# 0: boolean, 1: symbol +compiler.note.lambda.stat=\u8F6C\u6362 lambda \u8868\u8FBE\u5F0F\n\u66FF\u4EE3 metafactory = {0}\n\u5408\u6210\u65B9\u6CD5 = {1} + +# 0: boolean, 1: unused +compiler.note.mref.stat=\u8F6C\u6362\u65B9\u6CD5\u5F15\u7528\n\u66FF\u4EE3 metafactory = {0}\n +# 0: boolean, 1: symbol +compiler.note.mref.stat.1=\u8F6C\u6362\u65B9\u6CD5\u5F15\u7528\n\u66FF\u4EE3 metafactory = {0}\nbridge \u65B9\u6CD5 = {1} + compiler.note.note=\u6CE8: # 0: file name @@ -1015,6 +1029,14 @@ compiler.warn.static.not.qualified.by.type=static {0}\u5E94\u7531\u7C7B\u578B\u5 # 0: string compiler.warn.source.no.bootclasspath=\u672A\u4E0E -source {0} \u4E00\u8D77\u8BBE\u7F6E\u5F15\u5BFC\u7C7B\u8DEF\u5F84 +# 0: string +compiler.warn.option.obsolete.source=\u6E90\u503C{0}\u5DF2\u8FC7\u65F6, \u5C06\u5728\u672A\u6765\u6240\u6709\u53D1\u884C\u7248\u4E2D\u5220\u9664 + +# 0: string +compiler.warn.option.obsolete.target=\u76EE\u6807\u503C{0}\u5DF2\u8FC7\u65F6, \u5C06\u5728\u672A\u6765\u6240\u6709\u53D1\u884C\u7248\u4E2D\u5220\u9664 + +compiler.warn.option.obsolete.suppression=\u8981\u9690\u85CF\u6709\u5173\u5DF2\u8FC7\u65F6\u9009\u9879\u7684\u8B66\u544A, \u8BF7\u4F7F\u7528 -Xlint:-options\u3002 + # 0: name, 1: number, 2: number, 3: number, 4: number compiler.warn.future.attr={1}.{2} \u7248\u7C7B\u6587\u4EF6\u4E2D\u5F15\u5165\u7684 {0} \u5C5E\u6027\u5728 {3}.{4} \u7248\u7C7B\u6587\u4EF6\u4E2D\u88AB\u5FFD\u7565 @@ -1550,7 +1572,7 @@ compiler.warn.enum.as.identifier=\u4ECE\u53D1\u884C\u7248 5 \u5F00\u59CB, ''enum compiler.warn.assert.as.identifier=\u4ECE\u53D1\u884C\u7248 1.4 \u5F00\u59CB, ''assert'' \u662F\u4E00\u4E2A\u5173\u952E\u5B57, \u4F46\u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26\n(\u8BF7\u4F7F\u7528 -source 1.4 \u6216\u66F4\u9AD8\u7248\u672C\u4EE5\u5C06 ''assert'' \u7528\u4F5C\u5173\u952E\u5B57) -compiler.warn.underscore.as.identifier=''_'' \u5DF2\u7528\u4F5C\u6807\u8BC6\u7B26\n(\u4EE5\u540E\u7684\u53D1\u884C\u7248\u53EF\u80FD\u4E0D\u652F\u6301\u5C06 ''_'' \u7528\u4F5C\u6807\u8BC6\u7B26) +compiler.warn.underscore.as.identifier=''_'' \u7528\u4F5C\u6807\u8BC6\u7B26\n(Java SE 8 \u4E4B\u540E\u7684\u53D1\u884C\u7248\u4E2D\u53EF\u80FD\u4E0D\u652F\u6301\u4F7F\u7528 ''_'' \u4F5C\u4E3A\u6807\u8BC6\u7B26) compiler.err.enum.as.identifier=\u4ECE\u53D1\u884C\u7248 5 \u5F00\u59CB, ''enum'' \u4E3A\u5173\u952E\u5B57, \u800C\u4E0D\u7528\u4F5C\u6807\u8BC6\u7B26\n(\u8BF7\u4F7F\u7528 -source 1.4 \u6216\u66F4\u4F4E\u7248\u672C\u4EE5\u5C06 ''enum'' \u7528\u4F5C\u6807\u8BC6\u7B26) @@ -1567,7 +1589,7 @@ compiler.err.cant.annotate.static.class=\u65E0\u6CD5\u5BF9\u5C01\u95ED\u9759\u60 # TODO 308: make a better error message # 0: unused -compiler.err.cant.annotate.nested.type=\u65E0\u6CD5\u5BF9\u5D4C\u5957\u7C7B\u578B\u8FDB\u884C\u6CE8\u91CA +compiler.err.cant.annotate.nested.type=\u65E0\u6CD5\u6CE8\u91CA\u7528\u4E8E\u9759\u6001\u5D4C\u5957\u7C7B\u578B\u7684\u786E\u5B9A\u4F5C\u7528\u57DF\u7ED3\u6784 # 0: type, 1: type compiler.err.incorrect.receiver.name=\u63A5\u6536\u65B9\u540D\u79F0\u4E0E\u5C01\u95ED\u7C7B\u7C7B\u578B\u4E0D\u5339\u914D\n\u9700\u8981: {0}\n\u627E\u5230: {1} diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/javac_ja.properties index 0170a70384d..2c68780c9a6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -87,8 +87,12 @@ javac.opt.arg.file= javac.opt.Xlint=\u63A8\u5968\u306E\u8B66\u544A\u3092\u6709\u52B9\u306B\u3059\u308B javac.opt.Xlint.suboptlist=\u7279\u5B9A\u306E\u8B66\u544A\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3059\u308B javac.opt.Xdoclint=javadoc\u30B3\u30E1\u30F3\u30C8\u306E\u554F\u984C\u306B\u95A2\u3059\u308B\u63A8\u5968\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u306B\u3059\u308B -javac.opt.Xdoclint.subopts = (all|[-])[/] -javac.opt.Xdoclint.custom=\n javadoc\u30B3\u30E1\u30F3\u30C8\u306E\u554F\u984C\u306B\u95A2\u3059\u308B\u7279\u5B9A\u306E\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3057\u307E\u3059\u3002\n \u3053\u3053\u3067\u3001\u306Faccessibility\u3001html\u3001reference\u307E\u305F\u306Fsyntax\u306E\u3044\u305A\u308C\u304B\u3067\u3001\n \u306Fpublic\u3001protected\u3001package\u307E\u305F\u306Fprivate\u306E\u3044\u305A\u308C\u304B\u3067\u3059\u3002 +# L10N: do not localize: all none +javac.opt.Xdoclint.subopts = (all|none|[-])[/] + +# L10N: do not localize: accessibility html missing reference syntax +# L10N: do not localize: public protected package private +javac.opt.Xdoclint.custom=\n javadoc\u30B3\u30E1\u30F3\u30C8\u306E\u554F\u984C\u306B\u95A2\u3059\u308B\u7279\u5B9A\u306E\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u307E\u305F\u306F\u7121\u52B9\u306B\u3057\u307E\u3059\u3002\n \u3053\u3053\u3067\u3001\u306Faccessibility\u3001html\u3001missing\u3001reference\u307E\u305F\u306Fsyntax\u306E\u3044\u305A\u308C\u304B\u3067\u3001\n \u306Fpublic\u3001protected\u3001package\u307E\u305F\u306Fprivate\u306E\u3044\u305A\u308C\u304B\u3067\u3059\u3002 javac.opt.Xstdout=\u6A19\u6E96\u51FA\u529B\u3092\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u3059\u308B javac.opt.X=\u975E\u6A19\u6E96\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u6982\u8981\u3092\u51FA\u529B\u3059\u308B javac.opt.help=\u6A19\u6E96\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u6982\u8981\u3092\u51FA\u529B\u3059\u308B @@ -105,6 +109,7 @@ javac.err.empty.A.argument=-A\u306B\u306F\u5F15\u6570\u304C\u5FC5\u8981\u3067\u3 javac.err.invalid.arg={0}\u306F\u7121\u52B9\u306A\u5F15\u6570\u3067\u3059 javac.err.invalid.A.key=\u6CE8\u91C8\u30D7\u30ED\u30BB\u30C3\u30B5\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3''{0}''\u306E\u30AD\u30FC\u306B\u6307\u5B9A\u3055\u308C\u3066\u3044\u308B\u4E00\u9023\u306E\u8B58\u5225\u5B50\u304C\u3001\u30C9\u30C3\u30C8\u3067\u533A\u5207\u3089\u308C\u3066\u3044\u307E\u305B\u3093 javac.err.invalid.flag={0}\u306F\u7121\u52B9\u306A\u30D5\u30E9\u30B0\u3067\u3059 +javac.err.profile.bootclasspath.conflict=profile\u3068bootclasspath\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u540C\u6642\u306B\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 javac.err.invalid.profile=\u7121\u52B9\u306A\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: {0} javac.err.invalid.target={0}\u306F\u7121\u52B9\u306A\u30BF\u30FC\u30B2\u30C3\u30C8\u30FB\u30EA\u30EA\u30FC\u30B9\u3067\u3059 javac.err.no.source.files=\u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308A\u307E\u305B\u3093 diff --git a/langtools/src/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index 79e497f1f87..2ad0c68edbd 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -87,8 +87,12 @@ javac.opt.arg.file=<\u6587\u4EF6\u540D> javac.opt.Xlint=\u542F\u7528\u5EFA\u8BAE\u7684\u8B66\u544A javac.opt.Xlint.suboptlist=\u542F\u7528\u6216\u7981\u7528\u7279\u5B9A\u7684\u8B66\u544A javac.opt.Xdoclint=\u4E3A javadoc \u6CE8\u91CA\u4E2D\u7684\u95EE\u9898\u542F\u7528\u5EFA\u8BAE\u7684\u68C0\u67E5 -javac.opt.Xdoclint.subopts = (all|[-])[/] -javac.opt.Xdoclint.custom=\n \u4E3A javadoc \u6CE8\u91CA\u4E2D\u7684\u95EE\u9898\u542F\u7528\u6216\u7981\u7528\u7279\u5B9A\u68C0\u67E5,\n \u5176\u4E2D \u4E3A\u53EF\u8BBF\u95EE\u6027, html, \u5F15\u7528\u6216\u8BED\u6CD5\u4E4B\u4E00,\n \u4E3A public, protected, package \u6216 private \u4E4B\u4E00\u3002 +# L10N: do not localize: all none +javac.opt.Xdoclint.subopts = (all|none|[-])[/] + +# L10N: do not localize: accessibility html missing reference syntax +# L10N: do not localize: public protected package private +javac.opt.Xdoclint.custom=\n \u4E3A javadoc \u6CE8\u91CA\u4E2D\u7684\u95EE\u9898\u542F\u7528\u6216\u7981\u7528\u7279\u5B9A\u68C0\u67E5,\n \u5176\u4E2D \u4E3A accessibility, html, missing, reference \u6216 syntax \u4E4B\u4E00\u3002\n \u4E3A public, protected, package \u6216 private \u4E4B\u4E00\u3002 javac.opt.Xstdout=\u91CD\u5B9A\u5411\u6807\u51C6\u8F93\u51FA javac.opt.X=\u8F93\u51FA\u975E\u6807\u51C6\u9009\u9879\u7684\u63D0\u8981 javac.opt.help=\u8F93\u51FA\u6807\u51C6\u9009\u9879\u7684\u63D0\u8981 @@ -105,6 +109,7 @@ javac.err.empty.A.argument=-A \u9700\u8981\u4E00\u4E2A\u53C2\u6570; \u4F7F\u7528 javac.err.invalid.arg=\u65E0\u6548\u7684\u53C2\u6570: {0} javac.err.invalid.A.key=\u6CE8\u91CA\u5904\u7406\u7A0B\u5E8F\u9009\u9879 ''{0}'' \u4E2D\u7684\u5173\u952E\u5B57\u4E0D\u662F\u4EE5\u70B9\u5206\u9694\u7684\u6807\u8BC6\u7B26\u5E8F\u5217 javac.err.invalid.flag=\u65E0\u6548\u7684\u6807\u8BB0: {0} +javac.err.profile.bootclasspath.conflict=\u6982\u8981\u4FE1\u606F\u548C\u5F15\u5BFC\u7C7B\u8DEF\u5F84\u9009\u9879\u4E0D\u80FD\u540C\u65F6\u4F7F\u7528 javac.err.invalid.profile=\u914D\u7F6E\u6587\u4EF6\u65E0\u6548: {0} javac.err.invalid.target=\u65E0\u6548\u7684\u76EE\u6807\u53D1\u884C\u7248: {0} javac.err.no.source.files=\u65E0\u6E90\u6587\u4EF6 diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java index d2e9b67324b..d1d71080027 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1596,7 +1596,6 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public List params; public JCTree body; public boolean canCompleteNormally = true; - public List inferredThrownTypes; public ParameterKind paramKind; public JCLambda(List params, @@ -1908,6 +1907,7 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { * Selects a member expression. */ public static class JCMemberReference extends JCFunctionalExpression implements MemberReferenceTree { + public ReferenceMode mode; public ReferenceKind kind; public Name name; @@ -1917,6 +1917,12 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition { public Type varargsElement; public PolyKind refPolyKind; public boolean ownerAccessible; + public OverloadKind overloadKind; + + public enum OverloadKind { + OVERLOADED, + UNOVERLOADED; + } /** * Javac-dependent classification for member references, based diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java index aa2ce423b4b..1ccbb53518e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeCopier.java @@ -234,7 +234,7 @@ public class TreeCopier

        implements TreeVisitor { public JCTree visitLabeledStatement(LabeledStatementTree node, P p) { JCLabeledStatement t = (JCLabeledStatement) node; JCStatement body = copy(t.body, p); - return M.at(t.pos).Labelled(t.label, t.body); + return M.at(t.pos).Labelled(t.label, body); } public JCTree visitLiteral(LiteralTree node, P p) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index b94dd5f8a4f..b39fd06471e 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java @@ -890,7 +890,7 @@ public class TreeMaker implements JCTree.Factory { /** Create a value parameter tree from its name, type, and owner. */ public JCVariableDecl Param(Name name, Type argtype, Symbol owner) { - return VarDef(new VarSymbol(0, name, argtype, owner), null); + return VarDef(new VarSymbol(PARAMETER, name, argtype, owner), null); } /** Create a a list of value parameter trees x0, ..., xn from a list of @@ -946,6 +946,7 @@ public class TreeMaker implements JCTree.Factory { boolean isUnqualifiable(Symbol sym) { if (sym.name == names.empty || sym.owner == null || + sym.owner == syms.rootPackage || sym.owner.kind == MTH || sym.owner.kind == VAR) { return true; } else if (sym.kind == TYP && toplevel != null) { diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java index 272bf0fd49c..f8db31a4665 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Bits.java @@ -27,8 +27,6 @@ package com.sun.tools.javac.util; import java.util.Arrays; -import static com.sun.tools.javac.util.Bits.BitsOpKind.*; - /** A class for extensible, mutable bit sets. * *

        This is NOT part of any supported API. @@ -38,20 +36,6 @@ import static com.sun.tools.javac.util.Bits.BitsOpKind.*; */ public class Bits { - public enum BitsOpKind { - INIT, - CLEAR, - INCL_BIT, - EXCL_BIT, - ASSIGN, - AND_SET, - OR_SET, - DIFF_SET, - XOR_SET, - INCL_RANGE, - EXCL_RANGE, - } - // ____________ reset _________ // / UNKNOWN \ <-------- / UNINIT \ // \____________/ | \_________/ @@ -64,11 +48,14 @@ public class Bits { // | | // ----------- // any - private enum BitsState { + protected enum BitsState { /* A Bits instance is in UNKNOWN state if it has been explicitly reset. * It is possible to get to this state from any other by calling the * reset method. An instance in the UNKNOWN state can pass to the * NORMAL state after being assigned another Bits instance. + * + * Bits instances are final fields in Flow so the UNKNOWN state models + * the null assignment. */ UNKNOWN, /* A Bits instance is in UNINIT when it is created with the default @@ -103,13 +90,9 @@ public class Bits { public int[] bits = null; // This field will store last version of bits after every change. - public int[] oldBits = null; - - public BitsOpKind lastOperation = null; - private static final int[] unassignedBits = new int[0]; - private BitsState currentState; + protected BitsState currentState; /** Construct an initially empty set. */ @@ -127,27 +110,20 @@ public class Bits { /** Construct a set consisting initially of given bit vector. */ - private Bits(int[] bits, BitsState initState) { + protected Bits(int[] bits, BitsState initState) { this.bits = bits; this.currentState = initState; switch (initState) { case UNKNOWN: - reset(); //this will also set current state; + this.bits = null; break; case NORMAL: Assert.check(bits != unassignedBits); - lastOperation = INIT; break; } } - /** This method will be called after any operation that causes a change to - * the bits. Subclasses can thus override it in order to extract information - * from the changes produced to the bits by the given operation. - */ - public void changed() {} - - private void sizeTo(int len) { + protected void sizeTo(int len) { if (bits.length < len) { bits = Arrays.copyOf(bits, len); } @@ -157,16 +133,18 @@ public class Bits { */ public void clear() { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = CLEAR; - for (int i = 0; i < bits.length; i++) bits[i] = 0; - changed(); + for (int i = 0; i < bits.length; i++) { + bits[i] = 0; + } currentState = BitsState.NORMAL; } public void reset() { + internalReset(); + } + + protected void internalReset() { bits = null; - oldBits = null; currentState = BitsState.UNKNOWN; } @@ -175,40 +153,40 @@ public class Bits { } public Bits assign(Bits someBits) { - lastOperation = ASSIGN; - oldBits = bits; bits = someBits.dup().bits; - changed(); currentState = BitsState.NORMAL; return this; } /** Return a copy of this set. */ - private Bits dup() { + public Bits dup() { Assert.check(currentState != BitsState.UNKNOWN); Bits tmp = new Bits(); - if (currentState != BitsState.NORMAL) { - tmp.bits = bits; - } else { - tmp.bits = new int[bits.length]; - System.arraycopy(bits, 0, tmp.bits, 0, bits.length); - } + tmp.bits = dupBits(); currentState = BitsState.NORMAL; return tmp; } + protected int[] dupBits() { + int [] result; + if (currentState != BitsState.NORMAL) { + result = bits; + } else { + result = new int[bits.length]; + System.arraycopy(bits, 0, result, 0, bits.length); + } + return result; + } + /** Include x in this set. */ public void incl(int x) { Assert.check(currentState != BitsState.UNKNOWN); - Assert.check(x >= 0); - oldBits = bits; - lastOperation = INCL_BIT; + Assert.check(x >= 0, "Value of x " + x); sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); - changed(); currentState = BitsState.NORMAL; } @@ -217,14 +195,11 @@ public class Bits { */ public void inclRange(int start, int limit) { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = INCL_RANGE; sizeTo((limit >>> wordshift) + 1); for (int x = start; x < limit; x++) { bits[x >>> wordshift] = bits[x >>> wordshift] | (1 << (x & wordmask)); } - changed(); currentState = BitsState.NORMAL; } @@ -232,13 +207,10 @@ public class Bits { */ public void excludeFrom(int start) { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = EXCL_RANGE; Bits temp = new Bits(); temp.sizeTo(bits.length); temp.inclRange(0, start); internalAndSet(temp); - changed(); currentState = BitsState.NORMAL; } @@ -247,12 +219,9 @@ public class Bits { public void excl(int x) { Assert.check(currentState != BitsState.UNKNOWN); Assert.check(x >= 0); - oldBits = bits; - lastOperation = EXCL_BIT; sizeTo((x >>> wordshift) + 1); bits[x >>> wordshift] = bits[x >>> wordshift] & ~(1 << (x & wordmask)); - changed(); currentState = BitsState.NORMAL; } @@ -269,15 +238,12 @@ public class Bits { */ public Bits andSet(Bits xs) { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = AND_SET; internalAndSet(xs); - changed(); currentState = BitsState.NORMAL; return this; } - private void internalAndSet(Bits xs) { + protected void internalAndSet(Bits xs) { Assert.check(currentState != BitsState.UNKNOWN); sizeTo(xs.bits.length); for (int i = 0; i < xs.bits.length; i++) { @@ -289,13 +255,10 @@ public class Bits { */ public Bits orSet(Bits xs) { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = OR_SET; sizeTo(xs.bits.length); for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] | xs.bits[i]; } - changed(); currentState = BitsState.NORMAL; return this; } @@ -304,14 +267,11 @@ public class Bits { */ public Bits diffSet(Bits xs) { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = DIFF_SET; for (int i = 0; i < bits.length; i++) { if (i < xs.bits.length) { bits[i] = bits[i] & ~xs.bits[i]; } } - changed(); currentState = BitsState.NORMAL; return this; } @@ -320,13 +280,10 @@ public class Bits { */ public Bits xorSet(Bits xs) { Assert.check(currentState != BitsState.UNKNOWN); - oldBits = bits; - lastOperation = XOR_SET; sizeTo(xs.bits.length); for (int i = 0; i < xs.bits.length; i++) { bits[i] = bits[i] ^ xs.bits[i]; } - changed(); currentState = BitsState.NORMAL; return this; } @@ -336,7 +293,9 @@ public class Bits { */ private static int trailingZeroBits(int x) { Assert.check(wordlen == 32); - if (x == 0) return 32; + if (x == 0) { + return 32; + } int n = 1; if ((x & 0xffff) == 0) { n += 16; x >>>= 16; } if ((x & 0x00ff) == 0) { n += 8; x >>>= 8; } @@ -355,24 +314,31 @@ public class Bits { public int nextBit(int x) { Assert.check(currentState != BitsState.UNKNOWN); int windex = x >>> wordshift; - if (windex >= bits.length) return -1; + if (windex >= bits.length) { + return -1; + } int word = bits[windex] & ~((1 << (x & wordmask))-1); while (true) { - if (word != 0) + if (word != 0) { return (windex << wordshift) + trailingZeroBits(word); + } windex++; - if (windex >= bits.length) return -1; + if (windex >= bits.length) { + return -1; + } word = bits[windex]; } } /** a string representation of this set. */ + @Override public String toString() { - if (bits.length > 0) { + if (bits != null && bits.length > 0) { char[] digits = new char[bits.length * wordlen]; - for (int i = 0; i < bits.length * wordlen; i++) + for (int i = 0; i < bits.length * wordlen; i++) { digits[i] = isMember(i) ? '1' : '0'; + } return new String(digits); } else { return "[]"; @@ -396,6 +362,8 @@ public class Bits { System.out.println("found " + i); count ++; } - if (count != 125) throw new Error(); + if (count != 125) { + throw new Error(); + } } } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java b/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java index c15f1ec66b9..f1be519d6c9 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/GraphUtils.java @@ -32,6 +32,18 @@ package com.sun.tools.javac.util; */ public class GraphUtils { + /** + * Basic interface for defining various dependency kinds. All dependency kinds + * must at least support basic capabilities to tell the DOT engine how to render them. + */ + public interface DependencyKind { + /** + * Returns the DOT representation (to be used in a {@code style} attribute + * that's most suited for this dependency kind. + */ + String getDotStyle(); + } + /** * This class is a basic abstract class for representing a node. * A node is associated with a given data. @@ -43,9 +55,20 @@ public class GraphUtils { this.data = data; } - public abstract Iterable> getDependencies(); + /** + * Get an array of the dependency kinds supported by this node. + */ + public abstract DependencyKind[] getSupportedDependencyKinds(); - public abstract String printDependency(Node to); + /** + * Get all dependencies, regardless of their kind. + */ + public abstract Iterable> getAllDependencies(); + + /** + * Get a name for the dependency (of given kind) linking this node to a given node + */ + public abstract String getDependencyName(Node to, DependencyKind dk); @Override public String toString() { @@ -66,7 +89,9 @@ public class GraphUtils { super(data); } - public abstract Iterable> getDependencies(); + public abstract Iterable> getAllDependencies(); + + public abstract Iterable> getDependenciesByKind(DependencyKind dk); public int compareTo(TarjanNode o) { return (index < o.index) ? -1 : (index == o.index) ? 0 : 1; @@ -78,8 +103,8 @@ public class GraphUtils { * directed graph in linear time. Works on TarjanNode. */ public static > List> tarjan(Iterable nodes) { - ListBuffer> cycles = ListBuffer.lb(); - ListBuffer stack = ListBuffer.lb(); + ListBuffer> cycles = new ListBuffer<>(); + ListBuffer stack = new ListBuffer<>(); int index = 0; for (N node: nodes) { if (node.index == -1) { @@ -95,7 +120,7 @@ public class GraphUtils { index++; stack.prepend(v); v.active = true; - for (TarjanNode nd: v.getDependencies()) { + for (TarjanNode nd: v.getAllDependencies()) { @SuppressWarnings("unchecked") N n = (N)nd; if (n.index == -1) { @@ -107,7 +132,7 @@ public class GraphUtils { } if (v.lowlink == v.index) { N n; - ListBuffer cycle = ListBuffer.lb(); + ListBuffer cycle = new ListBuffer<>(); do { n = stack.remove(); n.active = false; @@ -134,9 +159,11 @@ public class GraphUtils { } //dump arcs for (TarjanNode from : nodes) { - for (TarjanNode to : from.getDependencies()) { - buf.append(String.format("%s -> %s [label = \" %s \"];\n", - from.hashCode(), to.hashCode(), from.printDependency(to))); + for (DependencyKind dk : from.getSupportedDependencyKinds()) { + for (TarjanNode to : from.getDependenciesByKind(dk)) { + buf.append(String.format("%s -> %s [label = \" %s \" style = %s ];\n", + from.hashCode(), to.hashCode(), from.getDependencyName(to, dk), dk.getDotStyle())); + } } } buf.append("}\n"); diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/List.java b/langtools/src/share/classes/com/sun/tools/javac/util/List.java index 611798d9caa..3ba7d8b59dc 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/List.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/List.java @@ -97,7 +97,7 @@ public class List extends AbstractCollection implements java.util.List } public List intersect(List that) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (A el : this) { if (that.contains(el)) { buf.append(el); @@ -107,7 +107,7 @@ public class List extends AbstractCollection implements java.util.List } public List diff(List that) { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (A el : this) { if (!that.contains(el)) { buf.append(el); @@ -116,6 +116,19 @@ public class List extends AbstractCollection implements java.util.List return buf.toList(); } + /** + * Create a new list from the first {@code n} elements of this list + */ + public List take(int n) { + ListBuffer buf = new ListBuffer<>(); + int count = 0; + for (A el : this) { + if (count++ == n) break; + buf.append(el); + } + return buf.toList(); + } + /** Construct a list consisting of given element. */ public static List of(A x1) { @@ -154,7 +167,7 @@ public class List extends AbstractCollection implements java.util.List } public static List from(Iterable coll) { - ListBuffer xs = ListBuffer.lb(); + ListBuffer xs = new ListBuffer<>(); for (A a : coll) { xs.append(a); } diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java b/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java index 0aa751ffe96..6d9c1ccda55 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/ListBuffer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,10 +40,6 @@ import java.util.NoSuchElementException; */ public class ListBuffer extends AbstractQueue { - public static ListBuffer lb() { - return new ListBuffer(); - } - public static ListBuffer of(T x) { ListBuffer lb = new ListBuffer(); lb.add(x); diff --git a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java index 5ed6d784103..d0d9d5934a6 100644 --- a/langtools/src/share/classes/com/sun/tools/javac/util/Log.java +++ b/langtools/src/share/classes/com/sun/tools/javac/util/Log.java @@ -123,7 +123,7 @@ public class Log extends AbstractLog { * active diagnostic handler. */ public static class DeferredDiagnosticHandler extends DiagnosticHandler { - private Queue deferred = ListBuffer.lb(); + private Queue deferred = new ListBuffer<>(); private final Filter filter; public DeferredDiagnosticHandler(Log log) { diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java index a49dc8a3134..eb49e10f79a 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/AnnotatedTypeImpl.java @@ -40,7 +40,7 @@ import com.sun.tools.javac.util.List; public class AnnotatedTypeImpl extends AbstractTypeImpl implements AnnotatedType { - AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type.AnnotatedType type) { + AnnotatedTypeImpl(DocEnv env, com.sun.tools.javac.code.Type type) { super(env, type); } @@ -50,7 +50,7 @@ public class AnnotatedTypeImpl */ @Override public AnnotationDesc[] annotations() { - List tas = ((com.sun.tools.javac.code.Type.AnnotatedType)type).typeAnnotations; + List tas = type.getAnnotationMirrors(); if (tas == null || tas.isEmpty()) { return new AnnotationDesc[0]; @@ -65,7 +65,7 @@ public class AnnotatedTypeImpl @Override public com.sun.javadoc.Type underlyingType() { - return TypeMaker.getType(env, ((com.sun.tools.javac.code.Type.AnnotatedType)type).underlyingType, true, false); + return TypeMaker.getType(env, type.unannotatedType(), true, false); } @Override diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java index 79580f60fb5..160ccbceb10 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/ClassDocImpl.java @@ -289,7 +289,7 @@ public class ClassDocImpl extends ProgramElementDocImpl implements ClassDoc { } public boolean isFunctionalInterface() { - return env.types.isFunctionalInterface(tsym); + return env.types.isFunctionalInterface(tsym) && env.source.allowLambda(); } /** diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java index 3a1c891984e..d0ff14b70ea 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/DocEnv.java @@ -123,6 +123,11 @@ public class DocEnv { */ private boolean silent = false; + /** + * The source language version. + */ + protected Source source; + /** * Constructor * @@ -144,6 +149,7 @@ public class DocEnv { // Default. Should normally be reset with setLocale. this.doclocale = new DocLocale(this, "", breakiterator); + source = Source.instance(context); } public void setSilent(boolean silent) { diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java index 1cc3de3c8c3..f30251ab737 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/JavadocTool.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -134,7 +134,7 @@ public class JavadocTool extends com.sun.tools.javac.main.JavaCompiler { docenv.setEncoding(encoding); docenv.docClasses = docClasses; docenv.legacyDoclet = legacyDoclet; - javadocReader.sourceCompleter = docClasses ? null : this; + javadocReader.sourceCompleter = docClasses ? null : thisCompleter; ListBuffer names = new ListBuffer(); ListBuffer classTrees = new ListBuffer(); diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java index 721d33b7b4c..de4d54a651d 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeMaker.java @@ -63,10 +63,8 @@ public class TypeMaker { t = env.types.erasure(t); } - if (considerAnnotations && - t.isAnnotated()) { - Type.AnnotatedType at = (Type.AnnotatedType) t; - return new AnnotatedTypeImpl(env, at); + if (considerAnnotations && t.isAnnotated()) { + return new AnnotatedTypeImpl(env, t); } switch (t.getTag()) { @@ -143,8 +141,7 @@ public class TypeMaker { static String getTypeString(DocEnv env, Type t, boolean full) { // TODO: should annotations be included here? if (t.isAnnotated()) { - Type.AnnotatedType at = (Type.AnnotatedType)t; - t = at.underlyingType; + t = t.unannotatedType(); } switch (t.getTag()) { case ARRAY: diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java index 3840c916ee4..48f97088ebc 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java +++ b/langtools/src/share/classes/com/sun/tools/javadoc/TypeVariableImpl.java @@ -140,7 +140,7 @@ public class TypeVariableImpl extends AbstractTypeImpl implements TypeVariable { if (!type.isAnnotated()) { return new AnnotationDesc[0]; } - List tas = ((com.sun.tools.javac.code.Type.AnnotatedType) type).typeAnnotations; + List tas = type.getAnnotationMirrors(); AnnotationDesc res[] = new AnnotationDesc[tas.length()]; int i = 0; for (Attribute.Compound a : tas) { diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties index a31ba5973da..b95a435689f 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,13 @@ main.errors=\u30A8\u30E9\u30FC{0}\u500B main.error=\u30A8\u30E9\u30FC{0}\u500B main.warnings=\u8B66\u544A{0}\u500B main.warning=\u8B66\u544A{0}\u500B -main.usage=\u4F7F\u7528\u65B9\u6CD5: javadoc [options] [packagenames] [sourcefiles] [@files]\n-overview HTML\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u6982\u8981\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u8AAD\u307F\u8FBC\u3080\n-public public\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u306E\u307F\u3092\u793A\u3059\n-protected protected/public\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u3092\u793A\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8)\n-package package/protected/public\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u3092\u793A\u3059\n-private \u3059\u3079\u3066\u306E\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u3092\u793A\u3059\n-help \u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u8868\u793A\u3057\u3066\u7D42\u4E86\u3059\u308B\n-doclet \u4EE3\u66FFdoclet\u3092\u4ECB\u3057\u3066\u51FA\u529B\u3092\u751F\u6210\u3059\u308B\n-docletpath doclet\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u63A2\u3059\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\n-sourcepath \u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u3042\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\n-classpath \u30E6\u30FC\u30B6\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u3042\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\n-exclude \u9664\u5916\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30B9\u30C8\u3092\u6307\u5B9A\u3059\u308B\n-subpackages \u518D\u5E30\u7684\u306B\u30ED\u30FC\u30C9\u3059\u308B\u30B5\u30D6\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u6307\u5B9A\u3059\u308B\n-breakiterator BreakIterator\u3067\u6700\u521D\u306E\u6587\u3092\u8A08\u7B97\u3059\u308B\n-bootclasspath \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u30FB\u30ED\u30FC\u30C0\u30FC\u306B\u3088\u308A\u30ED\u30FC\u30C9\u3055\u308C\u305F\n\t\t\t \u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u5834\u6240\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n-source \u6307\u5B9A\u3055\u308C\u305F\u30EA\u30EA\u30FC\u30B9\u3068\u30BD\u30FC\u30B9\u306E\u4E92\u63DB\u6027\u3092\u63D0\u4F9B\u3059\u308B\n-extdirs \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u305F\u62E1\u5F35\u6A5F\u80FD\u306E\u5834\u6240\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n-verbose Javadoc\u306E\u52D5\u4F5C\u306B\u3064\u3044\u3066\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u3059\u308B\n-locale en_US\u3084en_US_WIN\u306A\u3069\u306E\u4F7F\u7528\u3059\u308B\u30ED\u30B1\u30FC\u30EB\n-encoding \u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u540D\n-quiet \u72B6\u614B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u306A\u3044\n-J \u3092\u5B9F\u884C\u6642\u30B7\u30B9\u30C6\u30E0\u306B\u76F4\u63A5\u6E21\u3059\n-X \u975E\u6A19\u6E96\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u6982\u8981\u3092\u51FA\u529B\u3059\u308B\n -main.Xusage=-Xmaxerrs \u51FA\u529B\u3059\u308B\u30A8\u30E9\u30FC\u306E\u6700\u5927\u6570\u3092\u8A2D\u5B9A\u3059\u308B\n-Xmaxwarns \u51FA\u529B\u3059\u308B\u8B66\u544A\u306E\u6700\u5927\u6570\u3092\u8A2D\u5B9A\u3059\u308B\n\n\u3053\u308C\u3089\u306F\u975E\u6A19\u6E96\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3042\u308A\u4E88\u544A\u306A\u3057\u306B\u5909\u66F4\u3055\u308C\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002 + +main.usage=\u4F7F\u7528\u65B9\u6CD5: javadoc [options] [packagenames] [sourcefiles] [@files]\n -overview HTML\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u6982\u8981\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u8AAD\u307F\u8FBC\u3080\n -public public\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u306E\u307F\u3092\u793A\u3059\n -protected protected/public\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u3092\u793A\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8)\n -package package/protected/public\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u3092\u793A\u3059\n -private \u3059\u3079\u3066\u306E\u30AF\u30E9\u30B9\u3068\u30E1\u30F3\u30D0\u30FC\u3092\u793A\u3059\n -help \u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u8868\u793A\u3057\u3066\u7D42\u4E86\u3059\u308B\n -doclet \u4EE3\u66FFdoclet\u3092\u4ECB\u3057\u3066\u51FA\u529B\u3092\u751F\u6210\u3059\u308B\n -docletpath doclet\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u63A2\u3059\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\n -sourcepath \u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u3042\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\n -classpath \u30E6\u30FC\u30B6\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u3042\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\n -cp \u30E6\u30FC\u30B6\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u3042\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B\r\n -exclude \u9664\u5916\u3059\u308B\u30D1\u30C3\u30B1\u30FC\u30B8\u30FB\u30EA\u30B9\u30C8\u3092\u6307\u5B9A\u3059\u308B\n -subpackages \u518D\u5E30\u7684\u306B\u30ED\u30FC\u30C9\u3059\u308B\u30B5\u30D6\u30D1\u30C3\u30B1\u30FC\u30B8\u3092\u6307\u5B9A\u3059\u308B\n -breakiterator BreakIterator\u3067\u6700\u521D\u306E\u6587\u3092\u8A08\u7B97\u3059\u308B\n -bootclasspath \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u30FB\u30ED\u30FC\u30C0\u30FC\u306B\u3088\u308A\u30ED\u30FC\u30C9\u3055\u308C\u305F\n \u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u5834\u6240\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n -source \u6307\u5B9A\u3055\u308C\u305F\u30EA\u30EA\u30FC\u30B9\u3068\u30BD\u30FC\u30B9\u306E\u4E92\u63DB\u6027\u3092\u63D0\u4F9B\u3059\u308B\n -extdirs \u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3055\u308C\u305F\u62E1\u5F35\u6A5F\u80FD\u306E\u5834\u6240\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n -verbose Javadoc\u306E\u52D5\u4F5C\u306B\u3064\u3044\u3066\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u51FA\u529B\u3059\u308B\n -locale en_US\u3084en_US_WIN\u306A\u3069\u306E\u4F7F\u7528\u3059\u308B\u30ED\u30B1\u30FC\u30EB\n -encoding \u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u30A8\u30F3\u30B3\u30FC\u30C7\u30A3\u30F3\u30B0\u540D\n -quiet \u72B6\u614B\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u306A\u3044\n -J \u3092\u5B9F\u884C\u6642\u30B7\u30B9\u30C6\u30E0\u306B\u76F4\u63A5\u6E21\u3059\n -X \u975E\u6A19\u6E96\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u6982\u8981\u3092\u51FA\u529B\u3057\u7D42\u4E86\u3059\u308B\n + +main.Xusage=\ -Xmaxerrs \u51FA\u529B\u3059\u308B\u30A8\u30E9\u30FC\u306E\u6700\u5927\u6570\u3092\u8A2D\u5B9A\u3059\u308B\n -Xmaxwarns \u51FA\u529B\u3059\u308B\u8B66\u544A\u306E\u6700\u5927\u6570\u3092\u8A2D\u5B9A\u3059\u308B\n + +main.Xusage.foot=\u3053\u308C\u3089\u306F\u975E\u6A19\u6E96\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3042\u308A\u4E88\u544A\u306A\u3057\u306B\u5909\u66F4\u3055\u308C\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002 + main.option.already.seen={0}\u30AA\u30D7\u30B7\u30E7\u30F3\u304C\u8907\u6570\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059\u3002 main.requires_argument=\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306B\u306F\u5F15\u6570\u304C\u5FC5\u8981\u3067\u3059\u3002 main.locale_first=\u30AA\u30D7\u30B7\u30E7\u30F3-locale\u306F\u3001\u30B3\u30DE\u30F3\u30C9\u30E9\u30A4\u30F3\u306E\u6700\u521D\u306B\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 diff --git a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties index bb16ec27d9b..591f5771a07 100644 --- a/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javadoc/resources/javadoc_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,8 +27,13 @@ main.errors={0} \u4E2A\u9519\u8BEF main.error={0} \u4E2A\u9519\u8BEF main.warnings={0} \u4E2A\u8B66\u544A main.warning={0} \u4E2A\u8B66\u544A -main.usage=\u7528\u6CD5: javadoc [options] [packagenames] [sourcefiles] [@files]\n-overview \u4ECE HTML \u6587\u4EF6\u8BFB\u53D6\u6982\u89C8\u6587\u6863\n-public \u4EC5\u663E\u793A public \u7C7B\u548C\u6210\u5458\n-protected \u663E\u793A protected/public \u7C7B\u548C\u6210\u5458 (\u9ED8\u8BA4\u503C)\n-package \u663E\u793A package/protected/public \u7C7B\u548C\u6210\u5458\n-private \u663E\u793A\u6240\u6709\u7C7B\u548C\u6210\u5458\n-help \u663E\u793A\u547D\u4EE4\u884C\u9009\u9879\u5E76\u9000\u51FA\n-doclet \u901A\u8FC7\u66FF\u4EE3 doclet \u751F\u6210\u8F93\u51FA\n-docletpath \u6307\u5B9A\u67E5\u627E doclet \u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n-sourcepath \u6307\u5B9A\u67E5\u627E\u6E90\u6587\u4EF6\u7684\u4F4D\u7F6E\n-classpath \u6307\u5B9A\u67E5\u627E\u7528\u6237\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n-exclude \u6307\u5B9A\u8981\u6392\u9664\u7684\u7A0B\u5E8F\u5305\u5217\u8868\n-subpackages \u6307\u5B9A\u8981\u9012\u5F52\u52A0\u8F7D\u7684\u5B50\u7A0B\u5E8F\u5305\n-breakiterator \u8BA1\u7B97\u5E26\u6709 BreakIterator \u7684\u7B2C\u4E00\u4E2A\u8BED\u53E5\n-bootclasspath \u8986\u76D6\u7531\u5F15\u5BFC\u7C7B\u52A0\u8F7D\u5668\u6240\u52A0\u8F7D\u7684\n\t\t\t \u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n-source \u63D0\u4F9B\u4E0E\u6307\u5B9A\u53D1\u884C\u7248\u7684\u6E90\u517C\u5BB9\u6027\n-extdirs \u8986\u76D6\u6240\u5B89\u88C5\u6269\u5C55\u7684\u4F4D\u7F6E\n-verbose \u8F93\u51FA\u6709\u5173 Javadoc \u6B63\u5728\u6267\u884C\u7684\u64CD\u4F5C\u7684\u4FE1\u606F\n-locale \u8981\u4F7F\u7528\u7684\u533A\u57DF\u8BBE\u7F6E, \u4F8B\u5982 en_US \u6216 en_US_WIN\n-encoding \u6E90\u6587\u4EF6\u7F16\u7801\u540D\u79F0\n-quiet \u4E0D\u663E\u793A\u72B6\u6001\u6D88\u606F\n-J \u76F4\u63A5\u5C06 \u4F20\u9012\u5230\u8FD0\u884C\u65F6\u7CFB\u7EDF\n-X \u8F93\u51FA\u975E\u6807\u51C6\u9009\u9879\u7684\u63D0\u8981\n -main.Xusage=-Xmaxerrs \u8BBE\u7F6E\u8981\u8F93\u51FA\u7684\u6700\u5927\u9519\u8BEF\u6570\n-Xmaxwarns \u8BBE\u7F6E\u8981\u8F93\u51FA\u7684\u6700\u5927\u8B66\u544A\u6570\n\n\u8FD9\u4E9B\u9009\u9879\u90FD\u662F\u975E\u6807\u51C6\u9009\u9879, \u5982\u6709\u66F4\u6539, \u6055\u4E0D\u53E6\u884C\u901A\u77E5\u3002 + +main.usage=\u7528\u6CD5: javadoc [options] [packagenames] [sourcefiles] [@files]\n -overview \u4ECE HTML \u6587\u4EF6\u8BFB\u53D6\u6982\u89C8\u6587\u6863\n -public \u4EC5\u663E\u793A public \u7C7B\u548C\u6210\u5458\n -protected \u663E\u793A protected/public \u7C7B\u548C\u6210\u5458 (\u9ED8\u8BA4\u503C)\n -package \u663E\u793A package/protected/public \u7C7B\u548C\u6210\u5458\n -private \u663E\u793A\u6240\u6709\u7C7B\u548C\u6210\u5458\n -help \u663E\u793A\u547D\u4EE4\u884C\u9009\u9879\u5E76\u9000\u51FA\n -doclet \u901A\u8FC7\u66FF\u4EE3 doclet \u751F\u6210\u8F93\u51FA\n -docletpath \u6307\u5B9A\u67E5\u627E doclet \u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n -sourcepath \u6307\u5B9A\u67E5\u627E\u6E90\u6587\u4EF6\u7684\u4F4D\u7F6E\n -classpath \u6307\u5B9A\u67E5\u627E\u7528\u6237\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n -cp \u6307\u5B9A\u67E5\u627E\u7528\u6237\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n -exclude \u6307\u5B9A\u8981\u6392\u9664\u7684\u7A0B\u5E8F\u5305\u5217\u8868\n -subpackages \u6307\u5B9A\u8981\u9012\u5F52\u52A0\u8F7D\u7684\u5B50\u7A0B\u5E8F\u5305\n -breakiterator \u8BA1\u7B97\u5E26\u6709 BreakIterator \u7684\u7B2C\u4E00\u4E2A\u8BED\u53E5\n -bootclasspath \u8986\u76D6\u7531\u5F15\u5BFC\u7C7B\u52A0\u8F7D\u5668\u6240\u52A0\u8F7D\u7684\n \u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E\n -source \u63D0\u4F9B\u4E0E\u6307\u5B9A\u53D1\u884C\u7248\u7684\u6E90\u517C\u5BB9\u6027\n -extdirs \u8986\u76D6\u6240\u5B89\u88C5\u6269\u5C55\u7684\u4F4D\u7F6E\n -verbose \u8F93\u51FA\u6709\u5173 Javadoc \u6B63\u5728\u6267\u884C\u7684\u64CD\u4F5C\u7684\u4FE1\u606F\n -locale \u8981\u4F7F\u7528\u7684\u533A\u57DF\u8BBE\u7F6E, \u4F8B\u5982 en_US \u6216 en_US_WIN\n -encoding \u6E90\u6587\u4EF6\u7F16\u7801\u540D\u79F0\n -quiet \u4E0D\u663E\u793A\u72B6\u6001\u6D88\u606F\n -J \u76F4\u63A5\u5C06 \u4F20\u9012\u5230\u8FD0\u884C\u65F6\u7CFB\u7EDF\n -X \u8F93\u51FA\u975E\u6807\u51C6\u9009\u9879\u7684\u63D0\u8981\n + +main.Xusage=\ -Xmaxerrs \u8BBE\u7F6E\u8981\u8F93\u51FA\u7684\u6700\u5927\u9519\u8BEF\u6570\n -Xmaxwarns \u8BBE\u7F6E\u8981\u8F93\u51FA\u7684\u6700\u5927\u8B66\u544A\u6570\n + +main.Xusage.foot=\u8FD9\u4E9B\u9009\u9879\u90FD\u662F\u975E\u6807\u51C6\u9009\u9879, \u5982\u6709\u66F4\u6539, \u6055\u4E0D\u53E6\u884C\u901A\u77E5\u3002 + main.option.already.seen={0}\u9009\u9879\u53EA\u80FD\u6307\u5B9A\u4E00\u6B21\u3002 main.requires_argument=\u9009\u9879{0}\u9700\u8981\u53C2\u6570\u3002 main.locale_first=\u5728\u547D\u4EE4\u884C\u4E2D, \u9009\u9879 -locale \u5FC5\u987B\u4E3A\u7B2C\u4E00\u4E2A\u9009\u9879\u3002 diff --git a/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_ja.properties b/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_ja.properties index 6a5e90e7836..27aa006bdc6 100644 --- a/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ tracing.not.supported=\u8B66\u544A: \u30C8\u30EC\u30FC\u30B9\u306F\u73FE\u5728\u # # Usage message. # -usage=\u4F7F\u7528\u65B9\u6CD5: javah [options] \n\n[options]\u306B\u306F\u6B21\u306E\u3082\u306E\u304C\u3042\u308A\u307E\u3059\u3002\n\n\t-help \u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u3066\u7D42\u4E86\u3059\u308B\n\t-classpath \u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9\n\t-bootclasspath \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9\n\t-d

        \u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n\t-o \u51FA\u529B\u30D5\u30A1\u30A4\u30EB(-d\u304B-o\u306E\u3069\u3061\u3089\u304B\u4E00\u65B9\u3092\u4F7F\u7528\u3059\u308B)\n\t-jni JNI\u5F62\u5F0F\u306E\u30D8\u30C3\u30C0\u30FC\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3059\u308B(\u30C7\u30D5\u30A9\u30EB\u30C8)\n\t-version \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3059\u308B\n\t-verbose \u8A73\u7D30\u306A\u51FA\u529B\u3092\u884C\u3046\n\t-force \u5E38\u306B\u51FA\u529B\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080\n\n \u306F\u5B8C\u5168\u6307\u5B9A\u306E\u540D\u524D\u3067\u6307\u5B9A\u3057\u307E\u3059\n(java.lang.Object\u306A\u3069)\u3002\n +usage=\u4F7F\u7528\u65B9\u6CD5: javah [options] \n\n[options]\u306B\u306F\u6B21\u306E\u3082\u306E\u304C\u3042\u308A\u307E\u3059\u3002\n\n\t-help \u30D8\u30EB\u30D7\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u3066\u7D42\u4E86\u3059\u308B\n\t-classpath \u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9\n\t-cp \u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9\r\n\t-bootclasspath \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9\n\t-d \u51FA\u529B\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n\t-o \u51FA\u529B\u30D5\u30A1\u30A4\u30EB(-d\u304B-o\u306E\u3069\u3061\u3089\u304B\u4E00\u65B9\u3092\u4F7F\u7528\u3059\u308B)\n\t-jni JNI\u5F62\u5F0F\u306E\u30D8\u30C3\u30C0\u30FC\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3059\u308B(\u30C7\u30D5\u30A9\u30EB\u30C8)\n\t-version \u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\u8868\u793A\u3059\u308B\n\t-verbose \u8A73\u7D30\u306A\u51FA\u529B\u3092\u884C\u3046\n\t-force \u5E38\u306B\u51FA\u529B\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080\n\n\u306F\u5B8C\u5168\u6307\u5B9A\u306E\u540D\u524D\u3067\u6307\u5B9A\u3057\u307E\u3059\n(java.lang.Object\u306A\u3069)\u3002\n main.usage=\u4F7F\u7528\u65B9\u6CD5: \n javah [options] \n[options]\u306B\u306F\u6B21\u306E\u3082\u306E\u304C\u3042\u308A\u307E\u3059\u3002 main.opt.o=\ -o \u51FA\u529B\u30D5\u30A1\u30A4\u30EB(-d\u304B-o\u306E\u3069\u3061\u3089\u304B\u4E00\u65B9\u3092\u4F7F\u7528\u3059\u308B) @@ -60,6 +60,7 @@ main.opt.version=\ -version \u30D0\u30FC\u30B8\u30E7\u30F3\u60C main.opt.jni=\ -jni JNI\u5F62\u5F0F\u306E\u30D8\u30C3\u30C0\u30FC\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u751F\u6210\u3059\u308B(\u30C7\u30D5\u30A9\u30EB\u30C8) main.opt.force=\ -force \u5E38\u306B\u51FA\u529B\u30D5\u30A1\u30A4\u30EB\u3092\u66F8\u304D\u8FBC\u3080 main.opt.classpath=\ -classpath \u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9 +main.opt.cp=\ -cp \u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9 main.opt.bootclasspath=\ -bootclasspath \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u3092\u30ED\u30FC\u30C9\u3059\u308B\u30D1\u30B9 main.usage.foot=\u306F\u5B8C\u5168\u6307\u5B9A\u306E\u540D\u524D\u3067\u6307\u5B9A\u3057\u307E\u3059\n(java.lang.Object\u306A\u3069)\u3002 @@ -90,7 +91,7 @@ unknown.type.in.method.signature=\u53E4\u3044\u5F62\u5F0F\u306E\u30B9\u30BF\u30D err.prefix=\u30A8\u30E9\u30FC: err.cant.use.option.for.fm=\u6307\u5B9A\u3055\u308C\u305F\u30D5\u30A1\u30A4\u30EB\u30FB\u30DE\u30CD\u30FC\u30B8\u30E3\u3067{0}\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 err.internal.error=\u5185\u90E8\u30A8\u30E9\u30FC: {0} -err.ioerror=\u5165\u51FA\u529B\u30A8\u30E9\u30FC: {0} +err.ioerror=IO\u30A8\u30E9\u30FC: {0} err.missing.arg={0}\u306E\u5024\u304C\u3042\u308A\u307E\u305B\u3093 err.no.classes.specified=\u30AF\u30E9\u30B9\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 err.unknown.option=\u4E0D\u660E\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0} diff --git a/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_zh_CN.properties index 995b1cad499..e4565df67fd 100644 --- a/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javah/resources/l10n_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -49,7 +49,7 @@ tracing.not.supported=\u8B66\u544A: \u4E0D\u518D\u652F\u6301\u8DDF\u8E2A\u3002\u # # Usage message. # -usage=\u7528\u6CD5: javah [options] \n\n\u5176\u4E2D, [options] \u5305\u62EC:\n\n\t-help \u8F93\u51FA\u6B64\u5E2E\u52A9\u6D88\u606F\u5E76\u9000\u51FA\n\t-classpath \u4ECE\u4E2D\u52A0\u8F7D\u7C7B\u7684\u8DEF\u5F84\n\t-bootclasspath \u4ECE\u4E2D\u52A0\u8F7D\u5F15\u5BFC\u7C7B\u7684\u8DEF\u5F84\n\t-d \u8F93\u51FA\u76EE\u5F55\n\t-o \u8F93\u51FA\u6587\u4EF6 (\u53EA\u80FD\u4F7F\u7528 -d \u6216 -o \u4E4B\u4E00)\n\t-jni \u751F\u6210 JNI \u6837\u5F0F\u7684\u6807\u5934\u6587\u4EF6 (\u9ED8\u8BA4\u503C)\n\t-version \u8F93\u51FA\u7248\u672C\u4FE1\u606F\n\t-verbose \u542F\u7528\u8BE6\u7EC6\u8F93\u51FA\n\t-force \u59CB\u7EC8\u5199\u5165\u8F93\u51FA\u6587\u4EF6\n\n \u662F\u4F7F\u7528\u5176\u5168\u9650\u5B9A\u540D\u79F0\u6307\u5B9A\u7684,\n(\u4F8B\u5982 java.lang.Object)\u3002\n +usage=\u7528\u6CD5: javah [options] \n\n\u5176\u4E2D, [options] \u5305\u62EC:\n\n\t-help \u8F93\u51FA\u6B64\u5E2E\u52A9\u6D88\u606F\u5E76\u9000\u51FA\n\t-classpath \u4ECE\u4E2D\u52A0\u8F7D\u7C7B\u7684\u8DEF\u5F84\n\t-cp \u4ECE\u4E2D\u52A0\u8F7D\u7C7B\u7684\u8DEF\u5F84\n\t-bootclasspath \u4ECE\u4E2D\u52A0\u8F7D\u5F15\u5BFC\u7C7B\u7684\u8DEF\u5F84\n\t-d \u8F93\u51FA\u76EE\u5F55\n\t-o \u8F93\u51FA\u6587\u4EF6 (\u53EA\u80FD\u4F7F\u7528 -d \u6216 -o \u4E4B\u4E00)\n\t-jni \u751F\u6210 JNI \u6837\u5F0F\u7684\u6807\u5934\u6587\u4EF6 (\u9ED8\u8BA4\u503C)\n\t-version \u8F93\u51FA\u7248\u672C\u4FE1\u606F\n\t-verbose \u542F\u7528\u8BE6\u7EC6\u8F93\u51FA\n\t-force \u59CB\u7EC8\u5199\u5165\u8F93\u51FA\u6587\u4EF6\n\n \u662F\u4F7F\u7528\u5176\u5168\u9650\u5B9A\u540D\u79F0\u6307\u5B9A\u7684,\n(\u4F8B\u5982, java.lang.Object)\u3002\n main.usage=\u7528\u6CD5: \n javah [options] \n\u5176\u4E2D, [options] \u5305\u62EC: main.opt.o=\ -o \u8F93\u51FA\u6587\u4EF6 (\u53EA\u80FD\u4F7F\u7528 -d \u6216 -o \u4E4B\u4E00) @@ -60,6 +60,7 @@ main.opt.version=\ -version \u8F93\u51FA\u7248\u672C\u4FE1\u606 main.opt.jni=\ -jni \u751F\u6210 JNI \u6837\u5F0F\u7684\u6807\u5934\u6587\u4EF6 (\u9ED8\u8BA4\u503C) main.opt.force=\ -force \u59CB\u7EC8\u5199\u5165\u8F93\u51FA\u6587\u4EF6 main.opt.classpath=\ -classpath \u4ECE\u4E2D\u52A0\u8F7D\u7C7B\u7684\u8DEF\u5F84 +main.opt.cp=\ -cp \u4ECE\u4E2D\u52A0\u8F7D\u7C7B\u7684\u8DEF\u5F84 main.opt.bootclasspath=\ -bootclasspath \u4ECE\u4E2D\u52A0\u8F7D\u5F15\u5BFC\u7C7B\u7684\u8DEF\u5F84 main.usage.foot= \u662F\u4F7F\u7528\u5176\u5168\u9650\u5B9A\u540D\u79F0\u6307\u5B9A\u7684\n(\u4F8B\u5982, java.lang.Object)\u3002 diff --git a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java index 657194d19c6..6211a2a13cf 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java +++ b/langtools/src/share/classes/com/sun/tools/javap/CodeWriter.java @@ -208,7 +208,7 @@ public class CodeWriter extends BasicWriter { public void writeExceptionTable(Code_attribute attr) { - if (attr.exception_table_langth > 0) { + if (attr.exception_table_length > 0) { println("Exception table:"); indent(+1); println(" from to target type"); diff --git a/langtools/src/share/classes/com/sun/tools/javap/resources/javap_ja.properties b/langtools/src/share/classes/com/sun/tools/javap/resources/javap_ja.properties index e5b96053f10..72787232d52 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/resources/javap_ja.properties +++ b/langtools/src/share/classes/com/sun/tools/javap/resources/javap_ja.properties @@ -1,5 +1,5 @@ -err.prefix=\u30A8\u30E9\u30FC: +err.prefix=\u30A8\u30E9\u30FC: err.bad.constant.pool={0}\u306E\u5B9A\u6570\u30D7\u30FC\u30EB\u306E\u8AAD\u53D6\u308A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F: {1} err.class.not.found=\u30AF\u30E9\u30B9\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0} @@ -55,6 +55,8 @@ main.opt.s=\ -s \u5185\u90E8\u30BF\u30A4\u30D7\u7F72\u540 main.opt.classpath=\ -classpath \u30E6\u30FC\u30B6\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B +main.opt.cp=\ -cp \u30E6\u30FC\u30B6\u30FC\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u691C\u7D22\u3059\u308B\u5834\u6240\u3092\u6307\u5B9A\u3059\u308B + main.opt.bootclasspath=\ -bootclasspath \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306E\u4F4D\u7F6E\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B main.opt.constants=\ -constants \u9759\u7684final\u5B9A\u6570\u3092\u8868\u793A\u3059\u308B diff --git a/langtools/src/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties b/langtools/src/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties index 97e4f5ce972..b9027ec9500 100644 --- a/langtools/src/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties +++ b/langtools/src/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties @@ -1,5 +1,5 @@ -err.prefix=\u9519\u8BEF: +err.prefix=\u9519\u8BEF: err.bad.constant.pool=\u8BFB\u53D6{0}\u7684\u5E38\u91CF\u6C60\u65F6\u51FA\u9519: {1} err.class.not.found=\u627E\u4E0D\u5230\u7C7B: {0} @@ -55,6 +55,8 @@ main.opt.s=\ -s \u8F93\u51FA\u5185\u90E8\u7C7B\u578B\u7B7 main.opt.classpath=\ -classpath \u6307\u5B9A\u67E5\u627E\u7528\u6237\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E +main.opt.cp=\ -cp \u6307\u5B9A\u67E5\u627E\u7528\u6237\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E + main.opt.bootclasspath=\ -bootclasspath \u8986\u76D6\u5F15\u5BFC\u7C7B\u6587\u4EF6\u7684\u4F4D\u7F6E main.opt.constants=\ -constants \u663E\u793A\u9759\u6001\u6700\u7EC8\u5E38\u91CF diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java b/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java index 9b90950290c..43606b2b715 100644 --- a/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java +++ b/langtools/src/share/classes/com/sun/tools/sjavac/BuildState.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,12 +81,13 @@ public class BuildState { } /** - * Collect all packages, sources and artifacts for all modules - * into the build state. + * Store references to all packages, sources and artifacts for all modules + * into the build state. I.e. flatten the module tree structure + * into global maps stored in the BuildState for easy access. * * @param m The set of modules. */ - public void collectPackagesSourcesAndArtifacts(Map m) { + public void flattenPackagesSourcesAndArtifacts(Map m) { modules = m; // Extract all the found packages. for (Module i : modules.values()) { @@ -121,11 +122,12 @@ public class BuildState { } /** - * Collect all the artifacts of all modules and packages. + * Store references to all artifacts found in the module tree into the maps + * stored in the build state. * * @param m The set of modules. */ - public void collectArtifacts(Map m) { + public void flattenArtifacts(Map m) { modules = m; // Extract all the found packages. for (Module i : modules.values()) { @@ -270,6 +272,8 @@ public class BuildState { Module mnew = findModuleFromPackageName(pkg); Package pprev = prev.packages().get(pkg); mnew.addPackage(pprev); + // Do not forget to update the flattened data. + packages.put(pkg, pprev); } } } diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/Main.java b/langtools/src/share/classes/com/sun/tools/sjavac/Main.java index f0ed51432ee..183ebb56e27 100644 --- a/langtools/src/share/classes/com/sun/tools/sjavac/Main.java +++ b/langtools/src/share/classes/com/sun/tools/sjavac/Main.java @@ -274,7 +274,7 @@ public class Main { // findFiles(args, "-modulepath", Util.set(".class"), modules_to_link_to, modules, current_module, true); // Add the set of sources to the build database. - javac_state.now().collectPackagesSourcesAndArtifacts(modules); + javac_state.now().flattenPackagesSourcesAndArtifacts(modules); javac_state.now().checkInternalState("checking sources", false, sources); javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to); javac_state.setVisibleSources(sources_to_link_to); @@ -311,7 +311,7 @@ public class Main { Map generated_sources = new HashMap(); Source.scanRoot(gensrc_dir, Util.set(".java"), null, null, null, null, generated_sources, modules, current_module, false, true, false); - javac_state.now().collectPackagesSourcesAndArtifacts(modules); + javac_state.now().flattenPackagesSourcesAndArtifacts(modules); // Recheck the the source files and their timestamps again. javac_state.checkSourceStatus(true); @@ -336,8 +336,8 @@ public class Main { // Only update the state if the compile went well. if (rc[0]) { javac_state.save(); - // Collect all the artifacts. - javac_state.now().collectArtifacts(modules); + // Reflatten only the artifacts. + javac_state.now().flattenArtifacts(modules); // Remove artifacts that were generated during the last compile, but not this one. javac_state.removeSuperfluousArtifacts(recently_compiled); } diff --git a/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java b/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java index 2e59f275fd8..66e3022a76e 100644 --- a/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java +++ b/langtools/src/share/classes/com/sun/tools/sjavac/server/JavacServer.java @@ -464,7 +464,7 @@ public class JavacServer { PrintStream err) { int rc = -3; try { - int port = portFile.getPort(); + int port = portFile.containsPortInfo() ? portFile.getPort() : 0; if (port == 0) { return ERROR_BUT_TRY_AGAIN; } diff --git a/langtools/test/com/sun/javadoc/AccessSkipNav/AccessSkipNav.java b/langtools/test/com/sun/javadoc/AccessSkipNav/AccessSkipNav.java index d88329cb5db..6ad89feb8bf 100644 --- a/langtools/test/com/sun/javadoc/AccessSkipNav/AccessSkipNav.java +++ b/langtools/test/com/sun/javadoc/AccessSkipNav/AccessSkipNav.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4638136 + * @bug 4638136 7198273 * @summary Add ability to skip over nav bar for accessibility * @author dkramer * @run main AccessSkipNav @@ -42,7 +42,7 @@ import java.io.*; */ public class AccessSkipNav { - private static final String BUGID = "4638136"; + private static final String BUGID = "4638136 - 7198273"; private static final String BUGNAME = "AccessSkipNav"; private static final String FS = System.getProperty("file.separator"); private static final String PS = System.getProperty("path.separator"); @@ -86,7 +86,7 @@ public class AccessSkipNav { // Testing only for the presence of the and // Top navbar - { "", + { "Skip navigation links", TMPDEST_DIR1 + "p1" + FS + "C1.html" }, // Top navbar @@ -95,7 +95,7 @@ public class AccessSkipNav { TMPDEST_DIR1 + "p1" + FS + "C1.html" }, // Bottom navbar - { "", + { "Skip navigation links", TMPDEST_DIR1 + "p1" + FS + "C1.html" }, // Bottom navbar diff --git a/langtools/test/com/sun/javadoc/lib/JavadocTester.java b/langtools/test/com/sun/javadoc/lib/JavadocTester.java index 23b8c80482e..e5af454fee8 100644 --- a/langtools/test/com/sun/javadoc/lib/JavadocTester.java +++ b/langtools/test/com/sun/javadoc/lib/JavadocTester.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,7 @@ public abstract class JavadocTester { protected static final String SRC_DIR = System.getProperty("test.src", "."); protected static final String JAVA_VERSION = System.getProperty("java.version"); protected static final String[][] NO_TEST = new String[][] {}; + protected static final String[] NO_FILE_TEST = new String[] {}; /** * Use this as the file name in the test array when you want to search @@ -165,6 +166,26 @@ public abstract class JavadocTester { return returnCode; } + /** + * Execute the tests. + * + * @param tester the tester to execute + * @param args the arguments to pass to Javadoc + * @param testArray the array of tests + * @param negatedTestArray the array of negated tests + * @param fileTestArray the array of file tests + * @param negatedFileTestArray the array of negated file tests + * @return the return code for the execution of Javadoc + */ + public static int run(JavadocTester tester, String[] args, + String[][] testArray, String[][] negatedTestArray, String[] fileTestArray, + String[] negatedFileTestArray) { + int returnCode = tester.runJavadoc(args); + tester.runTestsOnHTML(testArray, negatedTestArray); + tester.runTestsOnFile(fileTestArray, negatedFileTestArray); + return returnCode; + } + /** * Execute Javadoc using the default doclet. * @@ -243,6 +264,19 @@ public abstract class JavadocTester { runTestsOnHTML(negatedTestArray, true); } + /** + * Run array of tests on the generated files. + * This method accepts a fileTestArray for testing if a file is generated + * and a negatedFileTestArray for testing if a file is not found. + * + * @param testArray the array of file tests + * @param negatedTestArray the array of negated file tests + */ + public void runTestsOnFile(String[] fileTestArray, String[] negatedFileTestArray) { + runTestsOnFile(fileTestArray, false); + runTestsOnFile(negatedFileTestArray, true); + } + /** * Run the array of tests on the resulting HTML. * @@ -265,9 +299,11 @@ public abstract class JavadocTester { fileString = readFileToString(testArray[i][0]); } catch (Error e) { if (isNegated) { - numTestsPassed += 1; - System.out.println("Passed\n not found:\n" - + stringToFind + " in non-existent " + testArray[i][0] + "\n"); + System.out.println( "FAILED" + "\n" + + "for bug " + getBugId() + + " (" + getBugName() + ") " + + "due to " + + e + "\n"); continue; } throw e; @@ -290,6 +326,39 @@ public abstract class JavadocTester { } } + /** + * Run the array of file tests on the generated files. + * + * @param testArray the array of file tests + * @param isNegated true if test is negated; false otherwise + */ + private void runTestsOnFile(String[] testArray, boolean isNegated) { + String fileName; + String failedString; + String passedString; + for (int i = 0; i < testArray.length; i++) { + numTestsRun++; + fileName = testArray[i]; + failedString = "FAILED" + "\n" + + "for bug " + getBugId() + " (" + getBugName() + ") " + + "file (" + fileName + ") found" + "\n"; + passedString = "Passed" + "\n" + + "file (" + fileName + ") not found" + "\n"; + System.out.print("Running subtest #" + numTestsRun + "... "); + try { + File file = new File(fileName); + if ((file.exists() && !isNegated) || (!file.exists() && isNegated)) { + numTestsPassed += 1; + System.out.println(passedString); + } else { + System.out.println(failedString); + } + } catch (Error e) { + System.err.println(e); + } + } + } + /** * Iterate through the list of given file pairs and diff each file. * diff --git a/langtools/test/com/sun/javadoc/testAnnotationTypes/TestAnnotationTypes.java b/langtools/test/com/sun/javadoc/testAnnotationTypes/TestAnnotationTypes.java index 65a8e5d7cfa..5ffdbab12b2 100644 --- a/langtools/test/com/sun/javadoc/testAnnotationTypes/TestAnnotationTypes.java +++ b/langtools/test/com/sun/javadoc/testAnnotationTypes/TestAnnotationTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,20 +23,19 @@ /* * @test - * @bug 4973609 + * @bug 4973609 8015249 * @summary Make sure that annotation types with 0 members does not have * extra HR tags. * @author jamieh * @library ../lib/ - * @build JavadocTester - * @build TestAnnotationTypes + * @build JavadocTester TestAnnotationTypes * @run main TestAnnotationTypes */ public class TestAnnotationTypes extends JavadocTester { //Test information. - private static final String BUG_ID = "4973609"; + private static final String BUG_ID = "4973609-8015249"; //Javadoc arguments. private static final String[] ARGS = new String[] { @@ -44,7 +43,31 @@ public class TestAnnotationTypes extends JavadocTester { }; //Input for string search tests. - private static final String[][] TEST = NO_TEST; + private static final String[][] TEST = { + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + "
      • Summary: 
      • " + NL + "
      • Field | 
      • "}, + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + "
      • Detail: 
      • " + NL + "
      • Field | 
      • "}, + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + ""}, + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + "

        Field Summary

        "}, + {BUG_ID + FS + "pkg" + FS + "AnnotationTypeField.html", + "

    DEFAULT_NAME" + + " 
    " + - "
    Finish this class.
    "}}; + "
    Finish this class.
    "}, + {BUG_ID + FS + "C.html", + "
    To Do:
    " + + "
    Tag in Method.
    "} + }; private static final String[][] NEGATED_TEST = NO_TEST; @@ -59,6 +60,9 @@ public class TestLegacyTaglet extends JavadocTester { public static void main(String[] args) { TestLegacyTaglet tester = new TestLegacyTaglet(); run(tester, ARGS, TEST, NEGATED_TEST); + if (tester.getErrorOutput().contains("NullPointerException")) { + throw new AssertionError("javadoc threw NullPointerException"); + } tester.printSummary(); } diff --git a/langtools/test/com/sun/javadoc/testLinkTaglet/TestLinkTaglet.java b/langtools/test/com/sun/javadoc/testLinkTaglet/TestLinkTaglet.java index 4720fe4d2be..ef9dd2bbb9a 100644 --- a/langtools/test/com/sun/javadoc/testLinkTaglet/TestLinkTaglet.java +++ b/langtools/test/com/sun/javadoc/testLinkTaglet/TestLinkTaglet.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4732864 6280605 7064544 8014636 + * @bug 4732864 6280605 7064544 8014636 8016328 * @summary Make sure that you can link from one member to another using * non-qualified name, furthermore, ensure the right one is linked. * @author jamieh @@ -49,9 +49,9 @@ public class TestLinkTaglet extends JavadocTester { "Qualified Link: C.InnerC.
    " + NL + " Unqualified Link1: C.InnerC.
    " + NL + " Unqualified Link2: C.InnerC.
    " + NL + - " Qualified Link: method(pkg.C.InnerC, pkg.C.InnerC2).
    " + NL + - " Unqualified Link: method(C.InnerC, C.InnerC2).
    " + NL + - " Unqualified Link: method(InnerC, InnerC2).
    " + " Qualified Link: method(pkg.C.InnerC, pkg.C.InnerC2).
    " + NL + + " Unqualified Link: method(C.InnerC, C.InnerC2).
    " + NL + + " Unqualified Link: method(InnerC, InnerC2).
    " }, {BUG_ID + FS + "pkg" + FS + "C.InnerC.html", "Link to member in outer class: C.MEMBER
    " + NL + diff --git a/langtools/test/com/sun/javadoc/testMethodTypes/TestMethodTypes.java b/langtools/test/com/sun/javadoc/testMethodTypes/TestMethodTypes.java index 634ee4e4407..b0b79de0981 100644 --- a/langtools/test/com/sun/javadoc/testMethodTypes/TestMethodTypes.java +++ b/langtools/test/com/sun/javadoc/testMethodTypes/TestMethodTypes.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 8002304 + * @bug 8002304 8024096 * @summary Test for various method types in the method summary table * @author Bhavesh Patel * @library ../lib/ @@ -107,7 +107,7 @@ public class TestMethodTypes extends JavadocTester { "" }, - {BUG_ID + FS + "pkg" + FS + "D.html", + {BUG_ID + FS + "pkg1" + FS + "D.html", "Methods " + "" }, diff --git a/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java b/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java index 9fefe1b7869..4466eb87d0e 100644 --- a/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java +++ b/langtools/test/com/sun/javadoc/testNavigation/TestNavigation.java @@ -23,13 +23,12 @@ /* * @test - * @bug 4131628 4664607 7025314 + * @bug 4131628 4664607 7025314 8023700 7198273 * @summary Make sure the Next/Prev Class links iterate through all types. * Make sure the navagation is 2 columns, not 3. * @author jamieh * @library ../lib/ - * @build JavadocTester - * @build TestNavigation + * @build JavadocTester TestNavigation * @run main TestNavigation */ @@ -45,23 +44,23 @@ public class TestNavigation extends JavadocTester { //Input for string search tests. private static final String[][] TEST = { - {BUG_ID + FS + "pkg" + FS + "A.html", "
  • Prev Class
  • "}, + {BUG_ID + FS + "pkg" + FS + "A.html", "
  • Prev Class
  • "}, {BUG_ID + FS + "pkg" + FS + "A.html", - "Next Class"}, + "Next Class"}, {BUG_ID + FS + "pkg" + FS + "C.html", - "Prev Class"}, + "Prev Class"}, {BUG_ID + FS + "pkg" + FS + "C.html", - "Next Class"}, + "Next Class"}, {BUG_ID + FS + "pkg" + FS + "E.html", - "Prev Class"}, + "Prev Class"}, {BUG_ID + FS + "pkg" + FS + "E.html", - "Next Class"}, + "Next Class"}, {BUG_ID + FS + "pkg" + FS + "I.html", - "Prev Class"}, - {BUG_ID + FS + "pkg" + FS + "I.html", "
  • Next Class
  • "}, + "Prev Class"}, + {BUG_ID + FS + "pkg" + FS + "I.html", "
  • Next Class
  • "}, // Test for 4664607 {BUG_ID + FS + "pkg" + FS + "I.html", - "" + NL + + "" + NL + "" + NL + "" + NL + ""} }; private static final String[][] NEGATED_TEST = NO_TEST; diff --git a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java index e16fd5450f2..ad0e024bfe6 100644 --- a/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java +++ b/langtools/test/com/sun/javadoc/testNewLanguageFeatures/TestNewLanguageFeatures.java @@ -155,13 +155,13 @@ public class TestNewLanguageFeatures extends JavadocTester { //================================= //Make sure the summary links are correct. {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", - "
  • Summary: 
  • " + NL + + "
  • Summary: 
  • " + NL + "
  • Field | 
  • " + NL + "
  • " + "Required | 
  • " + NL + "
  • " + "Optional
  • "}, //Make sure the detail links are correct. {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", - "
  • Detail: 
  • " + NL + + "
  • Detail: 
  • " + NL + "
  • Field | 
  • " + NL + "
  • Element
  • "}, //Make sure the heading is correct. {BUG_ID + FS + "pkg" + FS + "AnnotationType.html", diff --git a/langtools/test/com/sun/javadoc/testPrivateClasses/TestPrivateClasses.java b/langtools/test/com/sun/javadoc/testPrivateClasses/TestPrivateClasses.java index b6ae263d8a4..b7a9bc73a10 100644 --- a/langtools/test/com/sun/javadoc/testPrivateClasses/TestPrivateClasses.java +++ b/langtools/test/com/sun/javadoc/testPrivateClasses/TestPrivateClasses.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4780441 4874845 4978816 8014017 + * @bug 4780441 4874845 4978816 8014017 8016328 * @summary Make sure that when the -private flag is not used, members * inherited from package private class are documented in the child. * @@ -177,7 +177,7 @@ public class TestPrivateClasses extends JavadocTester { // Should document that a method overrides method from private class. {BUG_ID + "-2" + FS + "pkg" + FS + "PublicChild.html", "
    Overrides:
    " + NL + - "
    " + + "
    " + "methodOverridenFromParent in class " + "" + "PrivateParent
    "}, diff --git a/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java b/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java index 7d878d7ecd3..4dd70ea2359 100644 --- a/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java +++ b/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java @@ -23,9 +23,9 @@ /* * @test - * @bug 8006124 8009684 8016921 + * @bug 8006124 8009684 8016921 8023700 8024096 * @summary Test javadoc support for profiles. - * @author Bhavesh Patel + * @author Bhavesh Patel, Evgeniya Stepanova * @library ../lib/ * @build JavadocTester TestProfiles * @run main TestProfiles @@ -38,8 +38,9 @@ public class TestProfiles extends JavadocTester { private static final String PACKAGE_BUG_ID = BUG_ID + "-2"; //Javadoc arguments. private static final String[] ARGS1 = new String[]{ - "-d", PROFILE_BUG_ID, "-sourcepath", SRC_DIR, "-Xprofilespath", SRC_DIR + FS - + "profile-rtjar-includes.txt", "pkg1", "pkg2", "pkg3", "pkg4", "pkg5" + "-d", PROFILE_BUG_ID, "-sourcepath", SRC_DIR, "-Xprofilespath", + SRC_DIR + FS + "profile-rtjar-includes.txt", "pkg1", "pkg2", + "pkg3", "pkg4", "pkg5", "pkgDeprecated" }; private static final String[] ARGS2 = new String[]{ "-d", PACKAGE_BUG_ID, "-sourcepath", SRC_DIR, "pkg1", "pkg2", "pkg3", "pkg4", "pkg5" @@ -49,7 +50,7 @@ public class TestProfiles extends JavadocTester { // Tests for profile-overview-frame.html listing all profiles. {PROFILE_BUG_ID + FS + "profile-overview-frame.html", "All Packages" + + "target=\"packageListFrame\">All Packages" }, {PROFILE_BUG_ID + FS + "profile-overview-frame.html", "
  • " @@ -58,8 +59,8 @@ public class TestProfiles extends JavadocTester { // Tests for profileName-frame.html listing all packages in a profile. {PROFILE_BUG_ID + FS + "compact2-frame.html", "" - + "All PackagesAll Profiles" + + "All PackagesAll Profiles" }, {PROFILE_BUG_ID + FS + "compact2-frame.html", "
  • Prev Profile
  • " + NL - + "
  • Next Profile
  • " + "
  • Prev Profile
  • " + NL + + "
  • Next Profile
  • " }, {PROFILE_BUG_ID + FS + "compact2-summary.html", "

    Profile compact2

    " @@ -87,7 +88,7 @@ public class TestProfiles extends JavadocTester { // Tests for profileName-package-summary.html listing the summary for a // package in a profile. {PROFILE_BUG_ID + FS + "pkg5" + FS + "compact3-package-summary.html", - "
  • Prev Package" + "
  • Prev Package" + "
  • " }, {PROFILE_BUG_ID + FS + "pkg5" + FS + "compact3-package-summary.html", @@ -96,7 +97,7 @@ public class TestProfiles extends JavadocTester { //Test for "overview-frame.html" showing the "All Profiles" link. {PROFILE_BUG_ID + FS + "overview-frame.html", "All Profiles" + + "target=\"packageListFrame\">All Profiles" }, //Test for "className.html" showing the profile information for the type. {PROFILE_BUG_ID + FS + "pkg2" + FS + "Class1Pkg2.html", @@ -113,6 +114,49 @@ public class TestProfiles extends JavadocTester { "target=\"classFrame\">compact2" + NL + "
  • compact3
  • " + NL + "" + }, + //Test deprecated class in profiles + {PROFILE_BUG_ID + FS + "compact1-summary.html","" + + "Class1Pkg2" + + NL + "Deprecated" + }, + {PROFILE_BUG_ID + FS + "deprecated-list.html","" + + "pkg2.Class1Pkg2" + + NL +"
    Class1Pkg2. This class is deprecated
    " + }, + //Test deprecated package in profile + {PROFILE_BUG_ID + FS + "deprecated-list.html","" + + "pkgDeprecated" + + NL +"
    This package is Deprecated." + + " Use pkg1.
    " + }, + {PROFILE_BUG_ID + FS + "pkgDeprecated" + FS + "package-summary.html", + "
    Deprecated." + + NL + "
    This package is Deprecated." + + " Use pkg1.
    " + }, + // need to add teststring when JDK-8015496 will be fixed + //Test exception in profiles + {PROFILE_BUG_ID + FS + "compact1-summary.html","" + + NL + "" + NL + "" + NL + "" + NL + "" + NL + "" + NL + "" + NL + "" + + NL + "" + }, + //Test errors in profiles + {PROFILE_BUG_ID + FS + "compact1-summary.html", + "
    Exception Summary" + + " 
    Exception" + + "Description
    ClassException
    " + + NL + "" + NL + "" + NL + "" + NL + "" + NL + "" + NL + "" + + NL + "" + NL + "" } }; private static final String[][] PROFILES_NEGATED_TEST = { @@ -125,6 +169,8 @@ public class TestProfiles extends JavadocTester { {PROFILE_BUG_ID + FS + "pkg4" + FS + "compact2-package-frame.html", "
  • Anno1Pkg4
  • " + }, + {PROFILE_BUG_ID + FS + "compact1-summary.html","
  • Use
  • " } }; private static final String[][] PACKAGES_TEST = { @@ -141,29 +187,9 @@ public class TestProfiles extends JavadocTester { } }; private static final String[][] PACKAGES_NEGATED_TEST = { - {PACKAGE_BUG_ID + FS + "profile-overview-frame.html", - "All Packages" - }, - {PACKAGE_BUG_ID + FS + "compact2-frame.html", - "" - + "All PackagesAll Profiles" - }, - {PACKAGE_BUG_ID + FS + "pkg2" + FS + "compact2-package-frame.html", - "" - + "compact2 - pkg2" - }, - {PACKAGE_BUG_ID + FS + "compact2-summary.html", - "

    Profile compact2

    " - }, - {PACKAGE_BUG_ID + FS + "pkg5" + FS + "compact3-package-summary.html", - "
    compact3
    " - }, {PACKAGE_BUG_ID + FS + "overview-frame.html", "All Profiles" + + "target=\"packageListFrame\">All Profiles" }, {PACKAGE_BUG_ID + FS + "pkg2" + FS + "Class1Pkg2.html", "
    compact1, compact2, compact3
    " @@ -176,6 +202,13 @@ public class TestProfiles extends JavadocTester { "" } }; + private static final String[] PACKAGES_NEGATED_FILE_TEST = { + PACKAGE_BUG_ID + FS + "profile-overview-frame.html", + PACKAGE_BUG_ID + FS + "compact2-frame.html", + PACKAGE_BUG_ID + FS + "pkg2" + FS + "compact2-package-frame.html", + PACKAGE_BUG_ID + FS + "compact2-summary.html", + PACKAGE_BUG_ID + FS + "pkg5" + FS + "compact3-package-summary.html" + }; /** * The entry point of the test. @@ -185,7 +218,7 @@ public class TestProfiles extends JavadocTester { public static void main(String[] args) { TestProfiles tester = new TestProfiles(); run(tester, ARGS1, PROFILES_TEST, PROFILES_NEGATED_TEST); - run(tester, ARGS2, PACKAGES_TEST, PACKAGES_NEGATED_TEST); + run(tester, ARGS2, PACKAGES_TEST, PACKAGES_NEGATED_TEST, NO_FILE_TEST, PACKAGES_NEGATED_FILE_TEST); tester.printSummary(); } diff --git a/langtools/test/com/sun/javadoc/testProfiles/TestProfilesConfiguration.java b/langtools/test/com/sun/javadoc/testProfiles/TestProfilesConfiguration.java new file mode 100644 index 00000000000..287cca02952 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testProfiles/TestProfilesConfiguration.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8006124 8009684 8015663 8015496 + * @summary Test javadoc options support for profiles. + * @author Evgeniya Stepanova + * @library ../lib/ + * @build JavadocTester TestProfilesConfiguration + * @run main TestProfilesConfiguration + */ +public class TestProfilesConfiguration extends JavadocTester { + + //Test information. + private static final String BUG_ID = "8006124-8009684"; + private static final String PROFILE_CONFIGURATION_BUG_ID = BUG_ID + "-3"; + private static final String NODEPR_NOPKGS_BUG_ID = BUG_ID + "-4"; + //Javadoc arguments. + private static final String[] ARGS3 = new String[]{ + "-d", PROFILE_CONFIGURATION_BUG_ID, "-sourcepath", SRC_DIR, "-nocomment", + "-keywords", "-Xprofilespath", SRC_DIR + FS + "profile-rtjar-includes.txt", + "-doctitle", "Simple doctitle", "-use", "pkg3", "pkg1", "pkg2", "pkg4", + "pkg5", "-packagesheader", "Simple packages header","pkgDeprecated" + }; + private static final String[] ARGS4 = new String[]{ + "-d", NODEPR_NOPKGS_BUG_ID, "-sourcepath", SRC_DIR, "-nocomment", "-nodeprecated", + "-keywords", "-Xprofilespath", SRC_DIR + FS + "profile-rtjar-includes-nopkgs.txt", + "-doctitle", "Simple doctitle", "-use", "-packagesheader", "Simple packages header", + "pkg1", "pkg2", "pkg3", "pkg4", "pkg5", "pkgDeprecated" + }; + private static final String[][] NODEPR_NOPKGS_TEST = { + {NODEPR_NOPKGS_BUG_ID + FS + "overview-summary.html", + "" + }, + {NODEPR_NOPKGS_BUG_ID + FS + "profile-overview-frame.html", + "" + } + }; + private static final String[][] NODEPR_NOPKGS_NEGATED_TEST = { + {NODEPR_NOPKGS_BUG_ID + FS + "overview-summary.html", + "compact1" + } + }; + + private static final String[][] PROFILES_CONFIGURATION_TEST = { + //-use option test string fo profile view page + {PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html","
  • Use
  • " + }, + //-doctitle option test string + {PROFILE_CONFIGURATION_BUG_ID + FS + "overview-summary.html", + "
    " + NL + "

    Simple doctitle

    " + }, + //-packagesheader option test string fo profiles + {PROFILE_CONFIGURATION_BUG_ID + FS + "profile-overview-frame.html", + "

    Simple packages header

    " + }, + //-keywords option test string for profiles + {PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html", + "" + }, + //Deprecated information on a package + {PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html", + "

    pkgDeprecated

    " + NL + "
    " + + "Deprecated.
    " + } + }; + private static final String[][] PROFILES_CONFIGURATION_NEGATED_TEST = { + //-nocomments option test string + {PROFILE_CONFIGURATION_BUG_ID + FS + "compact1-summary.html", + "
    Class1Pkg2.
    " + } + }; + + /** + * The entry point of the test. + * + * @param args the array of command line arguments. + */ + public static void main(String[] args) { + TestProfilesConfiguration tester = new TestProfilesConfiguration(); + run(tester, ARGS3, PROFILES_CONFIGURATION_TEST, + PROFILES_CONFIGURATION_NEGATED_TEST); + run(tester, ARGS4, NODEPR_NOPKGS_TEST, + NODEPR_NOPKGS_NEGATED_TEST); + tester.printSummary(); + } + + /** + * {@inheritDoc} + */ + public String getBugId() { + return BUG_ID; + } + + /** + * {@inheritDoc} + */ + public String getBugName() { + return getClass().getName(); + } +} diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java index afa13d8444e..935bd3643ae 100644 --- a/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java +++ b/langtools/test/com/sun/javadoc/testProfiles/pkg2/Class1Pkg2.java @@ -24,7 +24,7 @@ package pkg2; /** - * Another test class. + * @deprecated Class1Pkg2. This class is deprecated * * @author Bhavesh Patel */ diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassError.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassError.java new file mode 100644 index 00000000000..427b8f9c896 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassError.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg2; + +/** + * Simple error class. + * + * @author Evgeniya Stepanova + */ +public class ClassError extends Error {} diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassException.java b/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassException.java new file mode 100644 index 00000000000..d56412e7da2 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testProfiles/pkg2/ClassException.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package pkg2; + +/** + * Simple exception class. + * + * @author Evgeniya Stepanova + */ +public class ClassException extends Exception {} diff --git a/langtools/test/tools/javac/diags/examples/CyclicInference.java b/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/Class1PkgDeprecated.java similarity index 78% rename from langtools/test/tools/javac/diags/examples/CyclicInference.java rename to langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/Class1PkgDeprecated.java index 0a6bc7a2b82..51475499286 100644 --- a/langtools/test/tools/javac/diags/examples/CyclicInference.java +++ b/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/Class1PkgDeprecated.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -21,17 +21,16 @@ * questions. */ -// key: compiler.err.prob.found.req -// key: compiler.misc.cyclic.inference +package pkgDeprecated; -class CyclicInference { - interface SAM { - void m(X x); - } +/** + * Simple deprecated class of deprecated package. + * + * @author Evgeniya Stepanova + */ +public class Class1PkgDeprecated { - void g(SAM sz) { } - - void test() { - g(x-> {}); + public void method(int t) { + return null; } } diff --git a/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/package-info.java b/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/package-info.java new file mode 100644 index 00000000000..0cc070077cb --- /dev/null +++ b/langtools/test/com/sun/javadoc/testProfiles/pkgDeprecated/package-info.java @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * Deprecated package. + * + * @deprecated This package is Deprecated. Use pkg1. + */ +package pkgDeprecated; diff --git a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes-nopkgs.txt b/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes-nopkgs.txt new file mode 100644 index 00000000000..c63a4e85214 --- /dev/null +++ b/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes-nopkgs.txt @@ -0,0 +1,41 @@ +PROFILE_1_RTJAR_INCLUDE_PACKAGES := + +PROFILE_1_RTJAR_INCLUDE_TYPES := + +PROFILE_1_RTJAR_EXCLUDE_TYPES := + +PROFILE_1_INCLUDE_METAINF_SERVICES := + + +PROFILE_2_RTJAR_INCLUDE_PACKAGES := \ + pkg4 \ + pkgDeprecated + +PROFILE_2_RTJAR_INCLUDE_TYPES := + +PROFILE_2_RTJAR_EXCLUDE_TYPES := \ + pkg4/Anno1Pkg4.class + +PROFILE_2_INCLUDE_METAINF_SERVICES := + + +PROFILE_3_RTJAR_INCLUDE_PACKAGES := \ + pkg5 + +PROFILE_3_RTJAR_INCLUDE_TYPES := + +PROFILE_3_RTJAR_EXCLUDE_TYPES := + +PROFILE_3_INCLUDE_METAINF_SERVICES := + + +PROFILE_4_RTJAR_INCLUDE_PACKAGES := \ + pkg1 + +PROFILE_4_RTJAR_INCLUDE_TYPES := + +PROFILE_4_RTJAR_EXCLUDE_TYPES := + +PROFILE_4_INCLUDE_METAINF_SERVICES := + + diff --git a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt b/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt index 9460b3f985b..eff8d14b438 100644 --- a/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt +++ b/langtools/test/com/sun/javadoc/testProfiles/profile-rtjar-includes.txt @@ -1,5 +1,6 @@ PROFILE_1_RTJAR_INCLUDE_PACKAGES := \ - pkg2 + pkg2 \ + pkgDeprecated PROFILE_1_RTJAR_INCLUDE_TYPES := \ pkg3/Class1Pkg3.class diff --git a/langtools/test/com/sun/javadoc/testStylesheet/TestStylesheet.java b/langtools/test/com/sun/javadoc/testStylesheet/TestStylesheet.java index c4044a53d91..b6192fb8959 100644 --- a/langtools/test/com/sun/javadoc/testStylesheet/TestStylesheet.java +++ b/langtools/test/com/sun/javadoc/testStylesheet/TestStylesheet.java @@ -23,7 +23,7 @@ /* * @test - * @bug 4494033 7028815 7052425 8007338 + * @bug 4494033 7028815 7052425 8007338 8023608 * @summary Run tests on doclet stylesheet. * @author jamieh * @library ../lib/ @@ -72,7 +72,46 @@ public class TestStylesheet extends JavadocTester { " overflow:hidden;" + NL + " padding:0px;" + NL + " margin:0px;" + NL + - " white-space:pre;" + NL + + "}"}, + {BUG_ID + FS + "stylesheet.css", + ".overviewSummary caption span, .packageSummary caption span, " + + ".contentContainer ul.blockList li.blockList caption span, " + + ".summary caption span, .classUseContainer caption span, " + + ".constantValuesContainer caption span {" + NL + + " white-space:nowrap;" + NL + + " padding-top:8px;" + NL + + " padding-left:8px;" + NL + + " display:inline-block;" + NL + + " float:left;" + NL + + " background-image:url(resources/titlebar.gif);" + NL + + "}"}, + {BUG_ID + FS + "stylesheet.css", + ".contentContainer ul.blockList li.blockList caption " + + "span.activeTableTab span {" + NL + + " white-space:nowrap;" + NL + + " padding-top:8px;" + NL + + " padding-left:8px;" + NL + + " display:inline-block;" + NL + + " float:left;" + NL + + " background-image:url(resources/activetitlebar.gif);" + NL + + "}"}, + {BUG_ID + FS + "stylesheet.css", + ".contentContainer ul.blockList li.blockList caption span.tableTab span {" + NL + + " white-space:nowrap;" + NL + + " padding-top:8px;" + NL + + " padding-left:8px;" + NL + + " display:inline-block;" + NL + + " float:left;" + NL + + " background-image:url(resources/titlebar.gif);" + NL + + "}"}, + {BUG_ID + FS + "stylesheet.css", + ".contentContainer ul.blockList li.blockList caption span.tableTab, " + + ".contentContainer ul.blockList li.blockList caption span.activeTableTab {" + NL + + " padding-top:0px;" + NL + + " padding-left:0px;" + NL + + " background-image:none;" + NL + + " float:none;" + NL + + " display:inline-block;" + NL + "}"}, // Test whether a link to the stylesheet file is inserted properly // in the class documentation. diff --git a/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java b/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java index 6a61e43f3b1..a1e0e970af0 100644 --- a/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java +++ b/langtools/test/com/sun/javadoc/testUseOption/TestUseOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 4496290 4985072 7006178 7068595 + * @bug 4496290 4985072 7006178 7068595 8016328 * @summary A simple test to determine if -use works. * @author jamieh * @library ../lib/ @@ -60,7 +60,7 @@ public class TestUseOption extends JavadocTester { "UsedInC in <Unnamed>" }, {BUG_ID + "-3" + FS + "package-use.html", "
    " + "UsedInC " } }; diff --git a/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java b/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java index ba0f291dc81..1d24a52798a 100644 --- a/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java +++ b/langtools/test/com/sun/javadoc/testValueTag/TestValueTag.java @@ -23,13 +23,12 @@ /* * @test - * @bug 4764045 + * @bug 4764045 8004825 * @summary This test ensures that the value tag works in all * use cases. The explainations for each test case are written below. * @author jamieh * @library ../lib/ - * @build JavadocTester - * @build TestValueTag + * @build JavadocTester TestValueTag * @run main TestValueTag */ @@ -41,11 +40,17 @@ public class TestValueTag extends JavadocTester { //Javadoc arguments. private static final String[] ARGS = new String[] { - "-Xdoclint:none", "-d", BUG_ID, "-sourcepath", SRC_DIR, "-tag", "todo", "pkg1", "pkg2" }; + private static final String[] ARGS1 = + new String[] { + "-Xdoclint:none", + "-d", BUG_ID + "-1", "-sourcepath", SRC_DIR, "-tag", + "todo", "pkg1", "pkg2" + }; + //Input for string search tests. private static final String[][] TEST = { //Base case: using @value on a constant. @@ -91,16 +96,58 @@ public class TestValueTag extends JavadocTester { {BUG_ID + FS + "pkg1" + FS + "CustomTagUsage.html", "
    Todo:
    " + NL + "
    the value of this constant is 55.
    "}, + //Test @value errors printed dues to invalid use or when used with + //non-constant or with bad references. + {ERROR_OUTPUT,"error: value does not refer to a constant" + NL + + " * Result: {@value TEST_12_ERROR}" + }, + {ERROR_OUTPUT,"error: {@value} not allowed here" + NL + + " * Result: {@value}" + }, + {ERROR_OUTPUT,"error: value does not refer to a constant" + NL + + " * Result: {@value NULL}" + }, + {ERROR_OUTPUT,"error: {@value} not allowed here" + NL + + " * Invalid (null): {@value}" + }, + {ERROR_OUTPUT,"error: {@value} not allowed here" + NL + + " * Invalid (non-constant field): {@value}" + }, + {ERROR_OUTPUT,"error: value does not refer to a constant" + NL + + " * Here is a bad value reference: {@value UnknownClass#unknownConstant}" + }, + {ERROR_OUTPUT,"error: reference not found" + NL + + " * Here is a bad value reference: {@value UnknownClass#unknownConstant}" + }, + {ERROR_OUTPUT,"error: {@value} not allowed here" + NL + + " * @todo the value of this constant is {@value}" + } + }; + private static final String[][] TEST1 = { //Test @value warning printed when used with non-constant. {WARNING_OUTPUT,"warning - @value tag (which references nonConstant) " + "can only be used in constants." }, + {WARNING_OUTPUT,"warning - @value tag (which references NULL) " + + "can only be used in constants." + }, + {WARNING_OUTPUT,"warning - @value tag (which references TEST_12_ERROR) " + + "can only be used in constants." + }, //Test warning printed for bad reference. {WARNING_OUTPUT,"warning - UnknownClass#unknownConstant (referenced by " + "@value tag) is an unknown reference." }, + //Test warning printed for invalid use of @value. + {WARNING_OUTPUT,"warning - @value tag cannot be used here." + } + }; + private static final String[][] NEGATED_TEST = { + //Base case: using @value on a constant. + {BUG_ID + FS + "pkg1" + FS + "Class1.html", + "Result: \"Test 12 " + + "generates an error message\""}, }; - private static final String[][] NEGATED_TEST = NO_TEST; /** * The entry point of the test. @@ -109,9 +156,18 @@ public class TestValueTag extends JavadocTester { public static void main(String[] args) { TestValueTag tester = new TestValueTag(); run(tester, ARGS, TEST, NEGATED_TEST); + checkForException(tester); + run(tester, ARGS1, TEST1, NO_TEST); + checkForException(tester); tester.printSummary(); } + public static void checkForException(TestValueTag tester) { + if (tester.getErrorOutput().contains("DocletAbortException")) { + throw new AssertionError("javadoc threw DocletAbortException"); + } + } + /** * {@inheritDoc} */ diff --git a/langtools/test/com/sun/javadoc/testValueTag/pkg1/Class1.java b/langtools/test/com/sun/javadoc/testValueTag/pkg1/Class1.java index 7cd1c69c70f..3b03881c7f9 100644 --- a/langtools/test/com/sun/javadoc/testValueTag/pkg1/Class1.java +++ b/langtools/test/com/sun/javadoc/testValueTag/pkg1/Class1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,16 @@ public class Class1 { public static final String TEST_10_PASSES = "Test 10 passes"; public static final String TEST_11_PASSES = "Test 11 passes"; + /** + * Invalid (non-constant field): {@value} + */ + public static String TEST_12_ERROR = "Test 12 generates an error message"; + + /** + * Invalid (null): {@value} + */ + public static final String NULL = null; + /** * Result: {@value TEST_3_PASSES} */ @@ -59,6 +69,21 @@ public class Class1 { */ public void method() {} + /** + * Result: {@value TEST_12_ERROR} + */ + public void invalidValueTag1() {} + + /** + * Result: {@value} + */ + public void invalidValueTag2() {} + + /** + * Result: {@value NULL} + */ + public void testNullConstant() {} + /** * Result: {@value pkg1.Class1#TEST_6_PASSES} */ diff --git a/langtools/test/lib/combo/TEST.properties b/langtools/test/lib/combo/TEST.properties new file mode 100644 index 00000000000..341ff2af467 --- /dev/null +++ b/langtools/test/lib/combo/TEST.properties @@ -0,0 +1,4 @@ +# This file identifies root(s) of the test-ng hierarchy. + + +TestNG.dirs = . diff --git a/langtools/test/lib/combo/tools/javac/combo/Diagnostics.java b/langtools/test/lib/combo/tools/javac/combo/Diagnostics.java new file mode 100644 index 00000000000..6f1774d6572 --- /dev/null +++ b/langtools/test/lib/combo/tools/javac/combo/Diagnostics.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package tools.javac.combo; + +import javax.tools.Diagnostic; +import javax.tools.JavaFileObject; +import java.util.ArrayList; +import java.util.List; + +import static java.util.stream.Collectors.toList; + +/** +* A container for compiler diagnostics, separated into errors and warnings, + * used by JavacTemplateTestBase. + * + * @author Brian Goetz +*/ +public class Diagnostics implements javax.tools.DiagnosticListener { + + protected List> diags = new ArrayList<>(); + protected boolean foundErrors = false; + + public void report(Diagnostic diagnostic) { + diags.add(diagnostic); + foundErrors = foundErrors || diagnostic.getKind() == Diagnostic.Kind.ERROR; + } + + /** Were there any errors found? */ + public boolean errorsFound() { + return foundErrors; + } + + /** Get all diagnostic keys */ + public List keys() { + return diags.stream() + .map(Diagnostic::getCode) + .collect(toList()); + } + + /** Do the diagnostics contain the specified error key? */ + public boolean containsErrorKey(String key) { + return diags.stream() + .filter(d -> d.getKind() == Diagnostic.Kind.ERROR) + .anyMatch(d -> d.getCode().equals(key)); + } + + /** Get the error keys */ + public List errorKeys() { + return diags.stream() + .filter(d -> d.getKind() == Diagnostic.Kind.ERROR) + .map(Diagnostic::getCode) + .collect(toList()); + } + + public String toString() { return keys().toString(); } + + /** Clear all diagnostic state */ + public void reset() { + diags.clear(); + foundErrors = false; + } +} diff --git a/langtools/test/lib/combo/tools/javac/combo/JavacTemplateTestBase.java b/langtools/test/lib/combo/tools/javac/combo/JavacTemplateTestBase.java new file mode 100644 index 00000000000..e2a8bd7cac3 --- /dev/null +++ b/langtools/test/lib/combo/tools/javac/combo/JavacTemplateTestBase.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package tools.javac.combo; + +import java.io.File; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.atomic.AtomicInteger; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.tools.javac.util.Pair; +import org.testng.ITestResult; +import org.testng.annotations.AfterMethod; +import org.testng.annotations.AfterSuite; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import static org.testng.Assert.fail; + +/** + * Base class for template-driven TestNG javac tests that support on-the-fly + * source file generation, compilation, classloading, execution, and separate + * compilation. + * + *

    Manages a set of templates (which have embedded tags of the form + * {@code #\{NAME\}}), source files (which are also templates), and compile + * options. Test cases can register templates and source files, cause them to + * be compiled, validate whether the set of diagnostic messages output by the + * compiler is correct, and optionally load and run the compiled classes. + * + * @author Brian Goetz + */ +@Test +public abstract class JavacTemplateTestBase { + private static final Set suiteErrors = Collections.synchronizedSet(new HashSet<>()); + private static final AtomicInteger counter = new AtomicInteger(); + private static final File root = new File("gen"); + private static final File nullDir = new File("empty"); + + protected final Map templates = new HashMap<>(); + protected final Diagnostics diags = new Diagnostics(); + protected final List> sourceFiles = new ArrayList<>(); + protected final List compileOptions = new ArrayList<>(); + protected final List classpaths = new ArrayList<>(); + protected final Template.Resolver defaultResolver = new MapResolver(templates); + + private Template.Resolver currentResolver = defaultResolver; + + /** Add a template with a specified name */ + protected void addTemplate(String name, Template t) { + templates.put(name, t); + } + + /** Add a template with a specified name */ + protected void addTemplate(String name, String s) { + templates.put(name, new StringTemplate(s)); + } + + /** Add a source file */ + protected void addSourceFile(String name, Template t) { + sourceFiles.add(new Pair<>(name, t)); + } + + /** Add a File to the class path to be used when loading classes; File values + * will generally be the result of a previous call to {@link #compile()}. + * This enables testing of separate compilation scenarios if the class path + * is set up properly. + */ + protected void addClassPath(File path) { + classpaths.add(path); + } + + /** + * Add a set of compilation command-line options + */ + protected void addCompileOptions(String... opts) { + Collections.addAll(compileOptions, opts); + } + + /** Reset the compile options to the default (empty) value */ + protected void resetCompileOptions() { compileOptions.clear(); } + + /** Remove all templates */ + protected void resetTemplates() { templates.clear(); } + + /** Remove accumulated diagnostics */ + protected void resetDiagnostics() { diags.reset(); } + + /** Remove all source files */ + protected void resetSourceFiles() { sourceFiles.clear(); } + + /** Remove registered class paths */ + protected void resetClassPaths() { classpaths.clear(); } + + // Before each test method, reset everything + @BeforeMethod + public void reset() { + resetCompileOptions(); + resetDiagnostics(); + resetSourceFiles(); + resetTemplates(); + resetClassPaths(); + } + + // After each test method, if the test failed, capture source files and diagnostics and put them in the log + @AfterMethod + public void copyErrors(ITestResult result) { + if (!result.isSuccess()) { + suiteErrors.addAll(diags.errorKeys()); + + List list = new ArrayList<>(); + Collections.addAll(list, result.getParameters()); + list.add("Test case: " + getTestCaseDescription()); + for (Pair e : sourceFiles) + list.add("Source file " + e.fst + ": " + e.snd); + if (diags.errorsFound()) + list.add("Compile diagnostics: " + diags.toString()); + result.setParameters(list.toArray(new Object[list.size()])); + } + } + + @AfterSuite + // After the suite is done, dump any errors to output + public void dumpErrors() { + if (!suiteErrors.isEmpty()) + System.err.println("Errors found in test suite: " + suiteErrors); + } + + /** + * Get a description of this test case; since test cases may be combinatorially + * generated, this should include all information needed to describe the test case + */ + protected String getTestCaseDescription() { + return this.toString(); + } + + /** Assert that all previous calls to compile() succeeded */ + protected void assertCompileSucceeded() { + if (diags.errorsFound()) + fail("Expected successful compilation"); + } + + /** + * If the provided boolean is true, assert all previous compiles succeeded, + * otherwise assert that a compile failed. + * */ + protected void assertCompileSucceededIff(boolean b) { + if (b) + assertCompileSucceeded(); + else + assertCompileFailed(); + } + + /** Assert that a previous call to compile() failed */ + protected void assertCompileFailed() { + if (!diags.errorsFound()) + fail("Expected failed compilation"); + } + + /** Assert that a previous call to compile() failed with a specific error key */ + protected void assertCompileFailed(String message) { + if (!diags.errorsFound()) + fail("Expected failed compilation: " + message); + } + + /** Assert that a previous call to compile() failed with all of the specified error keys */ + protected void assertCompileErrors(String... keys) { + if (!diags.errorsFound()) + fail("Expected failed compilation"); + for (String k : keys) + if (!diags.containsErrorKey(k)) + fail("Expected compilation error " + k); + } + + /** Convert an object, which may be a Template or a String, into a Template */ + protected Template asTemplate(Object o) { + if (o instanceof Template) + return (Template) o; + else if (o instanceof String) + return new StringTemplate((String) o); + else + return new StringTemplate(o.toString()); + } + + /** Compile all registered source files */ + protected void compile() throws IOException { + compile(false); + } + + /** Compile all registered source files, optionally generating class files + * and returning a File describing the directory to which they were written */ + protected File compile(boolean generate) throws IOException { + List files = new ArrayList<>(); + for (Pair e : sourceFiles) + files.add(new FileAdapter(e.fst, asTemplate(e.snd))); + return compile(classpaths, files, generate); + } + + /** Compile all registered source files, using the provided list of class paths + * for finding required classfiles, optionally generating class files + * and returning a File describing the directory to which they were written */ + protected File compile(List classpaths, boolean generate) throws IOException { + List files = new ArrayList<>(); + for (Pair e : sourceFiles) + files.add(new FileAdapter(e.fst, asTemplate(e.snd))); + return compile(classpaths, files, generate); + } + + private File compile(List classpaths, List files, boolean generate) throws IOException { + JavaCompiler systemJavaCompiler = ToolProvider.getSystemJavaCompiler(); + StandardJavaFileManager fm = systemJavaCompiler.getStandardFileManager(null, null, null); + if (classpaths.size() > 0) + fm.setLocation(StandardLocation.CLASS_PATH, classpaths); + JavacTask ct = (JavacTask) systemJavaCompiler.getTask(null, fm, diags, compileOptions, null, files); + if (generate) { + File destDir = new File(root, Integer.toString(counter.incrementAndGet())); + // @@@ Assert that this directory didn't exist, or start counter at max+1 + destDir.mkdirs(); + fm.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(destDir)); + ct.generate(); + return destDir; + } + else { + ct.analyze(); + return nullDir; + } + } + + /** Load the given class using the provided list of class paths */ + protected Class loadClass(String className, File... destDirs) { + try { + List list = new ArrayList<>(); + for (File f : destDirs) + list.add(new URL("file:" + f.toString().replace("\\", "/") + "/")); + return Class.forName(className, true, new URLClassLoader(list.toArray(new URL[list.size()]))); + } catch (ClassNotFoundException | MalformedURLException e) { + throw new RuntimeException("Error loading class " + className, e); + } + } + + /** An implementation of Template which is backed by a String */ + protected class StringTemplate implements Template { + protected final String template; + + public StringTemplate(String template) { + this.template = template; + } + + public String expand(String selector) { + return Behavior.expandTemplate(template, currentResolver); + } + + public String toString() { + return expand(""); + } + + public StringTemplate with(final String key, final String value) { + return new StringTemplateWithResolver(template, new KeyResolver(key, value)); + } + + } + + /** An implementation of Template which is backed by a String and which + * encapsulates a Resolver for resolving embedded tags. */ + protected class StringTemplateWithResolver extends StringTemplate { + private final Resolver localResolver; + + public StringTemplateWithResolver(String template, Resolver localResolver) { + super(template); + this.localResolver = localResolver; + } + + @Override + public String expand(String selector) { + Resolver saved = currentResolver; + currentResolver = new ChainedResolver(currentResolver, localResolver); + try { + return super.expand(selector); + } + finally { + currentResolver = saved; + } + } + + @Override + public StringTemplate with(String key, String value) { + return new StringTemplateWithResolver(template, new ChainedResolver(localResolver, new KeyResolver(key, value))); + } + } + + /** A Resolver which uses a Map to resolve tags */ + private class KeyResolver implements Template.Resolver { + private final String key; + private final String value; + + public KeyResolver(String key, String value) { + this.key = key; + this.value = value; + } + + @Override + public Template lookup(String k) { + return key.equals(k) ? new StringTemplate(value) : null; + } + } + + private class FileAdapter extends SimpleJavaFileObject { + private final String filename; + private final Template template; + + public FileAdapter(String filename, Template template) { + super(URI.create("myfo:/" + filename), Kind.SOURCE); + this.template = template; + this.filename = filename; + } + + public CharSequence getCharContent(boolean ignoreEncodingErrors) { + return toString(); + } + + public String toString() { + return Template.Behavior.expandTemplate(template.expand(filename), defaultResolver); + } + } +} diff --git a/langtools/test/lib/combo/tools/javac/combo/Template.java b/langtools/test/lib/combo/tools/javac/combo/Template.java new file mode 100644 index 00000000000..ad8aeb9f956 --- /dev/null +++ b/langtools/test/lib/combo/tools/javac/combo/Template.java @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package tools.javac.combo; + +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +/** + * A template into which tags of the form {@code #\{KEY\}} or + * {@code #\{KEY.SUBKEY\}} can be expanded. + */ +public interface Template { + String expand(String selector); + + interface Resolver { + public Template lookup(String key); + } + + public static class Behavior { + /* Looks for expandable keys. An expandable key can take the form: + * #{MAJOR} + * #{MAJOR.} + * #{MAJOR.MINOR} + * where MAJOR can be IDENTIFIER or IDENTIFIER[NUMERIC_INDEX] + * and MINOR can be an identifier. + * + * The ability to have an empty minor is provided on the + * assumption that some tests that can be written with this + * will find it useful to make a distinction akin to + * distinguishing F from F(), where F is a function pointer, + * and also cases of #{FOO.#{BAR}}, where BAR expands to an + * empty string. + * + * However, this being a general-purpose framework, the exact + * use is left up to the test writers. + */ + private static final Pattern pattern = Pattern.compile("#\\{([A-Z_][A-Z0-9_]*(?:\\[\\d+\\])?)(?:\\.([A-Z0-9_]*))?\\}"); + + public static String expandTemplate(String template, final Map vars) { + return expandTemplate(template, new MapResolver(vars)); + } + + public static String expandTemplate(String template, Resolver res) { + CharSequence in = template; + StringBuffer out = new StringBuffer(); + while (true) { + boolean more = false; + Matcher m = pattern.matcher(in); + while (m.find()) { + String major = m.group(1); + String minor = m.group(2); + Template key = res.lookup(major); + if (key == null) + throw new IllegalStateException("Unknown major key " + major); + + String replacement = key.expand(minor == null ? "" : minor); + more |= pattern.matcher(replacement).find(); + m.appendReplacement(out, replacement); + } + m.appendTail(out); + if (!more) + return out.toString(); + else { + in = out; + out = new StringBuffer(); + } + } + } + + } +} + +class MapResolver implements Template.Resolver { + private final Map vars; + + public MapResolver(Map vars) {this.vars = vars;} + + public Template lookup(String key) { + return vars.get(key); + } +} + +class ChainedResolver implements Template.Resolver { + private final Template.Resolver upstreamResolver, thisResolver; + + public ChainedResolver(Template.Resolver upstreamResolver, Template.Resolver thisResolver) { + this.upstreamResolver = upstreamResolver; + this.thisResolver = thisResolver; + } + + public Template.Resolver getUpstreamResolver() { + return upstreamResolver; + } + + @Override + public Template lookup(String key) { + Template result = thisResolver.lookup(key); + if (result == null) + result = upstreamResolver.lookup(key); + return result; + } +} diff --git a/langtools/test/lib/combo/tools/javac/combo/TemplateTest.java b/langtools/test/lib/combo/tools/javac/combo/TemplateTest.java new file mode 100644 index 00000000000..356456872dd --- /dev/null +++ b/langtools/test/lib/combo/tools/javac/combo/TemplateTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +package tools.javac.combo; + +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.testng.Assert.assertEquals; + +/** + * TemplateTest + */ +@Test +public class TemplateTest { + Map vars = new HashMap<>(); + + @BeforeTest + void before() { vars.clear(); } + + private void assertTemplate(String expected, String template) { + String result = Template.Behavior.expandTemplate(template, vars); + assertEquals(result, expected, "for " + template); + } + + private String dotIf(String s) { + return s == null || s.isEmpty() ? "" : "." + s; + } + + public void testTemplateExpansion() { + vars.put("A", s -> "a" + dotIf(s)); + vars.put("B", s -> "b" + dotIf(s)); + vars.put("C", s -> "#{A}#{B}"); + vars.put("D", s -> "#{A" + dotIf(s) + "}#{B" + dotIf(s) + "}"); + vars.put("_D", s -> "d"); + + assertTemplate("", ""); + assertTemplate("foo", "foo"); + assertTemplate("a", "#{A}"); + assertTemplate("a", "#{A.}"); + assertTemplate("a.FOO", "#{A.FOO}"); + assertTemplate("aa", "#{A}#{A}"); + assertTemplate("ab", "#{C}"); + assertTemplate("ab", "#{C.FOO}"); + assertTemplate("ab", "#{C.}"); + assertTemplate("a.FOOb.FOO", "#{D.FOO}"); + assertTemplate("ab", "#{D}"); + assertTemplate("d", "#{_D}"); + assertTemplate("#{A", "#{A"); + } + + public void testIndexedTemplate() { + vars.put("A[0]", s -> "a" ); + vars.put("A[1]", s -> "b" ); + vars.put("A[2]", s -> "c" ); + vars.put("X", s -> "0"); + assertTemplate("a", "#{A[0]}"); + assertTemplate("b", "#{A[1]}"); + assertTemplate("c", "#{A[2]}"); + } + + public void testAngleBrackets() { + vars.put("X", s -> "xyz"); + assertTemplate("List ls = xyz;", "List ls = #{X};"); + } + + @Test(expectedExceptions = IllegalStateException.class ) + public void testUnknownKey() { + assertTemplate("#{Q}", "#{Q}"); + } +} diff --git a/langtools/test/tools/doclint/ReferenceTest.java b/langtools/test/tools/doclint/ReferenceTest.java index 57b26aeff24..1ffd633e866 100644 --- a/langtools/test/tools/doclint/ReferenceTest.java +++ b/langtools/test/tools/doclint/ReferenceTest.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8004832 8020556 + * @bug 8004832 8020556 8002154 * @summary Add new doclint package * @build DocLintTester * @run main DocLintTester -Xmsgs:-reference ReferenceTest.java @@ -54,5 +54,13 @@ public class ReferenceTest { * @throws T description */ public void valid_throws_generic() throws T { } + + /** + * {@link java.util.List} + * {@link java.util.List#equals} + * @see java.util.List + * @see java.util.List#equals + */ + public void invalid_type_args() { } } diff --git a/langtools/test/tools/doclint/ReferenceTest.out b/langtools/test/tools/doclint/ReferenceTest.out index df21e5ef990..ab288a34b00 100644 --- a/langtools/test/tools/doclint/ReferenceTest.out +++ b/langtools/test/tools/doclint/ReferenceTest.out @@ -25,6 +25,18 @@ ReferenceTest.java:43: error: invalid use of @return ReferenceTest.java:48: error: exception not thrown: java.lang.Exception * @throws Exception description ^ -8 errors +ReferenceTest.java:59: error: type arguments not allowed here + * {@link java.util.List} + ^ +ReferenceTest.java:60: error: type arguments not allowed here + * {@link java.util.List#equals} + ^ +ReferenceTest.java:61: error: type arguments not allowed here + * @see java.util.List + ^ +ReferenceTest.java:62: error: type arguments not allowed here + * @see java.util.List#equals + ^ +12 errors 1 warning diff --git a/langtools/test/tools/doclint/ValueTest.java b/langtools/test/tools/doclint/ValueTest.java new file mode 100644 index 00000000000..f9de36daf15 --- /dev/null +++ b/langtools/test/tools/doclint/ValueTest.java @@ -0,0 +1,67 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8025272 + * @summary doclint needs to check for valid usage of at-value tag + * @build DocLintTester + * @run main DocLintTester -ref ValueTest.out ValueTest.java + */ + +/** */ +public class ValueTest { + /* + * Tests for {@value} without a reference + */ + + /** valid: {@value} */ + public static final boolean cBoolean = false; + + /** valid: {@value} */ + public static final byte cByte = 0; + + /** valid: {@value} */ + public static final short cShort = 0; + + /** valid: {@value} */ + public static final int cInt = 0; + + /** valid: {@value} */ + public static final long cLong = 0L; + + /** valid: {@value} */ + public static final float cFloat = 0.0f; + + /** valid: {@value} */ + public static final double cDouble = 0.0; + + /** valid: {@value} */ + public static final String cString = ""; + + /** invalid class C: {@value} */ + public class C { } + + /** invalid enum E: {@value} */ + public enum E { + /** invalid enum constant E1: {@value} */ + E1 + } + + /** invalid field 1: {@value} */ + public int f1; + + /** invalid field 2: {@value} */ + public int f2 = 3; + + + /* + * Tests for {@value} with a reference + */ + + /** valid: {@value Integer#SIZE} */ + public int intRef; + + /** invalid method: {@value Object#toString} */ + public int badMethod; + + /** invalid enum constant: {@value Thread.State#NEW} */ + public int badEnum; +} diff --git a/langtools/test/tools/doclint/ValueTest.out b/langtools/test/tools/doclint/ValueTest.out new file mode 100644 index 00000000000..3b2977f9f72 --- /dev/null +++ b/langtools/test/tools/doclint/ValueTest.out @@ -0,0 +1,22 @@ +ValueTest.java:39: error: {@value} not allowed here + /** invalid class C: {@value} */ + ^ +ValueTest.java:42: error: {@value} not allowed here + /** invalid enum E: {@value} */ + ^ +ValueTest.java:44: error: {@value} not allowed here + /** invalid enum constant E1: {@value} */ + ^ +ValueTest.java:48: error: {@value} not allowed here + /** invalid field 1: {@value} */ + ^ +ValueTest.java:51: error: {@value} not allowed here + /** invalid field 2: {@value} */ + ^ +ValueTest.java:62: error: value does not refer to a constant + /** invalid method: {@value Object#toString} */ + ^ +ValueTest.java:65: error: value does not refer to a constant + /** invalid enum constant: {@value Thread.State#NEW} */ + ^ +7 errors diff --git a/langtools/test/tools/doclint/anchorTests/p/Test.java b/langtools/test/tools/doclint/anchorTests/p/Test.java new file mode 100644 index 00000000000..131629d7ac6 --- /dev/null +++ b/langtools/test/tools/doclint/anchorTests/p/Test.java @@ -0,0 +1,53 @@ +/* @test /nodynamiccopyright/ + * @bug 8025246 + * @summary doclint is showing error on anchor already defined when it's not + * @library ../.. + * @build DocLintTester + * @run main DocLintTester -ref Test.out Test.java + * @compile/fail/ref=Test.javac.out -XDrawDiagnostics -Werror -Xdoclint:all Test.java + */ + +package p; + +/** + * dupTest + * dupTest again + * + * dupTestField + * dupTestMethod + + * okClass + * okField + * okMethod + */ +public class Test { + /** dupTestField again */ + public int f; + + /** dupTestMethod again */ + public void m() { } + + /** + * dupNested + * dupNested again + * dupNestedField + * dupNestedMethod + * + * okClass again + */ + public class Nested { + /** + * dupNestedField + * + * okField again + */ + public int f; + + /** + * dupNestedMethod + * + * okMethod again + */ + public void m() { } + } +} diff --git a/langtools/test/tools/doclint/anchorTests/p/Test.javac.out b/langtools/test/tools/doclint/anchorTests/p/Test.javac.out new file mode 100644 index 00000000000..44a723969eb --- /dev/null +++ b/langtools/test/tools/doclint/anchorTests/p/Test.javac.out @@ -0,0 +1,7 @@ +Test.java:14:7: compiler.err.proc.messager: anchor already defined: dupTest +Test.java:24:12: compiler.err.proc.messager: anchor already defined: dupTestField +Test.java:27:12: compiler.err.proc.messager: anchor already defined: dupTestMethod +Test.java:32:11: compiler.err.proc.messager: anchor already defined: dupNested +Test.java:40:15: compiler.err.proc.messager: anchor already defined: dupNestedField +Test.java:47:15: compiler.err.proc.messager: anchor already defined: dupNestedMethod +6 errors diff --git a/langtools/test/tools/doclint/anchorTests/p/Test.out b/langtools/test/tools/doclint/anchorTests/p/Test.out new file mode 100644 index 00000000000..6f39fcf1e28 --- /dev/null +++ b/langtools/test/tools/doclint/anchorTests/p/Test.out @@ -0,0 +1,19 @@ +Test.java:14: error: anchor already defined: dupTest + * dupTest again + ^ +Test.java:24: error: anchor already defined: dupTestField + /** dupTestField again */ + ^ +Test.java:27: error: anchor already defined: dupTestMethod + /** dupTestMethod again */ + ^ +Test.java:32: error: anchor already defined: dupNested + * dupNested again + ^ +Test.java:40: error: anchor already defined: dupNestedField + * dupNestedField + ^ +Test.java:47: error: anchor already defined: dupNestedMethod + * dupNestedMethod + ^ +6 errors diff --git a/langtools/test/tools/doclint/anchorTests/p/package-info.java b/langtools/test/tools/doclint/anchorTests/p/package-info.java new file mode 100644 index 00000000000..af7682a3676 --- /dev/null +++ b/langtools/test/tools/doclint/anchorTests/p/package-info.java @@ -0,0 +1,15 @@ +/* @test /nodynamiccopyright/ + * @bug 8025246 + * @summary doclint is showing error on anchor already defined when it's not + * @library ../.. + * @build DocLintTester + * @run main DocLintTester -ref package-info.out package-info.java + * @compile/fail/ref=package-info.javac.out -XDrawDiagnostics -Werror -Xdoclint:all package-info.java + */ + +/** + * here + * here again + */ +package p; + diff --git a/langtools/test/tools/doclint/anchorTests/p/package-info.javac.out b/langtools/test/tools/doclint/anchorTests/p/package-info.javac.out new file mode 100644 index 00000000000..0a859df5894 --- /dev/null +++ b/langtools/test/tools/doclint/anchorTests/p/package-info.javac.out @@ -0,0 +1,2 @@ +package-info.java:12:7: compiler.err.proc.messager: anchor already defined: here +1 error diff --git a/langtools/test/tools/doclint/anchorTests/p/package-info.out b/langtools/test/tools/doclint/anchorTests/p/package-info.out new file mode 100644 index 00000000000..dda1b19f0dd --- /dev/null +++ b/langtools/test/tools/doclint/anchorTests/p/package-info.out @@ -0,0 +1,4 @@ +package-info.java:12: error: anchor already defined: here + * here again + ^ +1 error diff --git a/langtools/test/tools/doclint/html/InlineTagsTest.java b/langtools/test/tools/doclint/html/InlineTagsTest.java index 4835b36a9a0..5dda7c27c55 100644 --- a/langtools/test/tools/doclint/html/InlineTagsTest.java +++ b/langtools/test/tools/doclint/html/InlineTagsTest.java @@ -39,6 +39,7 @@ public class InlineTagsTest { *
    * abc * abc + * abc * abc * abc * abc diff --git a/langtools/test/tools/doclint/tidy/util/Main.java b/langtools/test/tools/doclint/tidy/util/Main.java index 62a559b1a74..77b356f1d2e 100644 --- a/langtools/test/tools/doclint/tidy/util/Main.java +++ b/langtools/test/tools/doclint/tidy/util/Main.java @@ -1,3 +1,27 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + package tidystats; import java.io.IOException; @@ -17,6 +41,35 @@ import java.util.TreeSet; import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * Generate statistics from the files generated by tidy.sh. + * + *

    The tidy.sh script is used to run tidy on all the HTML files + * in a directory, creating files in a new directory, and for each + * HTML file, it writes the console output from tidy into a file + * beside the fixed up file, with an additional .tidy extension. + * + *

    This program will scan a directory for *.tidy files and + * analyze the messages reported by tidy, in order to generate a + * report with statistics on the various messages that were + * reported by tidy. + * + *

    Typical usage: + *

    + * $ bash /path/to/tidy.sh /path/to/htmldir
    + * $ javac -d /path/to/classes /path/to/Main.java
    + * $ java -cp /path/to/classes tidystats.Main /path/to/htmldir.tidy
    + * 
    + * + *

    Internally, the program works by matching lines in the *.tidy + * files against a series of regular expressions that are used to + * categorize the messages. The set of regular expressions was + * empirically determined by running the program on the output from + * running tidy.sh on all the generated JDK documentation. It is + * possible that tidy may generate more/different messages on other + * doc sets, in which case, the set of regexes in the program should + * be updated. + */ public class Main { public static void main(String... args) throws IOException { new Main().run(args); diff --git a/langtools/test/tools/doclint/tidy/util/tidy.sh b/langtools/test/tools/doclint/tidy/util/tidy.sh index 711d320b3b9..eeea6606f53 100644 --- a/langtools/test/tools/doclint/tidy/util/tidy.sh +++ b/langtools/test/tools/doclint/tidy/util/tidy.sh @@ -1,6 +1,6 @@ -#!/bin/sh +#!/bin/bash # -# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ # # Run the "tidy" program over the files in a directory. +# The "tidy" program must be on your PATH. # # Usage: # sh tidy.sh

    diff --git a/langtools/test/tools/javac/Diagnostics/compressed/T8012003c.out b/langtools/test/tools/javac/Diagnostics/compressed/T8012003c.out index 7af49cc18e5..e2e2c8549c9 100644 --- a/langtools/test/tools/javac/Diagnostics/compressed/T8012003c.out +++ b/langtools/test/tools/javac/Diagnostics/compressed/T8012003c.out @@ -1,3 +1,2 @@ T8012003c.java:18:15: compiler.err.report.access: m(), private, P -- compiler.note.compressed.diags 1 error diff --git a/langtools/test/tools/javac/T4881267.java b/langtools/test/tools/javac/T4881267.java new file mode 100644 index 00000000000..33690add37b --- /dev/null +++ b/langtools/test/tools/javac/T4881267.java @@ -0,0 +1,12 @@ +/* + * @test /nodynamiccopyright/ + * @bug 4881267 + * @summary improve diagnostic for "instanceof T" for type parameter T + * @compile/fail/ref=T4881267.out -XDrawDiagnostics T4881267.java + */ + +class T4881267 { + void m(Object o) { + boolean b = o instanceof T; + } +} diff --git a/langtools/test/tools/javac/T4881267.out b/langtools/test/tools/javac/T4881267.out new file mode 100644 index 00000000000..01a732a612e --- /dev/null +++ b/langtools/test/tools/javac/T4881267.out @@ -0,0 +1,2 @@ +T4881267.java:10:34: compiler.err.illegal.generic.type.for.instof +1 error diff --git a/langtools/test/tools/javac/T7090499.java b/langtools/test/tools/javac/T7090499.java new file mode 100644 index 00000000000..b05cda52c4b --- /dev/null +++ b/langtools/test/tools/javac/T7090499.java @@ -0,0 +1,14 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7090499 + * @summary missing rawtypes warnings in anonymous inner class + * @compile/ref=T7090499.out -Xlint:rawtypes -XDrawDiagnostics T7090499.java + */ + +class T7090499 { + { + new Object() { + T7090499 x; + }; + } +} diff --git a/langtools/test/tools/javac/T7090499.out b/langtools/test/tools/javac/T7090499.out new file mode 100644 index 00000000000..54b68474f79 --- /dev/null +++ b/langtools/test/tools/javac/T7090499.out @@ -0,0 +1,2 @@ +T7090499.java:11:13: compiler.warn.raw.class.use: T7090499, T7090499 +1 warning diff --git a/langtools/test/tools/javac/T7093325.java b/langtools/test/tools/javac/T7093325.java index dcdc6e62856..fb11a87e77e 100644 --- a/langtools/test/tools/javac/T7093325.java +++ b/langtools/test/tools/javac/T7093325.java @@ -208,7 +208,7 @@ public class T7093325 } int actualGapsCount = 0; - for (int i = 0; i < code.exception_table_langth ; i++) { + for (int i = 0; i < code.exception_table_length ; i++) { int catchType = code.exception_table[i].catch_type; if (catchType == 0) { //any actualGapsCount++; diff --git a/langtools/test/tools/javac/T7120463.java b/langtools/test/tools/javac/T7120463.java new file mode 100644 index 00000000000..9f64a17178a --- /dev/null +++ b/langtools/test/tools/javac/T7120463.java @@ -0,0 +1,11 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7120463 + * @summary Fix method reference parser support in order to avoid ambiguities + * @compile/fail/ref=T7120463.out -XDrawDiagnostics T7120463.java + */ + +class T7120463 { + void test() { that(i < len, "oopmap"); } + void that(int i, String s) { }; +} diff --git a/langtools/test/tools/javac/T7120463.out b/langtools/test/tools/javac/T7120463.out new file mode 100644 index 00000000000..527bd52acf2 --- /dev/null +++ b/langtools/test/tools/javac/T7120463.out @@ -0,0 +1,3 @@ +T7120463.java:9:24: compiler.err.cant.resolve.location: kindname.variable, i, , , (compiler.misc.location: kindname.class, T7120463, null) +T7120463.java:9:28: compiler.err.cant.resolve.location: kindname.variable, len, , , (compiler.misc.location: kindname.class, T7120463, null) +2 errors diff --git a/langtools/test/tools/javac/T7126754.java b/langtools/test/tools/javac/T7126754.java new file mode 100644 index 00000000000..0b9d32409db --- /dev/null +++ b/langtools/test/tools/javac/T7126754.java @@ -0,0 +1,19 @@ +/* + * @test /nodynamiccopyright/ + * @bug 7126754 + * @summary Generics compilation failure casting List to List + * @compile T7126754.java + */ + +import java.util.List; +import java.util.Set; + +public class T7126754 { + public static void main(String[] args) { + List> a = null; + List> b = a; + + List> c = null; + List> d = (List>)c; + } +} diff --git a/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java b/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java new file mode 100644 index 00000000000..4e9eaf2fb8f --- /dev/null +++ b/langtools/test/tools/javac/T8022162/IncorrectSignatureDeterminationForInnerClassesTest.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8022162 + * @summary Incorrect signature determination for certain inner class generics + * @library /tools/javac/lib + * @build ToolBox + * @run main IncorrectSignatureDeterminationForInnerClassesTest + */ + +import java.nio.file.Files; +import java.nio.file.Paths; + +public class IncorrectSignatureDeterminationForInnerClassesTest { + + private static final String DSrc = + "package p1;\n" + + + "public class D {\n" + + "}\n" + + + "abstract class Q {\n" + + " protected void m(M.E e) {}\n" + + + " public class M extends D {\n" + + " public class E {}\n" + + " }\n" + + "}"; + + private static final String HSrc = + "package p1;\n" + + + "public class H {\n" + + " static class EQ extends Q {\n" + + " private void m2(M.E item) {\n" + + " m(item);\n" + + " }\n" + + " }\n" + + "}"; + + public static void main(String args[]) throws Exception { + new IncorrectSignatureDeterminationForInnerClassesTest().run(); + } + + void run() throws Exception { + compile(); + } + + void compile() throws Exception { + Files.createDirectory(Paths.get("classes")); + + ToolBox.JavaToolArgs javacParams = + new ToolBox.JavaToolArgs() + .appendArgs("-d", "classes") + .setSources(DSrc); + + ToolBox.javac(javacParams); + + // compile class H against the class files for classes D and Q + javacParams = + new ToolBox.JavaToolArgs() + .appendArgs("-d", "classes", "-cp", "classes") + .setSources(HSrc); + ToolBox.javac(javacParams); + } + +} diff --git a/langtools/test/tools/javac/T8023545/MisleadingErrorMsgDiamondPlusPrivateCtorTest.java b/langtools/test/tools/javac/T8023545/MisleadingErrorMsgDiamondPlusPrivateCtorTest.java new file mode 100644 index 00000000000..75959e29e22 --- /dev/null +++ b/langtools/test/tools/javac/T8023545/MisleadingErrorMsgDiamondPlusPrivateCtorTest.java @@ -0,0 +1,16 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8023545 + * @summary Misleading error message when using diamond operator with private constructor + * @compile/fail/ref=MisleadingErrorMsgDiamondPlusPrivateCtorTest.out -XDrawDiagnostics MisleadingErrorMsgDiamondPlusPrivateCtorTest.java + */ + +public class MisleadingErrorMsgDiamondPlusPrivateCtorTest { + public void foo() { + MyClass foo = new MyClass<>(); + } +} + +class MyClass { + private MyClass() {} +} diff --git a/langtools/test/tools/javac/T8023545/MisleadingErrorMsgDiamondPlusPrivateCtorTest.out b/langtools/test/tools/javac/T8023545/MisleadingErrorMsgDiamondPlusPrivateCtorTest.out new file mode 100644 index 00000000000..488e6a1041c --- /dev/null +++ b/langtools/test/tools/javac/T8023545/MisleadingErrorMsgDiamondPlusPrivateCtorTest.out @@ -0,0 +1,2 @@ +MisleadingErrorMsgDiamondPlusPrivateCtorTest.java:10:31: compiler.err.report.access: MyClass(), private, MyClass +1 error diff --git a/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java b/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java new file mode 100644 index 00000000000..9b69b074624 --- /dev/null +++ b/langtools/test/tools/javac/T8024039/NoDeadCodeGenerationOnTrySmtTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 8024039 + * @summary javac, previous solution for JDK-8022186 was incorrect + * @library /tools/javac/lib + * @build ToolBox + * @run main NoDeadCodeGenerationOnTrySmtTest + */ + +import java.io.File; +import java.nio.file.Paths; + +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.Code_attribute.Exception_data; +import com.sun.tools.classfile.Method; +import com.sun.tools.javac.util.Assert; + +public class NoDeadCodeGenerationOnTrySmtTest { + + static final String testSource = + "public class Test {\n" + + " void m1(int arg) {\n" + + " synchronized (new Integer(arg)) {\n" + + " {\n" + + " label0:\n" + + " do {\n" + + " break label0;\n" + + " } while (arg != 0);\n" + + " }\n" + + " }\n" + + " }\n" + + + " void m2(int arg) {\n" + + " synchronized (new Integer(arg)) {\n" + + " {\n" + + " label0:\n" + + " {\n" + + " break label0;\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}"; + + static final int[][] expectedExceptionTable = { + // {from, to, target, type}, + {11, 13, 16, 0}, + {16, 19, 16, 0} + }; + + static final String[] methodsToLookFor = {"m1", "m2"}; + + public static void main(String[] args) throws Exception { + new NoDeadCodeGenerationOnTrySmtTest().run(); + } + + void run() throws Exception { + compileTestClass(); + checkClassFile(new File(Paths.get(System.getProperty("user.dir"), + "Test.class").toUri()), methodsToLookFor); + } + + void compileTestClass() throws Exception { + ToolBox.JavaToolArgs javacSuccessArgs = + new ToolBox.JavaToolArgs().setSources(testSource); + ToolBox.javac(javacSuccessArgs); + } + + void checkClassFile(final File cfile, String[] methodsToFind) throws Exception { + ClassFile classFile = ClassFile.read(cfile); + int numberOfmethodsFound = 0; + for (String methodToFind : methodsToFind) { + for (Method method : classFile.methods) { + if (method.getName(classFile.constant_pool).equals(methodToFind)) { + numberOfmethodsFound++; + Code_attribute code = (Code_attribute) method.attributes.get("Code"); + Assert.check(code.exception_table_length == expectedExceptionTable.length, + "The ExceptionTable found has a length different to the expected one"); + int i = 0; + for (Exception_data entry: code.exception_table) { + Assert.check(entry.start_pc == expectedExceptionTable[i][0] && + entry.end_pc == expectedExceptionTable[i][1] && + entry.handler_pc == expectedExceptionTable[i][2] && + entry.catch_type == expectedExceptionTable[i][3], + "Exception table entry at pos " + i + " differ from expected."); + i++; + } + } + } + } + Assert.check(numberOfmethodsFound == 2, "Some seek methods were not found"); + } + + void error(String msg) { + throw new AssertionError(msg); + } + +} diff --git a/langtools/test/tools/javac/T8024207/FlowCrashTest.java b/langtools/test/tools/javac/T8024207/FlowCrashTest.java new file mode 100644 index 00000000000..5040c0ad448 --- /dev/null +++ b/langtools/test/tools/javac/T8024207/FlowCrashTest.java @@ -0,0 +1,23 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8024207 + * @summary javac crash in Flow$AssignAnalyzer.visitIdent + * @compile/fail/ref=FlowCrashTest.out -XDrawDiagnostics FlowCrashTest.java + */ + +import java.util.*; +import java.util.stream.*; + +public class FlowCrashTest { + static class ViewId { } + + public void crash() { + + Map viewToProfile = null; + new TreeMap<>(viewToProfile.entrySet().stream() + .collect(Collectors.toMap((vid, prn) -> prn, + (vid, prn) -> Arrays.asList(vid), + (a, b) -> { a.addAll(b); return a; }))); + + } +} diff --git a/langtools/test/tools/javac/T8024207/FlowCrashTest.out b/langtools/test/tools/javac/T8024207/FlowCrashTest.out new file mode 100644 index 00000000000..7eab7ccbb39 --- /dev/null +++ b/langtools/test/tools/javac/T8024207/FlowCrashTest.out @@ -0,0 +1,2 @@ +FlowCrashTest.java:18:42: compiler.err.cant.apply.symbols: kindname.method, toMap, @475,@542,@624,{(compiler.misc.inapplicable.method: kindname.method, java.util.stream.Collectors, toMap(java.util.function.Function,java.util.function.Function), (compiler.misc.infer.arg.length.mismatch: T,K,U)),(compiler.misc.inapplicable.method: kindname.method, java.util.stream.Collectors, toMap(java.util.function.Function,java.util.function.Function,java.util.function.BinaryOperator), (compiler.misc.infer.no.conforming.assignment.exists: T,K,U, (compiler.misc.incompatible.arg.types.in.lambda))),(compiler.misc.inapplicable.method: kindname.method, java.util.stream.Collectors, toMap(java.util.function.Function,java.util.function.Function,java.util.function.BinaryOperator,java.util.function.Supplier), (compiler.misc.infer.arg.length.mismatch: T,K,U,M))} +1 error diff --git a/langtools/test/tools/javac/T8024398/NPETryTest.java b/langtools/test/tools/javac/T8024398/NPETryTest.java new file mode 100644 index 00000000000..7d5b11fb6e0 --- /dev/null +++ b/langtools/test/tools/javac/T8024398/NPETryTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 8024398 + * @summary javac, compiler crashes with try with empty body + * @compile NPETryTest.java + */ + +public class NPETryTest { + void m() + { + /* This is the statement provoking the error the rest are provided as + * additional tests + */ + try {} + catch (Exception e) {} + + try {} + catch (Exception e) {} + finally {} + + try {} + finally {} + } +} diff --git a/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java b/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java new file mode 100644 index 00000000000..250b18a0614 --- /dev/null +++ b/langtools/test/tools/javac/T8024437/ExceptionInferenceFromClassFileTest.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 8024437 + * @summary Inferring the exception thrown by a lambda: sometimes fails to compile + * @library /tools/javac/lib + * @build ToolBox + * @run main ExceptionInferenceFromClassFileTest + */ + +import java.nio.file.Files; +import java.nio.file.Paths; + +public class ExceptionInferenceFromClassFileTest { + + static final String ABSrc = + "class B {\n" + + " public static void t(A a) throws E {\n" + + " a.run();\n" + + " }\n" + + "}\n" + + + "interface A {\n" + + " void run() throws E;\n" + + "}"; + + static final String CSrc = + "class C {\n" + + " public void d() {\n" + + " B.t(null);\n" + + " }\n" + + "}"; + + public static void main(String[] args) throws Exception { + Files.createDirectory(Paths.get("out")); + + ToolBox.JavaToolArgs compileABParams = + new ToolBox.JavaToolArgs() + .setOptions("-d", "out") + .setSources(ABSrc); + ToolBox.javac(compileABParams); + + ToolBox.JavaToolArgs compileCParams = + new ToolBox.JavaToolArgs() + .setOptions("-d", "out", "-cp", "out") + .setSources(CSrc); + ToolBox.javac(compileCParams); + } + +} diff --git a/langtools/test/tools/javac/annotations/neg/NoDefault.java b/langtools/test/tools/javac/annotations/neg/NoDefault.java new file mode 100644 index 00000000000..282bc98bf3a --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoDefault.java @@ -0,0 +1,9 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8022322 + * @summary Default methods are not allowed in an annotation. + * @compile/fail/ref=NoDefault.out -XDrawDiagnostics NoDefault.java + */ +@interface NoDefault { + default int m() {return 0;} +} diff --git a/langtools/test/tools/javac/annotations/neg/NoDefault.out b/langtools/test/tools/javac/annotations/neg/NoDefault.out new file mode 100644 index 00000000000..ffcbf823351 --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoDefault.out @@ -0,0 +1,3 @@ +NoDefault.java:8:17: compiler.err.mod.not.allowed.here: default +NoDefault.java:8:21: compiler.err.intf.meth.cant.have.body +2 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/annotations/neg/NoDefaultAbstract.java b/langtools/test/tools/javac/annotations/neg/NoDefaultAbstract.java new file mode 100644 index 00000000000..6c288810fe1 --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoDefaultAbstract.java @@ -0,0 +1,9 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8022322 + * @summary Default methods are not allowed in an annotation. + * @compile/fail/ref=NoDefaultAbstract.out -XDrawDiagnostics NoDefaultAbstract.java + */ +@interface NoDefaultAbstract { + default int m(); +} diff --git a/langtools/test/tools/javac/annotations/neg/NoDefaultAbstract.out b/langtools/test/tools/javac/annotations/neg/NoDefaultAbstract.out new file mode 100644 index 00000000000..ea445c68e13 --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoDefaultAbstract.out @@ -0,0 +1,2 @@ +NoDefaultAbstract.java:8:17: compiler.err.mod.not.allowed.here: default +1 error diff --git a/langtools/test/tools/javac/annotations/neg/NoStatic.java b/langtools/test/tools/javac/annotations/neg/NoStatic.java new file mode 100644 index 00000000000..3a62dc7c748 --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoStatic.java @@ -0,0 +1,10 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8022322 + * @summary Static methods are not allowed in an annotation. + * @compile/fail/ref=NoStatic.out -XDrawDiagnostics NoStatic.java + */ + +@interface NoStatic { + static int m() {return 0;} +} diff --git a/langtools/test/tools/javac/annotations/neg/NoStatic.out b/langtools/test/tools/javac/annotations/neg/NoStatic.out new file mode 100644 index 00000000000..8d9d3131915 --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoStatic.out @@ -0,0 +1,3 @@ +NoStatic.java:9:16: compiler.err.mod.not.allowed.here: static +NoStatic.java:9:20: compiler.err.intf.meth.cant.have.body +2 errors diff --git a/langtools/test/tools/javac/annotations/neg/NoStaticAbstract.java b/langtools/test/tools/javac/annotations/neg/NoStaticAbstract.java new file mode 100644 index 00000000000..af27fa75b9a --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoStaticAbstract.java @@ -0,0 +1,10 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8022322 + * @summary Static methods are not allowed in an annotation. + * @compile/fail/ref=NoStaticAbstract.out -XDrawDiagnostics NoStaticAbstract.java + */ + +@interface NoStaticAbstract { + static int m(); +} diff --git a/langtools/test/tools/javac/annotations/neg/NoStaticAbstract.out b/langtools/test/tools/javac/annotations/neg/NoStaticAbstract.out new file mode 100644 index 00000000000..694cea1771f --- /dev/null +++ b/langtools/test/tools/javac/annotations/neg/NoStaticAbstract.out @@ -0,0 +1,2 @@ +NoStaticAbstract.java:9:16: compiler.err.mod.not.allowed.here: static +1 error diff --git a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java index 7aea2d42476..a398ec1791b 100644 --- a/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java +++ b/langtools/test/tools/javac/cast/intersection/IntersectionTypeCastTest.java @@ -237,7 +237,7 @@ public class IntersectionTypeCastTest } static List allCastInfo() { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (CastKind kind : CastKind.values()) { for (ClassKind clazz : ClassKind.values()) { if (kind == CastKind.INTERFACE && clazz != ClassKind.OBJECT) { diff --git a/langtools/test/tools/javac/cast/intersection/model/Model01.java b/langtools/test/tools/javac/cast/intersection/model/Model01.java index 21740179f49..782644726ca 100644 --- a/langtools/test/tools/javac/cast/intersection/model/Model01.java +++ b/langtools/test/tools/javac/cast/intersection/model/Model01.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8002099 + * @bug 8002099 6499673 * @summary Add support for intersection types in cast expression * @library /tools/javac/lib * @build JavacTestingAbstractProcessor ModelChecker @@ -46,7 +46,7 @@ class Test { } void test(){ - @IntersectionTypeInfo({"java.lang.Object", "Test.A", "Test.B"}) + @IntersectionTypeInfo({"Test.A", "Test.B"}) Object o = (A & B)null; } } diff --git a/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java b/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java index 1486d21bf1b..d2dbf697fdc 100644 --- a/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java +++ b/langtools/test/tools/javac/cast/intersection/model/ModelChecker.java @@ -97,7 +97,7 @@ public class ModelChecker extends JavacTestingAbstractProcessor { } } - assertTrue(assertionCount == 10, "Expected 10 assertions - found " + assertionCount); + assertTrue(assertionCount == 9, "Expected 9 assertions - found " + assertionCount); return super.visitVariable(node, p); } } diff --git a/langtools/test/tools/javac/defaultMethods/ClassReaderTest/ClassReaderTest.java b/langtools/test/tools/javac/defaultMethods/ClassReaderTest/ClassReaderTest.java index 0e533acbe6f..491486f106e 100644 --- a/langtools/test/tools/javac/defaultMethods/ClassReaderTest/ClassReaderTest.java +++ b/langtools/test/tools/javac/defaultMethods/ClassReaderTest/ClassReaderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that default methods don't cause ClassReader to complete classes recursively * @author Maurizio Cimadamore * @compile pkg/Foo.java diff --git a/langtools/test/tools/javac/defaultMethods/Neg01.java b/langtools/test/tools/javac/defaultMethods/Neg01.java index bbf1aba7eaa..0457b5de9bc 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg01.java +++ b/langtools/test/tools/javac/defaultMethods/Neg01.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary negative test for ambiguous defaults * @compile/fail/ref=Neg01.out -XDrawDiagnostics Neg01.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg02.java b/langtools/test/tools/javac/defaultMethods/Neg02.java index deb35a19d78..2ba1319ae96 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg02.java +++ b/langtools/test/tools/javac/defaultMethods/Neg02.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that ill-formed MI hierarchies do not compile * @compile/fail/ref=Neg02.out -XDrawDiagnostics Neg02.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg03.java b/langtools/test/tools/javac/defaultMethods/Neg03.java index ba6262c853b..2a1fbe48df2 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg03.java +++ b/langtools/test/tools/javac/defaultMethods/Neg03.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that re-abstraction works properly * @compile/fail/ref=Neg03.out -XDrawDiagnostics Neg03.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg04.java b/langtools/test/tools/javac/defaultMethods/Neg04.java index a057f35d620..c1abcfad8f3 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg04.java +++ b/langtools/test/tools/javac/defaultMethods/Neg04.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default method must have most specific return type * @compile/fail/ref=Neg04.out -XDrawDiagnostics Neg04.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg05.java b/langtools/test/tools/javac/defaultMethods/Neg05.java index 3550c497241..8be5cf59019 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg05.java +++ b/langtools/test/tools/javac/defaultMethods/Neg05.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that abstract methods are compatible with inherited defaults * @compile/fail/ref=Neg05.out -XDrawDiagnostics Neg05.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg06.java b/langtools/test/tools/javac/defaultMethods/Neg06.java index 602ece8166f..23a757f5791 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg06.java +++ b/langtools/test/tools/javac/defaultMethods/Neg06.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary flow analysis is not run on inlined default bodies * @compile/fail/ref=Neg06.out -XDrawDiagnostics Neg06.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg07.java b/langtools/test/tools/javac/defaultMethods/Neg07.java index c11f3157b22..763a253623a 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg07.java +++ b/langtools/test/tools/javac/defaultMethods/Neg07.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default overrides are properly type-checked * @compile/fail/ref=Neg07.out -XDrawDiagnostics Neg07.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg08.java b/langtools/test/tools/javac/defaultMethods/Neg08.java index 5e3ef07e719..b6eb221c1e2 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg08.java +++ b/langtools/test/tools/javac/defaultMethods/Neg08.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default overrides are properly type-checked * @compile/fail/ref=Neg08.out -XDrawDiagnostics Neg08.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg09.java b/langtools/test/tools/javac/defaultMethods/Neg09.java index cabda07c321..dc7801a0a2c 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg09.java +++ b/langtools/test/tools/javac/defaultMethods/Neg09.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default overrides are properly type-checked * @compile/fail/ref=Neg09.out -Werror -Xlint:unchecked -XDrawDiagnostics Neg09.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg10.java b/langtools/test/tools/javac/defaultMethods/Neg10.java index 3ecb1af86e1..188fd7f0747 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg10.java +++ b/langtools/test/tools/javac/defaultMethods/Neg10.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default overrides are properly type-checked * @compile/fail/ref=Neg10.out -Werror -Xlint:unchecked -XDrawDiagnostics Neg10.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg11.java b/langtools/test/tools/javac/defaultMethods/Neg11.java index acf88f65ef2..c3b35b68b38 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg11.java +++ b/langtools/test/tools/javac/defaultMethods/Neg11.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default overrides are properly type-checked * @compile/fail/ref=Neg11.out -XDrawDiagnostics Neg11.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg12.java b/langtools/test/tools/javac/defaultMethods/Neg12.java index e61245bf7e3..267dc86f70e 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg12.java +++ b/langtools/test/tools/javac/defaultMethods/Neg12.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that abstract methods are discarded in overload resolution diags * @compile/fail/ref=Neg12.out -XDrawDiagnostics Neg12.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg13.java b/langtools/test/tools/javac/defaultMethods/Neg13.java index e512cc3a65b..a166adab3f1 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg13.java +++ b/langtools/test/tools/javac/defaultMethods/Neg13.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that default method overriding object members are flagged as error * @compile/fail/ref=Neg13.out -XDrawDiagnostics Neg13.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg14.java b/langtools/test/tools/javac/defaultMethods/Neg14.java index 9c3c6a69e3c..842b51607a1 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg14.java +++ b/langtools/test/tools/javac/defaultMethods/Neg14.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that a class cannot have two sibling interfaces with a default and abstract method * @compile/fail/ref=Neg14.out -XDrawDiagnostics Neg14.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg15.java b/langtools/test/tools/javac/defaultMethods/Neg15.java index 7c42167d75f..1845733fe91 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg15.java +++ b/langtools/test/tools/javac/defaultMethods/Neg15.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that level skipping in default super calls is correctly rejected * @compile/fail/ref=Neg15.out -XDrawDiagnostics Neg15.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Neg16.java b/langtools/test/tools/javac/defaultMethods/Neg16.java index 1022fda22c8..cb5ce4930f5 100644 --- a/langtools/test/tools/javac/defaultMethods/Neg16.java +++ b/langtools/test/tools/javac/defaultMethods/Neg16.java @@ -1,5 +1,5 @@ -/* - * @test /nodynamiccopyright/ +/* @test /nodynamiccopyright/ + * @bug 7192246 * @summary check that level skipping in default super calls is correctly rejected * @compile/fail/ref=Neg16.out -XDrawDiagnostics Neg16.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Pos01.java b/langtools/test/tools/javac/defaultMethods/Pos01.java index 13fa6b47e83..30a3e3179f0 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos01.java +++ b/langtools/test/tools/javac/defaultMethods/Pos01.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary basic test for default methods * @author Maurizio Cimadamore */ diff --git a/langtools/test/tools/javac/defaultMethods/Pos02.java b/langtools/test/tools/javac/defaultMethods/Pos02.java index 597e7f50c79..5b71e36f8bd 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos02.java +++ b/langtools/test/tools/javac/defaultMethods/Pos02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary test for explicit resolution of ambiguous default methods * @author Maurizio Cimadamore * @compile Pos02.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos04.java b/langtools/test/tools/javac/defaultMethods/Pos04.java index 3cc0cd4c4c5..e238e280dd5 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos04.java +++ b/langtools/test/tools/javac/defaultMethods/Pos04.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary test for overriding with default method * @author Maurizio Cimadamore * @compile Pos04.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos05.java b/langtools/test/tools/javac/defaultMethods/Pos05.java index 92a7eaccc9c..181ce39d4ab 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos05.java +++ b/langtools/test/tools/javac/defaultMethods/Pos05.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that indirectly inherited default methods are discovered during resolution * @author Maurizio Cimadamore * @compile Pos05.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos06.java b/langtools/test/tools/javac/defaultMethods/Pos06.java index 3263e9276e2..15bcec46e4c 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos06.java +++ b/langtools/test/tools/javac/defaultMethods/Pos06.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that well-formed MI hierarchies behaves well w.r.t. method resolution (i.e. no ambiguities) * @author Maurizio Cimadamore * @compile Pos06.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos07.java b/langtools/test/tools/javac/defaultMethods/Pos07.java index 6e1c2308bb5..a48e8ba3993 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos07.java +++ b/langtools/test/tools/javac/defaultMethods/Pos07.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that compilation order does not matter * @author Maurizio Cimadamore * @compile Pos07.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos08.java b/langtools/test/tools/javac/defaultMethods/Pos08.java index b12486a7f8b..78bc0792257 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos08.java +++ b/langtools/test/tools/javac/defaultMethods/Pos08.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that common overrider solves default method conflicts * @author Maurizio Cimadamore * @compile Pos08.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos10.java b/langtools/test/tools/javac/defaultMethods/Pos10.java index 7f0039a685b..b4c6546fa2f 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos10.java +++ b/langtools/test/tools/javac/defaultMethods/Pos10.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that type-variables in generic extension decl can be accessed from default impl * @author Maurizio Cimadamore * @compile Pos10.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos11.java b/langtools/test/tools/javac/defaultMethods/Pos11.java index 91b83ccbb1c..3d6305e3be1 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos11.java +++ b/langtools/test/tools/javac/defaultMethods/Pos11.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary complex test with conflict resolution via overriding * @author Brian Goetz * @compile Pos11.java diff --git a/langtools/test/tools/javac/defaultMethods/Pos12.java b/langtools/test/tools/javac/defaultMethods/Pos12.java index 4db7f3ca182..56d2d0ea5a5 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos12.java +++ b/langtools/test/tools/javac/defaultMethods/Pos12.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that 'this' can be used from within an extension method * @compile Pos12.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Pos13.java b/langtools/test/tools/javac/defaultMethods/Pos13.java index b9acba34b44..e267f4a3ecd 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos13.java +++ b/langtools/test/tools/javac/defaultMethods/Pos13.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary qualified 'this' inside default method causes StackOverflowException * @compile Pos13.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Pos14.java b/langtools/test/tools/javac/defaultMethods/Pos14.java index d8ac04af981..07801d35529 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos14.java +++ b/langtools/test/tools/javac/defaultMethods/Pos14.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that overload resolution selects most specific signature * @compile Pos14.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Pos15.java b/langtools/test/tools/javac/defaultMethods/Pos15.java index a2dad21b237..b1a3281c583 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos15.java +++ b/langtools/test/tools/javac/defaultMethods/Pos15.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that overload resolution selects most specific signature * @compile Pos15.java */ diff --git a/langtools/test/tools/javac/defaultMethods/Pos16.java b/langtools/test/tools/javac/defaultMethods/Pos16.java index eca63b94faf..0d9a2b1da55 100644 --- a/langtools/test/tools/javac/defaultMethods/Pos16.java +++ b/langtools/test/tools/javac/defaultMethods/Pos16.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary 'class wins' should not short-circuit overload resolution * @compile Pos16.java */ diff --git a/langtools/test/tools/javac/defaultMethods/TestDefaultBody.java b/langtools/test/tools/javac/defaultMethods/TestDefaultBody.java index be3f6bfbf94..7f1be065bd1 100644 --- a/langtools/test/tools/javac/defaultMethods/TestDefaultBody.java +++ b/langtools/test/tools/javac/defaultMethods/TestDefaultBody.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that code attributed for default methods is correctly generated */ diff --git a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java index 328629c51e7..ab464b70314 100644 --- a/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java +++ b/langtools/test/tools/javac/defaultMethods/TestNoBridgeOnDefaults.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that javac does not generate bridge methods for defaults */ diff --git a/langtools/test/tools/javac/defaultMethods/crossCompile/CrossCompile.java b/langtools/test/tools/javac/defaultMethods/crossCompile/CrossCompile.java index de51d4afacd..6a6f9a12e49 100644 --- a/langtools/test/tools/javac/defaultMethods/crossCompile/CrossCompile.java +++ b/langtools/test/tools/javac/defaultMethods/crossCompile/CrossCompile.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary check that clinit in interface doesn't cause spurious default method diagnostics * @compile -source 1.4 -target 1.4 Clinit.java * @compile CrossCompile.java diff --git a/langtools/test/tools/javac/defaultMethods/separate/Separate.java b/langtools/test/tools/javac/defaultMethods/separate/Separate.java index 7dcf4e3ac2b..513fc996a9a 100644 --- a/langtools/test/tools/javac/defaultMethods/separate/Separate.java +++ b/langtools/test/tools/javac/defaultMethods/separate/Separate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,6 +23,7 @@ /* * @test + * @bug 7192246 * @summary smoke test for separate compilation of default methods * @author Maurizio Cimadamore * @compile pkg1/A.java diff --git a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java index 9c3a513c90f..1fbeed6d5c2 100644 --- a/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java +++ b/langtools/test/tools/javac/defaultMethods/super/TestDefaultSuperCall.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8006694 + * @bug 7192246 8006694 * @summary Automatic test for checking correctness of default super/this resolution * temporarily workaround combo tests are causing time out in several platforms * @library ../../lib diff --git a/langtools/test/tools/javac/depDocComment/SuppressDeprecation.out b/langtools/test/tools/javac/depDocComment/SuppressDeprecation.out index eb0c0ff686b..4a8b15f33fd 100644 --- a/langtools/test/tools/javac/depDocComment/SuppressDeprecation.out +++ b/langtools/test/tools/javac/depDocComment/SuppressDeprecation.out @@ -1,8 +1,8 @@ -SuppressDeprecation.java:130:17: compiler.warn.has.been.deprecated: X, compiler.misc.unnamed.package SuppressDeprecation.java:82:10: compiler.warn.has.been.deprecated: g(), T SuppressDeprecation.java:83:14: compiler.warn.has.been.deprecated: g(), T SuppressDeprecation.java:84:9: compiler.warn.has.been.deprecated: var, T SuppressDeprecation.java:87:9: compiler.warn.has.been.deprecated: T(), T SuppressDeprecation.java:90:9: compiler.warn.has.been.deprecated: T(int), T SuppressDeprecation.java:98:1: compiler.warn.has.been.deprecated: T(), T +SuppressDeprecation.java:130:17: compiler.warn.has.been.deprecated: X, compiler.misc.unnamed.package 7 warnings diff --git a/langtools/test/tools/javac/diags/examples/BadArgTypesInLambda.java b/langtools/test/tools/javac/diags/examples/BadArgTypesInLambda.java index 493c4c31efc..e4feea050d5 100644 --- a/langtools/test/tools/javac/diags/examples/BadArgTypesInLambda.java +++ b/langtools/test/tools/javac/diags/examples/BadArgTypesInLambda.java @@ -21,9 +21,6 @@ * questions. */ -// key: compiler.err.cant.apply.symbol -// key: compiler.misc.no.conforming.assignment.exists -// key: compiler.misc.bad.arg.types.in.lambda // key: compiler.err.prob.found.req // key: compiler.misc.inconvertible.types // options: -Xdiags:verbose diff --git a/langtools/test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java b/langtools/test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java index 999eb903296..a983af8663f 100644 --- a/langtools/test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java +++ b/langtools/test/tools/javac/diags/examples/IncompatibleArgTypesInMethodRef.java @@ -31,6 +31,7 @@ class IncompatibleArgTypesInMethodRef { } void g(String s, Integer i) { } + void g(Integer i, String s) { } void m(SAM s) { } diff --git a/langtools/test/tools/javac/diags/examples/MrefInferAndExplicitParams.java b/langtools/test/tools/javac/diags/examples/MrefInferAndExplicitParams.java new file mode 100644 index 00000000000..ce24f82e60e --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/MrefInferAndExplicitParams.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.err.invalid.mref +// key: compiler.misc.mref.infer.and.explicit.params + +public class MrefInferAndExplicitParams { + static class Foo {} + + interface Supplier { + X make(); + } + + Supplier> sfs = Foo::new; +} diff --git a/langtools/test/tools/javac/diags/examples/MrefStat.java.rej b/langtools/test/tools/javac/diags/examples/MrefStat.java.rej deleted file mode 100644 index f5286e5a2d2..00000000000 --- a/langtools/test/tools/javac/diags/examples/MrefStat.java.rej +++ /dev/null @@ -1,34 +0,0 @@ ---- MrefStat.java -+++ MrefStat.java -@@ -0,0 +1,31 @@ -+/* -+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ */ -+ -+// key: compiler.note.mref.stat -+// options: -XDdumpLambdaToMethodStats -+ -+class MrefStat { -+ Runnable r = MrefStat::m; -+ -+ static void m() { } -+} diff --git a/langtools/test/tools/javac/diags/examples/MrefStat1.java.rej b/langtools/test/tools/javac/diags/examples/MrefStat1.java.rej deleted file mode 100644 index b247270db53..00000000000 --- a/langtools/test/tools/javac/diags/examples/MrefStat1.java.rej +++ /dev/null @@ -1,37 +0,0 @@ ---- MrefStat1.java -+++ MrefStat1.java -@@ -0,0 +1,34 @@ -+/* -+ * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. -+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -+ * -+ * This code is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 only, as -+ * published by the Free Software Foundation. -+ * -+ * This code is distributed in the hope that it will be useful, but WITHOUT -+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -+ * version 2 for more details (a copy is included in the LICENSE file that -+ * accompanied this code). -+ * -+ * You should have received a copy of the GNU General Public License version -+ * 2 along with this work; if not, write to the Free Software Foundation, -+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -+ * or visit www.oracle.com if you need additional information or have any -+ * questions. -+ */ -+ -+// key: compiler.note.mref.stat.1 -+// options: -XDdumpLambdaToMethodStats -+ -+class MrefStat1 { -+ -+ void m() { } -+ -+ static class Sub extends MrefStat1 { -+ Runnable r = super::m; -+ } -+} diff --git a/langtools/test/tools/javac/diags/examples/PotentiallyAmbiguousOverload.java b/langtools/test/tools/javac/diags/examples/PotentiallyAmbiguousOverload.java new file mode 100644 index 00000000000..50660cf49e1 --- /dev/null +++ b/langtools/test/tools/javac/diags/examples/PotentiallyAmbiguousOverload.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +// key: compiler.warn.potentially.ambiguous.overload +// options: -Xlint:overloads + +class PotentiallyAmbiguousOverload { + interface F1 { + void m(String s); + } + + interface F2 { + void m(Integer s); + } + + void m(F1 f1) { } + void m(F2 f2) { } +} diff --git a/langtools/test/tools/javac/doclint/implicitSource/ImplicitSourceTest.java b/langtools/test/tools/javac/doclint/implicitSource/ImplicitSourceTest.java new file mode 100644 index 00000000000..6ae67ce2819 --- /dev/null +++ b/langtools/test/tools/javac/doclint/implicitSource/ImplicitSourceTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8024538 + * @summary -Xdoclint + -Xprefer:source + incremental compilation == FAIL + * @compile -Xdoclint -Xprefer:source ImplicitSourceTest.java + */ + +/** ImplicitSourceTest. */ +class ImplicitSourceTest { + /**

    {@link Other}

    */ + int i; +} diff --git a/langtools/test/tools/javac/doclint/implicitSource/Other.java b/langtools/test/tools/javac/doclint/implicitSource/Other.java new file mode 100644 index 00000000000..65a5dd5b45a --- /dev/null +++ b/langtools/test/tools/javac/doclint/implicitSource/Other.java @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** Other. */ +class Other { } diff --git a/langtools/test/tools/javac/flow/AliveRanges.java b/langtools/test/tools/javac/flow/AliveRanges.java new file mode 100644 index 00000000000..2494f77aca8 --- /dev/null +++ b/langtools/test/tools/javac/flow/AliveRanges.java @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import java.lang.annotation.*; + +@Repeatable(AliveRanges.class) +@Target({ElementType.METHOD}) +@interface AliveRange { + String varName(); + int bytecodeStart(); + int bytecodeLength(); +} + +@Target({ElementType.METHOD}) +@interface AliveRanges {AliveRange[] value();} diff --git a/langtools/test/tools/javac/flow/LVTHarness.java b/langtools/test/tools/javac/flow/LVTHarness.java new file mode 100644 index 00000000000..9aac87c4f00 --- /dev/null +++ b/langtools/test/tools/javac/flow/LVTHarness.java @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 7047734 + * @summary The LVT is not generated correctly during some try/catch scenarios + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor LVTHarness + * @run main LVTHarness + */ + +import java.io.File; +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Set; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +import javax.annotation.processing.RoundEnvironment; +import javax.lang.model.element.Element; +import javax.lang.model.element.TypeElement; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +import com.sun.source.util.JavacTask; +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.Code_attribute; +import com.sun.tools.classfile.ConstantPool.InvalidIndex; +import com.sun.tools.classfile.ConstantPool.UnexpectedEntry; +import com.sun.tools.classfile.Descriptor.InvalidDescriptor; +import com.sun.tools.classfile.LocalVariableTable_attribute; +import com.sun.tools.classfile.Method; + +import static javax.tools.StandardLocation.*; +import static com.sun.tools.classfile.LocalVariableTable_attribute.Entry; +import static javax.tools.JavaFileObject.Kind.SOURCE; + +public class LVTHarness { + + static int nerrors = 0; + + static final JavaCompiler comp = ToolProvider.getSystemJavaCompiler(); + static final StandardJavaFileManager fm = comp.getStandardFileManager(null, null, null); + + public static void main(String[] args) throws Exception { + + String testDir = System.getProperty("test.src"); + fm.setLocation(SOURCE_PATH, Arrays.asList(new File(testDir, "tests"))); + + // Make sure classes are written to scratch dir. + fm.setLocation(CLASS_OUTPUT, Arrays.asList(new File("."))); + + for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", Collections.singleton(SOURCE), true)) { + new LVTHarness(jfo).check(); + } + if (nerrors > 0) { + throw new AssertionError("Errors were found"); + } + } + + + JavaFileObject jfo; + Map aliveRangeMap = new HashMap<>(); + Set declaredKeys = new HashSet<>(); + List seenAliveRanges = new ArrayList<>(); + + protected LVTHarness(JavaFileObject jfo) { + this.jfo = jfo; + } + + protected void check() throws Exception { + + JavacTask ct = (JavacTask) comp.getTask(null, fm, null, Arrays.asList("-g"), + null, Arrays.asList(jfo)); + System.err.println("compiling code " + jfo); + ct.setProcessors(Collections.singleton(new AliveRangeFinder())); + if (!ct.call()) { + throw new AssertionError("Error during compilation"); + } + + + File javaFile = new File(jfo.getName()); + File classFile = new File(javaFile.getName().replace(".java", ".class")); + checkClassFile(classFile); + + //check all candidates have been used up + for (Map.Entry entry : aliveRangeMap.entrySet()) { + if (!seenAliveRanges.contains(entry.getKey())) { + error("Redundant @AliveRanges annotation on method " + + entry.getKey().elem); + } + } + } + + void checkClassFile(File file) + throws IOException, ConstantPoolException, InvalidDescriptor { + ClassFile classFile = ClassFile.read(file); + ConstantPool constantPool = classFile.constant_pool; + + //lets get all the methods in the class file. + for (Method method : classFile.methods) { + for (ElementKey elementKey: aliveRangeMap.keySet()) { + String methodDesc = method.getName(constantPool) + + method.descriptor.getParameterTypes(constantPool); + if (methodDesc.equals(elementKey.elem.toString())) { + checkMethod(constantPool, method, aliveRangeMap.get(elementKey)); + seenAliveRanges.add(elementKey); + } + } + } + } + + void checkMethod(ConstantPool constantPool, Method method, AliveRanges ranges) + throws InvalidIndex, UnexpectedEntry { + Code_attribute code = (Code_attribute) method.attributes.get(Attribute.Code); + LocalVariableTable_attribute lvt = + (LocalVariableTable_attribute) (code.attributes.get(Attribute.LocalVariableTable)); + List infoFromRanges = convertToStringList(ranges); + List infoFromLVT = convertToStringList(constantPool, lvt); + + // infoFromRanges most be contained in infoFromLVT + int i = 0; + int j = 0; + while (i < infoFromRanges.size() && j < infoFromLVT.size()) { + int comparison = infoFromRanges.get(i).compareTo(infoFromLVT.get(j)); + if (comparison == 0) { + i++; j++; + } else if (comparison > 0) { + j++; + } else { + break; + } + } + + if (i < infoFromRanges.size()) { + error(infoFromLVT, infoFromRanges); + } + } + + List convertToStringList(AliveRanges ranges) { + List result = new ArrayList<>(); + for (Annotation anno : ranges.value()) { + AliveRange range = (AliveRange)anno; + String str = formatLocalVariableData(range.varName(), + range.bytecodeStart(), range.bytecodeLength()); + result.add(str); + } + Collections.sort(result); + return result; + } + + List convertToStringList(ConstantPool constantPool, + LocalVariableTable_attribute lvt) throws InvalidIndex, UnexpectedEntry { + List result = new ArrayList<>(); + for (Entry entry : lvt.local_variable_table) { + String str = formatLocalVariableData(constantPool.getUTF8Value(entry.name_index), + entry.start_pc, entry.length); + result.add(str); + } + Collections.sort(result); + return result; + } + + String formatLocalVariableData(String varName, int start, int length) { + StringBuilder sb = new StringBuilder() + .append("var name: ").append(varName) + .append(" start: ").append(start) + .append(" length: ").append(length); + return sb.toString(); + } + + protected void error(List infoFromLVT, List infoFromRanges) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\n", jfo.getName()); + System.err.println("The range info from the annotations is"); + printStringListToErrOutput(infoFromRanges); + System.err.println(); + System.err.println("And the range info from the class file is"); + printStringListToErrOutput(infoFromLVT); + System.err.println(); + } + + void printStringListToErrOutput(List list) { + for (String s : list) { + System.err.println("\t" + s); + } + } + + protected void error(String msg) { + nerrors++; + System.err.printf("Error occurred while checking file: %s\nreason: %s\n", + jfo.getName(), msg); + } + + class AliveRangeFinder extends JavacTestingAbstractProcessor { + + @Override + public boolean process(Set annotations, + RoundEnvironment roundEnv) { + if (roundEnv.processingOver()) + return true; + + TypeElement aliveRangeAnno = elements.getTypeElement("AliveRanges"); + + if (!annotations.contains(aliveRangeAnno)) { + error("no @AliveRanges annotation found in test class"); + } + + for (Element elem: roundEnv.getElementsAnnotatedWith(aliveRangeAnno)) { + Annotation annotation = elem.getAnnotation(AliveRanges.class); + aliveRangeMap.put(new ElementKey(elem), (AliveRanges)annotation); + } + return true; + } + } + + class ElementKey { + + String key; + Element elem; + + public ElementKey(Element elem) { + this.elem = elem; + this.key = computeKey(elem); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof ElementKey) { + ElementKey other = (ElementKey)obj; + return other.key.equals(key); + } + return false; + } + + @Override + public int hashCode() { + return key.hashCode(); + } + + String computeKey(Element e) { + StringBuilder buf = new StringBuilder(); + while (e != null) { + buf.append(e.toString()); + e = e.getEnclosingElement(); + } + buf.append(jfo.getName()); + return buf.toString(); + } + + @Override + public String toString() { + return "Key{" + key + "}"; + } + } + +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseConditional.java b/langtools/test/tools/javac/flow/tests/TestCaseConditional.java new file mode 100644 index 00000000000..0e5915985d0 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseConditional.java @@ -0,0 +1,16 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseConditional { + + @AliveRange(varName="o", bytecodeStart=5, bytecodeLength=33) + @AliveRange(varName="oo", bytecodeStart=23, bytecodeLength=15) + void m(String[] args) { + Boolean o; + Boolean oo = ((o = Boolean.TRUE).booleanValue()) ? + o = Boolean.TRUE : + Boolean.FALSE; + oo.hashCode(); + o = Boolean.FALSE; + o.hashCode(); + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseDoLoop.java b/langtools/test/tools/javac/flow/tests/TestCaseDoLoop.java new file mode 100644 index 00000000000..68e3d20e6a4 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseDoLoop.java @@ -0,0 +1,15 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseDoLoop { + + @AliveRange(varName="o", bytecodeStart=3, bytecodeLength=15) + @AliveRange(varName="args", bytecodeStart=0, bytecodeLength=18) + void m(String[] args) { + Object o; + do { + o = ""; + o.hashCode(); + } while (args[0] != null); + o = ""; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseFor.java b/langtools/test/tools/javac/flow/tests/TestCaseFor.java new file mode 100644 index 00000000000..10056b88086 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseFor.java @@ -0,0 +1,27 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseFor { + + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=24, bytecodeLength=1) + void m1(String[] args) { + Object o; + for (int i = 0; i < 5; i++) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=24, bytecodeLength=1) + void m2(String[] args) { + Object o; + for (int i = 0; i < 5; i++) { + o = ""; + o.hashCode(); + continue; + } + o = ""; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseForEach.java b/langtools/test/tools/javac/flow/tests/TestCaseForEach.java new file mode 100644 index 00000000000..219f1180772 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseForEach.java @@ -0,0 +1,15 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseForEach { + + @AliveRange(varName="o", bytecodeStart=25, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=39, bytecodeLength=1) + void m(String[] args) { + Object o; + for (String s : args) { + o = ""; + o.hashCode(); + } + o = ""; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseIf.java b/langtools/test/tools/javac/flow/tests/TestCaseIf.java new file mode 100644 index 00000000000..9869443f773 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseIf.java @@ -0,0 +1,61 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseIf { + + @AliveRange(varName="o", bytecodeStart=9, bytecodeLength=5) + @AliveRange(varName="o", bytecodeStart=17, bytecodeLength=1) + void m0(String[] args) { + Object o; + if (args[0] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=5) + @AliveRange(varName="o", bytecodeStart=18, bytecodeLength=1) + void m1() { + Object o; + int i = 5; + if (i == 5) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=5) + @AliveRange(varName="o", bytecodeStart=18, bytecodeLength=1) + void m2() { + Object o; + int i = 5; + if (!(i == 5)) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=15, bytecodeLength=5) + @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=1) + void m3(String[] args) { + Object o; + if (args[0] != null && args[1] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=15, bytecodeLength=5) + @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=1) + void m4(String[] args) { + Object o; + if (args[0] != null || args[1] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java b/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java new file mode 100644 index 00000000000..3e6cc893794 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseIfElse.java @@ -0,0 +1,48 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseIfElse { + + @AliveRange(varName="o", bytecodeStart=9, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=20, bytecodeLength=9) + void m0(String[] args) { + Object o; + if (args[0] != null) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=21, bytecodeLength=9) + void m1() { + Object o; + int i = 5; + if (i == 5) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } + + @AliveRange(varName="o", bytecodeStart=10, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=21, bytecodeLength=9) + void m2(String[] args) { + Object o; + int i = 5; + if (i != 5) { + o = "then"; + o.hashCode(); + } else { + o = "else"; + o.hashCode(); + } + o = "finish"; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java b/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java new file mode 100644 index 00000000000..d96850ffd21 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseSwitch.java @@ -0,0 +1,73 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseSwitch { + + @AliveRange(varName="o", bytecodeStart=31, bytecodeLength=16) + @AliveRange(varName="o", bytecodeStart=50, bytecodeLength=15) + @AliveRange(varName="o", bytecodeStart=68, bytecodeLength=1) + @AliveRange(varName="oo", bytecodeStart=39, bytecodeLength=26) + @AliveRange(varName="uu", bytecodeStart=59, bytecodeLength=6) + void m1(String[] args) { + Object o; + switch (args.length) { + case 0: + o = "0"; + o.hashCode(); + Object oo = "oo"; + oo.hashCode(); + break; + case 1: + o = "1"; + o.hashCode(); + Object uu = "uu"; + uu.hashCode(); + break; + } + o = "return"; + } + + @AliveRange(varName="o", bytecodeStart=95, bytecodeLength=18) + @AliveRange(varName="o", bytecodeStart=116, bytecodeLength=15) + @AliveRange(varName="o", bytecodeStart=134, bytecodeLength=1) + @AliveRange(varName="oo", bytecodeStart=104, bytecodeLength=27) + @AliveRange(varName="uu", bytecodeStart=125, bytecodeLength=6) + void m2(String[] args) { + Object o; + switch (args[0]) { + case "string0": + o = "0"; + o.hashCode(); + Object oo = "oo"; + oo.hashCode(); + break; + case "string1": + o = "1"; + o.hashCode(); + Object uu = "uu"; + uu.hashCode(); + break; + } + o = "return"; + } + + @AliveRange(varName="o", bytecodeStart=31, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=42, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=53, bytecodeLength=9) + void m3(String[] args) { + Object o; + switch (args.length) { + case 0: + o = "0"; + o.hashCode(); + break; + case 1: + o = "1"; + o.hashCode(); + break; + default: + o = "default"; + o.hashCode(); + } + o = "finish"; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseTry.java b/langtools/test/tools/javac/flow/tests/TestCaseTry.java new file mode 100644 index 00000000000..e987534ddfc --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseTry.java @@ -0,0 +1,76 @@ +/* /nodynamiccopyright/ */ + +import java.io.BufferedReader; +import java.io.FileReader; + +public class TestCaseTry { + + @AliveRange(varName="o", bytecodeStart=3, bytecodeLength=8) + @AliveRange(varName="o", bytecodeStart=15, bytecodeLength=1) + void m0(String[] args) { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) {} + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=3, bytecodeLength=16) + @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=23) + void m1() { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) { + } + finally { + o = "finally"; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=3, bytecodeLength=16) + @AliveRange(varName="o", bytecodeStart=23, bytecodeLength=31) + void m2() { + Object o; + try { + o = ""; + o.hashCode(); + } catch (RuntimeException e) { + o = "catch"; + o.hashCode(); + } + finally { + o = "finally"; + o.hashCode(); + } + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=22, bytecodeLength=38) + @AliveRange(varName="o", bytecodeStart=103, bytecodeLength=8) + void m3() { + Object o; + try (BufferedReader br = + new BufferedReader(new FileReader("aFile"))) { + o = "inside try"; + o.hashCode(); + } catch (Exception e) {} + o = ""; + } + + @AliveRange(varName="o", bytecodeStart=12, bytecodeLength=96) + @AliveRange(varName="o", bytecodeStart=112, bytecodeLength=1) + void m4() { + String o; + try (BufferedReader br = + new BufferedReader(new FileReader(o = "aFile"))) { + o = "inside try"; + o.hashCode(); + } catch (Exception e) {} + o = ""; + } +} diff --git a/langtools/test/tools/javac/flow/tests/TestCaseWhile.java b/langtools/test/tools/javac/flow/tests/TestCaseWhile.java new file mode 100644 index 00000000000..bbe1f844422 --- /dev/null +++ b/langtools/test/tools/javac/flow/tests/TestCaseWhile.java @@ -0,0 +1,15 @@ +/* /nodynamiccopyright/ */ + +public class TestCaseWhile { + + @AliveRange(varName="o", bytecodeStart=9, bytecodeLength=5) + @AliveRange(varName="o", bytecodeStart=20, bytecodeLength=1) + void m(String[] args) { + Object o; + while (args[0] != null) { + o = ""; + o.hashCode(); + } + o = ""; + } +} diff --git a/langtools/test/tools/javac/generics/neg/OrderedIntersections.java b/langtools/test/tools/javac/generics/neg/OrderedIntersections.java new file mode 100644 index 00000000000..2213ac5a78a --- /dev/null +++ b/langtools/test/tools/javac/generics/neg/OrderedIntersections.java @@ -0,0 +1,21 @@ +/* + * @test /nodynamiccopyright/ + * @bug 6962494 + * @summary The order of elements of intersection types shouldn't matter + * @compile/fail/ref=OrderedIntersections.out -XDrawDiagnostics OrderedIntersections.java + */ + +interface i1 {} +interface i2 {} + +public class OrderedIntersections { + static Object smf(t1 x) { + System.out.println( " smf1 " ); + return null; + } + + static Object smf(t2 x) { + System.out.println( " smf2 " ); + return null; + } +} diff --git a/langtools/test/tools/javac/generics/neg/OrderedIntersections.out b/langtools/test/tools/javac/generics/neg/OrderedIntersections.out new file mode 100644 index 00000000000..69deb46b26d --- /dev/null +++ b/langtools/test/tools/javac/generics/neg/OrderedIntersections.out @@ -0,0 +1,2 @@ +OrderedIntersections.java:17:40: compiler.err.already.defined: kindname.method, smf(t1), kindname.class, OrderedIntersections +1 error diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177a.java b/langtools/test/tools/javac/lambda/8016177/T8016177a.java new file mode 100644 index 00000000000..bc36c2eae00 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177a.java @@ -0,0 +1,45 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8016177 8016178 + * @summary structural most specific and stuckness + * @compile/fail/ref=T8016177a.out -XDrawDiagnostics T8016177a.java + */ +import java.util.List; + +class T8016177a { + + interface ToIntFunction { + int m(X x); + } + + interface Function { + Y m(X x); + } + + void m1(List s, Function f) { } + void m1(List s, ToIntFunction f) { } + + List m2(List s, Function f) { return null; } + List m2(List s, ToIntFunction f) { return null; } + + List m3(List s, Function f) { return null; } + List m3(List s, ToIntFunction f) { return null; } + + List m4(List s, Function f) { return null; } + List m4(List s, ToIntFunction f) { return null; } + + List m5(List s, Function f) { return null; } + List m5(List s, ToIntFunction f) { return null; } + + List m6(List s, Function f) { return null; } + List m6(List s, ToIntFunction f) { return null; } + + void test(List ss) { + m1(ss, s->s.length()); //ambiguous + m2(ss, s->s.length()); //ambiguous + m3(ss, s->s.length()); //ambiguous + m4(ss, s->s.length()); //ambiguous + m5(ss, s->s.length()); //ambiguous + m6(ss, s->s.length()); //ambiguous + } +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177a.out b/langtools/test/tools/javac/lambda/8016177/T8016177a.out new file mode 100644 index 00000000000..7efd6ebfe45 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177a.out @@ -0,0 +1,8 @@ +T8016177a.java:38:10: compiler.err.ref.ambiguous: m1, kindname.method, m1(java.util.List,T8016177a.Function), T8016177a, kindname.method, m1(java.util.List,T8016177a.ToIntFunction), T8016177a +T8016177a.java:39:10: compiler.err.ref.ambiguous: m2, kindname.method, m2(java.util.List,T8016177a.Function), T8016177a, kindname.method, m2(java.util.List,T8016177a.ToIntFunction), T8016177a +T8016177a.java:40:10: compiler.err.ref.ambiguous: m3, kindname.method, m3(java.util.List,T8016177a.Function), T8016177a, kindname.method, m3(java.util.List,T8016177a.ToIntFunction), T8016177a +T8016177a.java:41:10: compiler.err.ref.ambiguous: m4, kindname.method, m4(java.util.List,T8016177a.Function), T8016177a, kindname.method, m4(java.util.List,T8016177a.ToIntFunction), T8016177a +T8016177a.java:42:10: compiler.err.ref.ambiguous: m5, kindname.method, m5(java.util.List,T8016177a.Function), T8016177a, kindname.method, m5(java.util.List,T8016177a.ToIntFunction), T8016177a +T8016177a.java:43:10: compiler.err.ref.ambiguous: m6, kindname.method, m6(java.util.List,T8016177a.Function), T8016177a, kindname.method, m6(java.util.List,T8016177a.ToIntFunction), T8016177a +T8016177a.java:43:12: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: T,R, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, java.lang.String))) +7 errors diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177b.java b/langtools/test/tools/javac/lambda/8016177/T8016177b.java new file mode 100644 index 00000000000..fddd6cbb8de --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177b.java @@ -0,0 +1,34 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8016177 8016178 + * @summary structural most specific and stuckness + * @compile/fail/ref=T8016177b.out -XDrawDiagnostics T8016177b.java + */ +class T8016177b { + interface ToIntFunction { + int m(X x); + } + + interface Function { + Y m(X x); + } + + Function id(Function arg) { return null; } + + Function id2(Function arg) { return null; } + ToIntFunction id2(ToIntFunction arg) { return null; } + + + X f(Y arg, Function f) { return null; } + + X f2(Y arg, Function f) { return null; } + X f2(Y arg, ToIntFunction f) { return null; } + + T g(T arg) { return null; } + + void test() { + g(f("hi", id(x->1))); //ok + g(f("hi", id2(x->1))); //ambiguous + g(f2("hi", id(x->1))); //ok + } +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177b.out b/langtools/test/tools/javac/lambda/8016177/T8016177b.out new file mode 100644 index 00000000000..09bc289fc85 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177b.out @@ -0,0 +1,2 @@ +T8016177b.java:31:19: compiler.err.ref.ambiguous: id2, kindname.method, id2(T8016177b.Function), T8016177b, kindname.method, id2(T8016177b.ToIntFunction), T8016177b +1 error diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177c.java b/langtools/test/tools/javac/lambda/8016177/T8016177c.java new file mode 100644 index 00000000000..d50b37beb9e --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177c.java @@ -0,0 +1,47 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8016081 8016178 + * @summary structural most specific and stuckness + * @compile/fail/ref=T8016177c.out -XDrawDiagnostics T8016177c.java + */ + +class T8016177c { + + interface Function { + Y m(X x); + } + + interface ExtFunction extends Function { } + + U m1(Function f) { return null; } + U m1(ExtFunction f) { return null; } + + void m2(Function f) { } + void m2(ExtFunction f) { } + + void m3(Function f) { } + void m3(ExtFunction f) { } + + int g1(Object s) { return 1; } + + int g2(Number s) { return 1; } + int g2(Object s) { return 1; } + + void test() { + m1((Integer x)->x); //ok - explicit lambda - subtyping picks most specific + m2((Integer x)->x); //ok - explicit lambda - subtyping picks most specific + m3((Integer x)->x); //ok - explicit lambda (only one applicable) + + m1(x->1); //ok - stuck lambda but nominal most specific wins + m2(x->1); //ok - stuck lambda but nominal most specific wins + m3(x->1); //ambiguous - implicit lambda & different params + + m1(this::g1); //ok - unambiguous ref - subtyping picks most specific + m2(this::g1); //ok - unambiguous ref - subtyping picks most specific + m3(this::g1); //ambiguous - both applicable, neither most specific + + m1(this::g2); //ok - stuck mref but nominal most specific wins + m2(this::g2); //ok - stuck mref but nominal most specific wins + m3(this::g2); //ambiguous - different params + } +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177c.out b/langtools/test/tools/javac/lambda/8016177/T8016177c.out new file mode 100644 index 00000000000..d5780901e96 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177c.out @@ -0,0 +1,4 @@ +T8016177c.java:37:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function), T8016177c, kindname.method, m3(T8016177c.ExtFunction), T8016177c +T8016177c.java:41:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function), T8016177c, kindname.method, m3(T8016177c.ExtFunction), T8016177c +T8016177c.java:45:9: compiler.err.ref.ambiguous: m3, kindname.method, m3(T8016177c.Function), T8016177c, kindname.method, m3(T8016177c.ExtFunction), T8016177c +3 errors diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177d.java b/langtools/test/tools/javac/lambda/8016177/T8016177d.java new file mode 100644 index 00000000000..e9cc243fe2f --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177d.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8016081 8016178 + * @summary structural most specific and stuckness + * @compile T8016177d.java + */ +import java.util.*; + +class T8016177d { + + interface UnaryOperator { + X m(X x); + } + + interface IntStream { + IntStream sorted(); + IntStream distinct(); + IntStream limit(int i); + } + + abstract class WrappingUnaryOperator implements UnaryOperator { } + + WrappingUnaryOperator wrap1(UnaryOperator uo) { return null; } + WrappingUnaryOperator wrap2(UnaryOperator uo) { return null; } + WrappingUnaryOperator wrap3(UnaryOperator uo) { return null; } + +

    List> perm(List

    l) { return null; } + + List>> intPermutationOfFunctions = + perm(Arrays.asList( + wrap1(s -> s.sorted()), + wrap2(s -> s.distinct()), + wrap3(s -> s.limit(5)) + )); +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177e.java b/langtools/test/tools/javac/lambda/8016177/T8016177e.java new file mode 100644 index 00000000000..b26af04bc1a --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177e.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8016081 8016178 + * @summary structural most specific and stuckness + * @compile T8016177e.java + */ +import java.util.*; + +class T8016177e { + + interface TerminalOp { } + + interface Consumer { + void m(X x); + } + + TerminalOp makeRef(Consumer action) { return null; } + + void test() { + Map map = null; + TerminalOp forEachOp = makeRef(t -> { map.put(t, null); }); + } +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177f.java b/langtools/test/tools/javac/lambda/8016177/T8016177f.java new file mode 100644 index 00000000000..5f07fbbf04b --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177f.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8016081 8016178 + * @summary structural most specific and stuckness + * @compile T8016177f.java + */ +import java.util.*; + +class T8016177f { + + interface Function { + T apply(S s); + } + + interface IntFunction { + T apply(int s); + } + + + interface BiConsumer { + void m(X x, Y y); + } + + interface Consumer { + void m(X x); + } + + interface Supplier { + X make(); + } + + interface TestData> { + interface OfRef extends TestData> { } + interface OfDouble extends TestData { } + } + + interface BaseStream> { } + + interface Stream extends BaseStream> { + Stream map(Function s); + R collect(Supplier resultFactory, BiConsumer accumulator, BiConsumer combiner); + Z[] toArray(IntFunction s); + } + + interface DoubleStream extends BaseStream { + DoubleStream filter(DoublePredicate dp); + double[] toArray(); + } + + interface DoublePredicate { + boolean p(double d); + } + + , S_OUT extends BaseStream> + R exerciseTerminalOps(TestData data, + Function streamF, + Function terminalF) { return null; } + + TestData.OfRef ofCollection(Collection collection) { return null; } + + void test1(TestData.OfDouble data, DoublePredicate dp) { + exerciseTerminalOps(data, s -> s.filter(dp), s -> s.toArray()); + } + + void test2(Function fdi, TestData.OfRef td, Stream si) { + exerciseTerminalOps( + ofCollection((List)null), + s -> s.map(fdi), + s -> s.toArray(Integer[]::new)); + } +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177g.java b/langtools/test/tools/javac/lambda/8016177/T8016177g.java new file mode 100644 index 00000000000..f8660e892f0 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177g.java @@ -0,0 +1,37 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8016081 8016178 + * @summary structural most specific and stuckness + * @compile/fail/ref=T8016177g.out -XDrawDiagnostics T8016177g.java + */ + + +class Test { + + interface Function { + Y m(X x); + } + + interface Box { + T get(); + R map(Function f); + } + + static class Person { + Person(String name) { } + } + + void print(Object arg) { } + void print(String arg) { } + + int abs(int a) { return 0; } + long abs(long a) { return 0; } + float abs(float a) { return 0; } + double abs(double a) { return 0; } + + void test() { + Box b = null; + print(b.map(s -> new Person(s))); + int i = abs(b.map(s -> Double.valueOf(s))); + } +} diff --git a/langtools/test/tools/javac/lambda/8016177/T8016177g.out b/langtools/test/tools/javac/lambda/8016177/T8016177g.out new file mode 100644 index 00000000000..beb47b0f53c --- /dev/null +++ b/langtools/test/tools/javac/lambda/8016177/T8016177g.out @@ -0,0 +1,2 @@ +T8016177g.java:35:20: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: double, int) +1 error diff --git a/langtools/test/tools/javac/lambda/8023389/T8023389.java b/langtools/test/tools/javac/lambda/8023389/T8023389.java new file mode 100644 index 00000000000..25eb0c8a066 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023389/T8023389.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023389 + * @summary Javac fails to infer type for lambda used with intersection type and wildcards + * @compile T8023389.java + */ +public class T8023389 { + + static class U1 {} + static class X1 extends U1 {} + + interface I { } + + interface SAM { + void m(T t); + } + + /* Strictly speaking only the second of the following declarations provokes the bug. + * But the first line is also a useful test case. + */ + SAM sam1 = (SAM) (X1 x) -> { }; + SAM sam2 = (SAM & I) (X1 x) -> { }; +} diff --git a/langtools/test/tools/javac/lambda/8023549/T8023549.java b/langtools/test/tools/javac/lambda/8023549/T8023549.java new file mode 100644 index 00000000000..efee943b8d6 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023549/T8023549.java @@ -0,0 +1,27 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8023549 + * @summary Compiler emitting spurious errors when constructor reference type is inferred and explicit type arguments are supplied + * @compile/fail/ref=T8023549.out -XDrawDiagnostics T8023549.java + */ + +public class T8023549 { + static class Foo { } + + interface Supplier { + X make(); + } + + interface ExtSupplier extends Supplier { } + + void m1(Supplier> sfs) { } + + void m2(Supplier> sfs) { } + void m2(ExtSupplier> sfs) { } + + void test() { + Supplier> sfs = Foo::new; + m1(Foo::new); + m2(Foo::new); + } +} diff --git a/langtools/test/tools/javac/lambda/8023549/T8023549.out b/langtools/test/tools/javac/lambda/8023549/T8023549.out new file mode 100644 index 00000000000..d25a412378e --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023549/T8023549.out @@ -0,0 +1,5 @@ +T8023549.java:23:37: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.mref.infer.and.explicit.params) +T8023549.java:24:12: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.mref.infer.and.explicit.params) +T8023549.java:25:9: compiler.err.ref.ambiguous: m2, kindname.method, m2(T8023549.Supplier>), T8023549, kindname.method, m2(T8023549.ExtSupplier>), T8023549 +T8023549.java:25:12: compiler.err.invalid.mref: kindname.constructor, (compiler.misc.mref.infer.and.explicit.params) +4 errors diff --git a/langtools/test/tools/javac/lambda/8023558/T8023558a.java b/langtools/test/tools/javac/lambda/8023558/T8023558a.java new file mode 100644 index 00000000000..be3ba6494f0 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023558/T8023558a.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023558 + * @summary Javac creates invalid bootstrap methods for complex lambda/methodref case + */ +public class T8023558a { + interface SAM { + T get(); + } + + static class K implements SAM { + public T get() { + return (T)this; + } + } + + public static void main(String[] args) { + SAM sam = new SAM() { public SAM get() { return new K<>(); } }; + SAM temp = sam.get()::get; + } +} diff --git a/langtools/test/tools/javac/lambda/8023558/T8023558b.java b/langtools/test/tools/javac/lambda/8023558/T8023558b.java new file mode 100644 index 00000000000..c4fe72894e3 --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023558/T8023558b.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023558 + * @summary Javac creates invalid bootstrap methods for complex lambda/methodref case + */ +public class T8023558b { + + interface Supplier { + X get(); + } + + static class A { + public A(Supplier supplier) { } + } + + static class B { } + + static class C { + public B getB() { + return new B(); + } + } + + public static void main(String[] args) { + new T8023558b().test(T8023558b::getC); + } + + private static C getC() { + return new C(); + } + + public void test(Supplier supplier) { + new A(supplier.get()::getB); + } +} diff --git a/langtools/test/tools/javac/lambda/8023558/T8023558c.java b/langtools/test/tools/javac/lambda/8023558/T8023558c.java new file mode 100644 index 00000000000..32234178e3b --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023558/T8023558c.java @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023558 + * @summary Javac creates invalid bootstrap methods for complex lambda/methodref case + */ + +interface SAM { + T get(); +} + +public class T8023558c { + public static void main(String[] args) { + SAM sam = () -> Object::new; + SAM temp = sam.get()::get; + } +} diff --git a/langtools/test/tools/javac/lambda/BadRecovery.out b/langtools/test/tools/javac/lambda/BadRecovery.out index 6035eecfd6f..427d97f0f81 100644 --- a/langtools/test/tools/javac/lambda/BadRecovery.out +++ b/langtools/test/tools/javac/lambda/BadRecovery.out @@ -1,2 +1,3 @@ +BadRecovery.java:17:9: compiler.err.cant.apply.symbol: kindname.method, m, BadRecovery.SAM1, @369, kindname.class, BadRecovery, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.arg.types.in.lambda)) BadRecovery.java:17:77: compiler.err.cant.resolve.location: kindname.variable, f, , , (compiler.misc.location: kindname.class, BadRecovery, null) -1 error +2 errors diff --git a/langtools/test/tools/javac/lambda/ByteCodeTest.java b/langtools/test/tools/javac/lambda/ByteCodeTest.java new file mode 100644 index 00000000000..792c00d6529 --- /dev/null +++ b/langtools/test/tools/javac/lambda/ByteCodeTest.java @@ -0,0 +1,647 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8011738 + * @author sogoel + * @summary Code translation test for Lambda expressions, method references + * @run main ByteCodeTest + */ + +import com.sun.tools.classfile.Attribute; +import com.sun.tools.classfile.BootstrapMethods_attribute; +import com.sun.tools.classfile.ClassFile; +import com.sun.tools.classfile.ConstantPool; +import com.sun.tools.classfile.ConstantPoolException; +import com.sun.tools.classfile.ConstantPool.*; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; + +public class ByteCodeTest { + + static boolean IS_DEBUG = false; + public static void main(String[] args) { + File classFile = null; + int err = 0; + boolean verifyResult = false; + for(TestCases tc : TestCases.values()) { + classFile = getCompiledFile(tc.name(), tc.srcCode); + if(classFile == null) { // either testFile or classFile was not created + err++; + } else { + verifyResult = verifyClassFileAttributes(classFile, tc); + if(!verifyResult) + System.out.println("Bootstrap class file attributes did not match for " + tc.name()); + } + } + if(err > 0) + throw new RuntimeException("Found " + err + " found"); + else + System.out.println("Test passed"); + } + + private static boolean verifyClassFileAttributes(File classFile, TestCases tc) { + ClassFile c = null; + try { + c = ClassFile.read(classFile); + } catch (IOException | ConstantPoolException e) { + e.printStackTrace(); + } + ConstantPoolVisitor cpv = new ConstantPoolVisitor(c, c.constant_pool.size()); + Map hm = cpv.getBSMMap(); + + List expectedValList = tc.getExpectedArgValues(); + expectedValList.add(tc.bsmSpecifier.specifier); + if(!(hm.values().containsAll(new HashSet(expectedValList)))) { + System.out.println("Values do not match"); + return false; + } + return true; + } + + private static File getCompiledFile(String fname, String srcString) { + File testFile = null, classFile = null; + boolean isTestFileCreated = true; + + try { + testFile = writeTestFile(fname+".java", srcString); + } catch(IOException ioe) { + isTestFileCreated = false; + System.err.println("fail to write" + ioe); + } + + if(isTestFileCreated) { + try { + classFile = compile(testFile); + } catch (Error err) { + System.err.println("fail compile. Source:\n" + srcString); + throw err; + } + } + return classFile; + } + + static File writeTestFile(String fname, String source) throws IOException { + File f = new File(fname); + PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f))); + out.println(source); + out.close(); + return f; + } + + static File compile(File f) { + int rc = com.sun.tools.javac.Main.compile(new String[] { + "-source", "1.8", "-g", f.getPath() }); + if (rc != 0) + throw new Error("compilation failed. rc=" + rc); + String path = f.getPath(); + return new File(path.substring(0, path.length() - 5) + ".class"); + } + + static void debugln(String str) { + if(IS_DEBUG) + System.out.println(str); + } + + enum BSMSpecifier { + SPECIFIER1("REF_invokeStatic java/lang/invoke/LambdaMetafactory metaFactory " + + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" + + "Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodHandle;Ljava/lang/invoke/MethodType;)" + + "Ljava/lang/invoke/CallSite;"), + SPECIFIER2("REF_invokeStatic java/lang/invoke/LambdaMetafactory altMetaFactory " + + "(Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;" + + "[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"); + + String specifier; + private BSMSpecifier(String specifier) { + this.specifier = specifier; + } + } + + enum TestCases { + // Single line lambda expression + TC1("class TC1 {\n" + + " public static void main(String[] args) {\n" + + " Object o = (Runnable) () -> { System.out.println(\"hi\");};\n" + + " }\n"+ + "}", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface java/lang/Runnable run ()V"); + valList.add("REF_invokeStatic TC1 lambda$0 ()V"); + valList.add("()V"); + return valList; + } + }, + + // Lambda expression in a for loop + TC2("import java.util.*;\n" + + "public class TC2 {\n" + + " void TC2_test() {\n" + + " List list = new ArrayList<>();\n" + + " list.add(\"A\");\n" + + " list.add(\"B\");\n" + + " list.stream().forEach( s -> { System.out.println(s); } );\n" + + " }\n" + + " public static void main(String[] args) {\n" + + " new TC2().TC2_test();\n" + + " }\n" + + "}", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface java/util/function/Consumer accept (Ljava/lang/Object;)V"); + valList.add("REF_invokeStatic TC2 lambda$0 (Ljava/lang/String;)V"); + valList.add("(Ljava/lang/String;)V"); + return valList; + } + }, + + // Lambda initializer + TC3("class TC3 {\n" + + " interface SAM {\n" + + " void m(int i);\n" + + " }\n" + + " SAM lambda_03 = (int pos) -> { };\n" + + "}", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC3$SAM m (I)V"); + valList.add("REF_invokeStatic TC3 lambda$0 (I)V"); + valList.add("(I)V"); + return valList; + } + }, + + // Array initializer + TC4("class TC4 {\n" + + " interface Block {\n" + + " void m(T t);\n" + + " }\n" + + " void test1() {\n" + + " Block[] arr1 = { t -> { }, t -> { } };\n" + + " }\n" + + "}", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC4$Block m (Ljava/lang/Object;)V"); + valList.add("REF_invokeStatic TC4 lambda$0 (Ljava/lang/Object;)V"); + valList.add("(Ljava/lang/Object;)V"); + valList.add("REF_invokeStatic TC4 lambda$1 (Ljava/lang/Object;)V"); + return valList; + } + }, + + //Lambda expression as a method arg + TC5("class TC5 {\n"+ + " interface MapFun { R m( T n); }\n" + + " void meth( MapFun mf ) {\n" + + " assert( mf.m(\"four\") == 4);\n" + + " }\n"+ + " void test(Integer i) {\n" + + " meth(s -> { Integer len = s.length(); return len; } );\n" + + " }\n"+ + "}", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC5$MapFun m (Ljava/lang/Object;)Ljava/lang/Object;"); + valList.add("REF_invokeStatic TC5 lambda$0 (Ljava/lang/String;)Ljava/lang/Integer;"); + valList.add("(Ljava/lang/String;)Ljava/lang/Integer;"); + return valList; + } + }, + + //Inner class of Lambda expression + TC6("class TC6 {\n" + + " interface MapFun { R m( T n); }\n" + + " MapFun,String> cs;\n" + + " void test() {\n" + + " cs = c -> {\n" + + " class innerClass {\n" + + " Class icc;\n" + + " innerClass(Class _c) { icc = _c; }\n" + + " String getString() { return icc.toString(); }\n" + + " }\n" + + " return new innerClass(c).getString();\n"+ + " };\n" + + " }\n" + + "}\n", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC6$MapFun m (Ljava/lang/Object;)Ljava/lang/Object;"); + valList.add("REF_invokeSpecial TC6 lambda$0 (Ljava/lang/Class;)Ljava/lang/String;"); + valList.add("(Ljava/lang/Class;)Ljava/lang/String;"); + return valList; + } + }, + + // Method reference + TC7("class TC7 {\n" + + " static interface SAM {\n" + + " void m(Integer i);\n" + + " }\n" + + " void m(Integer i) {}\n" + + " SAM s = this::m;\n" + + "}\n", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC7$SAM m (Ljava/lang/Integer;)V"); + valList.add("REF_invokeVirtual TC7 m (Ljava/lang/Integer;)V"); + valList.add("(Ljava/lang/Integer;)V"); + return valList; + } + }, + + // Constructor reference + TC8("public class TC8 {\n" + + " static interface A {Fee m();}\n" + + " static class Fee {\n" + + " private T t;\n" + + " public Fee() {}\n" + + " }\n" + + " public static void main(String[] args) {\n" + + " A a = Fee::new; \n" + + " }\n" + + "}\n", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC8$A m ()LTC8$Fee;"); + valList.add("REF_newInvokeSpecial TC8$Fee ()V"); + valList.add("()LTC8$Fee;"); + return valList; + } + }, + + // Recursive lambda expression + TC9("class TC9 {\n" + + " interface Recursive { T apply(R n); };\n" + + " Recursive factorial;\n" + + " void test(Integer j) {\n" + + " factorial = i -> { return i == 0 ? 1 : i * factorial.apply( i - 1 ); };\n" + + " }\n" + + "}\n", BSMSpecifier.SPECIFIER1) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeInterface TC9$Recursive apply (Ljava/lang/Object;)Ljava/lang/Object;"); + valList.add("REF_invokeSpecial TC9 lambda$0 (Ljava/lang/Integer;)Ljava/lang/Integer;"); + valList.add("(Ljava/lang/Integer;)Ljava/lang/Integer;"); + return valList; + } + }, + + //Serializable Lambda + TC10("import java.io.Serializable;\n" + + "class TC10 {\n" + + " interface Foo { int m(); }\n" + + " public static void main(String[] args) {\n" + + " Foo f1 = (Foo & Serializable)() -> 3;\n" + + " }\n" + + "}\n", BSMSpecifier.SPECIFIER2) { + + @Override + List getExpectedArgValues() { + List valList = new ArrayList<>(); + valList.add("REF_invokeStatic java/lang/invoke/LambdaMetafactory altMetaFactory (Ljava/lang/invoke/MethodHandles$Lookup;Ljava/lang/String;Ljava/lang/invoke/MethodType;[Ljava/lang/Object;)Ljava/lang/invoke/CallSite;"); + valList.add("REF_invokeInterface TC10$Foo m ()I"); + valList.add("REF_invokeStatic TC10 lambda$main$3231c38a$0 ()I"); + valList.add("()I"); + valList.add("1"); + return valList; + } + }; + + String srcCode; + BSMSpecifier bsmSpecifier; + + TestCases(String src, BSMSpecifier bsmSpecifier) { + this.srcCode = src; + // By default, all test cases will have bootstrap method specifier as Lambda.MetaFactory + // For serializable lambda test cases, bootstrap method specifier changed to altMetaFactory + this.bsmSpecifier = bsmSpecifier; + } + + List getExpectedArgValues() { + return null; + } + + void setSrcCode(String src) { + srcCode = src; + } + } + + static class ConstantPoolVisitor implements ConstantPool.Visitor { + final List slist; + final ClassFile cf; + final ConstantPool cfpool; + final Map bsmMap; + + + public ConstantPoolVisitor(ClassFile cf, int size) { + slist = new ArrayList<>(size); + for (int i = 0 ; i < size; i++) { + slist.add(null); + } + this.cf = cf; + this.cfpool = cf.constant_pool; + bsmMap = readBSM(); + } + + public Map getBSMMap() { + return Collections.unmodifiableMap(bsmMap); + } + + public String visit(CPInfo c, int index) { + return c.accept(this, index); + } + + private Map readBSM() { + BootstrapMethods_attribute bsmAttr = + (BootstrapMethods_attribute) cf.getAttribute(Attribute.BootstrapMethods); + if (bsmAttr != null) { + Map out = + new HashMap<>(bsmAttr.bootstrap_method_specifiers.length); + for (BootstrapMethods_attribute.BootstrapMethodSpecifier bsms : + bsmAttr.bootstrap_method_specifiers) { + int index = bsms.bootstrap_method_ref; + try { + String value = slist.get(index); + if (value == null) { + value = visit(cfpool.get(index), index); + debugln("[SG]: index " + index); + debugln("[SG]: value " + value); + slist.set(index, value); + out.put(index, value); + } + for (int idx : bsms.bootstrap_arguments) { + value = slist.get(idx); + if (value == null) { + value = visit(cfpool.get(idx), idx); + debugln("[SG]: idx " + idx); + debugln("[SG]: value " + value); + slist.set(idx, value); + out.put(idx, value); + } + } + } catch (InvalidIndex ex) { + ex.printStackTrace(); + } + } + return out; + } + return new HashMap<>(0); + } + + @Override + public String visitClass(CONSTANT_Class_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.name_index), c.name_index); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitDouble(CONSTANT_Double_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + value = Double.toString(c.value); + slist.set(p, value); + } + return value; + } + + @Override + public String visitFieldref(CONSTANT_Fieldref_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.class_index), c.class_index); + value = value.concat(" " + visit(cfpool.get(c.name_and_type_index), + c.name_and_type_index)); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitFloat(CONSTANT_Float_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + value = Float.toString(c.value); + slist.set(p, value); + } + return value; + } + + @Override + public String visitInteger(CONSTANT_Integer_info cnstnt, Integer p) { + + String value = slist.get(p); + if (value == null) { + value = Integer.toString(cnstnt.value); + slist.set(p, value); + } + return value; + } + + @Override + public String visitInterfaceMethodref(CONSTANT_InterfaceMethodref_info c, + Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.class_index), c.class_index); + value = value.concat(" " + + visit(cfpool.get(c.name_and_type_index), + c.name_and_type_index)); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitInvokeDynamic(CONSTANT_InvokeDynamic_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = bsmMap.get(c.bootstrap_method_attr_index) + " " + + visit(cfpool.get(c.name_and_type_index), c.name_and_type_index); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitLong(CONSTANT_Long_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + value = Long.toString(c.value); + slist.set(p, value); + } + return value; + } + + @Override + public String visitNameAndType(CONSTANT_NameAndType_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.name_index), c.name_index); + value = value.concat(" " + + visit(cfpool.get(c.type_index), c.type_index)); + slist.set(p, value); + } catch (InvalidIndex ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitMethodref(CONSTANT_Methodref_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.class_index), c.class_index); + value = value.concat(" " + + visit(cfpool.get(c.name_and_type_index), + c.name_and_type_index)); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitMethodHandle(CONSTANT_MethodHandle_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = c.reference_kind.name(); + value = value.concat(" " + + visit(cfpool.get(c.reference_index), c.reference_index)); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitMethodType(CONSTANT_MethodType_info c, Integer p) { + + String value = slist.get(p); + if (value == null) { + try { + value = visit(cfpool.get(c.descriptor_index), c.descriptor_index); + slist.set(p, value); + } catch (ConstantPoolException ex) { + ex.printStackTrace(); + } + } + return value; + } + + @Override + public String visitString(CONSTANT_String_info c, Integer p) { + + try { + String value = slist.get(p); + if (value == null) { + value = c.getString(); + slist.set(p, value); + } + return value; + } catch (ConstantPoolException ex) { + throw new RuntimeException("Fatal error", ex); + } + } + + @Override + public String visitUtf8(CONSTANT_Utf8_info cnstnt, Integer p) { + + String value = slist.get(p); + if (value == null) { + value = cnstnt.value; + slist.set(p, value); + } + return value; + } + } +} + diff --git a/langtools/test/tools/javac/lambda/EffectivelyFinalTest.java b/langtools/test/tools/javac/lambda/EffectivelyFinalTest.java index 9d1dff9b6e4..c701b3ca6d0 100644 --- a/langtools/test/tools/javac/lambda/EffectivelyFinalTest.java +++ b/langtools/test/tools/javac/lambda/EffectivelyFinalTest.java @@ -1,6 +1,6 @@ /* * @test /nodynamiccopyright/ - * @bug 8003280 + * @bug 7175538 8003280 * @summary Add lambda tests * Integrate effectively final check with DA/DU analysis * @compile/fail/ref=EffectivelyFinalTest01.out -XDrawDiagnostics EffectivelyFinalTest.java diff --git a/langtools/test/tools/javac/lambda/EffectivelyFinalThrows.java b/langtools/test/tools/javac/lambda/EffectivelyFinalThrows.java new file mode 100644 index 00000000000..54183173f3a --- /dev/null +++ b/langtools/test/tools/javac/lambda/EffectivelyFinalThrows.java @@ -0,0 +1,25 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8019521 + * @summary Check that enhanced rethrow/effectivelly final works correctly inside lambdas + * @compile EffectivelyFinalThrows.java + */ + +class EffectivelyFinalThrows { + interface SAM { + public void t() throws E; + } + void test(SAM s) throws E { + s.t(); + } + void test2(SAM s) throws Checked { + test(() -> { + try { + s.t(); + } catch (Throwable t) { + throw t; + } + }); + } + static class Checked extends Exception {} +} diff --git a/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.java b/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.java index be21473b241..173f084638b 100644 --- a/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.java +++ b/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013 Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,6 +26,7 @@ * @bug 8003280 * @summary Add lambda tests * stale state after speculative attribution round leads to missing classfiles + * @compile/fail/ref=ErroneousLambdaExpr.out -XDrawDiagnostics ErroneousLambdaExpr.java */ public class ErroneousLambdaExpr { diff --git a/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.out b/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.out new file mode 100644 index 00000000000..aeb312fb180 --- /dev/null +++ b/langtools/test/tools/javac/lambda/ErroneousLambdaExpr.out @@ -0,0 +1,2 @@ +ErroneousLambdaExpr.java:63:13: compiler.err.ref.ambiguous: call, kindname.method, call(ErroneousLambdaExpr.SAM1), ErroneousLambdaExpr, kindname.method, call(ErroneousLambdaExpr.SAM2), ErroneousLambdaExpr +1 error diff --git a/langtools/test/tools/javac/lambda/MethodReference22.out b/langtools/test/tools/javac/lambda/MethodReference22.out index d25b71e3a12..dfd2ebe554e 100644 --- a/langtools/test/tools/javac/lambda/MethodReference22.out +++ b/langtools/test/tools/javac/lambda/MethodReference22.out @@ -3,13 +3,17 @@ MethodReference22.java:41:15: compiler.err.invalid.mref: kindname.method, (compi MethodReference22.java:46:19: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String)) MethodReference22.java:47:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String)) MethodReference22.java:51:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22)) -MethodReference22.java:52:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1401, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22))) +MethodReference22.java:52:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1401, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m1, kindname.method, m1(MethodReference22,java.lang.String), MethodReference22, kindname.method, m1(java.lang.String), MethodReference22))) MethodReference22.java:53:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22)) -MethodReference22.java:54:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1504, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22))) +MethodReference22.java:54:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1504, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m2, kindname.method, m2(MethodReference22,java.lang.String), MethodReference22, kindname.method, m2(java.lang.String), MethodReference22))) MethodReference22.java:55:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22)) -MethodReference22.java:56:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1607, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22))) +MethodReference22.java:56:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1607, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m3, kindname.method, m3(MethodReference22,java.lang.String), MethodReference22, kindname.method, m3(java.lang.String), MethodReference22))) MethodReference22.java:57:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22)) -MethodReference22.java:58:9: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1710, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22))) +MethodReference22.java:58:14: compiler.err.cant.apply.symbol: kindname.method, call2, MethodReference22.SAM2, @1710, kindname.class, MethodReference22, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.ref.ambiguous: m4, kindname.method, m4(MethodReference22,java.lang.String), MethodReference22, kindname.method, m4(java.lang.String), MethodReference22))) +MethodReference22.java:62:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22 MethodReference22.java:62:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m1(java.lang.String)) +MethodReference22.java:63:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22 +MethodReference22.java:64:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22 +MethodReference22.java:65:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference22.SAM1), MethodReference22, kindname.method, call3(MethodReference22.SAM2), MethodReference22 MethodReference22.java:65:15: compiler.err.invalid.mref: kindname.method, (compiler.misc.non-static.cant.be.ref: kindname.method, m4(java.lang.String)) -14 errors +18 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference23.out b/langtools/test/tools/javac/lambda/MethodReference23.out index 3849d8631c6..462a75105ff 100644 --- a/langtools/test/tools/javac/lambda/MethodReference23.out +++ b/langtools/test/tools/javac/lambda/MethodReference23.out @@ -1,6 +1,6 @@ MethodReference23.java:52:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23)) -MethodReference23.java:53:9: compiler.err.cant.apply.symbol: kindname.method, call11, MethodReference23.SAM11, @1140, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23))) +MethodReference23.java:53:15: compiler.err.cant.apply.symbol: kindname.method, call11, MethodReference23.SAM11, @1140, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, MethodReference23, MethodReference23))) MethodReference23.java:57:19: compiler.err.prob.found.req: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23)) -MethodReference23.java:58:9: compiler.err.cant.apply.symbol: kindname.method, call12, MethodReference23.SAM12, @1282, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23))) +MethodReference23.java:58:15: compiler.err.cant.apply.symbol: kindname.method, call12, MethodReference23.SAM12, @1282, kindname.class, MethodReference23, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.access.inner.cls.constr: Inner1, , MethodReference23))) MethodReference23.java:72:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(MethodReference23.SAM21), MethodReference23, kindname.method, call3(MethodReference23.SAM22), MethodReference23 5 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference41.java b/langtools/test/tools/javac/lambda/MethodReference41.java index a2593320021..a3a8bddb605 100644 --- a/langtools/test/tools/javac/lambda/MethodReference41.java +++ b/langtools/test/tools/javac/lambda/MethodReference41.java @@ -1,43 +1,13 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 8003280 * @summary Add lambda tests * check that diamond inference is applied when using raw constructor reference qualifier - * @run main MethodReference41 + * @compile/fail/ref=MethodReference41.out -XDrawDiagnostics MethodReference41.java */ + public class MethodReference41 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface SAM1 { void m(String s); } @@ -54,13 +24,20 @@ public class MethodReference41 { Foo(X x) { } } + static void m1(SAM1 s) { } - static void m(SAM1 s) { assertTrue(false); } - static void m(SAM2 s) { assertTrue(true); } - static void m(SAM3 s) { assertTrue(false); } + static void m2(SAM2 s) { } + + static void m3(SAM3 s) { } + + static void m4(SAM1 s) { } + static void m4(SAM2 s) { } + static void m4(SAM3 s) { } public static void main(String[] args) { - m(Foo::new); - assertTrue(assertionCount == 1); + m1(Foo::new); + m2(Foo::new); + m3(Foo::new); + m4(Foo::new); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference41.out b/langtools/test/tools/javac/lambda/MethodReference41.out new file mode 100644 index 00000000000..a501b109bd3 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference41.out @@ -0,0 +1,4 @@ +MethodReference41.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference41.SAM1, @767, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference41.Foo, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number)))) +MethodReference41.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference41.SAM3, @811, kindname.class, MethodReference41, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference41.Foo, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number)))) +MethodReference41.java:41:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference41.SAM2), MethodReference41, kindname.method, m4(MethodReference41.SAM3), MethodReference41 +3 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference42.java b/langtools/test/tools/javac/lambda/MethodReference42.java index 1c8aaefab75..61bef68c770 100644 --- a/langtools/test/tools/javac/lambda/MethodReference42.java +++ b/langtools/test/tools/javac/lambda/MethodReference42.java @@ -1,43 +1,13 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 8003280 * @summary Add lambda tests * check that diamond inference is applied when using raw constructor reference qualifier - * @run main MethodReference42 + * @compile/fail/ref=MethodReference42.out -XDrawDiagnostics MethodReference42.java */ + public class MethodReference42 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - static class SuperFoo { } static class Foo extends SuperFoo { } @@ -54,12 +24,20 @@ public class MethodReference42 { SuperFoo m(); } - static void m(SAM1 s) { assertTrue(false); } - static void m(SAM2 s) { assertTrue(true); } - static void m(SAM3 s) { assertTrue(false); } + static void m1(SAM1 s) { } + + static void m2(SAM2 s) { } + + static void m3(SAM3 s) { } + + static void m4(SAM1 s) { } + static void m4(SAM2 s) { } + static void m4(SAM3 s) { } public static void main(String[] args) { - m(Foo::new); - assertTrue(assertionCount == 1); + m1(Foo::new); + m2(Foo::new); + m3(Foo::new); + m4(Foo::new); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference42.out b/langtools/test/tools/javac/lambda/MethodReference42.out new file mode 100644 index 00000000000..ab324c44665 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference42.out @@ -0,0 +1,4 @@ +MethodReference42.java:38:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference42.SAM1, @811, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)) +MethodReference42.java:40:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference42.SAM3, @855, kindname.class, MethodReference42, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number)) +MethodReference42.java:41:9: compiler.err.ref.ambiguous: m4, kindname.method, m4(MethodReference42.SAM2), MethodReference42, kindname.method, m4(MethodReference42.SAM3), MethodReference42 +3 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference43.java b/langtools/test/tools/javac/lambda/MethodReference43.java index f7b8203d1b1..99fbc3d5dd4 100644 --- a/langtools/test/tools/javac/lambda/MethodReference43.java +++ b/langtools/test/tools/javac/lambda/MethodReference43.java @@ -1,43 +1,13 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 8003280 * @summary Add lambda tests * check that diamond inference is applied when using raw constructor reference qualifier - * @run main MethodReference43 + * @compile/fail/ref=MethodReference43.out -XDrawDiagnostics MethodReference43.java */ + public class MethodReference43 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface SAM1 { Foo m(String s); } @@ -58,14 +28,24 @@ public class MethodReference43 { Foo(X x) { } } + static void m1(SAM1 s) { } - static void m(SAM1 s) { assertTrue(false); } - static void m(SAM2 s) { assertTrue(false); } - static void m(SAM3 s) { assertTrue(false); } - static void m(SAM4 s) { assertTrue(true); } + static void m2(SAM2 s) { } + + static void m3(SAM3 s) { } + + static void m4(SAM4 s) { } + + static void m5(SAM1 s) { } + static void m5(SAM2 s) { } + static void m5(SAM3 s) { } + static void m5(SAM4 s) { } public static void main(String[] args) { - m(Foo::new); - assertTrue(assertionCount == 1); + m1(Foo::new); + m2(Foo::new); + m3(Foo::new); + m4(Foo::new); + m5(Foo::new); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference43.out b/langtools/test/tools/javac/lambda/MethodReference43.out new file mode 100644 index 00000000000..dfe70b3c1f8 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference43.out @@ -0,0 +1,5 @@ +MethodReference43.java:45:11: compiler.err.cant.apply.symbol: kindname.method, m1, MethodReference43.SAM1, @897, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.String, kindname.class, MethodReference43.Foo, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number)))) +MethodReference43.java:47:11: compiler.err.cant.apply.symbol: kindname.method, m3, MethodReference43.SAM3, @941, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number)))) +MethodReference43.java:49:9: compiler.err.ref.ambiguous: m5, kindname.method, m5(MethodReference43.SAM3), MethodReference43, kindname.method, m5(MethodReference43.SAM4), MethodReference43 +MethodReference43.java:49:11: compiler.err.cant.apply.symbol: kindname.method, m5, MethodReference43.SAM3, @985, kindname.class, MethodReference43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.constructor, (compiler.misc.cant.apply.symbol: kindname.constructor, Foo, java.lang.Number, java.lang.Object, kindname.class, MethodReference43.Foo, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number)))) +4 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference44.java b/langtools/test/tools/javac/lambda/MethodReference44.java index 8c92593b43a..3a62d84657a 100644 --- a/langtools/test/tools/javac/lambda/MethodReference44.java +++ b/langtools/test/tools/javac/lambda/MethodReference44.java @@ -1,43 +1,13 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 8003280 * @summary Add lambda tests * check that generic method reference is inferred when type parameters are omitted - * @run main MethodReference44 + * @compile/fail/ref=MethodReference44.out -XDrawDiagnostics MethodReference44.java */ + public class MethodReference44 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - static class SuperFoo { } static class Foo extends SuperFoo { } @@ -56,12 +26,20 @@ public class MethodReference44 { static Foo m() { return null; } - static void g(SAM1 s) { assertTrue(false); } - static void g(SAM2 s) { assertTrue(true); } - static void g(SAM3 s) { assertTrue(false); } + static void g1(SAM1 s) { } + + static void g2(SAM2 s) { } + + static void g3(SAM3 s) { } + + static void g4(SAM1 s) { } + static void g4(SAM2 s) { } + static void g4(SAM3 s) { } public static void main(String[] args) { - g(MethodReference44::m); - assertTrue(assertionCount == 1); + g1(MethodReference44::m); + g2(MethodReference44::m); + g3(MethodReference44::m); + g4(MethodReference44::m); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference44.out b/langtools/test/tools/javac/lambda/MethodReference44.out new file mode 100644 index 00000000000..56c991c21f9 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference44.out @@ -0,0 +1,4 @@ +MethodReference44.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference44.SAM1, @864, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.String, java.lang.Number)) +MethodReference44.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference44.SAM3, @932, kindname.class, MethodReference44, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.eq.upper.bounds: X, java.lang.Object, java.lang.Number)) +MethodReference44.java:43:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference44.SAM2), MethodReference44, kindname.method, g4(MethodReference44.SAM3), MethodReference44 +3 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference46.java b/langtools/test/tools/javac/lambda/MethodReference46.java index 8f0c327faff..ee83739fcac 100644 --- a/langtools/test/tools/javac/lambda/MethodReference46.java +++ b/langtools/test/tools/javac/lambda/MethodReference46.java @@ -1,43 +1,13 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 8003280 * @summary Add lambda tests * check that generic method reference is inferred when type parameters are omitted - * @run main MethodReference46 + * @compile/fail/ref=MethodReference46.out -XDrawDiagnostics MethodReference46.java */ + public class MethodReference46 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface SAM1 { void m(String s); } @@ -56,12 +26,20 @@ public class MethodReference46 { static void m(X fx) { } - static void g(SAM1 s) { assertTrue(false); } - static void g(SAM2 s) { assertTrue(true); } - static void g(SAM3 s) { assertTrue(false); } + static void g1(SAM1 s) { } + + static void g2(SAM2 s) { } + + static void g3(SAM3 s) { } + + static void g4(SAM1 s) { } + static void g4(SAM2 s) { } + static void g4(SAM3 s) { } public static void main(String[] args) { - g(MethodReference46::m); - assertTrue(assertionCount == 1); + g1(MethodReference46::m); + g2(MethodReference46::m); + g3(MethodReference46::m); + g4(MethodReference46::m); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference46.out b/langtools/test/tools/javac/lambda/MethodReference46.out new file mode 100644 index 00000000000..7d409282749 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference46.out @@ -0,0 +1,4 @@ +MethodReference46.java:40:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference46.SAM1, @809, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.String, kindname.class, MethodReference46, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.String, java.lang.Number)))) +MethodReference46.java:42:11: compiler.err.cant.apply.symbol: kindname.method, g3, MethodReference46.SAM3, @877, kindname.class, MethodReference46, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m, X, java.lang.Object, kindname.class, MethodReference46, (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Object, java.lang.Number)))) +MethodReference46.java:43:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference46.SAM2), MethodReference46, kindname.method, g4(MethodReference46.SAM3), MethodReference46 +3 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference47.java b/langtools/test/tools/javac/lambda/MethodReference47.java index 5bc949dd03b..d5fff0dd4b4 100644 --- a/langtools/test/tools/javac/lambda/MethodReference47.java +++ b/langtools/test/tools/javac/lambda/MethodReference47.java @@ -7,14 +7,6 @@ */ public class MethodReference47 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface SAM1 { void m(Integer s); } @@ -34,7 +26,7 @@ public class MethodReference47 { static void g2(SAM2 s) { } public static void main(String[] args) { - g1(MethodReference46::m); - g2(MethodReference46::m); + g1(MethodReference47::m); + g2(MethodReference47::m); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference47.out b/langtools/test/tools/javac/lambda/MethodReference47.out index 39d3c31ba12..7a745728948 100644 --- a/langtools/test/tools/javac/lambda/MethodReference47.out +++ b/langtools/test/tools/javac/lambda/MethodReference47.out @@ -1,2 +1,2 @@ -MethodReference47.java:38:9: compiler.err.ref.ambiguous: g2, kindname.method, g2(MethodReference47.SAM1), MethodReference47, kindname.method, g2(MethodReference47.SAM2), MethodReference47 +MethodReference47.java:30:9: compiler.err.ref.ambiguous: g2, kindname.method, g2(MethodReference47.SAM1), MethodReference47, kindname.method, g2(MethodReference47.SAM2), MethodReference47 1 error diff --git a/langtools/test/tools/javac/lambda/MethodReference48.java b/langtools/test/tools/javac/lambda/MethodReference48.java index 8c3a704dd02..153ec900700 100644 --- a/langtools/test/tools/javac/lambda/MethodReference48.java +++ b/langtools/test/tools/javac/lambda/MethodReference48.java @@ -1,43 +1,13 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * @test + * @test /nodynamiccopyright/ * @bug 8003280 * @summary Add lambda tests * check that raw qualifier in unbound method reference is inferred from descriptor - * @run main MethodReference48 + * @compile/fail/ref=MethodReference48.out -XDrawDiagnostics MethodReference48.java */ + public class MethodReference48 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - static class Foo { X m() { return null; }; } @@ -54,12 +24,20 @@ public class MethodReference48 { Object m(Foo fi); } - static void g(SAM1 s) { assertTrue(false); } //return type not compatible - static void g(SAM2 s) { assertTrue(true); } //ok - static void g(SAM3 s) { assertTrue(false); } //ok but less specific + static void g1(SAM1 s) { } //return type not compatible + + static void g2(SAM2 s) { } //ok + + static void g3(SAM3 s) { } //ok + + static void g4(SAM1 s) { } //return type not compatible + static void g4(SAM2 s) { } //ok + static void g4(SAM3 s) { } //ok public static void main(String[] args) { - g(Foo::m); - assertTrue(assertionCount == 1); + g1(Foo::m); + g2(Foo::m); + g3(Foo::m); + g4(Foo::m); } } diff --git a/langtools/test/tools/javac/lambda/MethodReference48.out b/langtools/test/tools/javac/lambda/MethodReference48.out new file mode 100644 index 00000000000..41b8a6be69f --- /dev/null +++ b/langtools/test/tools/javac/lambda/MethodReference48.out @@ -0,0 +1,3 @@ +MethodReference48.java:38:11: compiler.err.cant.apply.symbol: kindname.method, g1, MethodReference48.SAM1, @869, kindname.class, MethodReference48, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.mref: (compiler.misc.inconvertible.types: java.lang.String, MethodReference48.Foo))) +MethodReference48.java:41:9: compiler.err.ref.ambiguous: g4, kindname.method, g4(MethodReference48.SAM2), MethodReference48, kindname.method, g4(MethodReference48.SAM3), MethodReference48 +2 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference70.out b/langtools/test/tools/javac/lambda/MethodReference70.out index 875b9d2d064..4cdccd5a50a 100644 --- a/langtools/test/tools/javac/lambda/MethodReference70.out +++ b/langtools/test/tools/javac/lambda/MethodReference70.out @@ -1,3 +1,3 @@ MethodReference70.java:26:10: compiler.err.ref.ambiguous: g, kindname.method, g(MethodReference70.F), MethodReference70, kindname.method, g(MethodReference70.G), MethodReference70 -MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) +MethodReference70.java:26:11: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbols: kindname.method, m2, java.lang.Object,{(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.Integer), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer))),(compiler.misc.inapplicable.method: kindname.method, MethodReference70, m2(java.lang.String), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.String)))}))) 2 errors diff --git a/langtools/test/tools/javac/lambda/MethodReference71.out b/langtools/test/tools/javac/lambda/MethodReference71.out index f1a8942e3d1..f95734da07e 100644 --- a/langtools/test/tools/javac/lambda/MethodReference71.out +++ b/langtools/test/tools/javac/lambda/MethodReference71.out @@ -1,3 +1,3 @@ MethodReference71.java:24:10: compiler.err.ref.ambiguous: g, kindname.method, g(MethodReference71.F), MethodReference71, kindname.method, g(MethodReference71.G), MethodReference71 -MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) +MethodReference71.java:24:11: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.invalid.mref: kindname.method, (compiler.misc.cant.apply.symbol: kindname.method, m2, java.lang.Integer[], java.lang.Object, kindname.class, MethodReference71, (compiler.misc.varargs.argument.mismatch: (compiler.misc.inconvertible.types: java.lang.Object, java.lang.Integer))))) 2 errors diff --git a/langtools/test/tools/javac/lambda/MostSpecific04.java b/langtools/test/tools/javac/lambda/MostSpecific04.java index c5fbc3d35a5..74ac24e4bc4 100644 --- a/langtools/test/tools/javac/lambda/MostSpecific04.java +++ b/langtools/test/tools/javac/lambda/MostSpecific04.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,17 +26,10 @@ * @bug 8003280 * @summary Add lambda tests * Structural most specific doesn't handle cases with wildcards in functional interfaces + * @compile/fail/ref=MostSpecific04.out -XDrawDiagnostics MostSpecific04.java */ public class MostSpecific04 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface DoubleMapper { double map(T t); } @@ -46,13 +39,13 @@ public class MostSpecific04 { } static class MyList { - void map(DoubleMapper m) { assertTrue(false); } - void map(LongMapper m) { assertTrue(true); } + void map(DoubleMapper m) { } + void map(LongMapper m) { } } public static void main(String[] args) { MyList ls = new MyList(); - ls.map(e->e.length()); - assertTrue(assertionCount == 1); + ls.map(e->e.length()); //ambiguous - implicit + ls.map((String e)->e.length()); //ok } } diff --git a/langtools/test/tools/javac/lambda/MostSpecific04.out b/langtools/test/tools/javac/lambda/MostSpecific04.out new file mode 100644 index 00000000000..3a672f0698e --- /dev/null +++ b/langtools/test/tools/javac/lambda/MostSpecific04.out @@ -0,0 +1,2 @@ +MostSpecific04.java:48:11: compiler.err.ref.ambiguous: map, kindname.method, map(MostSpecific04.DoubleMapper), MostSpecific04.MyList, kindname.method, map(MostSpecific04.LongMapper), MostSpecific04.MyList +1 error diff --git a/langtools/test/tools/javac/lambda/MostSpecific05.java b/langtools/test/tools/javac/lambda/MostSpecific05.java index 177a43e7637..f001ccc195b 100644 --- a/langtools/test/tools/javac/lambda/MostSpecific05.java +++ b/langtools/test/tools/javac/lambda/MostSpecific05.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,17 +26,10 @@ * @bug 8003280 * @summary Add lambda tests * Structural most specific doesn't handle cases with wildcards in functional interfaces + * @compile/fail/ref=MostSpecific05.out -XDrawDiagnostics MostSpecific05.java */ public class MostSpecific05 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface ObjectConverter { T map(Object o); } @@ -46,13 +39,13 @@ public class MostSpecific05 { } static class MyMapper { - void map(ObjectConverter m) { assertTrue(false); } - void map(NumberConverter m) { assertTrue(true); } + void map(ObjectConverter m) { } + void map(NumberConverter m) { } } public static void main(String[] args) { MyMapper mm = new MyMapper(); - mm.map(e->1.0); - assertTrue(assertionCount == 1); + mm.map(e->1.0); //ambiguous - implicit + mm.map((Object e)->1.0); //ok } } diff --git a/langtools/test/tools/javac/lambda/MostSpecific05.out b/langtools/test/tools/javac/lambda/MostSpecific05.out new file mode 100644 index 00000000000..d0d86c151b4 --- /dev/null +++ b/langtools/test/tools/javac/lambda/MostSpecific05.out @@ -0,0 +1,2 @@ +MostSpecific05.java:48:11: compiler.err.ref.ambiguous: map, kindname.method, map(MostSpecific05.ObjectConverter), MostSpecific05.MyMapper, kindname.method, map(MostSpecific05.NumberConverter), MostSpecific05.MyMapper +1 error diff --git a/langtools/test/tools/javac/lambda/MostSpecific08.java b/langtools/test/tools/javac/lambda/MostSpecific08.java index 453f04cd7f4..0673ef0ba06 100644 --- a/langtools/test/tools/javac/lambda/MostSpecific08.java +++ b/langtools/test/tools/javac/lambda/MostSpecific08.java @@ -25,7 +25,7 @@ * @test * @bug 8008813 * @summary Structural most specific fails when method reference is passed to overloaded method - * @compile MostSpecific08.java + * @compile/fail/ref=MostSpecific08.out -XDrawDiagnostics MostSpecific08.java */ class MostSpecific08 { @@ -51,12 +51,14 @@ class MostSpecific08 { } void testMref(Tester t) { - IntResult pr = t.apply(C::getInt); - ReferenceResult rr = t.apply(C::getInteger); + IntResult pr = t.apply(C::getInt); //ok - unoverloaded mref + ReferenceResult rr = t.apply(C::getInteger); //ok - unoverloaded mref } void testLambda(Tester t) { - IntResult pr = t.apply(c->c.getInt()); - ReferenceResult rr = t.apply(c->c.getInteger()); + IntResult pr1 = t.apply(c->c.getInt()); //ambiguous - implicit + IntResult pr2 = t.apply((C c)->c.getInt()); //ok + ReferenceResult rr1 = t.apply(c->c.getInteger()); //ambiguous - implicit + ReferenceResult rr2 = t.apply((C c)->c.getInteger()); //ok } } diff --git a/langtools/test/tools/javac/lambda/MostSpecific08.out b/langtools/test/tools/javac/lambda/MostSpecific08.out new file mode 100644 index 00000000000..f4e47d7d0ed --- /dev/null +++ b/langtools/test/tools/javac/lambda/MostSpecific08.out @@ -0,0 +1,4 @@ +MostSpecific08.java:59:26: compiler.err.ref.ambiguous: apply, kindname.method, apply(MostSpecific08.PrimitiveFunction), MostSpecific08.Tester, kindname.method, apply(MostSpecific08.ReferenceFunction), MostSpecific08.Tester +MostSpecific08.java:61:41: compiler.err.ref.ambiguous: apply, kindname.method, apply(MostSpecific08.PrimitiveFunction), MostSpecific08.Tester, kindname.method, apply(MostSpecific08.ReferenceFunction), MostSpecific08.Tester +MostSpecific08.java:61:47: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: MostSpecific08.IntResult, MostSpecific08.ReferenceResult) +3 errors diff --git a/langtools/test/tools/javac/lambda/TargetType01.java b/langtools/test/tools/javac/lambda/TargetType01.java index 0e8f16c045c..2ad86c64c88 100644 --- a/langtools/test/tools/javac/lambda/TargetType01.java +++ b/langtools/test/tools/javac/lambda/TargetType01.java @@ -26,7 +26,7 @@ * @bug 8003280 8009131 * @summary Add lambda tests * check nested case of overload resolution and lambda parameter inference - * @compile TargetType01.java + * @compile/fail/ref=TargetType01.out -XDrawDiagnostics TargetType01.java */ class TargetType01 { diff --git a/langtools/test/tools/javac/lambda/TargetType01.out b/langtools/test/tools/javac/lambda/TargetType01.out new file mode 100644 index 00000000000..b460bfc4230 --- /dev/null +++ b/langtools/test/tools/javac/lambda/TargetType01.out @@ -0,0 +1,3 @@ +TargetType01.java:45:9: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01 +TargetType01.java:45:26: compiler.err.ref.ambiguous: M, kindname.method, M(TargetType01.F_I_I), TargetType01, kindname.method, M(TargetType01.F_S_S), TargetType01 +2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType02.java b/langtools/test/tools/javac/lambda/TargetType02.java index f5141ed18eb..05077c88f3d 100644 --- a/langtools/test/tools/javac/lambda/TargetType02.java +++ b/langtools/test/tools/javac/lambda/TargetType02.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,19 +27,11 @@ * @summary Add lambda tests * check overload resolution and target type inference w.r.t. generic methods * @author Maurizio Cimadamore - * @run main TargetType02 + * @compile/fail/ref=TargetType02.out -XDrawDiagnostics TargetType02.java */ public class TargetType02 { - static int assertionCount = 0; - - static void assertTrue(boolean cond) { - assertionCount++; - if (!cond) - throw new AssertionError(); - } - interface S1 { X m(Integer x); } @@ -48,15 +40,16 @@ public class TargetType02 { abstract X m(Integer x); } - static void call(S1 s) { s.m(1); assertTrue(true); } - static void call(S2 s) { s.m(2); assertTrue(false); } + static void call1(S1 s) { } + + static void call2(S2 s) { } + + static void call3(S1 s) { } + static void call3(S2 s) { } void test() { - call(i -> { toString(); return i; }); - } - - public static void main(String[] args) { - new TargetType02().test(); - assertTrue(assertionCount == 1); + call1(i -> { toString(); return i; }); + call2(i -> { toString(); return i; }); + call3(i -> { toString(); return i; }); } } diff --git a/langtools/test/tools/javac/lambda/TargetType02.out b/langtools/test/tools/javac/lambda/TargetType02.out new file mode 100644 index 00000000000..2336ef70e6b --- /dev/null +++ b/langtools/test/tools/javac/lambda/TargetType02.out @@ -0,0 +1,3 @@ +TargetType02.java:52:14: compiler.err.prob.found.req: (compiler.misc.inferred.do.not.conform.to.upper.bounds: java.lang.Integer, java.lang.String) +TargetType02.java:53:9: compiler.err.ref.ambiguous: call3, kindname.method, call3(TargetType02.S1), TargetType02, kindname.method, call3(TargetType02.S2), TargetType02 +2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType10.java b/langtools/test/tools/javac/lambda/TargetType10.java index 39afaee727a..538b8e0221d 100644 --- a/langtools/test/tools/javac/lambda/TargetType10.java +++ b/langtools/test/tools/javac/lambda/TargetType10.java @@ -1,10 +1,10 @@ /* * @test /nodynamiccopyright/ - * @bug 8003280 + * @bug 8003280 8016177 * @summary Add lambda tests * check that wildcards in the target method of a lambda conversion is handled correctly * @author Maurizio Cimadamore - * @compile/fail/ref=TargetType10.out -XDrawDiagnostics TargetType10.java + * @compile TargetType10.java */ class TargetType10 { diff --git a/langtools/test/tools/javac/lambda/TargetType10.out b/langtools/test/tools/javac/lambda/TargetType10.out deleted file mode 100644 index eaf9bb3a07f..00000000000 --- a/langtools/test/tools/javac/lambda/TargetType10.out +++ /dev/null @@ -1,2 +0,0 @@ -TargetType10.java:17:18: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: B,A) -1 error diff --git a/langtools/test/tools/javac/lambda/TargetType21.java b/langtools/test/tools/javac/lambda/TargetType21.java index ac70cacb6dc..d55e803cb4a 100644 --- a/langtools/test/tools/javac/lambda/TargetType21.java +++ b/langtools/test/tools/javac/lambda/TargetType21.java @@ -26,8 +26,10 @@ class TargetType21 { void test() { call(x -> { throw new Exception(); }); //ambiguous + call((Integer x) -> { System.out.println(""); }); //ok (only one is void) + call((Integer x) -> { return (Object) null; }); //ok (only one returns Object) call(x -> { System.out.println(""); }); //ambiguous - call(x -> { return (Object) null; }); //cyclic inference + call(x -> { return (Object) null; }); //ambiguous call(x -> { return null; }); //ambiguous } } diff --git a/langtools/test/tools/javac/lambda/TargetType21.out b/langtools/test/tools/javac/lambda/TargetType21.out index 904e30f1278..90131dc4bfc 100644 --- a/langtools/test/tools/javac/lambda/TargetType21.out +++ b/langtools/test/tools/javac/lambda/TargetType21.out @@ -1,5 +1,7 @@ TargetType21.java:28:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 -TargetType21.java:29:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 -TargetType21.java:30:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: A) -TargetType21.java:31:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM1), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 -4 errors +TargetType21.java:31:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 +TargetType21.java:32:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 +TargetType21.java:32:13: compiler.err.cant.apply.symbol: kindname.method, call, TargetType21.SAM2, @888, kindname.class, TargetType21, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val))) +TargetType21.java:33:9: compiler.err.ref.ambiguous: call, kindname.method, call(TargetType21.SAM2), TargetType21, kindname.method, call(TargetType21.SAM3), TargetType21 +TargetType21.java:33:13: compiler.err.cant.apply.symbol: kindname.method, call, TargetType21.SAM2, @946, kindname.class, TargetType21, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.unexpected.ret.val))) +6 errors diff --git a/langtools/test/tools/javac/lambda/TargetType24.java b/langtools/test/tools/javac/lambda/TargetType24.java index b470a9169f9..5180cd5373f 100644 --- a/langtools/test/tools/javac/lambda/TargetType24.java +++ b/langtools/test/tools/javac/lambda/TargetType24.java @@ -29,11 +29,14 @@ class TargetType24 { } void test(Array as, final Array ac) { - final boolean b1 = as.forAll(s -> ac.forAll(c -> false)); //ok + final boolean b1 = as.forAll((String s) -> ac.forAll((Character c) -> false)); //ok + final boolean b2 = as.forAll(s -> ac.forAll(c -> false)); //ambiguous + final boolean b3 = as.forAll((String s) -> ac.forAll(c -> false)); //ambiguous + final boolean b4 = as.forAll(s -> ac.forAll((Character c) -> false)); //ambiguous final String s1 = as.forAll2(s -> ac.forAll2(c -> "")); //ok - final boolean b2 = as.forAll(s -> ac.forAll(c -> "" )); //fail + final boolean b5 = as.forAll(s -> ac.forAll(c -> "" )); //fail final String s2 = as.forAll2(s -> ac.forAll2(c -> false)); //fail - final boolean b3 = as.forAll((F)s -> ac.forAll((F)c -> "")); //fail + final boolean b6 = as.forAll((F)s -> ac.forAll((F)c -> "")); //fail final String s3 = as.forAll((FSub)s -> ac.forAll((FSub)c -> false)); //fail } } diff --git a/langtools/test/tools/javac/lambda/TargetType24.out b/langtools/test/tools/javac/lambda/TargetType24.out index 7554a6dd2c3..9542304a21b 100644 --- a/langtools/test/tools/javac/lambda/TargetType24.out +++ b/langtools/test/tools/javac/lambda/TargetType24.out @@ -1,5 +1,11 @@ -TargetType24.java:34:37: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, boolean) -TargetType24.java:35:45: compiler.err.cant.apply.symbol: kindname.method, forAll2, TargetType24.FSub, @945, kindname.class, TargetType24.Array, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String))) -TargetType24.java:36:101: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Boolean)) -TargetType24.java:37:104: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String)) -4 errors +TargetType24.java:33:30: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F), TargetType24.Array, kindname.method, forAll(TargetType24.FSub), TargetType24.Array +TargetType24.java:33:45: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F), TargetType24.Array, kindname.method, forAll(TargetType24.FSub), TargetType24.Array +TargetType24.java:34:54: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F), TargetType24.Array, kindname.method, forAll(TargetType24.FSub), TargetType24.Array +TargetType24.java:35:30: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F), TargetType24.Array, kindname.method, forAll(TargetType24.FSub), TargetType24.Array +TargetType24.java:37:30: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F), TargetType24.Array, kindname.method, forAll(TargetType24.FSub), TargetType24.Array +TargetType24.java:37:45: compiler.err.ref.ambiguous: forAll, kindname.method, forAll(TargetType24.F), TargetType24.Array, kindname.method, forAll(TargetType24.FSub), TargetType24.Array +TargetType24.java:37:52: compiler.err.cant.apply.symbol: kindname.method, forAll, TargetType24.F, @1149, kindname.class, TargetType24.Array, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Boolean))) +TargetType24.java:38:53: compiler.err.cant.apply.symbol: kindname.method, forAll2, TargetType24.FSub, @1221, kindname.class, TargetType24.Array, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String))) +TargetType24.java:39:101: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Boolean)) +TargetType24.java:40:104: compiler.err.prob.found.req: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: boolean, java.lang.String)) +10 errors diff --git a/langtools/test/tools/javac/lambda/TargetType26.out b/langtools/test/tools/javac/lambda/TargetType26.out index 15cfc615f45..b90c658302d 100644 --- a/langtools/test/tools/javac/lambda/TargetType26.out +++ b/langtools/test/tools/javac/lambda/TargetType26.out @@ -1,2 +1,2 @@ -TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: Z) +TargetType26.java:16:11: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: Z, (compiler.misc.not.a.functional.intf: java.lang.Object)) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType27.out b/langtools/test/tools/javac/lambda/TargetType27.out index bf388592025..61cb54ead88 100644 --- a/langtools/test/tools/javac/lambda/TargetType27.out +++ b/langtools/test/tools/javac/lambda/TargetType27.out @@ -1,2 +1,2 @@ -TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: R) +TargetType27.java:18:10: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: A,R, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.not.a.functional.intf: java.lang.Object))) 1 error diff --git a/langtools/test/tools/javac/lambda/TargetType39.out b/langtools/test/tools/javac/lambda/TargetType39.out index 36a61bce0e2..6229f690173 100644 --- a/langtools/test/tools/javac/lambda/TargetType39.out +++ b/langtools/test/tools/javac/lambda/TargetType39.out @@ -1,3 +1,3 @@ -TargetType39.java:19:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: U) -TargetType39.java:20:13: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: V) +TargetType39.java:19:13: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.incompatible.type.in.conditional: (compiler.misc.inconvertible.types: TargetType39.SAM, TargetType39.SAM))) +TargetType39.java:20:13: compiler.err.prob.found.req: (compiler.misc.infer.no.conforming.assignment.exists: U,V, (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.incompatible.type.in.conditional: (compiler.misc.not.a.functional.intf: java.lang.Object)))) 2 errors diff --git a/langtools/test/tools/javac/lambda/TargetType43.out b/langtools/test/tools/javac/lambda/TargetType43.out index 666e67c8341..7d50949d9a0 100644 --- a/langtools/test/tools/javac/lambda/TargetType43.out +++ b/langtools/test/tools/javac/lambda/TargetType43.out @@ -1,4 +1,5 @@ TargetType43.java:13:20: compiler.err.prob.found.req: (compiler.misc.not.a.functional.intf: java.lang.Object) TargetType43.java:13:30: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null) +TargetType43.java:14:9: compiler.err.cant.apply.symbol: kindname.method, m, java.lang.Object, @359, kindname.class, TargetType43, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.not.a.functional.intf: java.lang.Object)) TargetType43.java:14:21: compiler.err.cant.resolve.location: kindname.class, NonExistentClass, , , (compiler.misc.location: kindname.class, TargetType43, null) -3 errors +4 errors diff --git a/langtools/test/tools/javac/lambda/TargetType66.java b/langtools/test/tools/javac/lambda/TargetType66.java index d9e85a0c87e..db704fd3a6f 100644 --- a/langtools/test/tools/javac/lambda/TargetType66.java +++ b/langtools/test/tools/javac/lambda/TargetType66.java @@ -17,8 +17,8 @@ class TargetType66 { void g(SAM2 s2) { } void test() { - g(x->{ String s = x; }); //g(SAM1) - g(x->{ Integer i = x; }); //g(SAM2) + g(x->{ String s = x; }); //ambiguous + g(x->{ Integer i = x; }); //ambiguous g(x->{ Object o = x; }); //ambiguous g(x->{ Character c = x; }); //error: inapplicable methods g(x->{ Character c = ""; }); //error: incompatible types diff --git a/langtools/test/tools/javac/lambda/TargetType66.out b/langtools/test/tools/javac/lambda/TargetType66.out index b5c828df27b..8dd2ad710bb 100644 --- a/langtools/test/tools/javac/lambda/TargetType66.out +++ b/langtools/test/tools/javac/lambda/TargetType66.out @@ -1,4 +1,9 @@ +TargetType66.java:20:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66 +TargetType66.java:21:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66 +TargetType66.java:21:28: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Integer) TargetType66.java:22:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66 -TargetType66.java:23:9: compiler.err.cant.apply.symbols: kindname.method, g, @578,{(compiler.misc.inapplicable.method: kindname.method, TargetType66, g(TargetType66.SAM1), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.bad.arg.types.in.lambda: java.lang.String, (compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character))))),(compiler.misc.inapplicable.method: kindname.method, TargetType66, g(TargetType66.SAM2), (compiler.misc.no.conforming.assignment.exists: (compiler.misc.bad.arg.types.in.lambda: java.lang.Integer, (compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Integer, java.lang.Character)))))} +TargetType66.java:23:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66 +TargetType66.java:23:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character) +TargetType66.java:24:9: compiler.err.ref.ambiguous: g, kindname.method, g(TargetType66.SAM1), TargetType66, kindname.method, g(TargetType66.SAM2), TargetType66 TargetType66.java:24:30: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.String, java.lang.Character) -3 errors +8 errors diff --git a/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodTestCase.java b/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodTestCase.java new file mode 100644 index 00000000000..964a59658b1 --- /dev/null +++ b/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodTestCase.java @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +import java.io.File; +import java.io.IOException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.StringJoiner; + +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import tools.javac.combo.*; + +import static org.testng.Assert.fail; + +/** + * BridgeMethodTestCase -- used for asserting linkage to bridges under separate compilation. + * + * Example test case: + * public void test1() throws IOException, ReflectiveOperationException { + * compileSpec("C(Bc1(A))"); + * assertLinkage("C", LINKAGE_ERROR, "B1"); + * recompileSpec("C(Bc1(Ac0))", "A"); + * assertLinkage("C", "A0", "B1"); + * } + * + * This compiles A, B, and C, asserts that C.m()Object does not exist, asserts + * that C.m()Number eventually invokes B.m()Number, recompiles B, and then asserts + * that the result of calling C.m()Object now arrives at A. + * + * @author Brian Goetz + */ + +@Test +public abstract class BridgeMethodTestCase extends JavacTemplateTestBase { + + private static final String TYPE_LETTERS = "ABCDIJK"; + + private static final String BASE_INDEX_CLASS = "class C0 {\n" + + " int val;\n" + + " C0(int val) { this.val = val; }\n" + + " public int getVal() { return val; }\n" + + "}\n"; + private static final String INDEX_CLASS_TEMPLATE = "class C#ID extends C#PREV {\n" + + " C#ID(int val) { super(val); }\n" + + "}\n"; + + + + protected static String LINKAGE_ERROR = "-1"; + + private List compileDirs = new ArrayList<>(); + + /** + * Compile all the classes in a class spec, and put them on the classpath. + * + * The spec is the specification for a nest of classes, using the following notation + * A, B represent abstract classes + * C represents a concrete class + * I, J, K represent interfaces + * Lowercase 'c' following a class means that the method m() is concrete + * Lowercase 'a' following a class or interface means that the method m() is abstract + * Lowercase 'd' following an interface means that the method m() is default + * A number 0, 1, or 2 following the lowercase letter indicates the return type of that method + * 0 = Object, 1 = Number, 2 = Integer (these form an inheritance chain so bridges are generated) + * A classes supertypes follow its method spec, in parentheses + * Examples: + * C(Ia0, Jd0) -- C extends I and J, I has abstract m()Object, J has default m()Object + * Cc1(Ia0) -- C has concrete m()Number, extends I with abstract m()Object + * If a type must appear multiple times, its full spec must be in the first occurrence + * Example: + * C(I(Kd0), J(K)) + */ + protected void compileSpec(String spec) throws IOException { + compileSpec(spec, false); + } + + /** + * Compile all the classes in a class spec, and assert that there were compilation errors. + */ + protected void compileSpec(String spec, String... errorKeys) throws IOException { + compileSpec(spec, false, errorKeys); + } + + protected void compileSpec(String spec, boolean debug, String... errorKeys) throws IOException { + ClassModel cm = new Parser(spec).parseClassModel(); + for (int i = 0; i <= cm.maxIndex() ; i++) { + if (debug) System.out.println(indexClass(i)); + addSourceFile(String.format("C%d.java", i), new StringTemplate(indexClass(i))); + } + for (Map.Entry e : classes(cm).entrySet()) { + if (debug) System.out.println(e.getValue().toSource()); + addSourceFile(e.getKey() + ".java", new StringTemplate(e.getValue().toSource())); + } + compileDirs.add(compile(true)); + resetSourceFiles(); + if (errorKeys.length == 0) + assertCompileSucceeded(); + else + assertCompileErrors(errorKeys); + } + + /** + * Recompile only a subset of classes in the class spec, as named by names, + * and put them on the classpath such that they shadow earlier versions of that class. + */ + protected void recompileSpec(String spec, String... names) throws IOException { + List nameList = Arrays.asList(names); + ClassModel cm = new Parser(spec).parseClassModel(); + for (int i = 0; i <= cm.maxIndex() ; i++) { + addSourceFile(String.format("C%d.java", i), new StringTemplate(indexClass(i))); + } + for (Map.Entry e : classes(cm).entrySet()) + if (nameList.contains(e.getKey())) + addSourceFile(e.getKey() + ".java", new StringTemplate(e.getValue().toSource())); + compileDirs.add(compile(Arrays.asList(classPaths()), true)); + resetSourceFiles(); + assertCompileSucceeded(); + } + + protected void assertLinkage(String name, String... expected) throws ReflectiveOperationException { + for (int i=0; i classes(ClassModel cm) { + HashMap m = new HashMap<>(); + classesHelper(cm, m); + return m; + } + + private String indexClass(int index) { + if (index == 0) { + return BASE_INDEX_CLASS; + } else { + return INDEX_CLASS_TEMPLATE + .replace("#ID", String.valueOf(index)) + .replace("#PREV", String.valueOf(index - 1)); + } + } + + private static String overrideName(int index) { + return "C" + index; + } + + private void classesHelper(ClassModel cm, Map m) { + if (!m.containsKey(cm.name)) + m.put(cm.name, cm); + for (ClassModel s : cm.supertypes) + classesHelper(s, m); + } + + private static String fromNum(int num) { + return String.format("%c%d", TYPE_LETTERS.charAt(num / 10), num % 10); + } + + private static int toNum(String name, int index) { + return 10*(TYPE_LETTERS.indexOf(name.charAt(0))) + index; + } + + private static int toNum(String string) { + return 10*(TYPE_LETTERS.indexOf(string.charAt(0))) + Integer.parseInt(string.substring(1, 2)); + } + + private int invoke(String name, int index) throws ReflectiveOperationException { + File[] files = classPaths(); + Class clazz = loadClass(name, files); + Method[] ms = clazz.getMethods(); + for (Method m : ms) { + if (m.getName().equals("m") && m.getReturnType().getName().equals(overrideName(index))) { + m.setAccessible(true); + Object instance = clazz.newInstance(); + Object c0 = m.invoke(instance); + Method getVal = c0.getClass().getMethod("getVal"); + getVal.setAccessible(true); + return (int)getVal.invoke(c0); + } + } + throw new NoSuchMethodError("cannot find method m()" + index + " in class " + name); + } + + private File[] classPaths() { + File[] files = new File[compileDirs.size()]; + for (int i=0; i supertypes; + private final MethodType methodType; + private final int methodIndex; + + private ClassModel(String name, + boolean anInterface, + List supertypes, + MethodType methodType, + int methodIndex) { + this.name = name; + isInterface = anInterface; + this.supertypes = supertypes; + this.methodType = methodType; + this.methodIndex = methodIndex; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + sb.append(name); + if (methodType != null) { + sb.append(methodType.designator); + sb.append(methodIndex); + } + if (!supertypes.isEmpty()) { + sb.append("("); + for (int i=0; i 0) + sb.append(","); + sb.append(supertypes.get(i).toString()); + } + sb.append(")"); + } + return sb.toString(); + } + + int maxIndex() { + int maxSoFar = methodIndex; + for (ClassModel cm : supertypes) { + maxSoFar = Math.max(cm.maxIndex(), maxSoFar); + } + return maxSoFar; + } + + public String toSource() { + String extendsClause = ""; + String implementsClause = ""; + String methodBody = ""; + boolean isAbstract = "AB".contains(name); + + for (ClassModel s : supertypes) { + if (!s.isInterface) { + extendsClause = String.format("extends %s", s.name); + break; + } + } + + StringJoiner sj = new StringJoiner(", "); + for (ClassModel s : supertypes) + if (s.isInterface) + sj.add(s.name); + if (sj.length() > 0) { + if (isInterface) + implementsClause = "extends " + sj.toString(); + else + implementsClause = "implements " + sj.toString(); + } + if (methodType != null) { + switch (methodType) { + case ABSTRACT: + methodBody = String.format("public abstract %s m();", overrideName(methodIndex)); + break; + case CONCRETE: + methodBody = String.format("public %s m() { return new %s(%d); };", + overrideName(methodIndex), overrideName(methodIndex), toNum(name, methodIndex)); + break; + case DEFAULT: + methodBody = String.format("public default %s m() { return new %s(%d); };", + overrideName(methodIndex), overrideName(methodIndex), toNum(name, methodIndex)); + break; + + } + } + + return String.format("public %s %s %s %s %s { %s }", isAbstract ? "abstract" : "", + isInterface ? "interface" : "class", + name, extendsClause, implementsClause, methodBody); + } + } + + private static class Parser { + private final String input; + private final char[] chars; + private int index; + + private Parser(String s) { + input = s; + chars = s.toCharArray(); + } + + private char peek() { + return index < chars.length ? chars[index] : 0; + } + + private boolean peek(String validChars) { + return validChars.indexOf(peek()) >= 0; + } + + private char advanceIf(String validChars) { + if (peek(validChars)) + return chars[index++]; + else + return 0; + } + + private char advanceIfDigit() { + return advanceIf("0123456789"); + } + + private int index() { + StringBuilder buf = new StringBuilder(); + char c = advanceIfDigit(); + while (c != 0) { + buf.append(c); + c = advanceIfDigit(); + } + return Integer.valueOf(buf.toString()); + } + + private char advance() { + return chars[index++]; + } + + private char expect(String validChars) { + char c = advanceIf(validChars); + if (c == 0) + throw new IllegalArgumentException(String.format("Expecting %s at position %d of %s", validChars, index, input)); + return c; + } + + public ClassModel parseClassModel() { + List supers = new ArrayList<>(); + char name = expect(TYPE_LETTERS); + boolean isInterface = "IJK".indexOf(name) >= 0; + ClassModel.MethodType methodType = peek(isInterface ? "ad" : "ac") ? ClassModel.MethodType.find(advance()) : null; + int methodIndex = 0; + if (methodType != null) { + methodIndex = index(); + } + if (peek() == '(') { + advance(); + supers.add(parseClassModel()); + while (peek() == ',') { + advance(); + supers.add(parseClassModel()); + } + expect(")"); + } + return new ClassModel(new String(new char[]{ name }), isInterface, supers, methodType, methodIndex); + } + } +} diff --git a/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java b/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java new file mode 100644 index 00000000000..028602ea057 --- /dev/null +++ b/langtools/test/tools/javac/lambda/bridge/template_tests/BridgeMethodsTemplateTest.java @@ -0,0 +1,1082 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + * + */ +import java.io.IOException; + +import org.testng.annotations.Test; + +/** + * BridgeMethodsTemplateTest + * + * @author Brian Goetz + */ +@Test +public class BridgeMethodsTemplateTest extends BridgeMethodTestCase { + + /* + * Cc1(A) -> Cc1(Ac0) + * + * 0*: Inherited from A + * 1: Declared in C + */ + public void test1() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(A)"); + assertLinkage("C", LINKAGE_ERROR, "C1"); + recompileSpec("Cc1(Ac0)", "A"); + assertLinkage("C", "A0", "C1"); + } + + /* + * Cc1(I) -> Cc1(Id0) + * + * 0*: Inherited default from I + * 1: Declared in C + */ + public void test2() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(I)"); + assertLinkage("C", LINKAGE_ERROR, "C1"); + recompileSpec("Cc1(Id0)", "I"); + assertLinkage("C", "I0", "C1"); + } + + /* + * C(Bc1(A)) -> C(Bc1(Ac0)) + * + * 0*: Inherited from A + * 1: Inherited from B + */ + public void test3() throws IOException, ReflectiveOperationException { + compileSpec("C(Bc1(A))"); + assertLinkage("C", LINKAGE_ERROR, "B1"); + recompileSpec("C(Bc1(Ac0))", "A"); + assertLinkage("C", "A0", "B1"); + } + + /* + * C(B(Ac0)) -> C(Bc1(Ac0)) + * + * 0: Inherited from B (through bridge) + * 1: Inherited from B + */ + public void test4() throws IOException, ReflectiveOperationException { + compileSpec("C(B(Ac0))"); + assertLinkage("C", "A0", LINKAGE_ERROR); + recompileSpec("C(Bc1(Ac0))", "B"); + assertLinkage("C", "B1", "B1"); + } + + /* + * C(B(A)) -> C(Bc1(Ac0)) + * + * 0: Inherited from B (through bridge) + * 1: Inherited from B + */ + public void test5() throws IOException, ReflectiveOperationException { + compileSpec("C(B(A))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Bc1(Ac0))", "A", "B"); + assertLinkage("C", "B1", "B1"); + } + + /* + * C(Ac1(I)) -> C(Ac1(Id0)) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test6() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac1(I))"); + assertLinkage("C", LINKAGE_ERROR, "A1"); + recompileSpec("C(Ac1(Id0))", "I"); + assertLinkage("C", "I0", "A1"); + } + + /* + * C(A(Id0)) -> C(Ac1(Id0)) + * + * 0: Inherited from A (through bridge) + * 1: Inherited from A + */ + public void test7() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac1(Id0))", "A"); + assertLinkage("C", "A1", "A1"); + } + + /* + * C(A(I)) -> C(Ac1(Id0)) + * + * 0*: Inherited from A (through bridge) + * 1*: Inherited from A + */ + public void test8() throws IOException, ReflectiveOperationException { + compileSpec("C(A(I))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Ac1(Id0))", "A", "I"); + assertLinkage("C", "A1", "A1"); + } + + /* + * C(Id1(J)) -> C(Id1(Jd0)) + * + * 0*: Inherited default from J + * 1: Inherited default from I + */ + public void test9() throws IOException, ReflectiveOperationException { + compileSpec("C(Id1(J))"); + assertLinkage("C", LINKAGE_ERROR, "I1"); + recompileSpec("C(Id1(Jd0))", "J"); + assertLinkage("C", "J0", "I1"); + } + + /* + * C(I(Jd0)) -> C(Id1(Jd0)) + * + * 0: Inherited default from I (through bridge) + * 1: Inherited default from I + */ + public void test10() throws IOException, ReflectiveOperationException { + compileSpec("C(I(Jd0))"); + assertLinkage("C", "J0", LINKAGE_ERROR); + recompileSpec("C(Id1(Jd0))", "I"); + assertLinkage("C", "I1", "I1"); + } + + /* + * C(I(J)) -> C(Id1(Jd0)) + * + * 0: Inherited default from I (through bridge) + * 1: Inherited default from I + */ + public void test11() throws IOException, ReflectiveOperationException { + compileSpec("C(I(J))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Id1(Jd0))", "I", "J"); + assertLinkage("C", "I1", "I1"); + } + + /* + * Cc2(B(Ac0)) -> Cc2(Bc1(Ac0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from B + * 2: Declared in C + */ + public void test12() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(B(Ac0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Bc1(Ac0))", "B"); + assertLinkage("C", "C2", "B1", "C2"); + } + + /* + * Cc2(B(Aa0)) -> Cc2(Bc1(Aa0)) + * + * 0: Bridge in C (through bridge) + * 1*: Inherited from B + * 2: Declared in C + */ + public void test13() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(B(Aa0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Bc1(Aa0))", "B"); + assertLinkage("C", "C2", "B1", "C2"); + } + + /* + * Cc2(Bc1(A)) -> Cc2(Bc1(Ac0)) + * + * 0*: Inherited from A + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test14() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Bc1(A))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Bc1(Ac0))", "A"); + assertLinkage("C", "A0", "C2", "C2"); + } + + /* + * Cc2(Ba1(A)) -> Cc2(Ba1(Ac0)) + * + * 0*: Inherited from A + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test15() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ba1(A))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ba1(Ac0))", "A"); + assertLinkage("C", "A0", "C2", "C2"); + } + + /* + * Cc2(B(A)) -> Cc2(Bc1(Ac0)) + * + * 0*: Inherited from B (through bridge) + * 1*: Inherited from B + * 2: Declared in C + */ + public void test16() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(B(A))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Bc1(Ac0))", "B", "A"); + assertLinkage("C", "B1", "B1", "C2"); + } + + /* + * Cc2(A(Id0)) -> Cc2(Ac1(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test17() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Id0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A(Ia0)) -> Cc2(Ac1(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test18() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Ia0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(Ac1(I)) -> Cc2(Ac1(Id0)) + * + * 0*: Inherited from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test19() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ac1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ac1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(Aa1(I)) -> Cc2(Aa1(Id0)) + * + * 0*: Inherited from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test20() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Aa1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Aa1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(A(I)) -> Cc2(Ac1(Id0)) + * + * 0*: Inherited from A (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test21() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(I))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Id0))", "A", "I"); + assertLinkage("C", "A1", "A1", "C2"); + } + + /* + * Cc2(J(Id0)) -> Cc2(Jd1(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test22() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Id0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(J(Ia0)) -> Cc2(Jd1(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test23() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Ia0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(Jd1(I)) -> Cc2(Jd1(Id0)) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test24() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Jd1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Jd1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(Ja1(I)) -> Cc2(Ja1(Id0)) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test25() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ja1(I))"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ja1(Id0))", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(J(I)) -> Cc2(Jd1(Id0)) + * + * 0*: Inherited default from J (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test26() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(I))"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Id0))", "J", "I"); + assertLinkage("C", "J1", "J1", "C2"); + } + + /* + * C(Ac1, I) -> C(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test27() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac1,I)"); + assertLinkage("C", LINKAGE_ERROR, "A1"); + recompileSpec("C(Ac1,Id0)", "I"); + assertLinkage("C", "I0", "A1"); + } + + /* + * C(A, Id0) -> C(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test28() throws IOException, ReflectiveOperationException { + compileSpec("C(A,Id0)"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac1,Id0)", "A"); + assertLinkage("C", "I0", "A1"); + } + + /* + * C(A, I) -> C(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Inherited from A + */ + public void test29() throws IOException, ReflectiveOperationException { + compileSpec("C(A,I)"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR); + recompileSpec("C(Ac1,Id0)", "A", "I"); + assertLinkage("C", "I0", "A1"); + } + + /* + * Cc2(Ac1, I) -> Cc2(Ac1, Id0) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test30() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ac1,I)"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Ac1,Id0)", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(Aa1, I) -> Cc2(Aa1, Id0) + * + * 0*: Inherited default from I + * 1: Declared in C (through bridge) + * 2: Declared in C + */ + public void test31() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Aa1,I)"); + assertLinkage("C", LINKAGE_ERROR, "C2", "C2"); + recompileSpec("Cc2(Aa1,Id0)", "I"); + assertLinkage("C", "I0", "C2", "C2"); + } + + /* + * Cc2(A, Id0) -> Cc2(Ac1, Id0) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test32() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A,Id0)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1,Id0)", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A, Ia0) -> Cc2(Ac1, Ia0) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test33() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A,Ia0)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1,Ia0)", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A, I) -> Cc2(Ac1, Id0) + * + * 0*: Inherited from A + * 1*: Inherited default from I + * 2: Declared in C + */ + public void test34() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A,I)"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1,Id0)", "A", "I"); + assertLinkage("C", "I0", "A1", "C2"); + } + + /* + * Cc2(Id0, J) -> Cc2(Id0, Jd1) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test35() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Id0,J)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Id0,Jd1)", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(Ia0, J) -> Cc2(Ia0, Jd1) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test36() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(Ia0,J)"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ia0,Jd1)", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(I, J) -> Cc2(Id0, Jd1) + * + * 0*: Inherited default from I + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test37() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(I,J)"); + assertLinkage("C", LINKAGE_ERROR, LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Id0,Jd1)", "I", "J"); + assertLinkage("C", "I0", "J1", "C2"); + } + + /* + * C(A(Id0), J(Id0)) -> C(Ac1(Id0), J(Id0)) + * + * 0: Inherited default from I + * 0*: Inherited from A (through bridge) + * 1*: Inherited from A + */ + public void test38() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac1(Id0),J(Id0))", "A"); + assertLinkage("C", "A1", "A1"); + } + + /* + * C(A(Id0), J(Id0)) -> C(A(Id0), Jd1(Id0)) + * + * 0: Inherited default from I + * 0: Inherited default from J (through bridge) + * 1*: Inherited default from J + */ + public void test39() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(A(Id0),Jd1(Id0))", "J"); + assertLinkage("C", "J1", "J1"); + } + + /* + * C(A(Id0), J(Id0)) -> C(Ac2(Id0), Jd1(Id0)) + * + * 0: Inherited default from I + * 0*: Inherited from A (new bridge in A beats new bridge in J) + * 1*: Inherited default from J + * 2: Inherited from A + */ + public void test40() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Ac2(Id0),Jd1(Id0))", "A", "J"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(J(Id0), K(Id0)) -> C(Jd1(Id0), K(Id0)) + * + * 0: Inherited from I + * 0*: Inherited default from J (through bridge) + * 1: Inherited default from J + */ + public void test41() throws IOException, ReflectiveOperationException { + compileSpec("C(J(Id0),K(Id0))"); + assertLinkage("C", "I0", LINKAGE_ERROR); + recompileSpec("C(Jd1(Id0),K(Id0))", "J"); + assertLinkage("C", "J1", "J1"); + } + + /* + * C(Ac2(Id0), J(Id0)) -> C(Ac2(Id0), Jd1(Id0)) + * + * 0: Inherited from A (bridge in A beats new bridge in J) + * 1*: Inherited default from J + * 2: Inherited from A + */ + public void test42() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac2(Id0),J(Id0))"); + assertLinkage("C", "A2", LINKAGE_ERROR, "A2"); + recompileSpec("C(Ac2(Id0),Jd1(Id0))", "J"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(Ac2(Ia0), J(Ia0)) -> C(Ac2(Ia0), Jd1(Ia0)) + * + * 0: Inherited from A (bridge in A beats new bridge in J) + * 1*: Inherited default from J + * 2: Inherited from A + */ + public void test43() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac2(Ia0),J(Ia0))"); + assertLinkage("C", "A2", LINKAGE_ERROR, "A2"); + recompileSpec("C(Ac2(Ia0),Jd1(Ia0))", "J"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(A(Id0), Jd1(Id0)) -> C(Ac2(Id0), Jd1(Id0)) + * + * 0: Inherited from J + * 0*: Inherited from A (new bridge in A beats bridge in J) + * 1: Inherited default from J + * 2*: Inherited from A + */ + public void test44() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),Jd1(Id0))"); + assertLinkage("C", "J1", "J1", LINKAGE_ERROR); + recompileSpec("C(Ac2(Id0),Jd1(Id0))", "A"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * C(A(Ia0), Jd1(Ia0)) -> C(Ac2(Ia0), Jd1(Ia0)) + * + * 0: Inherited from J + * 0*: Inherited from A (new bridge in A beats bridge in J) + * 1: Inherited default from J + * 2*: Inherited from A + */ + public void test45() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Ia0),Jd1(Ia0))"); + assertLinkage("C", "J1", "J1", LINKAGE_ERROR); + recompileSpec("C(Ac2(Ia0),Jd1(Ia0))", "A"); + assertLinkage("C", "A2", "J1", "A2"); + } + + /* + * Cc2(A(Id0), J(Id0)) -> Cc2(Ac1(Id0), J(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test46() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Id0),J(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Id0),J(Id0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A(Ia0), J(Ia0)) -> Cc2(Ac1(Ia0), J(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C + */ + public void test47() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Ia0),J(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Ac1(Ia0),J(Ia0))", "A"); + assertLinkage("C", "C2", "A1", "C2"); + } + + /* + * Cc2(A(Id0), J(Id0)) -> Cc2(A(Id0), Jd1(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test48() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Id0),J(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(A(Id0),Jd1(Id0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(A(Ia0), J(Ia0)) -> Cc2(A(Ia0), Jd1(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test49() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(A(Ia0),J(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(A(Ia0),Jd1(Ia0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + + /* + * Cc3(A(Id0), J(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0)) + * + * 0: Bridge in C + * 1*: Inherited from A + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test50() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Id0),J(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "A", "J"); + assertLinkage("C", "C3", "A1", "J2", "C3"); + } + + /* + * Cc3(A(Ia0), J(Ia0)) -> Cc3(Ac1(Ia0), Jd2(Ia0)) + * + * 0: Bridge in C + * 1*: Inherited from A + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test51() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Ia0),J(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "A", "J"); + assertLinkage("C", "C3", "A1", "J2", "C3"); + } + + /* + * Cc2(J(Id0), K(Id0)) -> Cc2(Jd1(Id0), K(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test52() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Id0),K(Id0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Id0),K(Id0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc2(J(Ia0), K(Ia0)) -> Cc2(Jd1(Ia0), K(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2: Declared in C + */ + public void test53() throws IOException, ReflectiveOperationException { + compileSpec("Cc2(J(Ia0),K(Ia0))"); + assertLinkage("C", "C2", LINKAGE_ERROR, "C2"); + recompileSpec("Cc2(Jd1(Ia0),K(Ia0))", "J"); + assertLinkage("C", "C2", "J1", "C2"); + } + + /* + * Cc3(J(Id0), K(Id0)) -> Cc3(Jd1(Id0), Kd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test54() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(J(Id0),K(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "J", "K"); + assertLinkage("C", "C3", "J1", "K2", "C3"); + } + + /* + * Cc3(J(Ia0), K(Ia0)) -> Cc3(Jd1(Ia0), Kd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited default from J + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test55() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(J(Ia0),K(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "J", "K"); + assertLinkage("C", "C3", "J1", "K2", "C3"); + } + + /* + * Cc3(Ac1(Id0), J(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test56() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Ac1(Id0),J(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(Ac1(Ia0), J(Ia0)) -> Cc3(Ac1(Ia0), Jd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test57() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Ac1(Ia0),J(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(Aa1(Id0), J(Id0)) -> Cc3(Aa1(Id0), Jd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test58() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Aa1(Id0),J(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Aa1(Id0),Jd2(Id0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(Aa1(Ia0), J(Ia0)) -> Cc3(Aa1(Ia0), Jd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from J + * 3: Declared in C + */ + public void test59() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Aa1(Ia0),J(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Aa1(Ia0),Jd2(Ia0))", "J"); + assertLinkage("C", "C3", "C3", "J2", "C3"); + } + + /* + * Cc3(A(Id0), Jd2(Id0)) -> Cc3(Ac1(Id0), Jd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test60() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Id0),Jd2(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Id0),Jd2(Id0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(A(Im0), Jd2(Ia0)) -> Cc3(Ac1(Im0), Jd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test61() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Ia0),Jd2(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Ia0),Jd2(Ia0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(A(Im0), Ja2(Id0)) -> Cc3(Ac1(Id0), Ja2(Id0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test62() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Id0),Ja2(Id0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Id0),Ja2(Id0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(A(Im0), Ja2(Ia0)) -> Cc3(Ac1(Ia0), Ja2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1*: Inherited from A + * 2: Declared in C (through bridge) + * 3: Declared in C + */ + public void test63() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(A(Ia0),Ja2(Ia0))"); + assertLinkage("C", "C3", LINKAGE_ERROR, "C3", "C3"); + recompileSpec("Cc3(Ac1(Ia0),Ja2(Ia0))", "A"); + assertLinkage("C", "C3", "A1", "C3", "C3"); + } + + /* + * Cc3(Jd1(Id0), K(Id0)) -> Cc3(Jd1(Id0), Kd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test64() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Id0),K(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + /* + * Cc3(Jd1(Ia0), K(Ia0)) -> Cc3(Jd1(Ia0), Kd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test65() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Ia0),K(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + /* + * Cc3(Ja1(Id0), K(Id0)) -> Cc3(Ja1(Id0), Kd2(Id0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test66() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Id0),K(Id0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Id0),Kd2(Id0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + /* + * Cc3(Ja1(Ia0), K(Ia0)) -> Cc3(Ja1(Ia0), Kd2(Ia0)) + * + * 0: Declared in C (through bridge) + * 1: Declared in C (through bridge) + * 2*: Inherited default from K + * 3: Declared in C + */ + public void test67() throws IOException, ReflectiveOperationException { + compileSpec("Cc3(Jd1(Ia0),K(Ia0))"); + assertLinkage("C", "C3", "C3", LINKAGE_ERROR, "C3"); + recompileSpec("Cc3(Jd1(Ia0),Kd2(Ia0))", "K"); + assertLinkage("C", "C3", "C3", "K2", "C3"); + } + + // Dan's set A + public void testA1() throws IOException, ReflectiveOperationException { + compileSpec("C(Id0)"); + assertLinkage("C", "I0"); + } + + public void testA2() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0))"); + assertLinkage("C", "I0"); + } + + public void testA3() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),J)"); + assertLinkage("C", "I0"); + } + + public void testA4() throws IOException, ReflectiveOperationException { + compileSpec("D(C(Id0),Jd0(Id0))"); + assertLinkage("D", "J0"); + assertLinkage("C", "I0"); + } + + public void testA5() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0),Jd0)", + "compiler.err.types.incompatible.unrelated.defaults"); + } + + public void testA6() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Ia0,Jd0))", + "compiler.err.does.not.override.abstract", + "compiler.err.types.incompatible.abstract.default"); + } + + public void testA7() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Id0,Jd0))", + "compiler.err.types.incompatible.unrelated.defaults"); + } + + public void testA8() throws IOException, ReflectiveOperationException { + compileSpec("C(A(Ia0),J)", "compiler.err.does.not.override.abstract"); + } + + public void testA9() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac0(Id0))"); + assertLinkage("C", "A0"); + } + + public void testA10() throws IOException, ReflectiveOperationException { + compileSpec("C(Aa0,I)", "compiler.err.does.not.override.abstract"); + } + + public void testA11() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac0,Id0)"); + assertLinkage("C", "A0"); + } + + // Dan's set B + + /* B1 can't be done, needs a second concrete class D + public void testB1() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Dc0)"); + assertLinkage("C", "C1", "C1"); + assertLinkage("D", "A0", LINKAGE_ERROR); + } + */ + + public void testB2() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Ac0)"); + assertLinkage("C", "C1", "C1"); + } + + //??? B3 seems to suggest that we should create an abstract class + //public void testB3() throws IOException, ReflectiveOperationException { + // compileSpec("Ba1(Cc0)"); + // assertLinkage("B", "C0", "A1"); + //} + + // B4 needs too many classes + + public void testB5() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Aa1(Id0))"); + assertLinkage("C", "C1", "C1"); + } + + public void testB6() throws IOException, ReflectiveOperationException { + compileSpec("C(Ac1(Id0))"); + assertLinkage("C", "A1", "A1"); + } + + public void testB7() throws IOException, ReflectiveOperationException { + compileSpec("Cc1(Id0)"); + assertLinkage("C", "C1", "C1"); + } + + public void testB8() throws IOException, ReflectiveOperationException { + compileSpec("C(Jd1(Id0))"); + assertLinkage("C", "J1", "J1"); + } + + // B9 needs too many classes + + // The rest of Dan's tests need generics +} diff --git a/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties b/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties new file mode 100644 index 00000000000..9e96df01db6 --- /dev/null +++ b/langtools/test/tools/javac/lambda/bridge/template_tests/TEST.properties @@ -0,0 +1,7 @@ +# This file identifies root(s) of the test-ng hierarchy. + + + +TestNG.dirs = . + +lib.dirs = /lib/combo diff --git a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java index 660721ec849..36e18611ba5 100644 --- a/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java +++ b/langtools/test/tools/javac/lambda/intersection/IntersectionTargetTypeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -196,7 +196,7 @@ public class IntersectionTargetTypeTest { } static List allCastInfo() { - ListBuffer buf = ListBuffer.lb(); + ListBuffer buf = new ListBuffer<>(); for (CastKind kind : CastKind.values()) { for (TypeKind b1 : TypeKind.values()) { if (kind.nbounds == 1) { diff --git a/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceNullCheckTest.java b/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceNullCheckTest.java new file mode 100644 index 00000000000..fd2bf655649 --- /dev/null +++ b/langtools/test/tools/javac/lambda/methodReferenceExecution/MethodReferenceNullCheckTest.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. 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 8024696 + * @summary Missing null check in bound method reference capture + */ + +import com.sun.tools.javac.util.Assert; +import java.util.function.*; + +public class MethodReferenceNullCheckTest { + public static void main(String[] args) { + String s = null; + boolean npeFired = false; + try { + Supplier ss = s::isEmpty; + } catch (NullPointerException npe) { + npeFired = true; + } finally { + Assert.check(npeFired, "NPE should have been thrown"); + } + } +} diff --git a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java index dbd7d1366a0..0e1f144f418 100644 --- a/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java +++ b/langtools/test/tools/javac/lambda/mostSpecific/StructuralMostSpecificTest.java @@ -197,7 +197,7 @@ public class StructuralMostSpecificTest "class Test {\n" + " void m(SAM1 s) { }\n" + " void m(SAM2 s) { }\n" + - " { m(x->{ #LR }); }\n" + + " { m((#A1 x)->{ #LR }); }\n" + "}\n"; String source; @@ -236,14 +236,17 @@ public class StructuralMostSpecificTest void check() { checkCount.incrementAndGet(); + if (ak1 != ak2) + return; + if (!lrk.compatibleWith(rt1) || !lrk.compatibleWith(rt2)) return; if (lrk.needsConversion(rt1) != lrk.needsConversion(rt2)) return; - boolean m1MoreSpecific = moreSpecific(rt1, rt2, ek1, ek2, ak1, ak2); - boolean m2MoreSpecific = moreSpecific(rt2, rt1, ek2, ek1, ak2, ak1); + boolean m1MoreSpecific = rt1.moreSpecificThan(rt2); + boolean m2MoreSpecific = rt2.moreSpecificThan(rt1); boolean ambiguous = (m1MoreSpecific == m2MoreSpecific); @@ -268,17 +271,6 @@ public class StructuralMostSpecificTest } } - boolean moreSpecific(RetTypeKind rk1, RetTypeKind rk2, ExceptionKind ek1, - ExceptionKind ek2, ArgTypeKind ak1, ArgTypeKind ak2) { - if (!rk1.moreSpecificThan(rk2)) - return false; - - if (ak1 != ak2) - return false; - - return true; - } - static class DiagnosticChecker implements javax.tools.DiagnosticListener { diff --git a/langtools/test/tools/javac/lambda/typeInference/InferenceTest5.java b/langtools/test/tools/javac/lambda/typeInference/InferenceTest5.java deleted file mode 100644 index 291068070a4..00000000000 --- a/langtools/test/tools/javac/lambda/typeInference/InferenceTest5.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * 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 8003280 - * @summary Add lambda tests - * This test is for overloaded methods, verify that the specific method is - selected when type inference occurs - * @compile InferenceTest5.java - * @run main InferenceTest5 - */ - -import java.util.List; -import java.io.File; - -public class InferenceTest5 { - - private static void assertTrue(boolean b) { - if(!b) - throw new AssertionError(); - } - - public static void main(String[] args) { - InferenceTest5 test = new InferenceTest5(); - int n = test.method1((a, b) -> {} ); - assertTrue(n == 1); - - n = test.method1(() -> null); - assertTrue(n == 2); - - n = test.method1(a -> null); - assertTrue(n == 3); - - n = test.method1(a -> {}); - assertTrue(n == 4); - - n = test.method1(() -> {}); - assertTrue(n == 5); - - n = test.method1((a, b) -> 0); - assertTrue(n == 6); - - n = test.method1((a, b) -> null); - assertTrue(n == 6); - - n = test.method1((a, b) -> null, (a, b) -> null); - assertTrue(n == 7); - } - - int method1(SAM1 s) { - return 1; - } - - int method1(SAM2 s) { - return 2; - } - - int method1(SAM3 s) { - return 3; - } - - int method1(SAM4 s) { - return 4; - } - - int method1(SAM5 s) { - return 5; - } - - int method1(SAM6 s) { - return 6; - } - - int method1(SAM6... s) { - return 7; - } - - static interface SAM1 { - void foo(List a, List b); - } - - static interface SAM2 { - List foo(); - } - - static interface SAM3 { - String foo(int a); - } - - static interface SAM4 { - void foo(List a); - } - - static interface SAM5 { - void foo(); - } - - static interface SAM6 { - V get(T t, T t2); - } -} diff --git a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.java b/langtools/test/tools/javac/lambda/typeInference/InferenceTest6.java similarity index 76% rename from langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.java rename to langtools/test/tools/javac/lambda/typeInference/InferenceTest6.java index d5f757e1379..b80a5903299 100644 --- a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.java +++ b/langtools/test/tools/javac/lambda/typeInference/InferenceTest6.java @@ -1,16 +1,16 @@ /* * @test /nodynamiccopyright/ - * @bug 8003280 + * @bug 8003280 8016177 * @summary Add lambda tests * Missing cast to SAM type that causes type inference to not work. - * @compile/fail/ref=InferenceTest_neg5.out -XDrawDiagnostics InferenceTest_neg5.java + * @compile -XDrawDiagnostics InferenceTest6.java */ import java.util.*; -public class InferenceTest_neg5 { +public class InferenceTest6 { public static void main(String[] args) { - InferenceTest_neg5 test = new InferenceTest_neg5(); + InferenceTest6 test = new InferenceTest6(); test.method1(n -> {}); test.method1((SAM1)n -> {}); test.method1((SAM1)n -> {n++;}); diff --git a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg1_2.out b/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg1_2.out index cf0d1d587bf..8dc00a893ad 100644 --- a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg1_2.out +++ b/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg1_2.out @@ -1,4 +1,5 @@ InferenceTest_neg1_2.java:14:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM4), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5), InferenceTest_neg1_2 -InferenceTest_neg1_2.java:15:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM2), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM4), InferenceTest_neg1_2 -InferenceTest_neg1_2.java:16:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM3), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5), InferenceTest_neg1_2 -3 errors +InferenceTest_neg1_2.java:15:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM4), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5), InferenceTest_neg1_2 +InferenceTest_neg1_2.java:16:13: compiler.err.ref.ambiguous: method, kindname.method, method(InferenceTest_neg1_2.SAM4), InferenceTest_neg1_2, kindname.method, method(InferenceTest_neg1_2.SAM5), InferenceTest_neg1_2 +InferenceTest_neg1_2.java:16:20: compiler.err.cant.apply.symbol: kindname.method, method, InferenceTest_neg1_2.SAM4, @597, kindname.class, InferenceTest_neg1_2, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: int, java.lang.String))) +4 errors diff --git a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out b/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out deleted file mode 100644 index 7f647251ecf..00000000000 --- a/langtools/test/tools/javac/lambda/typeInference/InferenceTest_neg5.out +++ /dev/null @@ -1,2 +0,0 @@ -InferenceTest_neg5.java:14:21: compiler.err.prob.found.req: (compiler.misc.cyclic.inference: X) -1 error diff --git a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java index 9399eb7b284..744a3ff5511 100644 --- a/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java +++ b/langtools/test/tools/javac/lambda/typeInference/combo/TypeInferenceComboTest.java @@ -227,12 +227,7 @@ public class TypeInferenceComboTest } else if (lambdaBodyType != LambdaBody.RETURN_ARG) return false; - if ( genericDeclKind == GenericDeclKind.GENERIC_NOBOUND || - genericDeclKind == GenericDeclKind.GENERIC_BOUND ) { - if ( parameterType == TypeKind.GENERIC && - parameterKind == ParameterKind.IMPLICIT) //cyclic inference - return false; - } + return true; } diff --git a/langtools/test/tools/javac/lib/DPrinter.java b/langtools/test/tools/javac/lib/DPrinter.java index 8df4881cba4..8e67826c641 100644 --- a/langtools/test/tools/javac/lib/DPrinter.java +++ b/langtools/test/tools/javac/lib/DPrinter.java @@ -49,7 +49,7 @@ import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskListener; import com.sun.source.util.Trees; import com.sun.tools.javac.api.JavacTrees; -import com.sun.tools.javac.code.Annotations; +import com.sun.tools.javac.code.SymbolMetadata; import com.sun.tools.javac.code.Attribute; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds; @@ -186,21 +186,21 @@ public class DPrinter { FULL }; - public void printAnnotations(String label, Annotations annotations) { + public void printAnnotations(String label, SymbolMetadata annotations) { printAnnotations(label, annotations, Details.FULL); } - protected void printAnnotations(String label, Annotations annotations, Details details) { + protected void printAnnotations(String label, SymbolMetadata annotations, Details details) { if (annotations == null) { printNull(label); } else { // no SUMMARY format currently available to use // use reflection to get at private fields - Object DECL_NOT_STARTED = getField(null, Annotations.class, "DECL_NOT_STARTED"); - Object DECL_IN_PROGRESS = getField(null, Annotations.class, "DECL_IN_PROGRESS"); - Object attributes = getField(annotations, Annotations.class, "attributes"); - Object type_attributes = getField(annotations, Annotations.class, "type_attributes"); + Object DECL_NOT_STARTED = getField(null, SymbolMetadata.class, "DECL_NOT_STARTED"); + Object DECL_IN_PROGRESS = getField(null, SymbolMetadata.class, "DECL_IN_PROGRESS"); + Object attributes = getField(annotations, SymbolMetadata.class, "attributes"); + Object type_attributes = getField(annotations, SymbolMetadata.class, "type_attributes"); if (!showEmptyItems) { if (attributes instanceof List && ((List) attributes).isEmpty() diff --git a/langtools/test/tools/javac/multicatch/Pos05.java b/langtools/test/tools/javac/multicatch/Pos05.java index e3c3d50d321..32d76b2368b 100644 --- a/langtools/test/tools/javac/multicatch/Pos05.java +++ b/langtools/test/tools/javac/multicatch/Pos05.java @@ -95,7 +95,7 @@ public class Pos05 { throw new Error("Code attribute for test() method not found"); } Exception_data firstExceptionTable = null; - for (int i = 0 ; i < ea.exception_table_langth; i++) { + for (int i = 0 ; i < ea.exception_table_length; i++) { if (firstExceptionTable == null) { firstExceptionTable = ea.exception_table[i]; } diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java index 2ddcd10bd26..644ec9d5b17 100644 --- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java +++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.java @@ -31,6 +31,7 @@ * @compile/fail/ref=TestMissingElement.ref -proc:only -XprintRounds -XDrawDiagnostics -processor TestMissingElement InvalidSource.java */ +import java.io.PrintWriter; import java.util.*; import javax.annotation.processing.*; import javax.lang.model.element.*; @@ -38,7 +39,18 @@ import javax.lang.model.type.*; import javax.lang.model.util.*; import static javax.tools.Diagnostic.Kind.*; +import com.sun.tools.javac.processing.JavacProcessingEnvironment; +import com.sun.tools.javac.util.Log; + public class TestMissingElement extends JavacTestingAbstractProcessor { + private PrintWriter out; + + @Override + public void init(ProcessingEnvironment env) { + super.init(env); + out = ((JavacProcessingEnvironment) env).getContext().get(Log.outKey); + } + @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { for (TypeElement te: ElementFilter.typesIn(roundEnv.getRootElements())) { @@ -70,13 +82,13 @@ public class TestMissingElement extends JavacTestingAbstractProcessor { } private void checkInterfaces(TypeElement te, String expect) { - System.err.println("check interfaces: " + te + " -- " + expect); + out.println("check interfaces: " + te + " -- " + expect); String found = asString(te.getInterfaces(), ", "); checkEqual("interfaces", te, found, expect); } private void checkSupertype(TypeElement te, String expect) { - System.err.println("check supertype: " + te + " -- " + expect); + out.println("check supertype: " + te + " -- " + expect); String found = asString(te.getSuperclass()); checkEqual("supertype", te, found, expect); } @@ -85,7 +97,7 @@ public class TestMissingElement extends JavacTestingAbstractProcessor { if (found.equals(expect)) { // messager.printMessage(NOTE, "expected " + label + " found: " + expect, te); } else { - System.err.println("unexpected " + label + ": " + te + "\n" + out.println("unexpected " + label + ": " + te + "\n" + " found: " + found + "\n" + "expect: " + expect); messager.printMessage(ERROR, "unexpected " + label + " found: " + found + "; expected: " + expect, te); diff --git a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref index 4c31a101dbb..d71a2cce8ba 100644 --- a/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref +++ b/langtools/test/tools/javac/processing/model/element/TestMissingElement/TestMissingElement.ref @@ -2,6 +2,24 @@ Round 1: input files: {ExpectInterfaces, ExpectSupertype, OK, InvalidSource} annotations: [ExpectSupertype, ExpectInterfaces] last round: false +check supertype: InvalidSource.TestClassMissingClassA -- !:empty clss A! +check supertype: InvalidSource.TestClassMissingClassAB -- !:empty clss (pkg A).B! +check supertype: InvalidSource.TestClassMissingClass_juA -- !:empty clss (pkg java.util).A! +check supertype: InvalidSource.TestClassTMissingClassAT -- !:empty clss A! +check interfaces: InvalidSource.TestClassMissingIntfA -- !:empty intf A! +check interfaces: InvalidSource.TestClassMissingIntfAB -- !:empty intf (pkg A).B! +check interfaces: InvalidSource.TestClassMissingIntfAOK -- !:empty intf A!, intf OK +check interfaces: InvalidSource.TestClassOKMissingIntfA -- intf OK, !:empty intf A! +check interfaces: InvalidSource.TestClassMissingIntfA_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestIntfMissingIntfA -- !:empty intf A! +check interfaces: InvalidSource.TestIntfMissingIntfAOK -- !:empty intf A!, intf OK +check interfaces: InvalidSource.TestIntfOKMissingIntfA -- intf OK, !:empty intf A! +check interfaces: InvalidSource.TestIntfMissingIntfAB -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestClassTMissingIntfAT -- !:empty intf A! +check interfaces: InvalidSource.TestClassTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestIntfTMissingIntfAT -- !:empty intf A! +check interfaces: InvalidSource.TestIntfTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! +check interfaces: InvalidSource.TestClassListMissingX -- intf (pkg java.util).List Round 2: input files: {} annotations: [] @@ -28,22 +46,4 @@ InvalidSource.java:100:49: compiler.err.cant.resolve.location: kindname.class, A InvalidSource.java:103:51: compiler.err.cant.resolve.location: kindname.class, A, , , (compiler.misc.location: kindname.class, InvalidSource, null) InvalidSource.java:103:57: compiler.err.cant.resolve.location: kindname.class, B, , , (compiler.misc.location: kindname.class, InvalidSource, null) InvalidSource.java:106:58: compiler.err.cant.resolve.location: kindname.class, X, , , (compiler.misc.location: kindname.class, InvalidSource, null) -22 errors -check supertype: InvalidSource.TestClassMissingClassA -- !:empty clss A! -check supertype: InvalidSource.TestClassMissingClassAB -- !:empty clss (pkg A).B! -check supertype: InvalidSource.TestClassMissingClass_juA -- !:empty clss (pkg java.util).A! -check supertype: InvalidSource.TestClassTMissingClassAT -- !:empty clss A! -check interfaces: InvalidSource.TestClassMissingIntfA -- !:empty intf A! -check interfaces: InvalidSource.TestClassMissingIntfAB -- !:empty intf (pkg A).B! -check interfaces: InvalidSource.TestClassMissingIntfAOK -- !:empty intf A!, intf OK -check interfaces: InvalidSource.TestClassOKMissingIntfA -- intf OK, !:empty intf A! -check interfaces: InvalidSource.TestClassMissingIntfA_B -- !:empty intf A!, !:empty intf B! -check interfaces: InvalidSource.TestIntfMissingIntfA -- !:empty intf A! -check interfaces: InvalidSource.TestIntfMissingIntfAOK -- !:empty intf A!, intf OK -check interfaces: InvalidSource.TestIntfOKMissingIntfA -- intf OK, !:empty intf A! -check interfaces: InvalidSource.TestIntfMissingIntfAB -- !:empty intf A!, !:empty intf B! -check interfaces: InvalidSource.TestClassTMissingIntfAT -- !:empty intf A! -check interfaces: InvalidSource.TestClassTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! -check interfaces: InvalidSource.TestIntfTMissingIntfAT -- !:empty intf A! -check interfaces: InvalidSource.TestIntfTMissingIntfAT_B -- !:empty intf A!, !:empty intf B! -check interfaces: InvalidSource.TestClassListMissingX -- intf (pkg java.util).List \ No newline at end of file +22 errors \ No newline at end of file diff --git a/langtools/test/tools/javac/processing/model/type/BoundsTest.java b/langtools/test/tools/javac/processing/model/type/BoundsTest.java new file mode 100644 index 00000000000..59c73ef6a0c --- /dev/null +++ b/langtools/test/tools/javac/processing/model/type/BoundsTest.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6499673 + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor BoundsTest + * @run main BoundsTest + * @summary Assertion check for TypeVariable.getUpperBound() fails + */ + +import com.sun.source.util.*; +import com.sun.tools.javac.api.*; +import com.sun.tools.javac.file.*; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.type.*; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.element.*; +import javax.tools.*; +import java.util.*; +import java.io.*; + +public class BoundsTest { + + private int errors = 0; + private static final String Intersection_name = "IntersectionTest.java"; + private static final String Intersection_contents = + "import java.util.List;\n" + + "import java.io.Serializable;\t" + + "public class IntersectionTest {\n" + + " void method(S s) { }\n" + + "}"; + private static final String[] Intersection_bounds = { + "java.util.List", + "java.io.Serializable" + }; + private static final String[] Intersection_supers = { + "java.util.List", + "java.io.Serializable" + }; + + private static final String Single_name = "SingleTest.java"; + private static final String Single_contents = + "import java.util.List;\n" + + "public class SingleTest {\n" + + " void method(S s) { }\n" + + "}"; + private static final String[] Single_bounds = { + "java.util.List", + }; + private static final String[] Single_supers = { + "java.lang.Object", + "java.util.Collection" + }; + + private static final String NoBounds_name = "NoBoundsTest.java"; + private static final String NoBounds_contents = + "public class NoBoundsTest {\n" + + " void method(S s) { }\n" + + "}"; + private static final String[] NoBounds_bounds = { + "java.lang.Object", + }; + private static final String[] NoBounds_supers = {}; + + private HashSet expected_bounds; + private HashSet expected_supers; + + private static final File classesdir = new File("intersectionproperties"); + private static final JavaCompiler comp = + ToolProvider.getSystemJavaCompiler(); + private static final StandardJavaFileManager fm = + comp.getStandardFileManager(null, null, null); + + public void runOne(final String Test_name, final String Test_contents, + final String[] Test_bounds, final String[] Test_supers) + throws IOException { + System.err.println("Testing " + Test_name); + expected_bounds = new HashSet(Arrays.asList(Test_bounds)); + expected_supers = new HashSet(Arrays.asList(Test_supers)); + final Iterable files = + fm.getJavaFileObjectsFromFiles(Collections.singleton(writeFile(classesdir, Test_name, Test_contents))); + final JavacTask ct = + (JavacTask)comp.getTask(null, fm, null, null, null, files); + ct.setProcessors(Collections.singleton(new TestProcessor())); + + if (!ct.call()) { + System.err.println("Compilation unexpectedly failed"); + errors++; + } + } + + public void run() throws IOException { + runOne(Intersection_name, Intersection_contents, + Intersection_bounds, Intersection_supers); + runOne(Single_name, Single_contents, + Single_bounds, Single_supers); + runOne(NoBounds_name, NoBounds_contents, + NoBounds_bounds, NoBounds_supers); + + if (0 != errors) + throw new RuntimeException(errors + " errors occurred"); + } + + public static void main(String... args) throws IOException { + new IntersectionPropertiesTest().run(); + } + + private static File writeFile(File dir, String path, String body) + throws IOException { + File f = new File(dir, path); + f.getParentFile().mkdirs(); + try (FileWriter out = new FileWriter(f)) { + out.write(body); + } + return f; + } + + private class TestProcessor extends JavacTestingAbstractProcessor { + + private Set rootElements; + + public boolean process(Set annotations, RoundEnvironment roundEnv) { + rootElements = roundEnv.getRootElements(); + if (!rootElements.isEmpty()) { + performCheck(); + } + return true; + } + + private void performCheck() { + TypeElement typeElement = (TypeElement) rootElements.iterator().next(); + ExecutableElement method = ElementFilter.methodsIn(typeElement.getEnclosedElements()).get(0); + TypeVariable typeVariable = (TypeVariable) method.getParameters().get(0).asType(); + + final TypeMirror upperBound = typeVariable.getUpperBound(); + + TypeParameterElement typeParameterElement = ((TypeParameterElement) typeVariable.asElement()); + final List bounds = typeParameterElement.getBounds(); + final List supers = processingEnv.getTypeUtils().directSupertypes(upperBound); + + final HashSet actual_bounds = new HashSet(); + final HashSet actual_supers = new HashSet(); + + for(TypeMirror ty : bounds) { + actual_bounds.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName()); + } + + for(TypeMirror ty : supers) { + actual_supers.add(((TypeElement)((DeclaredType)ty).asElement()).getQualifiedName()); + } + + + if (!expected_bounds.equals(actual_bounds)) { + System.err.println("Mismatched expected and actual bounds."); + System.err.println("Expected:"); + for(CharSequence tm : expected_bounds) + System.err.println(" " + tm); + System.err.println("Actual:"); + for(CharSequence tm : actual_bounds) + System.err.println(" " + tm); + errors++; + } + + if (!expected_supers.equals(actual_supers)) { + System.err.println("Mismatched expected and actual bounds."); + System.err.println("Expected:"); + for(CharSequence tm : expected_supers) + System.err.println(" " + tm); + System.err.println("Actual:"); + for(CharSequence tm : actual_supers) + System.err.println(" " + tm); + errors++; + } + } + } + +} diff --git a/langtools/test/tools/javac/processing/model/type/IntersectionPropertiesTest.java b/langtools/test/tools/javac/processing/model/type/IntersectionPropertiesTest.java new file mode 100644 index 00000000000..9beeb6392c8 --- /dev/null +++ b/langtools/test/tools/javac/processing/model/type/IntersectionPropertiesTest.java @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6499673 + * @library /tools/javac/lib + * @build JavacTestingAbstractProcessor IntersectionPropertiesTest + * @run main IntersectionPropertiesTest + * @summary Assertion check for TypeVariable.getUpperBound() fails + */ + +import com.sun.source.util.*; +import com.sun.tools.javac.api.*; +import com.sun.tools.javac.file.*; +import javax.annotation.processing.*; +import javax.lang.model.SourceVersion; +import javax.lang.model.type.*; +import javax.lang.model.util.ElementFilter; +import javax.lang.model.element.*; +import javax.tools.*; +import java.util.*; +import java.io.*; + +public class IntersectionPropertiesTest { + + private int errors = 0; + private static final String Intersection_name = "IntersectionTest.java"; + private static final String Intersection_contents = + "import java.util.List;\n" + + "import java.io.Serializable;\t" + + "public class IntersectionTest {\n" + + " void method(S s) { }\n" + + "}"; + + private static final File classesdir = new File("intersectionproperties"); + private static final JavaCompiler comp = + ToolProvider.getSystemJavaCompiler(); + private static final StandardJavaFileManager fm = + comp.getStandardFileManager(null, null, null); + + public void runOne(final String Test_name, final String Test_contents) + throws IOException { + System.err.println("Testing " + Test_name); + final Iterable files = + fm.getJavaFileObjectsFromFiles(Collections.singleton(writeFile(classesdir, Test_name, Test_contents))); + final JavacTask ct = + (JavacTask)comp.getTask(null, fm, null, null, null, files); + ct.setProcessors(Collections.singleton(new TestProcessor())); + + if (!ct.call()) { + System.err.println("Compilation unexpectedly failed"); + errors++; + } + } + + public void run() throws IOException { + runOne(Intersection_name, Intersection_contents); + + if (0 != errors) + throw new RuntimeException(errors + " errors occurred"); + } + + public static void main(String... args) throws IOException { + new IntersectionPropertiesTest().run(); + } + + private static File writeFile(File dir, String path, String body) + throws IOException { + File f = new File(dir, path); + f.getParentFile().mkdirs(); + try (FileWriter out = new FileWriter(f)) { + out.write(body); + } + return f; + } + + private class TestProcessor extends JavacTestingAbstractProcessor { + + private Set rootElements; + + public boolean process(Set annotations, RoundEnvironment roundEnv) { + rootElements = roundEnv.getRootElements(); + if (!rootElements.isEmpty()) { + performCheck(); + } + return true; + } + + private void performCheck() { + TypeElement typeElement = (TypeElement) rootElements.iterator().next(); + ExecutableElement method = ElementFilter.methodsIn(typeElement.getEnclosedElements()).get(0); + TypeVariable typeVariable = (TypeVariable) method.getParameters().get(0).asType(); + + final TypeMirror upperBound = typeVariable.getUpperBound(); + + TypeParameterElement typeParameterElement = ((TypeParameterElement) typeVariable.asElement()); + final List bounds = typeParameterElement.getBounds(); + final HashSet actual = new HashSet(processingEnv.getTypeUtils().directSupertypes(upperBound)); + final HashSet expected = new HashSet(bounds); + if (!expected.equals(actual)) { + System.err.println("Mismatched expected and actual bounds."); + System.err.println("Expected:"); + for(TypeMirror tm : expected) + System.err.println(" " + tm); + System.err.println("Actual:"); + for(TypeMirror tm : actual) + System.err.println(" " + tm); + errors++; + } + } + + } + +} diff --git a/langtools/test/tools/javac/scope/7017664/CompoundScopeTest.java b/langtools/test/tools/javac/scope/7017664/CompoundScopeTest.java index 075a750a310..e9d44a84d41 100644 --- a/langtools/test/tools/javac/scope/7017664/CompoundScopeTest.java +++ b/langtools/test/tools/javac/scope/7017664/CompoundScopeTest.java @@ -176,7 +176,7 @@ public class CompoundScopeTest { */ void checkElems(CompoundScope cs, Filter sf) { int count = 0; - ListBuffer found = ListBuffer.lb(); + ListBuffer found = new ListBuffer<>(); List allSymbols = sf == null ? elems : filter(elems, sf); @@ -216,7 +216,7 @@ public class CompoundScopeTest { } List filter(List elems, Filter sf) { - ListBuffer res = ListBuffer.lb(); + ListBuffer res = new ListBuffer<>(); for (Symbol s : elems) { if (sf.accepts(s)) { res.append(s); diff --git a/langtools/test/tools/javac/tree/MakeQualIdent.java b/langtools/test/tools/javac/tree/MakeQualIdent.java new file mode 100644 index 00000000000..e4b71179672 --- /dev/null +++ b/langtools/test/tools/javac/tree/MakeQualIdent.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023835 + * @summary Verify that TreeMaker.QualIdent(Symbol) field access cascade ends with + * the top-level package (when no toplevel is set in TreeMaker) + * @run main MakeQualIdent + */ + +import com.sun.source.tree.IdentifierTree; +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.Tree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Symtab; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.util.Context; +import java.util.ArrayList; + +public class MakeQualIdent { + public static void main(String... args) throws Exception { + JavacTool tool = JavacTool.create(); + JavacTask task = tool.getTask(null, null, null, new ArrayList(), null, null); + Context ctx = ((JavacTaskImpl)task).getContext(); + TreeMaker treeMaker = TreeMaker.instance(ctx); + Symtab syms = Symtab.instance(ctx); + + String stringTree = printTree(treeMaker.QualIdent(syms.stringType.tsym)); + + if (!"java.lang.String".equals(stringTree)) { + throw new IllegalStateException(stringTree); + } + } + + private static String printTree(Tree tree) { + final StringBuilder result = new StringBuilder(); + + new TreeScanner() { + @Override public Void visitIdentifier(IdentifierTree node, Void p) { + result.append(node.getName()); + return super.visitIdentifier(node, p); + } + @Override public Void visitMemberSelect(MemberSelectTree node, Void p) { + scan(node.getExpression(), null); + result.append("."); + result.append(node.getIdentifier()); + return null; + } + }.scan(tree, null); + + return result.toString(); + } +} diff --git a/langtools/test/tools/javac/tree/ScopeTest.java b/langtools/test/tools/javac/tree/ScopeTest.java new file mode 100644 index 00000000000..5df625eacd0 --- /dev/null +++ b/langtools/test/tools/javac/tree/ScopeTest.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8023835 + * @summary Verify that implicit type of lambda parameter is correctly attributed + * in Scope + * @run main ScopeTest + */ + +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MemberSelectTree; +import com.sun.source.tree.Scope; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreePath; +import com.sun.source.util.TreePathScanner; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.model.JavacTypes; +import java.io.IOException; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import javax.lang.model.element.Element; +import javax.lang.model.type.TypeMirror; +import javax.lang.model.util.Types; +import javax.tools.JavaFileObject; +import javax.tools.JavaFileObject.Kind; +import javax.tools.SimpleJavaFileObject; + +public class ScopeTest { + + private static final String SOURCE_CODE = + "public class Test {\n" + + " private static void test() {\n" + + " InvokeOn f = null;\n" + + " f.run(x -> { x.correct(); });\n" + + " }\n" + + " public static final class FooBar {\n" + + " public void dontRun() { }\n" + + " }\n" + + "}\n" + + "class InvokeOn {\n" + + " public void run(I i) { }\n" + + "}\n" + + "class FooBar {\n" + + " public void correct() { }\n" + + "}\n" + + "interface I {\n" + + " public void run(FooBar f);\n" + + "}"; + + public static void main(String... args) throws Exception { + verifyLambdaScopeCorrect(""); + verifyLambdaScopeCorrect("package test;"); + } + + private static void verifyLambdaScopeCorrect(final String packageClause) throws Exception { + JavacTool tool = JavacTool.create(); + JavaFileObject source = new SimpleJavaFileObject(URI.create("mem://Test.java"), Kind.SOURCE) { + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return packageClause + SOURCE_CODE; + } + @Override public boolean isNameCompatible(String simpleName, Kind kind) { + return true; + } + }; + Iterable fos = Collections.singletonList(source); + JavacTask task = tool.getTask(null, null, null, new ArrayList(), null, fos); + final Types types = JavacTypes.instance(((JavacTaskImpl) task).getContext()); + final Trees trees = Trees.instance(task); + CompilationUnitTree cu = task.parse().iterator().next(); + + task.analyze(); + + new TreePathScanner() { + @Override public Void visitMemberSelect(MemberSelectTree node, Void p) { + if (node.getIdentifier().contentEquals("correct")) { + TypeMirror xType = trees.getTypeMirror(new TreePath(getCurrentPath(), node.getExpression())); + Scope scope = trees.getScope(getCurrentPath()); + for (Element l : scope.getLocalElements()) { + if (!l.getSimpleName().contentEquals("x")) continue; + if (!types.isSameType(xType, l.asType())) { + throw new IllegalStateException("Incorrect variable type in scope: " + l.asType() + "; should be: " + xType); + } + } + } + return super.visitMemberSelect(node, p); + } + }.scan(cu, null); + } +} diff --git a/langtools/test/tools/javac/types/TypeHarness.java b/langtools/test/tools/javac/types/TypeHarness.java index a53d94761ba..b4837907820 100644 --- a/langtools/test/tools/javac/types/TypeHarness.java +++ b/langtools/test/tools/javac/types/TypeHarness.java @@ -213,8 +213,8 @@ public class TypeHarness { /** compute a type substitution on 't' given a list of type mappings */ public Type subst(Type t, Mapping... maps) { - ListBuffer from = ListBuffer.lb(); - ListBuffer to = ListBuffer.lb(); + ListBuffer from = new ListBuffer<>(); + ListBuffer to = new ListBuffer<>(); for (Mapping tm : maps) { from.append(tm.from); to.append(tm.to); diff --git a/langtools/test/tools/javac/warnings/6594914/T6594914a.out b/langtools/test/tools/javac/warnings/6594914/T6594914a.out index d3d759ca044..62f99072a7a 100644 --- a/langtools/test/tools/javac/warnings/6594914/T6594914a.out +++ b/langtools/test/tools/javac/warnings/6594914/T6594914a.out @@ -1,7 +1,7 @@ T6594914a.java:11:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package T6594914a.java:16:16: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package -T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package T6594914a.java:16:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package T6594914a.java:17:20: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6594914a.java:16:52: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package T6594914a.java:24:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package 6 warnings diff --git a/langtools/test/tools/javac/warnings/6594914/T6594914b.out b/langtools/test/tools/javac/warnings/6594914/T6594914b.out index 652ad120d78..56e0794f1d8 100644 --- a/langtools/test/tools/javac/warnings/6594914/T6594914b.out +++ b/langtools/test/tools/javac/warnings/6594914/T6594914b.out @@ -1,7 +1,7 @@ T6594914b.java:11:13: compiler.warn.sun.proprietary: sun.misc.Lock T6594914b.java:16:24: compiler.warn.sun.proprietary: sun.misc.Lock -T6594914b.java:16:56: compiler.warn.sun.proprietary: sun.misc.Lock T6594914b.java:16:39: compiler.warn.sun.proprietary: sun.misc.Lock T6594914b.java:17:28: compiler.warn.sun.proprietary: sun.misc.CEFormatException +T6594914b.java:16:56: compiler.warn.sun.proprietary: sun.misc.Lock T6594914b.java:24:17: compiler.warn.sun.proprietary: sun.misc.Lock 6 warnings diff --git a/langtools/test/tools/javac/warnings/6747671/T6747671.java b/langtools/test/tools/javac/warnings/6747671/T6747671.java index c8060a06afd..2bb67ac132f 100644 --- a/langtools/test/tools/javac/warnings/6747671/T6747671.java +++ b/langtools/test/tools/javac/warnings/6747671/T6747671.java @@ -1,6 +1,6 @@ /** * @test /nodynamiccopyright/ - * @bug 6747671 + * @bug 6747671 8022567 * @summary -Xlint:rawtypes * @compile/ref=T6747671.out -XDrawDiagnostics -Xlint:rawtypes T6747671.java */ @@ -32,4 +32,11 @@ class T6747671 { A a2 = new A() {};//raw warning (2) a2.new Z() {};//raw warning } + + @TA B @TA[] arr = new @TA B @TA [0];//JDK-8022567: raw warning (2) + Class classes1;//no warning + Class[] classes2;//no warning + + @java.lang.annotation.Target(java.lang.annotation.ElementType.TYPE_USE) + @interface TA { } } diff --git a/langtools/test/tools/javac/warnings/6747671/T6747671.out b/langtools/test/tools/javac/warnings/6747671/T6747671.out index 43069572c62..518804d68b5 100644 --- a/langtools/test/tools/javac/warnings/6747671/T6747671.out +++ b/langtools/test/tools/javac/warnings/6747671/T6747671.out @@ -7,4 +7,6 @@ T6747671.java:29:28: compiler.warn.raw.class.use: T6747671.B, T6747671.B T6747671.java:32:9: compiler.warn.raw.class.use: T6747671.A, T6747671.A T6747671.java:32:20: compiler.warn.raw.class.use: T6747671.A, T6747671.A T6747671.java:33:16: compiler.warn.raw.class.use: T6747671.A.Z, T6747671.A.Z -9 warnings +T6747671.java:36:9: compiler.warn.raw.class.use: @T6747671.TA T6747671.B, T6747671.B +T6747671.java:36:27: compiler.warn.raw.class.use: T6747671.B, T6747671.B +11 warnings diff --git a/langtools/test/tools/javac/warnings/suppress/ImplicitTest.java b/langtools/test/tools/javac/warnings/suppress/ImplicitTest.java new file mode 100644 index 00000000000..1c4208ca902 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/ImplicitTest.java @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8021112 + * @summary Verify that deprecated warning is printed correctly for import + * statement when processing a file on demand while attributing another file. + * @clean pack.ImplicitUse pack.ImplicitMain pack.Dep + * @compile/ref=ImplicitTest.out -XDrawDiagnostics -Xlint:deprecation pack/ImplicitMain.java + */ diff --git a/langtools/test/tools/javac/warnings/suppress/ImplicitTest.out b/langtools/test/tools/javac/warnings/suppress/ImplicitTest.out new file mode 100644 index 00000000000..be39624289b --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/ImplicitTest.out @@ -0,0 +1,2 @@ +ImplicitUse.java:4:12: compiler.warn.has.been.deprecated: pack.Dep, pack +1 warning \ No newline at end of file diff --git a/langtools/test/tools/javac/warnings/suppress/PackageInfo.java b/langtools/test/tools/javac/warnings/suppress/PackageInfo.java new file mode 100644 index 00000000000..98a93102a7c --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/PackageInfo.java @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8021112 + * @summary Verify that deprecated warnings are printed correctly for package-info.java + * @clean pack.package-info pack.DeprecatedClass + * @compile/ref=PackageInfo.out -XDrawDiagnostics -Xlint:deprecation pack/package-info.java pack/DeprecatedClass.java + */ diff --git a/langtools/test/tools/javac/warnings/suppress/PackageInfo.out b/langtools/test/tools/javac/warnings/suppress/PackageInfo.out new file mode 100644 index 00000000000..d1379ce82ab --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/PackageInfo.out @@ -0,0 +1,3 @@ +package-info.java:5:12: compiler.warn.has.been.deprecated: pack.DeprecatedClass, pack +package-info.java:2:2: compiler.warn.has.been.deprecated: pack.DeprecatedClass, pack +2 warnings diff --git a/langtools/test/tools/javac/warnings/suppress/T6480588.java b/langtools/test/tools/javac/warnings/suppress/T6480588.java new file mode 100644 index 00000000000..88af4cca73d --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/T6480588.java @@ -0,0 +1,36 @@ +/** + * @test /nodynamiccopyright/ + * @bug 6470588 + * @summary Verify that \\@SuppressWarnings("deprecation") works OK for all parts + * of class/method/field "header", including (declaration) annotations + * @build VerifySuppressWarnings + * @compile/ref=T6480588.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast T6480588.java + * @run main VerifySuppressWarnings T6480588.java + */ + +@DeprecatedAnnotation +class T6480588 extends DeprecatedClass implements DeprecatedInterface { + @DeprecatedAnnotation + public DeprecatedClass method(DeprecatedClass param) throws DeprecatedClass { + DeprecatedClass lv = new DeprecatedClass(); + @Deprecated + DeprecatedClass lvd = new DeprecatedClass(); + return null; + } + + @Deprecated + public void methodD() { + } + + @DeprecatedAnnotation + DeprecatedClass field = new DeprecatedClass(); + + @DeprecatedAnnotation + class Inner extends DeprecatedClass implements DeprecatedInterface { + } + +} + +@Deprecated class DeprecatedClass extends Throwable { } +@Deprecated interface DeprecatedInterface { } +@Deprecated @interface DeprecatedAnnotation { } diff --git a/langtools/test/tools/javac/warnings/suppress/T6480588.out b/langtools/test/tools/javac/warnings/suppress/T6480588.out new file mode 100644 index 00000000000..6e6f36739f3 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/T6480588.out @@ -0,0 +1,18 @@ +T6480588.java:12:24: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:12:51: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package +T6480588.java:11:2: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package +T6480588.java:14:12: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:14:65: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:13:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package +T6480588.java:14:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:15:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:15:34: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:17:9: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:17:35: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:26:5: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:25:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package +T6480588.java:26:33: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:29:25: compiler.warn.has.been.deprecated: DeprecatedClass, compiler.misc.unnamed.package +T6480588.java:29:52: compiler.warn.has.been.deprecated: DeprecatedInterface, compiler.misc.unnamed.package +T6480588.java:28:6: compiler.warn.has.been.deprecated: DeprecatedAnnotation, compiler.misc.unnamed.package +17 warnings \ No newline at end of file diff --git a/langtools/test/tools/javac/warnings/suppress/T8021112a.java b/langtools/test/tools/javac/warnings/suppress/T8021112a.java new file mode 100644 index 00000000000..4e8b69895fa --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/T8021112a.java @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package test; + +/** + * @test + * @bug 8021112 + * @summary Verify that \\@SuppressWarnings work even if the value is defined + * inside the suppressed class itself, and verify that "unnecessary cast" + * lint can be properly suppressed. + * @compile -Xlint:cast -Werror T8021112a.java + */ + +import static test.T8021112a.D; + +@SuppressWarnings(D) +public class T8021112a { + public static final String D = (String) "cast"; +} + +class Other { + public static final String D = "cast"; + @SuppressWarnings(D) + public static final String D2 = (String) "cast"; +} diff --git a/langtools/test/tools/javac/warnings/suppress/T8021112b.java b/langtools/test/tools/javac/warnings/suppress/T8021112b.java new file mode 100644 index 00000000000..eb391bb1753 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/T8021112b.java @@ -0,0 +1,22 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8021112 + * @summary Verify that \\@SuppressWarnings("unchecked") works correctly for lazy attrib values + * @build VerifySuppressWarnings + * @compile/ref=T8021112b.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast T8021112b.java + * @run main VerifySuppressWarnings T8021112b.java + */ + +public class T8021112b { + public static final String D1 = Dep.D; + public static final String D2 = ""; + public static final Object[] o = { + new Object() { + Dep d; + } + }; +} + +@Deprecated class Dep { + public static final String D = T8021112b.D2; +} diff --git a/langtools/test/tools/javac/warnings/suppress/T8021112b.out b/langtools/test/tools/javac/warnings/suppress/T8021112b.out new file mode 100644 index 00000000000..bc45f324cde --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/T8021112b.out @@ -0,0 +1,3 @@ +T8021112b.java:11:37: compiler.warn.has.been.deprecated: Dep, compiler.misc.unnamed.package +T8021112b.java:15:13: compiler.warn.has.been.deprecated: Dep, compiler.misc.unnamed.package +2 warnings \ No newline at end of file diff --git a/langtools/test/tools/javac/warnings/suppress/TypeAnnotations.java b/langtools/test/tools/javac/warnings/suppress/TypeAnnotations.java new file mode 100644 index 00000000000..58d63bc9bd0 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/TypeAnnotations.java @@ -0,0 +1,51 @@ +/** + * @test /nodynamiccopyright/ + * @bug 8021112 + * @summary Verify that \\@SuppressWarnings("unchecked") works for type annotations + * @build VerifySuppressWarnings + * @compile/ref=TypeAnnotations.out -XDrawDiagnostics -Xlint:unchecked,deprecation,cast TypeAnnotations.java + * @run main VerifySuppressWarnings TypeAnnotations.java + */ + +import java.lang.annotation.*; + +public class TypeAnnotations extends @TA Object implements @TA Runnable { + + public @TA String @TA [] m(@TA String @TA [] p) throws @TA Throwable { + Runnable r = () -> { + @TA Object tested = null; + @TA boolean isAnnotated = tested instanceof @TA String; + }; + + @TA Object tested = null; + @TA boolean isAnnotated = tested instanceof @TA String; + + return (@TA String @TA []) null; + } + + { + Runnable r = () -> { + @TA Object tested = null; + @TA boolean isAnnotated = tested instanceof @TA String; + }; + + @TA Object tested = null; + @TA boolean isAnnotated = tested instanceof @TA String; + + @TA String @TA [] ret = (@TA String @TA []) null; + } + + @TA String @TA [] f = new @TA String @TA[0]; + + @Override public void run() { } + + public static class Inner extends @TA Object implements @TA Runnable { + @Override public void run() { } + } +} + +@Target({ElementType.TYPE_USE, ElementType.TYPE}) +@Deprecated +@interface TA { + +} diff --git a/langtools/test/tools/javac/warnings/suppress/TypeAnnotations.out b/langtools/test/tools/javac/warnings/suppress/TypeAnnotations.out new file mode 100644 index 00000000000..52a5484ea5e --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/TypeAnnotations.out @@ -0,0 +1,41 @@ +TypeAnnotations.java:12:39: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:12:61: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:14:24: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:14:61: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:14:13: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:14:44: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:14:33: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:23:29: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:23:18: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:16:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:17:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:17:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:17:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:20:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:21:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:21:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:21:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:23:18: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:23:29: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:28:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:29:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:29:14: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:29:58: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:32:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:33:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:33:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:33:54: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:35:46: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:35:35: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:35:21: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:35:10: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:35:35: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:35:46: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:38:17: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:38:6: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:38:43: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:38:32: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:38:32: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:42:40: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +TypeAnnotations.java:42:62: compiler.warn.has.been.deprecated: TA, compiler.misc.unnamed.package +40 warnings \ No newline at end of file diff --git a/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java b/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java new file mode 100644 index 00000000000..037f2a1764a --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/VerifySuppressWarnings.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.source.tree.ClassTree; +import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.tree.MethodTree; +import com.sun.source.tree.NewClassTree; +import com.sun.source.tree.Tree; +import com.sun.source.tree.VariableTree; +import com.sun.source.util.JavacTask; +import com.sun.source.util.TreeScanner; +import com.sun.source.util.Trees; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.file.JavacFileManager; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; +import java.io.File; +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import javax.tools.Diagnostic; +import javax.tools.DiagnosticListener; +import javax.tools.FileObject; +import javax.tools.ForwardingJavaFileManager; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.SimpleJavaFileObject; + +/**Takes a source file, parses it once to get the warnings inside the file and + * then for each and every declaration in the file, it tries to place + * the @SuppressWarnings annotation on the declaration and verifies than no + * warnings are produced inside the declaration, but all are produced outside it. + * + * Currently only works with unchecked,deprecation,cast warnings. + */ +public class VerifySuppressWarnings { + + private static final List STANDARD_PARAMS = Arrays.asList("-Xlint:unchecked,deprecation,cast", "-Xjcov"); + + public static void main(String... args) throws IOException, URISyntaxException { + if (args.length != 1) throw new IllegalStateException("Must provide class name!"); + String testContent = null; + List sourcePath = new ArrayList<>(); + for (String sourcePaths : System.getProperty("test.src.path").split(":")) { + sourcePath.add(new File(sourcePaths)); + } + JavacFileManager fm = JavacTool.create().getStandardFileManager(null, null, null); + for (File sp : sourcePath) { + File inp = new File(sp, args[0]); + + if (inp.canRead()) { + testContent = fm.getRegularFile(inp).getCharContent(true).toString(); + } + } + if (testContent == null) throw new IllegalStateException(); + final List> diagnostics = new ArrayList<>(); + DiagnosticListener collectDiagnostics = new DiagnosticListener() { + @Override public void report(Diagnostic diagnostic) { + diagnostics.add(diagnostic); + } + }; + JavaFileObject testFile = new TestFO(new URI("mem://" + args[0]), testContent); + JavacTask task = JavacTool.create().getTask(null, + new TestFM(fm), + collectDiagnostics, + STANDARD_PARAMS, + null, + Arrays.asList(testFile)); + final Trees trees = Trees.instance(task); + final CompilationUnitTree cut = task.parse().iterator().next(); + task.analyze(); + + final List declarationSpans = new ArrayList<>(); + + new TreeScanner() { + @Override public Void visitClass(ClassTree node, Void p) { + handleDeclaration(node); + return super.visitClass(node, p); + } + @Override public Void visitMethod(MethodTree node, Void p) { + handleDeclaration(node); + return super.visitMethod(node, p); + } + @Override public Void visitVariable(VariableTree node, Void p) { + handleDeclaration(node); + return super.visitVariable(node, p); + } + + @Override + public Void visitNewClass(NewClassTree node, Void p) { + if (node.getClassBody() != null) { + scan(node.getClassBody().getMembers(), null); + } + return null; + } + + private void handleDeclaration(Tree node) { + int endPos = (int) trees.getSourcePositions().getEndPosition(cut, node); + + if (endPos == (-1)) { + if (node.getKind() == Tree.Kind.METHOD && (((JCMethodDecl) node).getModifiers().flags & Flags.GENERATEDCONSTR) != 0) { + return ; + } + throw new IllegalStateException(); + } + + declarationSpans.add(new int[] {(int) trees.getSourcePositions().getStartPosition(cut, node), endPos}); + } + }.scan(cut, null); + + for (final int[] declarationSpan : declarationSpans) { + final String suppressWarnings = "@SuppressWarnings({\"deprecation\", \"unchecked\", \"serial\"})"; + final String updatedContent = testContent.substring(0, declarationSpan[0]) + suppressWarnings + testContent.substring(declarationSpan[0]); + final List> foundErrors = new ArrayList<>(diagnostics); + DiagnosticListener verifyDiagnostics = new DiagnosticListener() { + @Override public void report(Diagnostic diagnostic) { + long adjustedPos = diagnostic.getPosition(); + + if (adjustedPos >= declarationSpan[0]) adjustedPos -= suppressWarnings.length(); + + if (declarationSpan[0] <= adjustedPos && adjustedPos <= declarationSpan[1]) { + throw new IllegalStateException("unsuppressed: " + diagnostic.getMessage(null)); + } + + boolean found = false; + + for (Iterator> it = foundErrors.iterator(); it.hasNext();) { + Diagnostic d = it.next(); + if (d.getPosition() == adjustedPos && d.getCode().equals(diagnostic.getCode())) { + it.remove(); + found = true; + break; + } + } + + if (!found) { + throw new IllegalStateException("diagnostic not originally reported: " + diagnostic.getMessage(null)); + } + } + }; + + JavaFileObject updatedFile = new TestFO(new URI("mem://" + args[0]), updatedContent); + JavacTask testTask = JavacTool.create().getTask(null, + new TestFM(fm), + verifyDiagnostics, + STANDARD_PARAMS, + null, + Arrays.asList(updatedFile)); + + testTask.analyze(); + + for (Diagnostic d : foundErrors) { + if (d.getPosition() < declarationSpan[0] || declarationSpan[1] < d.getPosition()) { + throw new IllegalStateException("missing: " + d.getMessage(null)); + } + } + } + } + + private static final class TestFO extends SimpleJavaFileObject { + private final String content; + public TestFO(URI uri, String content) { + super(uri, Kind.SOURCE); + this.content = content; + } + + @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return content; + } + + @Override public boolean isNameCompatible(String simpleName, Kind kind) { + return true; + } + } + + private static final class TestFM extends ForwardingJavaFileManager { + + public TestFM(JavaFileManager fileManager) { + super(fileManager); + } + + @Override + public boolean isSameFile(FileObject a, FileObject b) { + return a.equals(b); + } + + } +} diff --git a/langtools/test/tools/javac/warnings/suppress/pack/DeprecatedClass.java b/langtools/test/tools/javac/warnings/suppress/pack/DeprecatedClass.java new file mode 100644 index 00000000000..8b7a482298e --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/pack/DeprecatedClass.java @@ -0,0 +1,5 @@ +/* /nodynamiccopyright/ */ +package pack; +@Deprecated +@interface DeprecatedClass { +} diff --git a/langtools/test/tools/javac/warnings/suppress/pack/ImplicitMain.java b/langtools/test/tools/javac/warnings/suppress/pack/ImplicitMain.java new file mode 100644 index 00000000000..22ed4e7def8 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/pack/ImplicitMain.java @@ -0,0 +1,14 @@ +/* /nodynamiccopyright/ */ +package pack; + +@SuppressWarnings("deprecation") +public class ImplicitMain { + private Object test() { + return new ImplicitUse(); + } +} + +@Deprecated +class Dep { + +} diff --git a/langtools/test/tools/javac/warnings/suppress/pack/ImplicitUse.java b/langtools/test/tools/javac/warnings/suppress/pack/ImplicitUse.java new file mode 100644 index 00000000000..9e9e6cd5916 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/pack/ImplicitUse.java @@ -0,0 +1,7 @@ +/* /nodynamiccopyright/ */ +package pack; + +import pack.Dep; + +public class ImplicitUse { +} diff --git a/langtools/test/tools/javac/warnings/suppress/pack/package-info.java b/langtools/test/tools/javac/warnings/suppress/pack/package-info.java new file mode 100644 index 00000000000..679de2b4f60 --- /dev/null +++ b/langtools/test/tools/javac/warnings/suppress/pack/package-info.java @@ -0,0 +1,5 @@ +/* /nodynamiccopyright/ */ +@DeprecatedClass +package pack; + +import pack.DeprecatedClass; diff --git a/langtools/test/tools/javadoc/api/basic/APITest.java b/langtools/test/tools/javadoc/api/basic/APITest.java index 358b6b3bc48..439d80c4a26 100644 --- a/langtools/test/tools/javadoc/api/basic/APITest.java +++ b/langtools/test/tools/javadoc/api/basic/APITest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.URI; +import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; import java.util.Arrays; @@ -164,11 +165,13 @@ class APITest { } private void listFiles(Path dir, Set files) throws IOException { - for (Path f: Files.newDirectoryStream(dir)) { - if (Files.isDirectory(f)) - listFiles(f, files); - else if (Files.isRegularFile(f)) - files.add(f); + try (DirectoryStream ds = Files.newDirectoryStream(dir)) { + for (Path f: ds) { + if (Files.isDirectory(f)) + listFiles(f, files); + else if (Files.isRegularFile(f)) + files.add(f); + } } } diff --git a/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java b/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java index 4532e619f9b..d5ab604f6ac 100644 --- a/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java +++ b/langtools/test/tools/javadoc/api/basic/GetTask_FileManagerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,7 @@ /* * @test - * @bug 6493690 + * @bug 6493690 8024434 * @summary javadoc should have a javax.tools.Tool service provider * @build APITest * @run main GetTask_FileManagerTest diff --git a/make/jprt.properties b/make/jprt.properties index b7bad856278..3860e9228ba 100644 --- a/make/jprt.properties +++ b/make/jprt.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -43,8 +43,8 @@ jprt.build.targets= \ linux_i586_2.6-{product|fastdebug}, \ linux_x64_2.6-{product|fastdebug}, \ macosx_x64_10.7-{product|fastdebug}, \ - windows_i586_5.1-{product|fastdebug}, \ - windows_x64_5.2-{product|fastdebug} + windows_i586_6.1-{product|fastdebug}, \ + windows_x64_6.1-{product|fastdebug} # User can select the test set with jprt submit "-testset name" option jprt.my.test.set=${jprt.test.set} @@ -58,8 +58,8 @@ jprt.my.test.target.set= \ linux_i586_2.6-product-{c1|c2}-TESTNAME, \ linux_x64_2.6-product-c2-TESTNAME, \ macosx_x64_10.7-product-c2-TESTNAME, \ - windows_i586_5.1-product-c1-TESTNAME, \ - windows_x64_5.2-product-c2-TESTNAME + windows_i586_6.1-product-c1-TESTNAME, \ + windows_x64_6.1-product-c2-TESTNAME # Default vm test targets (testset=default) jprt.vm.default.test.targets= \ diff --git a/make/scripts/webrev.ksh b/make/scripts/webrev.ksh index 9fef47fa69e..3839b7490f5 100644 --- a/make/scripts/webrev.ksh +++ b/make/scripts/webrev.ksh @@ -27,7 +27,7 @@ # Documentation is available via 'webrev -h'. # -WEBREV_UPDATED=24.0-hg+jbs +WEBREV_UPDATED=24.1-hg+openjdk.java.net HTML=' +# ' # JDK-1234567 my bugid' > .html # # framed_sdiff() is then called which creates $2.frames.html @@ -1476,7 +1476,7 @@ function treestatus # The first and last are simple addition while the middle one # is a move/rename or a copy. We can't distinguish from a rename vs a copy # without also getting the status of removed files. The middle case above - # is a rename if File4 is also shown a being removed. If File4 is not a + # is a rename if File4 is also shown a being removed. If File4 is not a # removed file, then the middle case is a copy from File4 to subdir/File4 # FIXME - we're not distinguishing copy from rename $HGCMD -aC | $FILTER | while read LINE; do @@ -1644,7 +1644,7 @@ function flist_from_mercurial # The first and last are simple addition while the middle one # is a move/rename or a copy. We can't distinguish from a rename vs a copy # without also getting the status of removed files. The middle case above - # is a rename if File4 is also shown a being removed. If File4 is not a + # is a rename if File4 is also shown a being removed. If File4 is not a # removed file, then the middle case is a copy from File4 to subdir/File4 # FIXME - we're not distinguishing copy from rename @@ -2529,7 +2529,7 @@ print " Output to: $WDIR" # Bug IDs will be replaced by a URL. Order of precedence # is: default location, $WEBREV_BUGURL, the -O flag. # -BUGURL='https://jbs.oracle.com/bugs/browse/' +BUGURL='https://bugs.openjdk.java.net/browse/' [[ -n $WEBREV_BUGURL ]] && BUGURL="$WEBREV_BUGURL" if [[ -n "$Oflag" ]]; then CRID=`echo $CRID | sed -e 's/JDK-//'` @@ -3056,7 +3056,7 @@ if [[ -n $CRID ]]; then for id in $CRID do if [[ -z "$Oflag" ]]; then - #add "JDK-" to raw bug id for jbs links. + #add "JDK-" to raw bug id for openjdk.java.net links. id=`echo ${id} | sed 's/^\([0-9]\{5,\}\)$/JDK-\1/'` fi print "

    Error Summary " + + "
    ErrorDescription
    " + + "ClassError" + - "UsedInC 
    Bug id:" diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 0cc3a707a66..f56727e2010 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -216,3 +216,6 @@ e966ff0a3ffef8a687eaf5a14167bb595b623d02 jdk8-b102 afc100513451d22f0b8135999d6eb52f36df3d36 jdk8-b104 f484bfb624dd06683cb33b524700a5dd4927a82b jdk8-b105 bf70cbd2c8369fd97ffdfcbe1a80dbc2797408ee jdk8-b106 +f35e1255024b66f7cf82517798f45f6e194e5567 jdk8-b107 +445ad3f6d3b4ba62ebc483323e1919110a304053 jdk8-b108 +6ec2f9e5ed5bd60c2900976e6a54fdcac2f37e9e jdk8-b109 diff --git a/nashorn/make/build-benchmark.xml b/nashorn/make/build-benchmark.xml index f1ce180a844..8f2296b028e 100644 --- a/nashorn/make/build-benchmark.xml +++ b/nashorn/make/build-benchmark.xml @@ -329,7 +329,7 @@ fork="true" dir="."> - + @@ -357,7 +357,7 @@ classpath="${run.test.classpath}" fork="true" dir="."> - + @@ -391,7 +391,7 @@ fork="true" dir="."> - + @@ -415,7 +415,7 @@ classpath="${run.test.classpath}" fork="true" dir="."> - + diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 9a31be88592..4bc1a398b4d 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -66,6 +66,8 @@ + + @@ -230,6 +232,10 @@ + + + + @@ -238,6 +244,7 @@ + @@ -264,6 +271,13 @@ grant codeBase "file:/${basedir}/test/script/basic/*" { permission java.util.PropertyPermission "nashorn.test.*", "read"; }; +grant codeBase "file:/${basedir}/test/script/basic/parser/*" { + permission java.io.FilePermission "${basedir}/test/script/-", "read"; + permission java.io.FilePermission "$${user.dir}", "read"; + permission java.util.PropertyPermission "user.dir", "read"; + permission java.util.PropertyPermission "nashorn.test.*", "read"; +}; + grant codeBase "file:/${basedir}/test/script/basic/JDK-8010946-privileged.js" { permission java.util.PropertyPermission "java.security.policy", "read"; }; @@ -308,7 +322,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" { - + @@ -324,7 +338,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" { - + @@ -340,7 +354,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" { - + @@ -357,7 +371,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" { - + @@ -375,7 +389,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" { description="Run the shell with a sample script"> - + @@ -385,7 +399,7 @@ grant codeBase "file:/${basedir}/test/script/basic/classloader.js" { description="Debug the shell with a sample script"> - + diff --git a/nashorn/make/project.properties b/nashorn/make/project.properties index 5523f6cbab8..e6eea02eaa9 100644 --- a/nashorn/make/project.properties +++ b/nashorn/make/project.properties @@ -216,13 +216,14 @@ run.test.classpath=\ src.dir=src test.src.dir=test/src +# -Xmx is used for all tests, -Xms only for octane benchmark run.test.xmx=3G run.test.xms=2G run.test.user.language=tr run.test.user.country=TR -run.test.jvmargs.common=-server -Xmx${run.test.xmx} -XX:+TieredCompilation -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} -XX:+HeapDumpOnOutOfMemoryError +run.test.jvmargs.common=-server -XX:+TieredCompilation -Dfile.encoding=UTF-8 -Duser.language=${run.test.user.language} -Duser.country=${run.test.user.country} -XX:+HeapDumpOnOutOfMemoryError #-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M # -XX:+PrintCompilation -XX:+UnlockDiagnosticVMOptions -XX:+PrintNMethods @@ -231,12 +232,12 @@ run.test.jvmargs.common=-server -Xmx${run.test.xmx} -XX:+TieredCompilation -Dfil run.test.jvmargs.main=${run.test.jvmargs.common} -ea #-XX:-UseCompressedKlassPointers -XX:+PrintHeapAtGC -XX:ClassMetaspaceSize=300M -run.test.jvmargs.octane.main=-Xms${run.test.xms} ${run.test.jvmargs.common} +run.test.jvmargs.octane.main=${run.test.jvmargs.common} run.test.jvmsecurityargs=-Xverify:all -Djava.security.properties=${basedir}/make/java.security.override -Djava.security.manager -Djava.security.policy=${basedir}/build/nashorn.policy # VM options for script tests with @fork option -test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} ${run.test.jvmsecurityargs} +test-sys-prop.test.fork.jvm.options=${run.test.jvmargs.main} -Xmx${run.test.xmx} ${run.test.jvmsecurityargs} # path of rhino.jar for benchmarks rhino.jar= diff --git a/nashorn/src/jdk/nashorn/api/scripting/JSObject.java b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java index 4f3a8e88f93..53b5790ee3e 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/JSObject.java +++ b/nashorn/src/jdk/nashorn/api/scripting/JSObject.java @@ -25,73 +25,210 @@ package jdk.nashorn.api.scripting; +import java.util.Collection; +import java.util.Collections; +import java.util.Set; + /** - * netscape.javascript.JSObject-like interface for nashorn script objects. + * This is the base class for nashorn ScriptObjectMirror class. + * + * 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 + * to appropriate method call of this class. */ public abstract class JSObject { /** - * Call a JavaScript function + * Call this object as a JavaScript function. This is equivalent to + * 'func.apply(thiz, args)' in JavaScript. * - * @param functionName name of function + * @param thiz 'this' object to be passed to the function * @param args arguments to method * @return result of call */ - public abstract Object call(String functionName, Object... args); + public Object call(Object thiz, Object... args) { + throw new UnsupportedOperationException("call"); + } /** - * Call a JavaScript method as a constructor. This is equivalent to - * calling new obj.Method(arg1, arg2...) in JavaScript. + * Call this 'constructor' JavaScript function to create a new object. + * This is equivalent to 'new func(arg1, arg2...)' in JavaScript. * - * @param functionName name of function * @param args arguments to method * @return result of constructor call */ - public abstract Object newObject(String functionName, Object... args); + public Object newObject(Object... args) { + throw new UnsupportedOperationException("newObject"); + } /** - * Evaluate a JavaScript expression + * Evaluate a JavaScript expression. * * @param s JavaScript expression to evaluate * @return evaluation result */ - public abstract Object eval(String s); + public Object eval(String s) { + throw new UnsupportedOperationException("eval"); + } /** - * Retrieves a named member of a JavaScript object. + * Call a JavaScript function member of this object. + * + * @param name name of the member function to call + * @param args arguments to be passed to the member function + * @return result of call + */ + public Object callMember(String name, Object... args) { + throw new UnsupportedOperationException("call"); + } + + /** + * Retrieves a named member of this JavaScript object. * * @param name of member * @return member */ - public abstract Object getMember(String name); + public Object getMember(String name) { + return null; + } /** - * Retrieves an indexed member of a JavaScript object. + * Retrieves an indexed member of this JavaScript object. * - * @param index index of member slot + * @param index index slot to retrieve * @return member */ - public abstract Object getSlot(int index); + public Object getSlot(int index) { + return null; + } /** - * Remove a named member from a JavaScript object + * Does this object have a named member? * * @param name name of member + * @return true if this object has a member of the given name */ - public abstract void removeMember(String name); + public boolean hasMember(String name) { + return false; + } /** - * Set a named member in a JavaScript object + * Does this object have a indexed property? * - * @param name name of member - * @param value value of member + * @param slot index to check + * @return true if this object has a slot */ - public abstract void setMember(String name, Object value); + public boolean hasSlot(int slot) { + return false; + } /** - * Set an indexed member in a JavaScript object + * Remove a named member from this JavaScript object * - * @param index index of member slot - * @param value value of member + * @param name name of the member */ - public abstract void setSlot(int index, Object value); + public void removeMember(String name) { + } + + /** + * Set a named member in this JavaScript object + * + * @param name name of the member + * @param value value of the member + */ + public void setMember(String name, Object value) { + } + + /** + * Set an indexed member in this JavaScript object + * + * @param index index of the member slot + * @param value value of the member + */ + public void setSlot(int index, Object value) { + } + + // property and value iteration + + /** + * Returns the set of all property names of this object. + * + * @return set of property names + */ + @SuppressWarnings("unchecked") + public Set keySet() { + return Collections.EMPTY_SET; + } + + /** + * Returns the set of all property values of this object. + * + * @return set of property values. + */ + @SuppressWarnings("unchecked") + public Collection values() { + return Collections.EMPTY_SET; + } + + // JavaScript instanceof check + + /** + * Checking whether the given object is an instance of 'this' object. + * + * @param instance instace to check + * @return true if the given 'instance' is an instance of this 'function' object + */ + 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' + */ + public boolean isInstanceOf(final Object clazz) { + if (clazz instanceof JSObject) { + return ((JSObject)clazz).isInstance(this); + } + + return false; + } + + /** + * ECMA [[Class]] property + * + * @return ECMA [[Class]] property value of this object + */ + public String getClassName() { + return getClass().getName(); + } + + /** + * Is this a function object? + * + * @return if this mirror wraps a ECMAScript function instance + */ + public boolean isFunction() { + return false; + } + + /** + * Is this a 'use strict' function object? + * + * @return true if this mirror represents a ECMAScript 'use strict' function + */ + public boolean isStrictFunction() { + return false; + } + + /** + * Is this an array object? + * + * @return if this mirror wraps a ECMAScript array object + */ + public boolean isArray() { + return false; + } } diff --git a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java index 9745d432783..4629665f98b 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java @@ -185,21 +185,12 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C @Override public Object eval(final Reader reader, final ScriptContext ctxt) throws ScriptException { - try { - if (reader instanceof URLReader) { - final URL url = ((URLReader)reader).getURL(); - final Charset cs = ((URLReader)reader).getCharset(); - return evalImpl(compileImpl(new Source(url.toString(), url, cs), ctxt), ctxt); - } - return evalImpl(Source.readFully(reader), ctxt); - } catch (final IOException e) { - throw new ScriptException(e); - } + return evalImpl(makeSource(reader, ctxt), ctxt); } @Override public Object eval(final String script, final ScriptContext ctxt) throws ScriptException { - return evalImpl(script.toCharArray(), ctxt); + return evalImpl(makeSource(script, ctxt), ctxt); } @Override @@ -221,16 +212,12 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C @Override public CompiledScript compile(final Reader reader) throws ScriptException { - try { - return asCompiledScript(compileImpl(Source.readFully(reader), context)); - } catch (final IOException e) { - throw new ScriptException(e); - } + return asCompiledScript(makeSource(reader, context)); } @Override public CompiledScript compile(final String str) throws ScriptException { - return asCompiledScript(compileImpl(str.toCharArray(), context)); + return asCompiledScript(makeSource(str, context)); } // Invocable methods @@ -292,6 +279,29 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C // Implementation only below this point + private static Source makeSource(final Reader reader, final ScriptContext ctxt) throws ScriptException { + try { + if (reader instanceof URLReader) { + final URL url = ((URLReader)reader).getURL(); + final Charset cs = ((URLReader)reader).getCharset(); + return new Source(url.toString(), url, cs); + } else { + return new Source(getScriptName(ctxt), Source.readFully(reader)); + } + } catch (final IOException ioExp) { + throw new ScriptException(ioExp); + } + } + + private static Source makeSource(final String src, final ScriptContext ctxt) { + return new Source(getScriptName(ctxt), src); + } + + private static String getScriptName(final ScriptContext ctxt) { + final Object val = ctxt.getAttribute(ScriptEngine.FILENAME); + return (val != null) ? val.toString() : ""; + } + private T getInterfaceInner(final Object thiz, final Class clazz) { if (clazz == null || !clazz.isInterface()) { throw new IllegalArgumentException(getMessage("interface.class.expected")); @@ -315,7 +325,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C final ScriptObjectMirror mirror = (ScriptObjectMirror)thiz; realSelf = mirror.getScriptObject(); realGlobal = mirror.getHomeGlobal(); - if (! realGlobal.isOfContext(nashornContext)) { + if (! isOfContext(realGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } } else if (thiz instanceof ScriptObject) { @@ -326,7 +336,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); } - if (! realGlobal.isOfContext(nashornContext)) { + if (! isOfContext(realGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } } @@ -394,7 +404,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C // Retrieve nashorn Global object from a given ScriptObjectMirror private ScriptObject globalFromMirror(final ScriptObjectMirror mirror) { ScriptObject sobj = mirror.getScriptObject(); - if (sobj instanceof GlobalObject && sobj.isOfContext(nashornContext)) { + if (sobj instanceof GlobalObject && isOfContext(sobj, nashornContext)) { return sobj; } @@ -429,7 +439,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C // current ScriptContext exposed as "context" // "context" is non-writable from script - but script engine still // needs to set it and so save the context Property object - contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, null); + contextProperty = newGlobal.addOwnProperty("context", NON_ENUMERABLE_CONSTANT, ctxt); // current ScriptEngine instance exposed as "engine". We added @SuppressWarnings("LeakingThisInConstructor") as // NetBeans identifies this assignment as such a leak - this is a false positive as we're setting this property // in the Global of a Context we just created - both the Context and the Global were just created and can not be @@ -470,7 +480,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C ScriptObjectMirror selfMirror = null; if (selfObject instanceof ScriptObjectMirror) { selfMirror = (ScriptObjectMirror)selfObject; - if (! selfMirror.getHomeGlobal().isOfContext(nashornContext)) { + if (! isOfContext(selfMirror.getHomeGlobal(), nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } } else if (selfObject instanceof ScriptObject) { @@ -481,7 +491,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C throw new IllegalArgumentException(getMessage("no.current.nashorn.global")); } - if (! oldGlobal.isOfContext(nashornContext)) { + if (! isOfContext(oldGlobal, nashornContext)) { throw new IllegalArgumentException(getMessage("script.object.from.another.engine")); } @@ -494,7 +504,7 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C if (selfMirror != null) { try { - return ScriptObjectMirror.translateUndefined(selfMirror.call(name, args)); + return ScriptObjectMirror.translateUndefined(selfMirror.callMember(name, args)); } catch (final Exception e) { final Throwable cause = e.getCause(); if (cause instanceof NoSuchMethodException) { @@ -509,8 +519,8 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C throw new IllegalArgumentException(getMessage("interface.on.non.script.object")); } - private Object evalImpl(final char[] buf, final ScriptContext ctxt) throws ScriptException { - return evalImpl(compileImpl(buf, ctxt), ctxt); + private Object evalImpl(final Source src, final ScriptContext ctxt) throws ScriptException { + return evalImpl(compileImpl(src, ctxt), ctxt); } private Object evalImpl(final ScriptFunction script, final ScriptContext ctxt) throws ScriptException { @@ -561,11 +571,20 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } } - private CompiledScript asCompiledScript(final ScriptFunction script) { + private CompiledScript asCompiledScript(final Source source) throws ScriptException { + final ScriptFunction func = compileImpl(source, context); return new CompiledScript() { @Override public Object eval(final ScriptContext ctxt) throws ScriptException { - return evalImpl(script, ctxt); + final ScriptObject global = getNashornGlobalFrom(ctxt); + // Are we running the script in the correct global? + if (func.getScope() == global) { + return evalImpl(func, ctxt, global); + } else { + // ScriptContext with a different global. Compile again! + // Note that we may still hit per-global compilation cache. + return evalImpl(compileImpl(source, ctxt), ctxt, global); + } } @Override public ScriptEngine getEngine() { @@ -574,12 +593,6 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C }; } - private ScriptFunction compileImpl(final char[] buf, final ScriptContext ctxt) throws ScriptException { - final Object val = ctxt.getAttribute(ScriptEngine.FILENAME); - final String fileName = (val != null) ? val.toString() : ""; - return compileImpl(new Source(fileName, buf), ctxt); - } - private ScriptFunction compileImpl(final Source source, final ScriptContext ctxt) throws ScriptException { return compileImpl(source, getNashornGlobalFrom(ctxt)); } @@ -617,4 +630,9 @@ public final class NashornScriptEngine extends AbstractScriptEngine implements C } return true; } + + private static boolean isOfContext(final ScriptObject global, final Context context) { + assert global instanceof GlobalObject: "Not a Global object"; + return ((GlobalObject)global).isOfContext(context); + } } diff --git a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java index 99ce73c1ca1..3a27d23e303 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java +++ b/nashorn/src/jdk/nashorn/api/scripting/ScriptObjectMirror.java @@ -42,14 +42,13 @@ import java.util.Set; import java.util.concurrent.Callable; import javax.script.Bindings; import jdk.nashorn.internal.runtime.Context; +import jdk.nashorn.internal.runtime.GlobalObject; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptObject; import jdk.nashorn.internal.runtime.ScriptRuntime; /** - * Mirror object that wraps a given ScriptObject instance. User can - * access ScriptObject via the javax.script.Bindings interface or - * netscape.javascript.JSObject interface. + * Mirror object that wraps a given Nashorn Script object. */ public final class ScriptObjectMirror extends JSObject implements Bindings { private static AccessControlContext getContextAccCtxt() { @@ -62,6 +61,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { private final ScriptObject sobj; private final ScriptObject global; + private final boolean strict; @Override public boolean equals(final Object other) { @@ -88,8 +88,9 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { } // JSObject methods + @Override - public Object call(final String functionName, final Object... args) { + public Object call(final Object thiz, final Object... args) { final ScriptObject oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != global); @@ -98,15 +99,13 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { Context.setGlobal(global); } - final Object val = functionName == null? sobj : sobj.get(functionName); - if (val instanceof ScriptFunction) { + if (sobj instanceof ScriptFunction) { final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - return wrap(ScriptRuntime.checkAndApply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); - } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) { - return ((ScriptObjectMirror)val).call(null, args); + final Object self = globalChanged? wrap(thiz, oldGlobal) : thiz; + return wrap(ScriptRuntime.apply((ScriptFunction)sobj, unwrap(self, global), unwrapArray(modArgs, global)), global); } - throw new NoSuchMethodException("No such function " + ((functionName != null)? functionName : "")); + throw new RuntimeException("not a function: " + toString()); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { @@ -119,7 +118,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { } @Override - public Object newObject(final String functionName, final Object... args) { + public Object newObject(final Object... args) { final ScriptObject oldGlobal = Context.getGlobal(); final boolean globalChanged = (oldGlobal != global); @@ -128,15 +127,12 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { Context.setGlobal(global); } - final Object val = functionName == null? sobj : sobj.get(functionName); - if (val instanceof ScriptFunction) { + if (sobj instanceof ScriptFunction) { final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; - return wrap(ScriptRuntime.checkAndConstruct((ScriptFunction)val, unwrapArray(modArgs, global)), global); - } else if (val instanceof ScriptObjectMirror && ((ScriptObjectMirror)val).isFunction()) { - return ((ScriptObjectMirror)val).newObject(null, args); + return wrap(ScriptRuntime.construct((ScriptFunction)sobj, unwrapArray(modArgs, global)), global); } - throw new RuntimeException("not a constructor " + ((functionName != null)? functionName : "")); + throw new RuntimeException("not a constructor: " + toString()); } catch (final RuntimeException | Error e) { throw e; } catch (final Throwable t) { @@ -165,8 +161,40 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { }); } + @Override + public Object callMember(final String functionName, final Object... args) { + functionName.getClass(); // null check + final ScriptObject oldGlobal = Context.getGlobal(); + final boolean globalChanged = (oldGlobal != global); + + try { + if (globalChanged) { + Context.setGlobal(global); + } + + final Object val = sobj.get(functionName); + if (val instanceof ScriptFunction) { + final Object[] modArgs = globalChanged? wrapArray(args, oldGlobal) : args; + return wrap(ScriptRuntime.apply((ScriptFunction)val, sobj, unwrapArray(modArgs, global)), global); + } else if (val instanceof JSObject && ((JSObject)val).isFunction()) { + return ((JSObject)val).call(sobj, args); + } + + throw new NoSuchMethodException("No such function " + functionName); + } catch (final RuntimeException | Error e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } finally { + if (globalChanged) { + Context.setGlobal(oldGlobal); + } + } + } + @Override public Object getMember(final String name) { + name.getClass(); return inGlobal(new Callable() { @Override public Object call() { return wrap(sobj.get(name), global); @@ -183,13 +211,34 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { }); } + @Override + public boolean hasMember(final String name) { + name.getClass(); + return inGlobal(new Callable() { + @Override public Boolean call() { + return sobj.has(name); + } + }); + } + + @Override + public boolean hasSlot(final int slot) { + return inGlobal(new Callable() { + @Override public Boolean call() { + return sobj.has(slot); + } + }); + } + @Override public void removeMember(final String name) { + name.getClass(); remove(name); } @Override public void setMember(final String name, final Object value) { + name.getClass(); put(name, value); } @@ -197,19 +246,58 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { public void setSlot(final int index, final Object value) { inGlobal(new Callable() { @Override public Void call() { - sobj.set(index, unwrap(value, global), global.isStrictContext()); + sobj.set(index, unwrap(value, global), strict); return null; } }); } + @Override + public boolean isInstance(final Object obj) { + if (! (obj instanceof ScriptObjectMirror)) { + return false; + } + + final ScriptObjectMirror instance = (ScriptObjectMirror)obj; + // if not belongs to my global scope, return false + if (global != instance.global) { + return false; + } + + return inGlobal(new Callable() { + @Override public Boolean call() { + return sobj.isInstance(instance.sobj); + } + }); + } + + @Override + public String getClassName() { + return sobj.getClassName(); + } + + @Override + public boolean isFunction() { + return sobj instanceof ScriptFunction; + } + + @Override + public boolean isStrictFunction() { + return isFunction() && ((ScriptFunction)sobj).isStrict(); + } + + @Override + public boolean isArray() { + return sobj.isArray(); + } + // javax.script.Bindings methods @Override public void clear() { inGlobal(new Callable() { @Override public Object call() { - sobj.clear(); + sobj.clear(strict); return null; } }); @@ -292,7 +380,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { return inGlobal(new Callable() { @Override public Object call() { final Object modValue = globalChanged? wrap(value, oldGlobal) : value; - return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global)), global)); + return translateUndefined(wrap(sobj.put(key, unwrap(modValue, global), strict), global)); } }); } @@ -303,7 +391,6 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { final boolean globalChanged = (oldGlobal != global); inGlobal(new Callable() { @Override public Object call() { - final boolean strict = global.isStrictContext(); for (final Map.Entry entry : map.entrySet()) { final Object value = entry.getValue(); final Object modValue = globalChanged? wrap(value, oldGlobal) : value; @@ -318,7 +405,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { public Object remove(final Object key) { return inGlobal(new Callable() { @Override public Object call() { - return wrap(sobj.remove(unwrap(key, global)), global); + return wrap(sobj.remove(unwrap(key, global), strict), global); } }); } @@ -333,7 +420,7 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { public boolean delete(final Object key) { return inGlobal(new Callable() { @Override public Boolean call() { - return sobj.delete(unwrap(key, global)); + return sobj.delete(unwrap(key, global), strict); } }); } @@ -390,15 +477,6 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { }); } - /** - * ECMA [[Class]] property - * - * @return ECMA [[Class]] property value of this object - */ - public String getClassName() { - return sobj.getClassName(); - } - /** * ECMA 8.12.1 [[GetOwnProperty]] (P) * @@ -505,55 +583,6 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { }); } - // ECMAScript instanceof check - - /** - * Checking whether a script object is an instance of another by - * walking the proto chain - * - * @param instance instace to check - * @return true if 'instance' is an instance of this object - */ - public boolean isInstance(final ScriptObjectMirror instance) { - // if not belongs to my global scope, return false - if (instance == null || global != instance.global) { - return false; - } - - return inGlobal(new Callable() { - @Override public Boolean call() { - return sobj.isInstance(instance.sobj); - } - }); - } - - /** - * is this a function object? - * - * @return if this mirror wraps a ECMAScript function instance - */ - public boolean isFunction() { - return sobj instanceof ScriptFunction; - } - - /** - * is this a 'use strict' function object? - * - * @return true if this mirror represents a ECMAScript 'use strict' function - */ - public boolean isStrictFunction() { - return isFunction() && ((ScriptFunction)sobj).isStrict(); - } - - /** - * is this an array object? - * - * @return if this mirror wraps a ECMAScript array object - */ - public boolean isArray() { - return sobj.isArray(); - } - /** * Utility to check if given object is ECMAScript undefined value * @@ -637,10 +666,11 @@ public final class ScriptObjectMirror extends JSObject implements Bindings { ScriptObjectMirror(final ScriptObject sobj, final ScriptObject global) { assert sobj != null : "ScriptObjectMirror on null!"; - assert global != null : "null global for ScriptObjectMirror!"; + assert global instanceof GlobalObject : "global is not a GlobalObject"; this.sobj = sobj; this.global = global; + this.strict = ((GlobalObject)global).isStrictContext(); } // accessors for script engine diff --git a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java index 294300626d2..55355c3efc8 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/Attr.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/Attr.java @@ -26,6 +26,7 @@ package jdk.nashorn.internal.codegen; import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; +import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR; import static jdk.nashorn.internal.codegen.CompilerConstants.CALLEE; import static jdk.nashorn.internal.codegen.CompilerConstants.EXCEPTION_PREFIX; import static jdk.nashorn.internal.codegen.CompilerConstants.ITERATOR_PREFIX; @@ -172,7 +173,9 @@ final class Attr extends NodeOperatorVisitor { initCompileConstant(VARARGS, body, IS_PARAM | IS_INTERNAL); if (functionNode.needsArguments()) { initCompileConstant(ARGUMENTS, body, IS_VAR | IS_INTERNAL | IS_ALWAYS_DEFINED); - addLocalDef(ARGUMENTS.symbolName()); + final String argumentsName = ARGUMENTS_VAR.symbolName(); + newType(defineSymbol(body, argumentsName, IS_VAR | IS_ALWAYS_DEFINED), Type.typeFor(ARGUMENTS_VAR.type())); + addLocalDef(argumentsName); } } @@ -491,30 +494,29 @@ final class Attr extends NodeOperatorVisitor { objectifySymbols(body); } + List syntheticInitializers = null; + if (body.getFlag(Block.NEEDS_SELF_SYMBOL)) { - final IdentNode callee = compilerConstant(CALLEE); - VarNode selfInit = - new VarNode( - newFunctionNode.getLineNumber(), - newFunctionNode.getToken(), - newFunctionNode.getFinish(), - newFunctionNode.getIdent(), - callee); + syntheticInitializers = new ArrayList<>(2); + LOG.info("Accepting self symbol init for ", newFunctionNode.getName()); + // "var fn = :callee" + syntheticInitializers.add(createSyntheticInitializer(newFunctionNode.getIdent(), CALLEE, newFunctionNode)); + } - LOG.info("Accepting self symbol init ", selfInit, " for ", newFunctionNode.getName()); + if(newFunctionNode.needsArguments()) { + if(syntheticInitializers == null) { + syntheticInitializers = new ArrayList<>(1); + } + // "var arguments = :arguments" + syntheticInitializers.add(createSyntheticInitializer(createImplicitIdentifier(ARGUMENTS_VAR.symbolName()), + ARGUMENTS, newFunctionNode)); + } - final List newStatements = new ArrayList<>(); - assert callee.getSymbol() != null && callee.getSymbol().hasSlot(); - - final IdentNode name = selfInit.getName(); - final Symbol nameSymbol = body.getExistingSymbol(name.getName()); - - assert nameSymbol != null; - - selfInit = selfInit.setName((IdentNode)name.setSymbol(lc, nameSymbol)); - - newStatements.add(selfInit); - newStatements.addAll(body.getStatements()); + if(syntheticInitializers != null) { + final List stmts = body.getStatements(); + final List newStatements = new ArrayList<>(stmts.size() + syntheticInitializers.size()); + newStatements.addAll(syntheticInitializers); + newStatements.addAll(stmts); newFunctionNode = newFunctionNode.setBody(lc, body.setStatements(lc, newStatements)); } @@ -533,6 +535,28 @@ final class Attr extends NodeOperatorVisitor { return newFunctionNode; } + /** + * Creates a synthetic initializer for a variable (a var statement that doesn't occur in the source code). Typically + * used to create assignmnent of {@code :callee} to the function name symbol in self-referential function + * expressions as well as for assignment of {@code :arguments} to {@code arguments}. + * + * @param name the ident node identifying the variable to initialize + * @param initConstant the compiler constant it is initialized to + * @param fn the function node the assignment is for + * @return a var node with the appropriate assignment + */ + private VarNode createSyntheticInitializer(final IdentNode name, final CompilerConstants initConstant, final FunctionNode fn) { + final IdentNode init = compilerConstant(initConstant); + assert init.getSymbol() != null && init.getSymbol().hasSlot(); + + VarNode synthVar = new VarNode(fn.getLineNumber(), fn.getToken(), fn.getFinish(), name, init); + + final Symbol nameSymbol = fn.getBody().getExistingSymbol(name.getName()); + assert nameSymbol != null; + + return synthVar.setName((IdentNode)name.setSymbol(lc, nameSymbol)); + } + @Override public Node leaveCONVERT(final UnaryNode unaryNode) { assert false : "There should be no convert operators in IR during Attribution"; @@ -783,9 +807,11 @@ final class Attr extends NodeOperatorVisitor { type = Type.OBJECT; } - type = Type.widest(type, newCaseNode.getTest().getType()); - if (type.isBoolean()) { + final Type newCaseType = newCaseNode.getTest().getType(); + if (newCaseType.isBoolean()) { type = Type.OBJECT; //booleans and integers aren't assignment compatible + } else { + type = Type.widest(type, newCaseType); } } @@ -886,10 +912,9 @@ final class Attr extends NodeOperatorVisitor { @Override public Node leaveDECINC(final UnaryNode unaryNode) { // @see assignOffset - final UnaryNode newUnaryNode = unaryNode.setRHS(ensureAssignmentSlots(unaryNode.rhs())); final Type type = arithType(); - newType(newUnaryNode.rhs().getSymbol(), type); - return end(ensureSymbol(type, newUnaryNode)); + newType(unaryNode.rhs().getSymbol(), type); + return end(ensureSymbol(type, unaryNode)); } @Override @@ -975,15 +1000,18 @@ final class Attr extends NodeOperatorVisitor { } private IdentNode compilerConstant(CompilerConstants cc) { - final FunctionNode functionNode = lc.getCurrentFunction(); - return (IdentNode) - new IdentNode( - functionNode.getToken(), - functionNode.getFinish(), - cc.symbolName()). - setSymbol( - lc, - functionNode.compilerConstant(cc)); + return (IdentNode)createImplicitIdentifier(cc.symbolName()).setSymbol(lc, lc.getCurrentFunction().compilerConstant(cc)); + } + + /** + * Creates an ident node for an implicit identifier within the function (one not declared in the script source + * code). These identifiers are defined with function's token and finish. + * @param name the name of the identifier + * @return an ident node representing the implicit identifier. + */ + private IdentNode createImplicitIdentifier(final String name) { + final FunctionNode fn = lc.getCurrentFunction(); + return new IdentNode(fn.getToken(), fn.getFinish(), name); } @Override @@ -1574,39 +1602,6 @@ final class Attr extends NodeOperatorVisitor { return newInternal(lc.getCurrentFunction().uniqueName(EXCEPTION_PREFIX.symbolName()), Type.typeFor(EXCEPTION_PREFIX.type())); } - /** - * In an assignment, recursively make sure that there are slots for - * everything that has to be laid out as temporary storage, which is the - * case if we are assign-op:ing a BaseNode subclass. This has to be - * recursive to handle things like multi dimensional arrays as lhs - * - * see NASHORN-258 - * - * @param assignmentDest the destination node of the assignment, e.g. lhs for binary nodes - */ - private Expression ensureAssignmentSlots(final Expression assignmentDest) { - final LexicalContext attrLexicalContext = lc; - return (Expression)assignmentDest.accept(new NodeVisitor(new LexicalContext()) { - @Override - public Node leaveIndexNode(final IndexNode indexNode) { - assert indexNode.getSymbol().isTemp(); - final Expression index = indexNode.getIndex(); - //only temps can be set as needing slots. the others will self resolve - //it is illegal to take a scope var and force it to be a slot, that breaks - Symbol indexSymbol = index.getSymbol(); - if (indexSymbol.isTemp() && !indexSymbol.isConstant() && !indexSymbol.hasSlot()) { - if(indexSymbol.isShared()) { - indexSymbol = temporarySymbols.createUnshared(indexSymbol); - } - indexSymbol.setNeedsSlot(true); - attrLexicalContext.getCurrentBlock().putSymbol(attrLexicalContext, indexSymbol); - return indexNode.setIndex(index.setSymbol(attrLexicalContext, indexSymbol)); - } - return indexNode; - } - }); - } - /** * Return the type that arithmetic ops should use. Until we have implemented better type * analysis (range based) or overflow checks that are fast enough for int arithmetic, @@ -1704,7 +1699,7 @@ final class Attr extends NodeOperatorVisitor { newType(lhs.getSymbol(), destType); //may not narrow if dest is already wider than destType // ensureSymbol(destType, binaryNode); //for OP= nodes, the node can carry a narrower types than its lhs rhs. This is perfectly fine - return end(ensureSymbol(destType, ensureAssignmentSlots(binaryNode))); + return end(ensureSymbol(destType, binaryNode)); } private Expression ensureSymbol(final Type type, final Expression expr) { diff --git a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java index 0ccc8a40489..d16a1e5ba1f 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -852,7 +852,6 @@ final class CodeGenerator extends NodeOperatorVisitor values = new ArrayList<>(); boolean hasGettersSetters = false; + Expression protoNode = null; for (PropertyNode propertyNode: elements) { final Expression value = propertyNode.getValue(); @@ -1369,6 +1369,9 @@ final class CodeGenerator extends NodeOperatorVisitor * * @return true if can have callsite type */ diff --git a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java index 3c0046c0879..97e7ca54fc1 100644 --- a/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java +++ b/nashorn/src/jdk/nashorn/internal/ir/WhileNode.java @@ -79,13 +79,12 @@ public final class WhileNode extends LoopNode { if (visitor.enterWhileNode(this)) { if (isDoWhile()) { return visitor.leaveWhileNode( - setTest(lc, (Expression)test.accept(visitor)). - setBody(lc, (Block)body.accept(visitor))); + setBody(lc, (Block)body.accept(visitor)). + setTest(lc, (Expression)test.accept(visitor))); } return visitor.leaveWhileNode( - setBody(lc, (Block)body.accept(visitor)). - setTest(lc, (Expression)test.accept(visitor))); - + setTest(lc, (Expression)test.accept(visitor)). + setBody(lc, (Block)body.accept(visitor))); } return this; } diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java index be4d49b444a..4702057a34c 100644 --- a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java +++ b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java @@ -27,6 +27,7 @@ package jdk.nashorn.internal.ir.debug; import java.util.Arrays; import java.util.List; +import java.util.ArrayList; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.ir.AccessNode; import jdk.nashorn.internal.ir.BinaryNode; @@ -197,10 +198,10 @@ public final class JSONWriter extends NodeVisitor { comma(); final IdentNode label = breakNode.getLabel(); + property("label"); if (label != null) { - property("label", label.getName()); + label.accept(this); } else { - property("label"); nullValue(); } @@ -256,13 +257,11 @@ public final class JSONWriter extends NodeVisitor { comma(); final Node guard = catchNode.getExceptionCondition(); - property("guard"); if (guard != null) { + property("guard"); guard.accept(this); - } else { - nullValue(); + comma(); } - comma(); property("body"); catchNode.getBody().accept(this); @@ -278,10 +277,10 @@ public final class JSONWriter extends NodeVisitor { comma(); final IdentNode label = continueNode.getLabel(); + property("label"); if (label != null) { - property("label", label.getName()); + label.accept(this); } else { - property("label"); nullValue(); } @@ -299,13 +298,20 @@ public final class JSONWriter extends NodeVisitor { @Override public boolean enterExpressionStatement(final ExpressionStatement expressionStatement) { + // handle debugger statement + final Node expression = expressionStatement.getExpression(); + if (expression instanceof RuntimeNode) { + expression.accept(this); + return false; + } + enterDefault(expressionStatement); type("ExpressionStatement"); comma(); property("expression"); - expressionStatement.getExpression().accept(this); + expression.accept(this); return leave(); } @@ -388,13 +394,14 @@ public final class JSONWriter extends NodeVisitor { @Override public boolean enterFunctionNode(final FunctionNode functionNode) { - enterDefault(functionNode); - final boolean program = functionNode.isProgram(); - final String name; if (program) { - name = "Program"; - } else if (functionNode.isDeclared()) { + return emitProgram(functionNode); + } + + enterDefault(functionNode); + final String name; + if (functionNode.isDeclared()) { name = "FunctionDeclaration"; } else { name = "FunctionExpression"; @@ -402,24 +409,42 @@ public final class JSONWriter extends NodeVisitor { type(name); comma(); - if (! program) { - property("id"); - if (functionNode.isAnonymous()) { - nullValue(); - } else { - functionNode.getIdent().accept(this); - } - comma(); + property("id"); + final FunctionNode.Kind kind = functionNode.getKind(); + if (functionNode.isAnonymous() || kind == FunctionNode.Kind.GETTER || kind == FunctionNode.Kind.SETTER) { + nullValue(); + } else { + functionNode.getIdent().accept(this); } + comma(); + + array("params", functionNode.getParameters()); + comma(); + + arrayStart("defaults"); + arrayEnd(); + comma(); property("rest"); nullValue(); comma(); - if (!program) { - array("params", functionNode.getParameters()); - comma(); - } + property("body"); + functionNode.getBody().accept(this); + comma(); + + property("generator", false); + comma(); + + property("expression", false); + + return leave(); + } + + private boolean emitProgram(final FunctionNode functionNode) { + enterDefault(functionNode); + type("Program"); + comma(); // body consists of nested functions and statements final List stats = functionNode.getBody().getStatements(); @@ -730,7 +755,31 @@ public final class JSONWriter extends NodeVisitor { tryNode.getBody().accept(this); comma(); - array("handlers", tryNode.getCatches()); + + final List catches = tryNode.getCatches(); + final List guarded = new ArrayList<>(); + CatchNode unguarded = null; + if (catches != null) { + for (Node n : catches) { + CatchNode cn = (CatchNode)n; + if (cn.getExceptionCondition() != null) { + guarded.add(cn); + } else { + assert unguarded == null: "too many unguarded?"; + unguarded = cn; + } + } + } + + array("guardedHandlers", guarded); + comma(); + + property("handler"); + if (unguarded != null) { + unguarded.accept(this); + } else { + nullValue(); + } comma(); property("finalizer"); @@ -760,8 +809,8 @@ public final class JSONWriter extends NodeVisitor { array("arguments", callNode.getArgs()); } else { - final boolean prefix; final String operator; + final boolean prefix; switch (tokenType) { case INCPOSTFIX: prefix = false; @@ -780,8 +829,9 @@ public final class JSONWriter extends NodeVisitor { prefix = true; break; default: - prefix = false; + prefix = true; operator = tokenType.getName(); + break; } type(unaryNode.isAssignment()? "UpdateExpression" : "UnaryExpression"); @@ -802,6 +852,14 @@ public final class JSONWriter extends NodeVisitor { @Override public boolean enterVarNode(final VarNode varNode) { + final Node init = varNode.getInit(); + if (init instanceof FunctionNode && ((FunctionNode)init).isDeclared()) { + // function declaration - don't emit VariableDeclaration instead + // just emit FunctionDeclaration using 'init' Node. + init.accept(this); + return false; + } + enterDefault(varNode); type("VariableDeclaration"); @@ -816,11 +874,11 @@ public final class JSONWriter extends NodeVisitor { type("VariableDeclarator"); comma(); - property("id", varNode.getName().toString()); + property("id"); + varNode.getName().accept(this); comma(); property("init"); - final Node init = varNode.getInit(); if (init != null) { init.accept(this); } else { @@ -855,7 +913,7 @@ public final class JSONWriter extends NodeVisitor { whileNode.getTest().accept(this); comma(); - property("block"); + property("body"); whileNode.getBody().accept(this); } @@ -894,23 +952,27 @@ public final class JSONWriter extends NodeVisitor { return buf.toString(); } - private void property(final String key, final String value) { + private void property(final String key, final String value, final boolean escape) { buf.append('"'); buf.append(key); buf.append("\":"); if (value != null) { - buf.append('"'); + if (escape) buf.append('"'); buf.append(value); - buf.append('"'); + if (escape) buf.append('"'); } } + private void property(final String key, final String value) { + property(key, value, true); + } + private void property(final String key, final boolean value) { - property(key, Boolean.toString(value)); + property(key, Boolean.toString(value), false); } private void property(final String key, final int value) { - property(key, Integer.toString(value)); + property(key, Integer.toString(value), false); } private void property(final String key) { diff --git a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java index 4d8a2977e33..34fe2eb6a87 100644 --- a/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java +++ b/nashorn/src/jdk/nashorn/internal/lookup/MethodHandleFactory.java @@ -565,7 +565,7 @@ public final class MethodHandleFactory { @Override public MethodHandle asSpreader(final MethodHandle handle, final Class arrayType, final int arrayLength) { - final MethodHandle mh = super.asCollector(handle, arrayType, arrayLength); + final MethodHandle mh = super.asSpreader(handle, arrayType, arrayLength); return debug(mh, "asSpreader", handle, arrayType, arrayLength); } diff --git a/nashorn/src/jdk/nashorn/internal/objects/Global.java b/nashorn/src/jdk/nashorn/internal/objects/Global.java index 6d7be378be6..161909bb3f6 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; +import java.lang.ref.ReferenceQueue; import java.lang.ref.SoftReference; import java.lang.reflect.Field; import java.util.Arrays; @@ -412,6 +413,14 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { // initialized by nasgen private static PropertyMap $nasgenmap$; + // context to which this global belongs to + private final Context context; + + @Override + protected Context getContext() { + return context; + } + // performs initialization checks for Global constructor and returns the // PropertyMap, if everything is fine. private static PropertyMap checkAndGetMap(final Context context) { @@ -439,7 +448,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { */ public Global(final Context context) { super(checkAndGetMap(context)); - this.setContext(context); + this.context = context; this.setIsScope(); final int cacheSize = context.getEnv()._class_cache_size; @@ -481,6 +490,16 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { // GlobalObject interface implementation + @Override + public boolean isOfContext(final Context context) { + return this.context == context; + } + + @Override + public boolean isStrictContext() { + return context.getEnv()._strict; + } + @Override public void initBuiltinObjects() { if (this.builtinObject != null) { @@ -673,17 +692,41 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { * Cache for compiled script classes. */ @SuppressWarnings("serial") - private static class ClassCache extends LinkedHashMap>> { + private static class ClassCache extends LinkedHashMap { private final int size; + private final ReferenceQueue> queue; ClassCache(int size) { super(size, 0.75f, true); this.size = size; + this.queue = new ReferenceQueue<>(); + } + + void cache(final Source source, final Class clazz) { + put(source, new ClassReference(clazz, queue, source)); } @Override - protected boolean removeEldestEntry(final Map.Entry>> eldest) { - return size() >= size; + protected boolean removeEldestEntry(final Map.Entry eldest) { + return size() > size; + } + + @Override + public ClassReference get(Object key) { + for (ClassReference ref; (ref = (ClassReference)queue.poll()) != null; ) { + remove(ref.source); + } + return super.get(key); + } + + } + + private static class ClassReference extends SoftReference> { + private final Source source; + + ClassReference(final Class clazz, final ReferenceQueue> queue, final Source source) { + super(clazz, queue); + this.source = source; } } @@ -691,22 +734,14 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { @Override public Class findCachedClass(final Source source) { assert classCache != null : "Class cache used without being initialized"; - SoftReference> ref = classCache.get(source); - if (ref != null) { - final Class clazz = ref.get(); - if (clazz == null) { - classCache.remove(source); - } - return clazz; - } - - return null; + ClassReference ref = classCache.get(source); + return ref != null ? ref.get() : null; } @Override public void cacheClass(final Source source, final Class clazz) { assert classCache != null : "Class cache used without being initialized"; - classCache.put(source, new SoftReference>(clazz)); + classCache.cache(source, clazz); } private static T getLazilyCreatedValue(final Object key, final Callable creator, final Map map) { @@ -1765,7 +1800,7 @@ public final class Global extends ScriptObject implements GlobalObject, Scope { // do not fill $ENV if we have a security manager around // Retrieve current state of ENV variables. final ScriptObject env = newObject(); - env.putAll(System.getenv()); + env.putAll(System.getenv(), scriptEnv._strict); addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, env); } else { addOwnProperty(ScriptingFunctions.ENV_NAME, Attribute.NOT_ENUMERABLE, UNDEFINED); diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java index 54f293873ed..8cb1ded934c 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeArray.java @@ -41,7 +41,7 @@ import java.util.Iterator; import java.util.List; import java.util.concurrent.Callable; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -374,7 +374,7 @@ public final class NativeArray extends ScriptObject { public static Object isArray(final Object self, final Object arg) { return isArray(arg) || (arg == Global.instance().getArrayPrototype()) || (arg instanceof NativeRegExpExecResult) - || (arg instanceof ScriptObjectMirror && ((ScriptObjectMirror)arg).isArray()); + || (arg instanceof JSObject && ((JSObject)arg).isArray()); } /** diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java index 859745f3dca..935285f02ad 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeDate.java @@ -75,11 +75,11 @@ public final class NativeDate extends ScriptObject { private static final int FORMAT_LOCAL_TIME = 5; // Constants defined in ECMA 15.9.1.10 - private static final double hoursPerDay = 24; - private static final double minutesPerHour = 60; - private static final double secondsPerMinute = 60; - private static final double msPerSecond = 1_000; - private static final double msPerMinute = 60_000; + private static final int hoursPerDay = 24; + private static final int minutesPerHour = 60; + private static final int secondsPerMinute = 60; + private static final int msPerSecond = 1_000; + private static final int msPerMinute = 60_000; private static final double msPerHour = 3_600_000; private static final double msPerDay = 86_400_000; @@ -926,13 +926,13 @@ public final class NativeDate extends ScriptObject { case FORMAT_DATE : case FORMAT_LOCAL_DATE_TIME: // EEE MMM dd yyyy - sb.append(weekDays[(int) weekDay(t)]) + sb.append(weekDays[weekDay(t)]) .append(' ') - .append(months[(int) monthFromTime(t)]) + .append(months[monthFromTime(t)]) .append(' '); - zeroPad(sb, (int) dayFromTime(t), 2); + zeroPad(sb, dayFromTime(t), 2); sb.append(' '); - zeroPad(sb, (int) yearFromTime(t), 4); + zeroPad(sb, yearFromTime(t), 4); if (format == FORMAT_DATE) { break; } @@ -948,11 +948,11 @@ public final class NativeDate extends ScriptObject { offset = (offset / 60) * 100 + offset % 60; // HH:mm:ss GMT+HHmm - zeroPad(sb, (int) hourFromTime(t), 2); + zeroPad(sb, hourFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) minFromTime(t), 2); + zeroPad(sb, minFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) secFromTime(t), 2); + zeroPad(sb, secFromTime(t), 2); sb.append(" GMT") .append(offset < 0 ? '-' : '+'); zeroPad(sb, Math.abs(offset), 4); @@ -963,20 +963,20 @@ public final class NativeDate extends ScriptObject { case FORMAT_LOCAL_DATE: // yyyy-MM-dd - zeroPad(sb, (int) yearFromTime(t), 4); + zeroPad(sb, yearFromTime(t), 4); sb.append('-'); - zeroPad(sb, (int) monthFromTime(t) + 1, 2); + zeroPad(sb, monthFromTime(t) + 1, 2); sb.append('-'); - zeroPad(sb, (int) dayFromTime(t), 2); + zeroPad(sb, dayFromTime(t), 2); break; case FORMAT_LOCAL_TIME: // HH:mm:ss - zeroPad(sb, (int) hourFromTime(t), 2); + zeroPad(sb, hourFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) minFromTime(t), 2); + zeroPad(sb, minFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) secFromTime(t), 2); + zeroPad(sb, secFromTime(t), 2); break; default: @@ -996,19 +996,19 @@ public final class NativeDate extends ScriptObject { final StringBuilder sb = new StringBuilder(29); final double t = nd.getTime(); // EEE, dd MMM yyyy HH:mm:ss z - sb.append(weekDays[(int) weekDay(t)]) + sb.append(weekDays[weekDay(t)]) .append(", "); - zeroPad(sb, (int) dayFromTime(t), 2); + zeroPad(sb, dayFromTime(t), 2); sb.append(' ') - .append(months[(int) monthFromTime(t)]) + .append(months[monthFromTime(t)]) .append(' '); - zeroPad(sb, (int) yearFromTime(t), 4); + zeroPad(sb, yearFromTime(t), 4); sb.append(' '); - zeroPad(sb, (int) hourFromTime(t), 2); + zeroPad(sb, hourFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) minFromTime(t), 2); + zeroPad(sb, minFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) secFromTime(t), 2); + zeroPad(sb, secFromTime(t), 2); sb.append(" GMT"); return sb.toString(); } @@ -1023,19 +1023,19 @@ public final class NativeDate extends ScriptObject { final StringBuilder sb = new StringBuilder(24); final double t = nd.getTime(); // yyyy-MM-dd'T'HH:mm:ss.SSS'Z' - zeroPad(sb, (int) yearFromTime(t), 4); + zeroPad(sb, yearFromTime(t), 4); sb.append('-'); - zeroPad(sb, (int) monthFromTime(t) + 1, 2); + zeroPad(sb, monthFromTime(t) + 1, 2); sb.append('-'); - zeroPad(sb, (int) dayFromTime(t), 2); + zeroPad(sb, dayFromTime(t), 2); sb.append('T'); - zeroPad(sb, (int) hourFromTime(t), 2); + zeroPad(sb, hourFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) minFromTime(t), 2); + zeroPad(sb, minFromTime(t), 2); sb.append(':'); - zeroPad(sb, (int) secFromTime(t), 2); + zeroPad(sb, secFromTime(t), 2); sb.append('.'); - zeroPad(sb, (int) msFromTime(t), 3); + zeroPad(sb, msFromTime(t), 3); sb.append("Z"); return sb.toString(); } @@ -1072,29 +1072,30 @@ public final class NativeDate extends ScriptObject { } // ECMA 15.9.1.3 Year Number - private static double timeFromYear(final double y) { + private static double timeFromYear(final int y) { return dayFromYear(y) * msPerDay; } - private static double yearFromTime(final double t) { - double y = Math.floor(t / (msPerDay * 365.2425)) + 1970; + // ECMA 15.9.1.3 Year Number + private static int yearFromTime(final double t) { + int y = (int) Math.floor(t / (msPerDay * 365.2425)) + 1970; final double t2 = timeFromYear(y); if (t2 > t) { y--; - } else if (t2 + msPerDay * daysInYear((int) y) <= t) { + } else if (t2 + msPerDay * daysInYear(y) <= t) { y++; } return y; } - private static double dayWithinYear(final double t, final double year) { - return day(t) - dayFromYear(year); + private static int dayWithinYear(final double t, final int year) { + return (int) (day(t) - dayFromYear(year)); } - private static double monthFromTime(final double t) { - final double year = yearFromTime(t); - final double day = dayWithinYear(t, year); - final int[] firstDay = firstDayInMonth[isLeapYear((int) year) ? 1 : 0]; + private static int monthFromTime(final double t) { + final int year = yearFromTime(t); + final int day = dayWithinYear(t, year); + final int[] firstDay = firstDayInMonth[isLeapYear(year) ? 1 : 0]; int month = 0; while (month < 11 && firstDay[month + 1] <= day) { @@ -1103,10 +1104,10 @@ public final class NativeDate extends ScriptObject { return month; } - private static double dayFromTime(final double t) { - final double year = yearFromTime(t); - final double day = dayWithinYear(t, year); - final int[] firstDay = firstDayInMonth[isLeapYear((int) year) ? 1 : 0]; + private static int dayFromTime(final double t) { + final int year = yearFromTime(t); + final int day = dayWithinYear(t, year); + final int[] firstDay = firstDayInMonth[isLeapYear(year) ? 1 : 0]; int month = 0; while (month < 11 && firstDay[month + 1] <= day) { @@ -1121,11 +1122,8 @@ public final class NativeDate extends ScriptObject { return firstDay[month]; } - private static double weekDay(final double time) { - if (isNaN(time)) { - return NaN; - } - final double day = (day(time) + 4) % 7; + private static int weekDay(final double time) { + final int day = (int) (day(time) + 4) % 7; return day < 0 ? day + 7 : day; } @@ -1140,26 +1138,26 @@ public final class NativeDate extends ScriptObject { } // ECMA 15.9.1.10 Hours, Minutes, Second, and Milliseconds - private static double hourFromTime(final double t) { - final double h = Math.floor(t / msPerHour) % hoursPerDay; + private static int hourFromTime(final double t) { + final int h = (int) (Math.floor(t / msPerHour) % hoursPerDay); return h < 0 ? h + hoursPerDay: h; } - private static double minFromTime(final double t) { - final double m = Math.floor(t / msPerMinute) % minutesPerHour; + private static int minFromTime(final double t) { + final int m = (int) (Math.floor(t / msPerMinute) % minutesPerHour); return m < 0 ? m + minutesPerHour : m; } - private static double secFromTime(final double t) { - final double s = Math.floor(t / msPerSecond) % secondsPerMinute; + private static int secFromTime(final double t) { + final int s = (int) (Math.floor(t / msPerSecond) % secondsPerMinute); return s < 0 ? s + secondsPerMinute : s; } - private static double msFromTime(final double t) { - final double m = t % msPerSecond; + private static int msFromTime(final double t) { + final int m = (int) (t % msPerSecond); return m < 0 ? m + msPerSecond : m; } - private static double valueFromTime(final int unit, final double t) { + private static int valueFromTime(final int unit, final double t) { switch (unit) { case YEAR: return yearFromTime(t); case MONTH: return monthFromTime(t); @@ -1180,12 +1178,12 @@ public final class NativeDate extends ScriptObject { // ECMA 15.9.1.12 MakeDay (year, month, date) private static double makeDay(final double year, final double month, final double date) { final double y = year + Math.floor(month / 12); - double m = month % 12; + int m = (int) (month % 12); if (m < 0) { m += 12; } - double d = Math.floor(dayFromYear(y)); - d += dayFromMonth((int) m, (int) y); + double d = dayFromYear(y); + d += dayFromMonth(m, (int) y); return d + date - 1; } @@ -1257,13 +1255,13 @@ public final class NativeDate extends ScriptObject { nullReturn = true; } - if (! nullReturn) { + if (!nullReturn && !isNaN(time)) { d[i - start] = valueFromTime(i, time); } } } - return nullReturn? null : d; + return nullReturn ? null : d; } // ECMA 15.9.1.14 TimeClip (time) diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java index c208a35ce7e..c77002e310b 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeFunction.java @@ -30,7 +30,7 @@ import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; import java.util.List; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Constructor; import jdk.nashorn.internal.objects.annotations.Function; @@ -88,7 +88,7 @@ public final class NativeFunction { */ @Function(attributes = Attribute.NOT_ENUMERABLE) public static Object apply(final Object self, final Object thiz, final Object array) { - if (!(self instanceof ScriptFunction)) { + if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } @@ -111,21 +111,27 @@ public final class NativeFunction { list.toArray(args = new Object[list.size()]); } else if (array == null || array == UNDEFINED) { args = ScriptRuntime.EMPTY_ARRAY; - } else if (array instanceof ScriptObjectMirror) { - // look for array-like ScriptObjectMirror object - final ScriptObjectMirror mirror = (ScriptObjectMirror)array; - final Object len = mirror.containsKey("length")? mirror.getMember("length") : Integer.valueOf(0); + } else if (array instanceof JSObject) { + // look for array-like JSObject object + final JSObject jsObj = (JSObject)array; + final Object len = jsObj.hasMember("length")? jsObj.getMember("length") : Integer.valueOf(0); final int n = (int)JSType.toUint32(len); args = new Object[n]; for (int i = 0; i < args.length; i++) { - args[i] = mirror.containsKey(i)? mirror.getSlot(i) : UNDEFINED; + args[i] = jsObj.hasSlot(i)? jsObj.getSlot(i) : UNDEFINED; } } else { throw typeError("function.apply.expects.array"); } - return ScriptRuntime.apply((ScriptFunction)self, thiz, args); + if (self instanceof ScriptFunction) { + return ScriptRuntime.apply((ScriptFunction)self, thiz, args); + } else if (self instanceof JSObject) { + return ((JSObject)self).call(thiz, args); + } + + throw new AssertionError("should not reach here"); } /** @@ -137,7 +143,7 @@ public final class NativeFunction { */ @Function(attributes = Attribute.NOT_ENUMERABLE, arity = 1) public static Object call(final Object self, final Object... args) { - if (!(self instanceof ScriptFunction)) { + if (!(self instanceof ScriptFunction) && !(self instanceof JSObject)) { throw typeError("not.a.function", ScriptRuntime.safeToString(self)); } @@ -151,7 +157,13 @@ public final class NativeFunction { arguments = ScriptRuntime.EMPTY_ARRAY; } - return ScriptRuntime.apply((ScriptFunction)self, thiz, arguments); + if (self instanceof ScriptFunction) { + return ScriptRuntime.apply((ScriptFunction)self, thiz, arguments); + } else if (self instanceof JSObject) { + return ((JSObject)self).call(thiz, arguments); + } + + throw new AssertionError("should not reach here"); } /** diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java index b2fa46d2b52..344b6da90d9 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJSON.java @@ -162,22 +162,27 @@ public final class NativeJSON extends ScriptObject { String gap; - if (space instanceof Number || space instanceof NativeNumber) { - int indent; - if (space instanceof NativeNumber) { - indent = ((NativeNumber)space).intValue(); + // modifiable 'space' - parameter is final + Object modSpace = space; + if (modSpace instanceof NativeNumber) { + modSpace = JSType.toNumber(JSType.toPrimitive(modSpace, Number.class)); + } else if (modSpace instanceof NativeString) { + modSpace = JSType.toString(JSType.toPrimitive(modSpace, String.class)); + } + + if (modSpace instanceof Number) { + int indent = Math.min(10, JSType.toInteger(modSpace)); + if (indent < 1) { + gap = ""; } else { - indent = ((Number)space).intValue(); + final StringBuilder sb = new StringBuilder(); + for (int i = 0; i < indent; i++) { + sb.append(' '); + } + gap = sb.toString(); } - - final StringBuilder sb = new StringBuilder(); - for (int i = 0; i < Math.min(10, indent); i++) { - sb.append(' '); - } - gap = sb.toString(); - - } else if (space instanceof String || space instanceof ConsString || space instanceof NativeString) { - final String str = (space instanceof String) ? (String)space : space.toString(); + } else if (modSpace instanceof String || modSpace instanceof ConsString) { + final String str = modSpace.toString(); gap = str.substring(0, Math.min(10, str.length())); } else { gap = ""; diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java index 011fd8bf84b..5e9ac83d5e1 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeJava.java @@ -34,6 +34,7 @@ import java.util.Deque; import java.util.List; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.support.TypeUtilities; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.objects.annotations.Attribute; import jdk.nashorn.internal.objects.annotations.Function; import jdk.nashorn.internal.objects.annotations.ScriptClass; @@ -43,6 +44,7 @@ import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ListAdapter; import jdk.nashorn.internal.runtime.PropertyMap; import jdk.nashorn.internal.runtime.ScriptObject; +import jdk.nashorn.internal.runtime.ScriptRuntime; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.JavaAdapterFactory; @@ -288,7 +290,9 @@ public final class NativeJava { return null; } - Global.checkObject(obj); + if (!(obj instanceof ScriptObject) && !(obj instanceof JSObject)) { + throw typeError("not.an.object", ScriptRuntime.safeToString(obj)); + } final Class targetClass; if(objType == UNDEFINED) { @@ -304,11 +308,11 @@ public final class NativeJava { } if(targetClass.isArray()) { - return ((ScriptObject)obj).getArray().asArrayOfType(targetClass.getComponentType()); + return JSType.toJavaArray(obj, targetClass.getComponentType()); } if(targetClass == List.class || targetClass == Deque.class) { - return new ListAdapter((ScriptObject)obj); + return ListAdapter.create(obj); } throw typeError("unsupported.java.to.type", targetClass.getName()); diff --git a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java index 5a2196356fe..318ca2a0edd 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java +++ b/nashorn/src/jdk/nashorn/internal/objects/NativeRegExp.java @@ -191,23 +191,21 @@ public final class NativeRegExp extends ScriptObject { public static NativeRegExp newRegExp(final Object regexp, final Object flags) { String patternString = ""; String flagString = ""; - boolean flagsDefined = false; - - if (flags != UNDEFINED) { - flagsDefined = true; - flagString = JSType.toString(flags); - } if (regexp != UNDEFINED) { if (regexp instanceof NativeRegExp) { - if (!flagsDefined) { - return (NativeRegExp)regexp; // 15.10.3.1 - undefined flags and regexp as + if (flags != UNDEFINED) { + throw typeError("regex.cant.supply.flags"); } - throw typeError("regex.cant.supply.flags"); + return (NativeRegExp)regexp; // 15.10.3.1 - undefined flags and regexp as } patternString = JSType.toString(regexp); } + if (flags != UNDEFINED) { + flagString = JSType.toString(flags); + } + return new NativeRegExp(patternString, flagString); } @@ -697,8 +695,13 @@ public final class NativeRegExp extends ScriptObject { appendReplacement(matcher, string, replacement, sb); } - // ECMA 15.5.4.10 String.prototype.match(regexp) thisIndex = matcher.end(); + if (thisIndex == string.length() && matcher.start() == matcher.end()) { + // Avoid getting empty match at end of string twice + break; + } + + // ECMA 15.5.4.10 String.prototype.match(regexp) if (thisIndex == previousLastIndex) { setLastIndex(thisIndex + 1); previousLastIndex = thisIndex + 1; @@ -883,7 +886,7 @@ public final class NativeRegExp extends ScriptObject { * @return last index property as int */ public int getLastIndex() { - return JSType.toInt32(lastIndex); + return JSType.toInteger(lastIndex); } /** diff --git a/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java b/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java index cb14fcdf0b8..51988f6a13a 100644 --- a/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java +++ b/nashorn/src/jdk/nashorn/internal/parser/JSONParser.java @@ -349,6 +349,10 @@ loop: case COMMARIGHT: next(); + // check for trailing comma - not allowed in JSON + if (type == RBRACKET) { + throw error(AbstractParser.message("trailing.comma.in.json", type.getNameOrType())); + } break; default: @@ -388,6 +392,10 @@ loop: case COMMARIGHT: next(); + // check for trailing comma - not allowed in JSON + if (type == RBRACE) { + throw error(AbstractParser.message("trailing.comma.in.json", type.getNameOrType())); + } break; default: diff --git a/nashorn/src/jdk/nashorn/internal/parser/Parser.java b/nashorn/src/jdk/nashorn/internal/parser/Parser.java index ab008900f50..9663401ff5e 100644 --- a/nashorn/src/jdk/nashorn/internal/parser/Parser.java +++ b/nashorn/src/jdk/nashorn/internal/parser/Parser.java @@ -25,7 +25,6 @@ package jdk.nashorn.internal.parser; -import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS; import static jdk.nashorn.internal.codegen.CompilerConstants.EVAL; import static jdk.nashorn.internal.codegen.CompilerConstants.FUNCTION_PREFIX; import static jdk.nashorn.internal.codegen.CompilerConstants.RUN_SCRIPT; @@ -60,6 +59,7 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import jdk.internal.dynalink.support.NameCodec; import jdk.nashorn.internal.codegen.CompilerConstants; import jdk.nashorn.internal.codegen.Namespace; import jdk.nashorn.internal.ir.AccessNode; @@ -115,6 +115,8 @@ import jdk.nashorn.internal.runtime.Timing; * Builds the IR. */ public class Parser extends AbstractParser { + private static final String ARGUMENTS_NAME = CompilerConstants.ARGUMENTS_VAR.symbolName(); + /** Current script environment. */ private final ScriptEnvironment env; @@ -511,13 +513,19 @@ loop: * @param ident Referenced property. */ private void detectSpecialProperty(final IdentNode ident) { - final String name = ident.getName(); - - if (ARGUMENTS.symbolName().equals(name)) { + if (isArguments(ident)) { lc.setFlag(lc.getCurrentFunction(), FunctionNode.USES_ARGUMENTS); } } + private static boolean isArguments(final String name) { + return ARGUMENTS_NAME.equals(name); + } + + private static boolean isArguments(final IdentNode ident) { + return isArguments(ident.getName()); + } + /** * Tells whether a IdentNode can be used as L-value of an assignment * @@ -2060,7 +2068,7 @@ loop: case FLOATING: return getLiteral(); default: - return getIdentifierName(); + return getIdentifierName().setIsPropertyName(); } } @@ -2101,7 +2109,7 @@ loop: case "get": final PropertyKey getIdent = propertyName(); final String getterName = getIdent.getPropertyName(); - final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, "get " + getterName); + final IdentNode getNameNode = new IdentNode(((Node)getIdent).getToken(), finish, "get " + NameCodec.encode(getterName)); expect(LPAREN); expect(RPAREN); functionNode = functionBody(getSetToken, getNameNode, new ArrayList(), FunctionNode.Kind.GETTER); @@ -2110,7 +2118,7 @@ loop: case "set": final PropertyKey setIdent = propertyName(); final String setterName = setIdent.getPropertyName(); - final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, "set " + setterName); + final IdentNode setNameNode = new IdentNode(((Node)setIdent).getToken(), finish, "set " + NameCodec.encode(setterName)); expect(LPAREN); final IdentNode argIdent = getIdent(); verifyStrictIdent(argIdent, "setter argument"); @@ -2449,7 +2457,7 @@ loop: } else if (env._function_statement == ScriptEnvironment.FunctionStatementBehavior.WARNING) { warning(JSErrorType.SYNTAX_ERROR, AbstractParser.message("no.func.decl.here.warn"), functionToken); } - if (ARGUMENTS.symbolName().equals(name.getName())) { + if (isArguments(name)) { lc.setFlag(lc.getCurrentFunction(), FunctionNode.DEFINES_ARGUMENTS); } } @@ -2468,7 +2476,7 @@ loop: final IdentNode parameter = parameters.get(i); String parameterName = parameter.getName(); - if (ARGUMENTS.symbolName().equals(parameterName)) { + if (isArguments(parameterName)) { functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS); } @@ -2486,7 +2494,7 @@ loop: parametersSet.add(parameterName); } } else if (arity == 1) { - if (ARGUMENTS.symbolName().equals(parameters.get(0).getName())) { + if (isArguments(parameters.get(0))) { functionNode = functionNode.setFlag(lc, FunctionNode.DEFINES_ARGUMENTS); } } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Context.java b/nashorn/src/jdk/nashorn/internal/runtime/Context.java index 2f0c95d89b9..7c69eb52035 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/Context.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/Context.java @@ -236,6 +236,10 @@ public final class Context { private static final ClassLoader myLoader = Context.class.getClassLoader(); private static final StructureLoader sharedLoader; + /*package-private*/ ClassLoader getSharedLoader() { + return sharedLoader; + } + private static AccessControlContext createNoPermAccCtxt() { return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, new Permissions()) }); } @@ -254,7 +258,7 @@ public final class Context { sharedLoader = AccessController.doPrivileged(new PrivilegedAction() { @Override public StructureLoader run() { - return new StructureLoader(myLoader, null); + return new StructureLoader(myLoader); } }, CREATE_LOADER_ACC_CTXT); } @@ -573,7 +577,7 @@ public final class Context { setGlobalTrusted(newGlobal); final Object[] wrapped = args == null? ScriptRuntime.EMPTY_ARRAY : ScriptObjectMirror.wrapArray(args, oldGlobal); - newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped)); + newGlobal.put("arguments", ((GlobalObject)newGlobal).wrapAsObject(wrapped), env._strict); try { // wrap objects from newGlobal's world as mirrors - but if result @@ -599,7 +603,7 @@ public final class Context { * @throws ClassNotFoundException if structure class cannot be resolved */ public static Class forStructureClass(final String fullName) throws ClassNotFoundException { - if (System.getSecurityManager() != null && !NashornLoader.isStructureClass(fullName)) { + if (System.getSecurityManager() != null && !StructureLoader.isStructureClass(fullName)) { throw new ClassNotFoundException(fullName); } return Class.forName(fullName, true, sharedLoader); @@ -792,12 +796,11 @@ public final class Context { static Context fromClass(final Class clazz) { final ClassLoader loader = clazz.getClassLoader(); - Context context = null; - if (loader instanceof NashornLoader) { - context = ((NashornLoader)loader).getContext(); + if (loader instanceof ScriptLoader) { + return ((ScriptLoader)loader).getContext(); } - return (context != null) ? context : Context.getContextTrusted(); + return Context.getContextTrusted(); } private Object evaluateSource(final Source source, final ScriptObject scope, final ScriptObject thiz) { @@ -899,7 +902,7 @@ public final class Context { new PrivilegedAction() { @Override public ScriptLoader run() { - return new ScriptLoader(sharedLoader, Context.this); + return new ScriptLoader(appLoader, Context.this); } }, CREATE_LOADER_ACC_CTXT); } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java index 5b608f4b37b..0ff843a4271 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ECMAErrors.java @@ -28,7 +28,6 @@ package jdk.nashorn.internal.runtime; import java.text.MessageFormat; import java.util.Locale; import java.util.ResourceBundle; - import jdk.nashorn.api.scripting.NashornException; import jdk.nashorn.internal.scripts.JS; diff --git a/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java b/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java index c504276f41c..c750d80e913 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalFunctions.java @@ -90,6 +90,7 @@ public final class GlobalFunctions { public static double parseInt(final Object self, final Object string, final Object rad) { final String str = JSType.trimLeft(JSType.toString(string)); final int length = str.length(); + int radix = JSType.toInt32(rad); // empty string is not valid if (length == 0) { @@ -113,7 +114,6 @@ public final class GlobalFunctions { } boolean stripPrefix = true; - int radix = JSType.toInt32(rad); if (radix != 0) { if (radix < 2 || radix > 36) { @@ -211,7 +211,7 @@ loop: switch (ch) { case '.': // dot allowed only once - if (dotSeen) { + if (exponentOffset != -1 || dotSeen) { break loop; } dotSeen = true; diff --git a/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java b/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java index 087b34554bc..7e01fd6e2ea 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/GlobalObject.java @@ -36,6 +36,18 @@ import jdk.nashorn.internal.runtime.linker.InvokeByName; */ public interface GlobalObject { + /** + * Is this global of the given Context? + * @return true if this global belongs to the given Context + */ + public boolean isOfContext(Context context); + + /** + * Does this global belong to a strict Context? + * @return true if this global belongs to a strict Context + */ + public boolean isStrictContext(); + /** * Initialize standard builtin objects like "Object", "Array", "Function" etc. * as well as our extension builtin objects like "Java", "JSAdapter" as properties diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java new file mode 100644 index 00000000000..3c430b29e03 --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/runtime/JSObjectListAdapter.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime; + +import jdk.nashorn.api.scripting.JSObject; + +/** + * A ListAdapter that can wraps a JSObject. + */ +public final class JSObjectListAdapter extends ListAdapter { + /** + * Creates a new list wrapper for the specified JSObject. + * @param obj JSOcript the object to wrap + */ + public JSObjectListAdapter(final JSObject obj) { + super(obj); + } + + @Override + public int size() { + return JSType.toInt32(((JSObject)obj).getMember("length")); + } + + @Override + protected Object getAt(int index) { + return ((JSObject)obj).getSlot(index); + } + + @Override + protected void setAt(int index, Object element) { + ((JSObject)obj).setSlot(index, element); + } +} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java index 073c237c69b..93f0835b465 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/JSType.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/JSType.java @@ -28,11 +28,14 @@ package jdk.nashorn.internal.runtime; import static jdk.nashorn.internal.codegen.CompilerConstants.staticCall; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; +import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; -import java.util.Locale; +import java.lang.reflect.Array; import jdk.internal.dynalink.beans.StaticClass; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.parser.Lexer; +import jdk.nashorn.internal.runtime.arrays.ArrayLikeIterator; import jdk.nashorn.internal.runtime.linker.Bootstrap; /** @@ -40,25 +43,28 @@ import jdk.nashorn.internal.runtime.linker.Bootstrap; */ public enum JSType { /** The undefined type */ - UNDEFINED, + UNDEFINED("undefined"), /** The null type */ - NULL, + NULL("object"), /** The boolean type */ - BOOLEAN, + BOOLEAN("boolean"), /** The number type */ - NUMBER, + NUMBER("number"), /** The string type */ - STRING, + STRING("string"), /** The object type */ - OBJECT, + OBJECT("object"), /** The function type */ - FUNCTION; + FUNCTION("function"); + + /** The type name as returned by ECMAScript "typeof" operator*/ + private final String typeName; /** Max value for an uint32 in JavaScript */ public static final long MAX_UINT = 0xFFFF_FFFFL; @@ -109,14 +115,22 @@ public enum JSType { private static final double INT32_LIMIT = 4294967296.0; + /** + * Constructor + * + * @param typeName the type name + */ + private JSType(final String typeName) { + this.typeName = typeName; + } + /** * The external type name as returned by ECMAScript "typeof" operator * * @return type name for this type */ public final String typeName() { - // For NULL, "object" has to be returned! - return ((this == NULL) ? OBJECT : this).name().toLowerCase(Locale.ENGLISH); + return this.typeName; } /** @@ -127,31 +141,32 @@ public enum JSType { * @return the JSType for the object */ public static JSType of(final Object obj) { - if (obj == ScriptRuntime.UNDEFINED) { - return JSType.UNDEFINED; - } - + // Order of these statements is tuned for performance (see JDK-8024476) if (obj == null) { return JSType.NULL; } + if (obj instanceof ScriptObject) { + return (obj instanceof ScriptFunction) ? JSType.FUNCTION : JSType.OBJECT; + } + if (obj instanceof Boolean) { return JSType.BOOLEAN; } - if (obj instanceof Number) { - return JSType.NUMBER; - } - if (obj instanceof String || obj instanceof ConsString) { return JSType.STRING; } - if (Bootstrap.isCallable(obj)) { - return JSType.FUNCTION; + if (obj instanceof Number) { + return JSType.NUMBER; } - return JSType.OBJECT; + if (obj == ScriptRuntime.UNDEFINED) { + return JSType.UNDEFINED; + } + + return Bootstrap.isCallable(obj) ? JSType.FUNCTION : JSType.OBJECT; } /** @@ -848,6 +863,53 @@ public enum JSType { return ((GlobalObject)global).wrapAsObject(obj); } + /** + * Script object to Java array conversion. + * + * @param obj script object to be converted to Java array + * @param componentType component type of the destination array required + * @return converted Java array + */ + public static Object toJavaArray(final Object obj, final Class componentType) { + if (obj instanceof ScriptObject) { + return convertArray(((ScriptObject)obj).getArray().asObjectArray(), componentType); + } else if (obj instanceof JSObject) { + final ArrayLikeIterator itr = ArrayLikeIterator.arrayLikeIterator(obj); + final int len = (int) itr.getLength(); + final Object[] res = new Object[len]; + int idx = 0; + while (itr.hasNext()) { + res[idx++] = itr.next(); + } + return convertArray(res, componentType); + } else { + throw new IllegalArgumentException("not a script object"); + } + } + + /** + * Java array to java array conversion - but using type conversions implemented by linker. + * + * @param src source array + * @param componentType component type of the destination array required + * @return converted Java array + */ + public static Object convertArray(final Object[] src, final Class componentType) { + final int l = src.length; + final Object dst = Array.newInstance(componentType, l); + final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType); + try { + for (int i = 0; i < src.length; i++) { + Array.set(dst, i, invoke(converter, src[i])); + } + } catch (final RuntimeException | Error e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + return dst; + } + /** * Check if an object is null or undefined * @@ -953,4 +1015,13 @@ public enum JSType { return Double.NaN; } + private static Object invoke(final MethodHandle mh, final Object arg) { + try { + return mh.invoke(arg); + } catch (final RuntimeException | Error e) { + throw e; + } catch (final Throwable t) { + throw new RuntimeException(t); + } + } } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java index ae6d74461a1..41d34600de4 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ListAdapter.java @@ -32,6 +32,7 @@ import java.util.ListIterator; import java.util.NoSuchElementException; import java.util.RandomAccess; import java.util.concurrent.Callable; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.runtime.linker.Bootstrap; import jdk.nashorn.internal.runtime.linker.InvokeByName; @@ -48,7 +49,7 @@ import jdk.nashorn.internal.runtime.linker.InvokeByName; * operations respectively, while {@link #addLast(Object)} and {@link #removeLast()} will translate to {@code push} and * {@code pop}. */ -public final class ListAdapter extends AbstractList implements RandomAccess, Deque { +public abstract class ListAdapter extends AbstractList implements RandomAccess, Deque { // These add to the back and front of the list private static final Object PUSH = new Object(); private static InvokeByName getPUSH() { @@ -56,7 +57,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc new Callable() { @Override public InvokeByName call() { - return new InvokeByName("push", ScriptObject.class, void.class, Object.class); + return new InvokeByName("push", Object.class, void.class, Object.class); } }); } @@ -67,7 +68,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc new Callable() { @Override public InvokeByName call() { - return new InvokeByName("unshift", ScriptObject.class, void.class, Object.class); + return new InvokeByName("unshift", Object.class, void.class, Object.class); } }); } @@ -79,7 +80,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc new Callable() { @Override public InvokeByName call() { - return new InvokeByName("pop", ScriptObject.class, Object.class); + return new InvokeByName("pop", Object.class, Object.class); } }); } @@ -90,7 +91,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc new Callable() { @Override public InvokeByName call() { - return new InvokeByName("shift", ScriptObject.class, Object.class); + return new InvokeByName("shift", Object.class, Object.class); } }); } @@ -102,7 +103,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc new Callable() { @Override public InvokeByName call() { - return new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class, Object.class); + return new InvokeByName("splice", Object.class, void.class, int.class, int.class, Object.class); } }); } @@ -113,40 +114,52 @@ public final class ListAdapter extends AbstractList implements RandomAcc new Callable() { @Override public InvokeByName call() { - return new InvokeByName("splice", ScriptObject.class, void.class, int.class, int.class); + return new InvokeByName("splice", Object.class, void.class, int.class, int.class); } }); } - private final ScriptObject obj; + protected final Object obj; - /** - * Creates a new list wrapper for the specified script object. - * @param obj script the object to wrap - */ - public ListAdapter(ScriptObject obj) { + // allow subclasses only in this package + ListAdapter(Object obj) { this.obj = obj; } - @Override - public int size() { - return JSType.toInt32(obj.getLength()); + /** + * Factory to create a ListAdapter for a given script object. + * + * @param obj script object to wrap as a ListAdapter + * @return A ListAdapter wrapper object + */ + public static ListAdapter create(final Object obj) { + if (obj instanceof ScriptObject) { + return new ScriptObjectListAdapter((ScriptObject)obj); + } else if (obj instanceof JSObject) { + return new JSObjectListAdapter((JSObject)obj); + } else { + throw new IllegalArgumentException("ScriptObject or JSObject expected"); + } } @Override - public Object get(int index) { + public final Object get(int index) { checkRange(index); - return obj.get(index); + return getAt(index); } + protected abstract Object getAt(final int index); + @Override public Object set(int index, Object element) { checkRange(index); - final Object prevValue = get(index); - obj.set(index, element, false); + final Object prevValue = getAt(index); + setAt(index, element); return prevValue; } + protected abstract void setAt(int index, Object element); + private void checkRange(int index) { if(index < 0 || index >= size()) { throw invalidIndex(index); @@ -154,18 +167,18 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public void push(Object e) { + public final void push(Object e) { addFirst(e); } @Override - public boolean add(Object e) { + public final boolean add(Object e) { addLast(e); return true; } @Override - public void addFirst(Object e) { + public final void addFirst(Object e) { try { final InvokeByName unshiftInvoker = getUNSHIFT(); final Object fn = unshiftInvoker.getGetter().invokeExact(obj); @@ -179,7 +192,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public void addLast(Object e) { + public final void addLast(Object e) { try { final InvokeByName pushInvoker = getPUSH(); final Object fn = pushInvoker.getGetter().invokeExact(obj); @@ -193,7 +206,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public void add(int index, Object e) { + public final void add(int index, Object e) { try { if(index < 0) { throw invalidIndex(index); @@ -229,40 +242,40 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public boolean offer(Object e) { + public final boolean offer(Object e) { return offerLast(e); } @Override - public boolean offerFirst(Object e) { + public final boolean offerFirst(Object e) { addFirst(e); return true; } @Override - public boolean offerLast(Object e) { + public final boolean offerLast(Object e) { addLast(e); return true; } @Override - public Object pop() { + public final Object pop() { return removeFirst(); } @Override - public Object remove() { + public final Object remove() { return removeFirst(); } @Override - public Object removeFirst() { + public final Object removeFirst() { checkNonEmpty(); return invokeShift(); } @Override - public Object removeLast() { + public final Object removeLast() { checkNonEmpty(); return invokePop(); } @@ -274,7 +287,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public Object remove(int index) { + public final Object remove(int index) { if(index < 0) { throw invalidIndex(index); } else if (index == 0) { @@ -320,7 +333,7 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - protected void removeRange(int fromIndex, int toIndex) { + protected final void removeRange(int fromIndex, int toIndex) { invokeSpliceRemove(fromIndex, toIndex - fromIndex); } @@ -338,54 +351,54 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public Object poll() { + public final Object poll() { return pollFirst(); } @Override - public Object pollFirst() { + public final Object pollFirst() { return isEmpty() ? null : invokeShift(); } @Override - public Object pollLast() { + public final Object pollLast() { return isEmpty() ? null : invokePop(); } @Override - public Object peek() { + public final Object peek() { return peekFirst(); } @Override - public Object peekFirst() { + public final Object peekFirst() { return isEmpty() ? null : get(0); } @Override - public Object peekLast() { + public final Object peekLast() { return isEmpty() ? null : get(size() - 1); } @Override - public Object element() { + public final Object element() { return getFirst(); } @Override - public Object getFirst() { + public final Object getFirst() { checkNonEmpty(); return get(0); } @Override - public Object getLast() { + public final Object getLast() { checkNonEmpty(); return get(size() - 1); } @Override - public Iterator descendingIterator() { + public final Iterator descendingIterator() { final ListIterator it = listIterator(size()); return new Iterator() { @Override @@ -406,12 +419,12 @@ public final class ListAdapter extends AbstractList implements RandomAcc } @Override - public boolean removeFirstOccurrence(Object o) { + public final boolean removeFirstOccurrence(Object o) { return removeOccurrence(o, iterator()); } @Override - public boolean removeLastOccurrence(Object o) { + public final boolean removeLastOccurrence(Object o) { return removeOccurrence(o, descendingIterator()); } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java index 4e349730451..e7837013f53 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/NashornLoader.java @@ -38,10 +38,7 @@ import java.security.SecureClassLoader; import jdk.nashorn.tools.Shell; /** - * Superclass for Nashorn class loader classes. This stores Context - * instance as an instance field. The current context can be - * efficiently accessed from a given Class via it's ClassLoader. - * + * Superclass for Nashorn class loader classes. */ abstract class NashornLoader extends SecureClassLoader { private static final String OBJECTS_PKG = "jdk.nashorn.internal.objects"; @@ -69,27 +66,8 @@ abstract class NashornLoader extends SecureClassLoader { }; } - private final Context context; - - final Context getContext() { - return context; - } - - NashornLoader(final ClassLoader parent, final Context context) { + NashornLoader(final ClassLoader parent) { super(parent); - this.context = context; - } - - - /** - * Called by subclass after package access check is done - * @param name name of the class to be loaded - * @param resolve whether the class should be resolved or not - * @return Class object - * @throws ClassNotFoundException if class cannot be loaded - */ - protected final Class loadClassTrusted(final String name, final boolean resolve) throws ClassNotFoundException { - return super.loadClass(name, resolve); } protected static void checkPackageAccess(final String name) { @@ -122,10 +100,6 @@ abstract class NashornLoader extends SecureClassLoader { return permCollection; } - static boolean isStructureClass(final String fullName) { - return fullName.startsWith(SCRIPTS_PKG); - } - /** * Create a secure URL class loader for the given classpath * @param classPath classpath for the loader to search from diff --git a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java index 9e725e339df..99ba9e19fa5 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/NativeJavaPackage.java @@ -198,7 +198,7 @@ public final class NativeJavaPackage extends ScriptObject { final String propertyName = desc.getNameToken(2); final String fullName = name.isEmpty() ? propertyName : name + "." + propertyName; - final Context context = getContext(); + final Context context = Context.getContextTrusted(); Class javaClass = null; try { diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java index 370faf312d0..736932ea318 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptLoader.java @@ -33,17 +33,42 @@ import java.security.ProtectionDomain; * */ final class ScriptLoader extends NashornLoader { + private static final String NASHORN_PKG_PREFIX = "jdk.nashorn.internal."; + + private final Context context; + + /*package-private*/ Context getContext() { + return context; + } + /** * Constructor. */ - ScriptLoader(final StructureLoader parent, final Context context) { - super(parent, context); + ScriptLoader(final ClassLoader parent, final Context context) { + super(parent); + this.context = context; } @Override protected Class loadClass(String name, boolean resolve) throws ClassNotFoundException { checkPackageAccess(name); - return super.loadClassTrusted(name, resolve); + try { + return super.loadClass(name, resolve); + } catch (final ClassNotFoundException | SecurityException e) { + // We'll get ClassNotFoundException for Nashorn 'struct' classes. + // Also, we'll get SecurityException for jdk.nashorn.internal.* + // classes. So, load these using to context's 'shared' loader. + // All these classes start with "jdk.nashorn.internal." prefix. + try { + if (name.startsWith(NASHORN_PKG_PREFIX)) { + return context.getSharedLoader().loadClass(name); + } + } catch (final ClassNotFoundException ignored) { + } + + // throw the original exception from here + throw e; + } } // package-private and private stuff below this point diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java index 9d7a7a6b260..a4ca6017b79 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObject.java @@ -87,6 +87,8 @@ import jdk.nashorn.internal.runtime.linker.NashornGuards; */ public abstract class ScriptObject extends PropertyListenerManager implements PropertyAccess { + /** __proto__ special property name */ + public static final String PROTO_PROPERTY_NAME = "__proto__"; /** Search fall back routine name for "no such method" */ static final String NO_SUCH_METHOD_NAME = "__noSuchMethod__"; @@ -118,9 +120,6 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr /** objects proto. */ private ScriptObject proto; - /** Context of the object, lazily cached. */ - private Context context; - /** Object flags. */ private int flags; @@ -130,6 +129,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr /** Indexed array data. */ private ArrayData arrayData; + static final MethodHandle GETPROTO = findOwnMH("getProto", ScriptObject.class); + static final MethodHandle SETPROTOCHECK = findOwnMH("setProtoCheck", void.class, Object.class); + static final MethodHandle SETFIELD = findOwnMH("setField", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, MethodHandle.class, Object.class, Object.class); static final MethodHandle SETSPILL = findOwnMH("setSpill", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class); static final MethodHandle SETSPILLWITHNEW = findOwnMH("setSpillWithNew", void.class, CallSiteDescriptor.class, PropertyMap.class, PropertyMap.class, int.class, Object.class, Object.class); @@ -150,6 +152,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr /** Method handle for setting the proto of a ScriptObject */ public static final Call SET_PROTO = virtualCallNoLookup(ScriptObject.class, "setProto", void.class, ScriptObject.class); + /** Method handle for setting the proto of a ScriptObject after checking argument */ + public static final Call SET_PROTO_CHECK = virtualCallNoLookup(ScriptObject.class, "setProtoCheck", void.class, Object.class); + /** Method handle for setting the user accessors of a ScriptObject */ public static final Call SET_USER_ACCESSORS = virtualCall(MethodHandles.lookup(), ScriptObject.class, "setUserAccessors", void.class, String.class, ScriptFunction.class, ScriptFunction.class); @@ -1034,41 +1039,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr set(key, value, false); } - /** - * Return true if the script object context is strict - * @return true if strict context - */ - public final boolean isStrictContext() { - return getContext()._strict; - } - - /** - * Checks if this object belongs to the given context - * @param ctx context to check against - * @return true if this object belongs to the given context - */ - public final boolean isOfContext(final Context ctx) { - return context == ctx; - } - /** * Return the current context from the object's map. * @return Current context. */ - protected final Context getContext() { - if (context == null) { - context = Context.fromClass(getClass()); - } - return context; - } - - /** - * Set the current context. - * @param ctx context instance to set - */ - protected final void setContext(final Context ctx) { - ctx.getClass(); - this.context = ctx; + protected Context getContext() { + return Context.fromClass(getClass()); } /** @@ -1474,9 +1450,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr /** * Clears the properties from a ScriptObject * (java.util.Map-like method to help ScriptObjectMirror implementation) + * + * @param strict strict mode or not */ - public void clear() { - final boolean strict = isStrictContext(); + public void clear(final boolean strict) { final Iterator iter = propertyIterator(); while (iter.hasNext()) { delete(iter.next(), strict); @@ -1560,11 +1537,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * * @param key property key * @param value property value + * @param strict strict mode or not * @return oldValue if property with same key existed already */ - public Object put(final Object key, final Object value) { + public Object put(final Object key, final Object value, final boolean strict) { final Object oldValue = get(key); - set(key, value, isStrictContext()); + set(key, value, strict); return oldValue; } @@ -1574,9 +1552,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * (java.util.Map-like method to help ScriptObjectMirror implementation) * * @param otherMap a {@literal } map of properties to add + * @param strict strict mode or not */ - public void putAll(final Map otherMap) { - final boolean strict = isStrictContext(); + public void putAll(final Map otherMap, final boolean strict) { for (final Map.Entry entry : otherMap.entrySet()) { set(entry.getKey(), entry.getValue(), strict); } @@ -1587,25 +1565,15 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * (java.util.Map-like method to help ScriptObjectMirror implementation) * * @param key the key of the property + * @param strict strict mode or not * @return the oldValue of the removed property */ - public Object remove(final Object key) { + public Object remove(final Object key, final boolean strict) { final Object oldValue = get(key); - delete(key, isStrictContext()); + delete(key, strict); return oldValue; } - /** - * Delete a property from the ScriptObject. - * (to help ScriptObjectMirror implementation) - * - * @param key the key of the property - * @return if the delete was successful or not - */ - public boolean delete(final Object key) { - return delete(key, isStrictContext()); - } - /** * Return the size of the ScriptObject - i.e. the number of properties * it contains @@ -1745,6 +1713,10 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr MethodHandle methodHandle; if (find == null) { + if (PROTO_PROPERTY_NAME.equals(name)) { + return new GuardedInvocation(GETPROTO, NashornGuards.getScriptObjectGuard()); + } + if ("getProp".equals(operator)) { return noSuchProperty(desc, request); } else if ("getMethod".equals(operator)) { @@ -1851,6 +1823,7 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr * toString = function() { print("global toString"); } // don't affect Object.prototype.toString */ FindProperty find = findProperty(name, true, scope, this); + // If it's not a scope search, then we don't want any inherited properties except those with user defined accessors. if (!scope && find != null && find.isInherited() && !(find.getProperty() instanceof UserAccessorProperty)) { // We should still check if inherited data property is not writable @@ -1866,9 +1839,12 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr // Existing, non-writable property return createEmptySetMethod(desc, "property.not.writable", true); } - } else if (!isExtensible()) { - // Non-existing property on a non-extensible object - return createEmptySetMethod(desc, "object.non.extensible", false); + } else { + if (PROTO_PROPERTY_NAME.equals(name)) { + return new GuardedInvocation(SETPROTOCHECK, NashornGuards.getScriptObjectGuard()); + } else if (! isExtensible()) { + return createEmptySetMethod(desc, "object.non.extensible", false); + } } return new SetMethodCreator(this, find, desc).createGuardedInvocation(); @@ -2317,11 +2293,9 @@ public abstract class ScriptObject extends PropertyListenerManager implements Pr return; } - final boolean isStrict = isStrictContext(); - if (newLength > arrayLength) { setArray(getArray().ensure(newLength - 1)); - if (getArray().canDelete(arrayLength, (newLength - 1), isStrict)) { + if (getArray().canDelete(arrayLength, (newLength - 1), false)) { setArray(getArray().delete(arrayLength, (newLength - 1))); } return; diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java new file mode 100644 index 00000000000..4fe2dc408f0 --- /dev/null +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptObjectListAdapter.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.internal.runtime; + +/** + * A ListAdapter that can wrap a ScriptObject. + */ +public final class ScriptObjectListAdapter extends ListAdapter { + /** + * Creates a new list wrapper for the specified ScriptObject. + * @param obj script the object to wrap + */ + public ScriptObjectListAdapter(final ScriptObject obj) { + super(obj); + } + + @Override + public int size() { + return JSType.toInt32(((ScriptObject)obj).getLength()); + } + + @Override + protected Object getAt(int index) { + return ((ScriptObject)obj).get(index); + } + + @Override + protected void setAt(int index, Object element) { + ((ScriptObject)obj).set(index, element, false); + } +} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java index 0fa0cc8a94e..c9b40512009 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/ScriptRuntime.java @@ -43,6 +43,7 @@ import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import jdk.internal.dynalink.beans.StaticClass; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.api.scripting.ScriptObjectMirror; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.ir.debug.JSONWriter; @@ -190,8 +191,8 @@ public final class ScriptRuntime { case FUNCTION: if (self instanceof ScriptObject) { className = ((ScriptObject)self).getClassName(); - } else if (self instanceof ScriptObjectMirror) { - className = ((ScriptObjectMirror)self).getClassName(); + } else if (self instanceof JSObject) { + className = ((JSObject)self).getClassName(); } else { className = self.getClass().getName(); } @@ -245,8 +246,8 @@ public final class ScriptRuntime { return new RangeIterator(Array.getLength(obj)); } - if (obj instanceof ScriptObjectMirror) { - return ((ScriptObjectMirror)obj).keySet().iterator(); + if (obj instanceof JSObject) { + return ((JSObject)obj).keySet().iterator(); } if (obj instanceof List) { @@ -323,8 +324,8 @@ public final class ScriptRuntime { }; } - if (obj instanceof ScriptObjectMirror) { - return ((ScriptObjectMirror)obj).values().iterator(); + if (obj instanceof JSObject) { + return ((JSObject)obj).values().iterator(); } if (obj instanceof Map) { @@ -351,35 +352,6 @@ public final class ScriptRuntime { return global; } - /** - * Check that the target function is associated with current Context. And also make sure that 'self', if - * ScriptObject, is from current context. - * - * Call a function given self and args. If the number of the arguments is known in advance, you can likely achieve - * better performance by {@link Bootstrap#createDynamicInvoker(String, Class, Class...) creating a dynamic invoker} - * for operation {@code "dyn:call"}, then using its {@link MethodHandle#invokeExact(Object...)} method instead. - * - * @param target ScriptFunction object. - * @param self Receiver in call. - * @param args Call arguments. - * @return Call result. - */ - public static Object checkAndApply(final ScriptFunction target, final Object self, final Object... args) { - final ScriptObject global = Context.getGlobalTrusted(); - assert (global instanceof GlobalObject): "No current global set"; - - if (target.getContext() != global.getContext()) { - throw new IllegalArgumentException("'target' function is not from current Context"); - } - - if (self instanceof ScriptObject && ((ScriptObject)self).getContext() != global.getContext()) { - throw new IllegalArgumentException("'self' object is not from current Context"); - } - - // all in order - call real 'apply' - return apply(target, self, args); - } - /** * Call a function given self and args. If the number of the arguments is known in advance, you can likely achieve * better performance by {@link Bootstrap#createDynamicInvoker(String, Class, Class...) creating a dynamic invoker} @@ -400,28 +372,6 @@ public final class ScriptRuntime { } } - /** - * Check that the target function is associated with current Context. - * And also make sure that 'self', if ScriptObject, is from current context. - * - * Call a function as a constructor given args. - * - * @param target ScriptFunction object. - * @param args Call arguments. - * @return Constructor call result. - */ - public static Object checkAndConstruct(final ScriptFunction target, final Object... args) { - final ScriptObject global = Context.getGlobalTrusted(); - assert (global instanceof GlobalObject): "No current global set"; - - if (target.getContext() != global.getContext()) { - throw new IllegalArgumentException("'target' function is not from current Context"); - } - - // all in order - call real 'construct' - return construct(target, args); - } - /** * Call a script function as a constructor with given args. * @@ -520,9 +470,12 @@ public final class ScriptRuntime { throw typeError(global, "cant.apply.with.to.null"); } - final ScriptObject withObject = new WithObject(scope, JSType.toScriptObject(global, expression)); + final Object wrappedExpr = JSType.toScriptObject(global, expression); + if (wrappedExpr instanceof ScriptObject) { + return new WithObject(scope, (ScriptObject)wrappedExpr); + } - return withObject; + throw typeError(global, "cant.apply.with.to.non.scriptobject"); } /** @@ -534,7 +487,7 @@ public final class ScriptRuntime { */ public static ScriptObject closeWith(final ScriptObject scope) { if (scope instanceof WithObject) { - return scope.getProto(); + return ((WithObject)scope).getParentScope(); } return scope; } @@ -619,8 +572,8 @@ public final class ScriptRuntime { throw typeError("cant.get.property", safeToString(property), "null"); } else if (JSType.isPrimitive(obj)) { obj = ((ScriptObject)JSType.toScriptObject(obj)).get(property); - } else if (obj instanceof ScriptObjectMirror) { - obj = ((ScriptObjectMirror)obj).getMember(property.toString()); + } else if (obj instanceof JSObject) { + obj = ((JSObject)obj).getMember(property.toString()); } else { obj = UNDEFINED; } @@ -672,6 +625,11 @@ public final class ScriptRuntime { return ((ScriptObject) JSType.toScriptObject(obj)).delete(property, Boolean.TRUE.equals(strict)); } + if (obj instanceof JSObject) { + ((JSObject)obj).removeMember(Objects.toString(property)); + return true; + } + // if object is not reference type, vacuously delete is successful. return true; } @@ -863,6 +821,10 @@ public final class ScriptRuntime { return ((ScriptObject)obj).has(property); } + if (obj instanceof JSObject) { + return ((JSObject)obj).hasMember(Objects.toString(property)); + } + return false; } @@ -889,11 +851,13 @@ public final class ScriptRuntime { return ((StaticClass)clazz).getRepresentedClass().isInstance(obj); } - if (clazz instanceof ScriptObjectMirror) { - if (obj instanceof ScriptObjectMirror) { - return ((ScriptObjectMirror)clazz).isInstance((ScriptObjectMirror)obj); - } - return false; + if (clazz instanceof JSObject) { + return ((JSObject)clazz).isInstance(obj); + } + + // provide for reverse hook + if (obj instanceof JSObject) { + return ((JSObject)obj).isInstanceOf(clazz); } throw typeError("instanceof.on.non.object"); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/Source.java b/nashorn/src/jdk/nashorn/internal/runtime/Source.java index 7e3c8684e91..9273e7a8bac 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/Source.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/Source.java @@ -169,7 +169,7 @@ public final class Source { final Source src = (Source)obj; // Only compare content as a last resort measure - return length == src.length && Objects.equals(name, src.name) && Arrays.equals(content, src.content); + return length == src.length && Objects.equals(url, src.url) && Objects.equals(name, src.name) && Arrays.equals(content, src.content); } @Override diff --git a/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java b/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java index bdc40eddcc9..41201cde847 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/StructureLoader.java @@ -34,7 +34,6 @@ import jdk.nashorn.internal.codegen.ObjectClassGenerator; /** * Responsible for on the fly construction of structure classes. - * */ final class StructureLoader extends NashornLoader { private static final String JS_OBJECT_PREFIX_EXTERNAL = binaryName(SCRIPTS_PACKAGE) + '.' + JS_OBJECT_PREFIX.symbolName(); @@ -42,27 +41,17 @@ final class StructureLoader extends NashornLoader { /** * Constructor. */ - StructureLoader(final ClassLoader parent, final Context context) { - super(parent, context); + StructureLoader(final ClassLoader parent) { + super(parent); } - @Override - protected synchronized Class loadClass(final String name, final boolean resolve) throws ClassNotFoundException { - // check the cache first - final Class loadedClass = findLoadedClass(name); - if (loadedClass != null) { - if (resolve) { - resolveClass(loadedClass); - } - return loadedClass; - } - - return super.loadClassTrusted(name, resolve); + static boolean isStructureClass(final String name) { + return name.startsWith(JS_OBJECT_PREFIX_EXTERNAL); } @Override protected Class findClass(final String name) throws ClassNotFoundException { - if (name.startsWith(JS_OBJECT_PREFIX_EXTERNAL)) { + if (isStructureClass(name)) { return generateClass(name, name.substring(JS_OBJECT_PREFIX_EXTERNAL.length())); } return super.findClass(name); @@ -75,11 +64,7 @@ final class StructureLoader extends NashornLoader { * @return Generated class. */ private Class generateClass(final String name, final String descriptor) { - Context context = getContext(); - - if (context == null) { - context = Context.getContextTrusted(); - } + final Context context = Context.getContextTrusted(); final byte[] code = new ObjectClassGenerator(context).generate(descriptor); return defineClass(name, code, 0, code.length, new ProtectionDomain(null, getPermissions(null))); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java index 46de1d13ee5..7dc8307cd91 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/WithObject.java @@ -30,26 +30,26 @@ import static jdk.nashorn.internal.lookup.Lookup.MH; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.lang.invoke.SwitchPoint; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; import jdk.internal.dynalink.support.CallSiteDescriptorFactory; import jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor; - /** * This class supports the handling of scope in a with body. * */ public final class WithObject extends ScriptObject implements Scope { - + private static final MethodHandle WITHEXPRESSIONGUARD = findOwnMH("withExpressionGuard", boolean.class, Object.class, PropertyMap.class, SwitchPoint.class); private static final MethodHandle WITHEXPRESSIONFILTER = findOwnMH("withFilterExpression", Object.class, Object.class); private static final MethodHandle WITHSCOPEFILTER = findOwnMH("withFilterScope", Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_OBJ = findOwnMH("bindToExpression", Object.class, Object.class, Object.class); private static final MethodHandle BIND_TO_EXPRESSION_FN = findOwnMH("bindToExpression", Object.class, ScriptFunction.class, Object.class); /** With expression object. */ - private final Object expression; + private final ScriptObject expression; /** * Constructor @@ -57,12 +57,13 @@ public final class WithObject extends ScriptObject implements Scope { * @param scope scope object * @param expression with expression */ - WithObject(final ScriptObject scope, final Object expression) { + WithObject(final ScriptObject scope, final ScriptObject expression) { super(scope, null); setIsScope(); this.expression = expression; } + /** * Delete a property based on a key. * @param key Any valid JavaScript value. @@ -71,15 +72,13 @@ public final class WithObject extends ScriptObject implements Scope { */ @Override public boolean delete(final Object key, final boolean strict) { - if (expression instanceof ScriptObject) { - final ScriptObject self = (ScriptObject)expression; - final String propName = JSType.toString(key); + final ScriptObject self = expression; + final String propName = JSType.toString(key); - final FindProperty find = self.findProperty(propName, true); + final FindProperty find = self.findProperty(propName, true); - if (find != null) { - return self.delete(propName, strict); - } + if (find != null) { + return self.delete(propName, strict); } return false; @@ -105,18 +104,16 @@ public final class WithObject extends ScriptObject implements Scope { name = null; } - if (expression instanceof ScriptObject) { - self = (ScriptObject)expression; - if (isNamedOperation) { - find = self.findProperty(name, true); - } + self = expression; + if (isNamedOperation) { + find = self.findProperty(name, true); + } - if (find != null) { - link = self.lookup(desc, request); + if (find != null) { + link = self.lookup(desc, request); - if (link != null) { - return fixExpressionCallSite(ndesc, link); - } + if (link != null) { + return fixExpressionCallSite(ndesc, link); } } @@ -126,7 +123,7 @@ public final class WithObject extends ScriptObject implements Scope { } if (find != null) { - return fixScopeCallSite(scope.lookup(desc, request)); + return fixScopeCallSite(scope.lookup(desc, request), name); } // the property is not found - now check for @@ -178,7 +175,7 @@ public final class WithObject extends ScriptObject implements Scope { link = scope.lookup(desc, request); if (link != null) { - return fixScopeCallSite(link); + return fixScopeCallSite(link, name); } return null; @@ -197,11 +194,9 @@ public final class WithObject extends ScriptObject implements Scope { */ @Override FindProperty findProperty(final String key, final boolean deep, final boolean stopOnNonScope, final ScriptObject start) { - if (expression instanceof ScriptObject) { - final FindProperty exprProperty = ((ScriptObject)expression).findProperty(key, deep, stopOnNonScope, start); - if(exprProperty != null) { - return exprProperty; - } + final FindProperty exprProperty = expression.findProperty(key, deep, stopOnNonScope, start); + if (exprProperty != null) { + return exprProperty; } return super.findProperty(key, deep, stopOnNonScope, start); } @@ -220,16 +215,17 @@ public final class WithObject extends ScriptObject implements Scope { * Get first parent scope that is not an instance of WithObject. */ private Scope getNonWithParent() { - ScriptObject proto = getProto(); + ScriptObject proto = getParentScope(); while (proto != null && proto instanceof WithObject) { - proto = proto.getProto(); + proto = ((WithObject)proto).getParentScope(); } assert proto instanceof Scope : "with scope without parent scope"; return (Scope) proto; } + private static GuardedInvocation fixReceiverType(final GuardedInvocation link, final MethodHandle filter) { // The receiver may be an Object or a ScriptObject. final MethodType invType = link.getInvocation().type(); @@ -256,9 +252,13 @@ public final class WithObject extends ScriptObject implements Scope { filterGuard(link, WITHEXPRESSIONFILTER)); } - private static GuardedInvocation fixScopeCallSite(final GuardedInvocation link) { + private GuardedInvocation fixScopeCallSite(final GuardedInvocation link, final String name) { final GuardedInvocation newLink = fixReceiverType(link, WITHSCOPEFILTER); - return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), filterGuard(newLink, WITHSCOPEFILTER)); + return link.replaceMethods(filter(newLink.getInvocation(), WITHSCOPEFILTER), + MH.guardWithTest( + expressionGuard(name), + filterGuard(newLink, WITHSCOPEFILTER), + MH.dropArguments(MH.constant(boolean.class, false), 0, Object.class))); } private static MethodHandle filterGuard(final GuardedInvocation link, final MethodHandle filter) { @@ -279,7 +279,6 @@ public final class WithObject extends ScriptObject implements Scope { return ((WithObject)receiver).expression; } - @SuppressWarnings("unused") private static Object bindToExpression(final Object fn, final Object receiver) { return fn instanceof ScriptFunction ? bindToExpression((ScriptFunction) fn, receiver) : fn; @@ -289,6 +288,17 @@ public final class WithObject extends ScriptObject implements Scope { return fn.makeBoundFunction(withFilterExpression(receiver), new Object[0]); } + private MethodHandle expressionGuard(final String name) { + final PropertyMap map = expression.getMap(); + final SwitchPoint sp = map.getProtoGetSwitchPoint(expression.getProto(), name); + return MH.insertArguments(WITHEXPRESSIONGUARD, 1, map, sp); + } + + @SuppressWarnings("unused") + private static boolean withExpressionGuard(final Object receiver, final PropertyMap map, final SwitchPoint sp) { + return ((WithObject)receiver).expression.getMap() == map && (sp == null || !sp.hasBeenInvalidated()); + } + /** * Drops the WithObject wrapper from the scope. * @param receiver WithObject wrapper. @@ -302,10 +312,14 @@ public final class WithObject extends ScriptObject implements Scope { * Get the with expression for this {@code WithObject} * @return the with expression */ - public Object getExpression() { + public ScriptObject getExpression() { return expression; } + public ScriptObject getParentScope() { + return getProto(); + } + private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { return MH.findStatic(MethodHandles.lookup(), WithObject.class, name, MH.type(rtype, types)); } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java index 1278d49ff95..ca4adb62e97 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayData.java @@ -26,10 +26,9 @@ package jdk.nashorn.internal.runtime.arrays; import java.lang.invoke.MethodHandle; -import java.lang.reflect.Array; import jdk.nashorn.internal.runtime.GlobalObject; +import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.PropertyDescriptor; -import jdk.nashorn.internal.runtime.linker.Bootstrap; /** * ArrayData - abstraction for wrapping array elements @@ -204,20 +203,7 @@ public abstract class ArrayData { * @return and array of the given type */ public Object asArrayOfType(final Class componentType) { - final Object[] src = asObjectArray(); - final int l = src.length; - final Object dst = Array.newInstance(componentType, l); - final MethodHandle converter = Bootstrap.getLinkerServices().getTypeConverter(Object.class, componentType); - try { - for (int i = 0; i < src.length; i++) { - Array.set(dst, i, invoke(converter, src[i])); - } - } catch (final RuntimeException | Error e) { - throw e; - } catch (final Throwable t) { - throw new RuntimeException(t); - } - return dst; + return JSType.convertArray(asObjectArray(), componentType); } /** diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java index 044b21d5879..962b1f9e031 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ArrayLikeIterator.java @@ -27,7 +27,7 @@ package jdk.nashorn.internal.runtime.arrays; import java.util.Iterator; import java.util.List; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.runtime.JSType; import jdk.nashorn.internal.runtime.ScriptObject; @@ -127,8 +127,8 @@ abstract public class ArrayLikeIterator implements Iterator { return new ScriptObjectIterator((ScriptObject)obj, includeUndefined); } - if (obj instanceof ScriptObjectMirror) { - return new ScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined); + if (obj instanceof JSObject) { + return new JSObjectIterator((JSObject)obj, includeUndefined); } if (obj instanceof List) { @@ -160,8 +160,8 @@ abstract public class ArrayLikeIterator implements Iterator { return new ReverseScriptObjectIterator((ScriptObject)obj, includeUndefined); } - if (obj instanceof ScriptObjectMirror) { - return new ReverseScriptObjectMirrorIterator((ScriptObjectMirror)obj, includeUndefined); + if (obj instanceof JSObject) { + return new ReverseJSObjectIterator((JSObject)obj, includeUndefined); } if (obj instanceof List) { diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java index 9b6cbb447fe..244739b389d 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/IteratorAction.java @@ -27,7 +27,7 @@ package jdk.nashorn.internal.runtime.arrays; import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.runtime.Context; import jdk.nashorn.internal.runtime.ScriptFunction; import jdk.nashorn.internal.runtime.ScriptRuntime; @@ -101,9 +101,9 @@ public abstract class IteratorAction { final boolean strict; if (callbackfn instanceof ScriptFunction) { strict = ((ScriptFunction)callbackfn).isStrict(); - } else if (callbackfn instanceof ScriptObjectMirror && - ((ScriptObjectMirror)callbackfn).isFunction()) { - strict = ((ScriptObjectMirror)callbackfn).isStrictFunction(); + } else if (callbackfn instanceof JSObject && + ((JSObject)callbackfn).isFunction()) { + strict = ((JSObject)callbackfn).isStrictFunction(); } else if (Bootstrap.isDynamicMethod(callbackfn) || Bootstrap.isFunctionalInterfaceObject(callbackfn)) { strict = false; } else { diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java similarity index 82% rename from nashorn/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java rename to nashorn/src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java index a7bef158f57..885c77eb570 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ScriptObjectMirrorIterator.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/JSObjectIterator.java @@ -26,21 +26,21 @@ package jdk.nashorn.internal.runtime.arrays; import java.util.NoSuchElementException; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.runtime.JSType; /** * Iterator over a ScriptObjectMirror */ -class ScriptObjectMirrorIterator extends ArrayLikeIterator { +class JSObjectIterator extends ArrayLikeIterator { - protected final ScriptObjectMirror obj; + protected final JSObject obj; private final long length; - ScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) { + JSObjectIterator(final JSObject obj, final boolean includeUndefined) { super(includeUndefined); this.obj = obj; - this.length = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0); + this.length = JSType.toUint32(obj.hasMember("length")? obj.getMember("length") : 0); this.index = 0; } @@ -60,7 +60,7 @@ class ScriptObjectMirrorIterator extends ArrayLikeIterator { } while (indexInArray()) { - if (obj.containsKey(index) || includeUndefined) { + if (obj.hasSlot((int)index) || includeUndefined) { break; } bumpIndex(); @@ -72,7 +72,7 @@ class ScriptObjectMirrorIterator extends ArrayLikeIterator { @Override public Object next() { if (indexInArray()) { - return obj.get(bumpIndex()); + return obj.getSlot((int)bumpIndex()); } throw new NoSuchElementException(); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJSObjectIterator.java similarity index 83% rename from nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java rename to nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJSObjectIterator.java index 1e3e4000cdb..84c5c46dd12 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseScriptObjectMirrorIterator.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/arrays/ReverseJSObjectIterator.java @@ -25,17 +25,17 @@ package jdk.nashorn.internal.runtime.arrays; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.runtime.JSType; /** * Reverse iterator over a ScriptObjectMirror */ -final class ReverseScriptObjectMirrorIterator extends ScriptObjectMirrorIterator { +final class ReverseJSObjectIterator extends JSObjectIterator { - ReverseScriptObjectMirrorIterator(final ScriptObjectMirror obj, final boolean includeUndefined) { + ReverseJSObjectIterator(final JSObject obj, final boolean includeUndefined) { super(obj, includeUndefined); - this.index = JSType.toUint32(obj.containsKey("length")? obj.getMember("length") : 0) - 1; + this.index = JSType.toUint32(obj.hasMember("length")? obj.getMember("length") : 0) - 1; } @Override diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java index e190224a07b..f725817af4b 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/Bootstrap.java @@ -39,7 +39,7 @@ import jdk.internal.dynalink.beans.BeansLinker; import jdk.internal.dynalink.beans.StaticClass; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkerServices; -import jdk.nashorn.api.scripting.ScriptObjectMirror; +import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.codegen.CompilerConstants.Call; import jdk.nashorn.internal.codegen.RuntimeCallSite; import jdk.nashorn.internal.runtime.JSType; @@ -87,7 +87,7 @@ public final class Bootstrap { } return obj instanceof ScriptFunction || - ((obj instanceof ScriptObjectMirror) && ((ScriptObjectMirror)obj).isFunction()) || + ((obj instanceof JSObject) && ((JSObject)obj).isFunction()) || isDynamicMethod(obj) || isFunctionalInterfaceObject(obj) || obj instanceof StaticClass; diff --git a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java index 1b7eb66b4e9..45451a8bad7 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/linker/JSObjectLinker.java @@ -30,7 +30,6 @@ import jdk.nashorn.internal.lookup.MethodHandleFactory; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.util.Objects; import jdk.internal.dynalink.CallSiteDescriptor; import jdk.internal.dynalink.linker.GuardedInvocation; import jdk.internal.dynalink.linker.LinkRequest; @@ -88,8 +87,9 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { case "setElem": return c > 2 ? findSetMethod(desc) : findSetIndexMethod(); case "call": - case "callMethod": return findCallMethod(desc, operator); + case "callMethod": + return findCallMethodMethod(desc, operator); case "new": return findNewMethod(desc); default: @@ -98,33 +98,37 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { } private static GuardedInvocation findGetMethod(final CallSiteDescriptor desc) { - final MethodHandle getter = MH.insertArguments(JSOBJECT_GET, 1, desc.getNameToken(2)); + final MethodHandle getter = MH.insertArguments(JSOBJECT_GETMEMBER, 1, desc.getNameToken(2)); return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD); } private static GuardedInvocation findGetIndexMethod() { - return new GuardedInvocation(JSOBJECT_GET, null, IS_JSOBJECT_GUARD); + return new GuardedInvocation(JSOBJECTLINKER_GET, null, IS_JSOBJECT_GUARD); } private static GuardedInvocation findSetMethod(final CallSiteDescriptor desc) { - final MethodHandle getter = MH.insertArguments(JSOBJECT_PUT, 1, desc.getNameToken(2)); + final MethodHandle getter = MH.insertArguments(JSOBJECT_SETMEMBER, 1, desc.getNameToken(2)); return new GuardedInvocation(getter, null, IS_JSOBJECT_GUARD); } private static GuardedInvocation findSetIndexMethod() { - return new GuardedInvocation(JSOBJECT_PUT, null, IS_JSOBJECT_GUARD); + return new GuardedInvocation(JSOBJECTLINKER_PUT, null, IS_JSOBJECT_GUARD); } - private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final String operator) { - // if operator is "call", then 'self' is a JSObject function object already. Use 'call' as the method name - final String methodName = "callMethod".equals(operator)? desc.getNameToken(2) : "call"; - MethodHandle func = MH.insertArguments(JSOBJECT_CALL, 1, methodName); + private static GuardedInvocation findCallMethodMethod(final CallSiteDescriptor desc, final String operator) { + final String methodName = desc.getNameToken(2); + MethodHandle func = MH.insertArguments(JSOBJECT_CALLMEMBER, 1, methodName); func = MH.asCollector(func, Object[].class, desc.getMethodType().parameterCount() - 1); return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); } + private static GuardedInvocation findCallMethod(final CallSiteDescriptor desc, final String operator) { + final MethodHandle func = MH.asCollector(JSOBJECT_CALL, Object[].class, desc.getMethodType().parameterCount() - 2); + return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); + } + private static GuardedInvocation findNewMethod(final CallSiteDescriptor desc) { - MethodHandle func = MH.asCollector(JSOBJECT_NEW, Object[].class, desc.getMethodType().parameterCount() - 1); + final MethodHandle func = MH.asCollector(JSOBJECT_NEW, Object[].class, desc.getMethodType().parameterCount() - 1); return new GuardedInvocation(func, null, IS_JSOBJECT_GUARD); } @@ -135,36 +139,30 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { @SuppressWarnings("unused") private static Object get(final Object jsobj, final Object key) { - if (key instanceof String) { - return ((JSObject)jsobj).getMember((String)key); + if (key instanceof Integer) { + return ((JSObject)jsobj).getSlot((int)(Integer)key); } else if (key instanceof Number) { final int index = getIndex((Number)key); if (index > -1) { return ((JSObject)jsobj).getSlot(index); } + } else if (key instanceof String) { + return ((JSObject)jsobj).getMember((String)key); } return null; } @SuppressWarnings("unused") private static void put(final Object jsobj, final Object key, final Object value) { - if (key instanceof String) { - ((JSObject)jsobj).setMember((String)key, value); + if (key instanceof Integer) { + ((JSObject)jsobj).setSlot((int)(Integer)key, value); } else if (key instanceof Number) { ((JSObject)jsobj).setSlot(getIndex((Number)key), value); + } else if (key instanceof String) { + ((JSObject)jsobj).setMember((String)key, value); } } - @SuppressWarnings("unused") - private static Object call(final Object jsobj, final Object method, final Object... args) { - return ((JSObject)jsobj).call(Objects.toString(method), args); - } - - @SuppressWarnings("unused") - private static Object newObject(final Object jsobj, final Object... args) { - return ((JSObject)jsobj).newObject(null, args); - } - private static int getIndex(final Number n) { final double value = n.doubleValue(); return JSType.isRepresentableAsInt(value) ? (int)value : -1; @@ -172,11 +170,17 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { private static final MethodHandleFunctionality MH = MethodHandleFactory.getFunctionality(); - private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH("isJSObject", boolean.class, Object.class); - private static final MethodHandle JSOBJECT_GET = findOwnMH("get", Object.class, Object.class, Object.class); - private static final MethodHandle JSOBJECT_PUT = findOwnMH("put", Void.TYPE, Object.class, Object.class, Object.class); - private static final MethodHandle JSOBJECT_CALL = findOwnMH("call", Object.class, Object.class, Object.class, Object[].class); - private static final MethodHandle JSOBJECT_NEW = findOwnMH("newObject", Object.class, Object.class, Object[].class); + // method handles of the current class + private static final MethodHandle IS_JSOBJECT_GUARD = findOwnMH("isJSObject", boolean.class, Object.class); + private static final MethodHandle JSOBJECTLINKER_GET = findOwnMH("get", Object.class, Object.class, Object.class); + private static final MethodHandle JSOBJECTLINKER_PUT = findOwnMH("put", Void.TYPE, Object.class, Object.class, Object.class); + + // method handles of JSObject class + private static final MethodHandle JSOBJECT_GETMEMBER = findJSObjectMH("getMember", Object.class, String.class); + private static final MethodHandle JSOBJECT_SETMEMBER = findJSObjectMH("setMember", Void.TYPE, String.class, Object.class); + private static final MethodHandle JSOBJECT_CALLMEMBER = findJSObjectMH("callMember", Object.class, String.class, Object[].class); + private static final MethodHandle JSOBJECT_CALL = findJSObjectMH("call", Object.class, Object.class, Object[].class); + private static final MethodHandle JSOBJECT_NEW = findJSObjectMH("newObject", Object.class, Object[].class); private static MethodHandle findOwnMH(final String name, final Class rtype, final Class... types) { final Class own = JSObjectLinker.class; @@ -187,4 +191,14 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker { return MH.findVirtual(MethodHandles.lookup(), own, name, mt); } } + + private static MethodHandle findJSObjectMH(final String name, final Class rtype, final Class... types) { + final Class own = JSObject.class; + final MethodType mt = MH.type(rtype, types); + try { + return MH.findVirtual(MethodHandles.publicLookup(), own, name, mt); + } catch (final MethodHandleFactory.LookupException e) { + return MH.findVirtual(MethodHandles.lookup(), own, name, mt); + } + } } diff --git a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java index 68df99f3af3..f4edecc40ca 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java +++ b/nashorn/src/jdk/nashorn/internal/runtime/regexp/RegExpScanner.java @@ -263,15 +263,6 @@ final class RegExpScanner extends Scanner { } if (atom()) { - // Check for character classes that never or always match - if (sb.toString().endsWith("[]")) { - sb.setLength(sb.length() - 1); - sb.append("^\\s\\S]"); - } else if (sb.toString().endsWith("[^]")) { - sb.setLength(sb.length() - 2); - sb.append("\\s\\S]"); - } - quantifier(); return true; } @@ -767,7 +758,18 @@ final class RegExpScanner extends Scanner { if (classRanges() && ch0 == ']') { pop(']'); - return commit(1); + commit(1); + + // Substitute empty character classes [] and [^] that never or always match + if (position == startIn + 2) { + sb.setLength(sb.length() - 1); + sb.append("^\\s\\S]"); + } else if (position == startIn + 3 && inNegativeClass) { + sb.setLength(sb.length() - 2); + sb.append("\\s\\S]"); + } + + return true; } } finally { inCharClass = false; // no nested character classes in JavaScript diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties index 68f68c0a25b..1a37ba7bf76 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -57,6 +57,7 @@ parser.error.missing.catch.or.finally=Missing catch or finally after try parser.error.regex.unsupported.flag=Unsupported RegExp flag: {0} parser.error.regex.repeated.flag=Repeated RegExp flag: {0} parser.error.regex.syntax={0} +parser.error.trailing.comma.in.json=Trailing comma is not allowed in JSON # strict mode error messages parser.error.strict.no.with="with" statement cannot be used in strict mode @@ -110,6 +111,7 @@ type.error.cannot.get.default.string=Cannot get default string value type.error.cannot.get.default.number=Cannot get default number value type.error.cant.apply.with.to.null=Cannot apply "with" to null type.error.cant.apply.with.to.undefined=Cannot apply "with" to undefined +type.error.cant.apply.with.to.non.scriptobject=Cannot apply "with" to non script object type.error.in.with.non.object=Right hand side of "in" cannot be non-Object, found {0} type.error.prototype.not.an.object="prototype" of {0} is not an Object, it is {1} type.error.cant.load.script=Cannot load script from {0} diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/base.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/base.js index 00559129298..b0bfc3fb1ee 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/base.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/base.js @@ -23,204 +23,126 @@ * questions. */ -Scene = Java.type("javafx.scene.Scene"); -Group = Java.type("javafx.scene.Group"); -Stage = Java.type("javafx.stage.Stage"); +var JFX_BASE_CLASSES = []; +var JFX_GRAPHICS_CLASSES = []; +var JFX_CONTROLS_CLASSES = []; +var JFX_FXML_CLASSES = []; +var JFX_WEB_CLASSES = []; +var JFX_MEDIA_CLASSES = []; +var JFX_SWING_CLASSES = []; +var JFX_SWT_CLASSES = []; -Binding = Java.type("javafx.beans.binding.Binding"); -Bindings = Java.type("javafx.beans.binding.Bindings"); -BooleanBinding = Java.type("javafx.beans.binding.BooleanBinding"); -BooleanExpression = Java.type("javafx.beans.binding.BooleanExpression"); -DoubleBinding = Java.type("javafx.beans.binding.DoubleBinding"); -DoubleExpression = Java.type("javafx.beans.binding.DoubleExpression"); -FloatBinding = Java.type("javafx.beans.binding.FloatBinding"); -FloatExpression = Java.type("javafx.beans.binding.FloatExpression"); -IntegerBinding = Java.type("javafx.beans.binding.IntegerBinding"); -IntegerExpression = Java.type("javafx.beans.binding.IntegerExpression"); -ListBinding = Java.type("javafx.beans.binding.ListBinding"); -ListExpression = Java.type("javafx.beans.binding.ListExpression"); -LongBinding = Java.type("javafx.beans.binding.LongBinding"); -LongExpression = Java.type("javafx.beans.binding.LongExpression"); -MapBinding = Java.type("javafx.beans.binding.MapBinding"); -MapExpression = Java.type("javafx.beans.binding.MapExpression"); -NumberBinding = Java.type("javafx.beans.binding.NumberBinding"); -NumberExpression = Java.type("javafx.beans.binding.NumberExpression"); -NumberExpressionBase = Java.type("javafx.beans.binding.NumberExpressionBase"); -ObjectBinding = Java.type("javafx.beans.binding.ObjectBinding"); -ObjectExpression = Java.type("javafx.beans.binding.ObjectExpression"); -SetBinding = Java.type("javafx.beans.binding.SetBinding"); -SetExpression = Java.type("javafx.beans.binding.SetExpression"); -StringBinding = Java.type("javafx.beans.binding.StringBinding"); -StringExpression = Java.type("javafx.beans.binding.StringExpression"); -When = Java.type("javafx.beans.binding.When"); -DefaultProperty = Java.type("javafx.beans.DefaultProperty"); -InvalidationListener = Java.type("javafx.beans.InvalidationListener"); -Observable = Java.type("javafx.beans.Observable"); -JavaBeanBooleanProperty = Java.type("javafx.beans.property.adapter.JavaBeanBooleanProperty"); -JavaBeanBooleanPropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanBooleanPropertyBuilder"); -JavaBeanDoubleProperty = Java.type("javafx.beans.property.adapter.JavaBeanDoubleProperty"); -JavaBeanDoublePropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanDoublePropertyBuilder"); -JavaBeanFloatProperty = Java.type("javafx.beans.property.adapter.JavaBeanFloatProperty"); -JavaBeanFloatPropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanFloatPropertyBuilder"); -JavaBeanIntegerProperty = Java.type("javafx.beans.property.adapter.JavaBeanIntegerProperty"); -JavaBeanIntegerPropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanIntegerPropertyBuilder"); -JavaBeanLongProperty = Java.type("javafx.beans.property.adapter.JavaBeanLongProperty"); -JavaBeanLongPropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanLongPropertyBuilder"); -JavaBeanObjectProperty = Java.type("javafx.beans.property.adapter.JavaBeanObjectProperty"); -JavaBeanObjectPropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanObjectPropertyBuilder"); -JavaBeanProperty = Java.type("javafx.beans.property.adapter.JavaBeanProperty"); -JavaBeanStringProperty = Java.type("javafx.beans.property.adapter.JavaBeanStringProperty"); -JavaBeanStringPropertyBuilder = Java.type("javafx.beans.property.adapter.JavaBeanStringPropertyBuilder"); -ReadOnlyJavaBeanBooleanProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanBooleanProperty"); -ReadOnlyJavaBeanBooleanPropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanBooleanPropertyBuilder"); -ReadOnlyJavaBeanDoubleProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanDoubleProperty"); -ReadOnlyJavaBeanDoublePropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanDoublePropertyBuilder"); -ReadOnlyJavaBeanFloatProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanFloatProperty"); -ReadOnlyJavaBeanFloatPropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanFloatPropertyBuilder"); -ReadOnlyJavaBeanIntegerProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanIntegerProperty"); -ReadOnlyJavaBeanIntegerPropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanIntegerPropertyBuilder"); -ReadOnlyJavaBeanLongProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanLongProperty"); -ReadOnlyJavaBeanLongPropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanLongPropertyBuilder"); -ReadOnlyJavaBeanObjectProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanObjectProperty"); -ReadOnlyJavaBeanObjectPropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanObjectPropertyBuilder"); -ReadOnlyJavaBeanProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanProperty"); -ReadOnlyJavaBeanStringProperty = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanStringProperty"); -ReadOnlyJavaBeanStringPropertyBuilder = Java.type("javafx.beans.property.adapter.ReadOnlyJavaBeanStringPropertyBuilder"); -BooleanProperty = Java.type("javafx.beans.property.BooleanProperty"); -BooleanPropertyBase = Java.type("javafx.beans.property.BooleanPropertyBase"); -DoubleProperty = Java.type("javafx.beans.property.DoubleProperty"); -DoublePropertyBase = Java.type("javafx.beans.property.DoublePropertyBase"); -FloatProperty = Java.type("javafx.beans.property.FloatProperty"); -FloatPropertyBase = Java.type("javafx.beans.property.FloatPropertyBase"); -IntegerProperty = Java.type("javafx.beans.property.IntegerProperty"); -IntegerPropertyBase = Java.type("javafx.beans.property.IntegerPropertyBase"); -ListProperty = Java.type("javafx.beans.property.ListProperty"); -ListPropertyBase = Java.type("javafx.beans.property.ListPropertyBase"); -LongProperty = Java.type("javafx.beans.property.LongProperty"); -LongPropertyBase = Java.type("javafx.beans.property.LongPropertyBase"); -MapProperty = Java.type("javafx.beans.property.MapProperty"); -MapPropertyBase = Java.type("javafx.beans.property.MapPropertyBase"); -ObjectProperty = Java.type("javafx.beans.property.ObjectProperty"); -ObjectPropertyBase = Java.type("javafx.beans.property.ObjectPropertyBase"); -Property = Java.type("javafx.beans.property.Property"); -ReadOnlyBooleanProperty = Java.type("javafx.beans.property.ReadOnlyBooleanProperty"); -ReadOnlyBooleanPropertyBase = Java.type("javafx.beans.property.ReadOnlyBooleanPropertyBase"); -ReadOnlyBooleanWrapper = Java.type("javafx.beans.property.ReadOnlyBooleanWrapper"); -ReadOnlyDoubleProperty = Java.type("javafx.beans.property.ReadOnlyDoubleProperty"); -ReadOnlyDoublePropertyBase = Java.type("javafx.beans.property.ReadOnlyDoublePropertyBase"); -ReadOnlyDoubleWrapper = Java.type("javafx.beans.property.ReadOnlyDoubleWrapper"); -ReadOnlyFloatProperty = Java.type("javafx.beans.property.ReadOnlyFloatProperty"); -ReadOnlyFloatPropertyBase = Java.type("javafx.beans.property.ReadOnlyFloatPropertyBase"); -ReadOnlyFloatWrapper = Java.type("javafx.beans.property.ReadOnlyFloatWrapper"); -ReadOnlyIntegerProperty = Java.type("javafx.beans.property.ReadOnlyIntegerProperty"); -ReadOnlyIntegerPropertyBase = Java.type("javafx.beans.property.ReadOnlyIntegerPropertyBase"); -ReadOnlyIntegerWrapper = Java.type("javafx.beans.property.ReadOnlyIntegerWrapper"); -ReadOnlyListProperty = Java.type("javafx.beans.property.ReadOnlyListProperty"); -ReadOnlyListPropertyBase = Java.type("javafx.beans.property.ReadOnlyListPropertyBase"); -ReadOnlyListWrapper = Java.type("javafx.beans.property.ReadOnlyListWrapper"); -ReadOnlyLongProperty = Java.type("javafx.beans.property.ReadOnlyLongProperty"); -ReadOnlyLongPropertyBase = Java.type("javafx.beans.property.ReadOnlyLongPropertyBase"); -ReadOnlyLongWrapper = Java.type("javafx.beans.property.ReadOnlyLongWrapper"); -ReadOnlyMapProperty = Java.type("javafx.beans.property.ReadOnlyMapProperty"); -ReadOnlyMapPropertyBase = Java.type("javafx.beans.property.ReadOnlyMapPropertyBase"); -ReadOnlyMapWrapper = Java.type("javafx.beans.property.ReadOnlyMapWrapper"); -ReadOnlyObjectProperty = Java.type("javafx.beans.property.ReadOnlyObjectProperty"); -ReadOnlyObjectPropertyBase = Java.type("javafx.beans.property.ReadOnlyObjectPropertyBase"); -ReadOnlyObjectWrapper = Java.type("javafx.beans.property.ReadOnlyObjectWrapper"); -ReadOnlyProperty = Java.type("javafx.beans.property.ReadOnlyProperty"); -ReadOnlySetProperty = Java.type("javafx.beans.property.ReadOnlySetProperty"); -ReadOnlySetPropertyBase = Java.type("javafx.beans.property.ReadOnlySetPropertyBase"); -ReadOnlySetWrapper = Java.type("javafx.beans.property.ReadOnlySetWrapper"); -ReadOnlyStringProperty = Java.type("javafx.beans.property.ReadOnlyStringProperty"); -ReadOnlyStringPropertyBase = Java.type("javafx.beans.property.ReadOnlyStringPropertyBase"); -ReadOnlyStringWrapper = Java.type("javafx.beans.property.ReadOnlyStringWrapper"); -SetProperty = Java.type("javafx.beans.property.SetProperty"); -SetPropertyBase = Java.type("javafx.beans.property.SetPropertyBase"); -SimpleBooleanProperty = Java.type("javafx.beans.property.SimpleBooleanProperty"); -SimpleDoubleProperty = Java.type("javafx.beans.property.SimpleDoubleProperty"); -SimpleFloatProperty = Java.type("javafx.beans.property.SimpleFloatProperty"); -SimpleIntegerProperty = Java.type("javafx.beans.property.SimpleIntegerProperty"); -SimpleListProperty = Java.type("javafx.beans.property.SimpleListProperty"); -SimpleLongProperty = Java.type("javafx.beans.property.SimpleLongProperty"); -SimpleMapProperty = Java.type("javafx.beans.property.SimpleMapProperty"); -SimpleObjectProperty = Java.type("javafx.beans.property.SimpleObjectProperty"); -SimpleSetProperty = Java.type("javafx.beans.property.SimpleSetProperty"); -SimpleStringProperty = Java.type("javafx.beans.property.SimpleStringProperty"); -StringProperty = Java.type("javafx.beans.property.StringProperty"); -StringPropertyBase = Java.type("javafx.beans.property.StringPropertyBase"); -ChangeListener = Java.type("javafx.beans.value.ChangeListener"); -ObservableBooleanValue = Java.type("javafx.beans.value.ObservableBooleanValue"); -ObservableDoubleValue = Java.type("javafx.beans.value.ObservableDoubleValue"); -ObservableFloatValue = Java.type("javafx.beans.value.ObservableFloatValue"); -ObservableIntegerValue = Java.type("javafx.beans.value.ObservableIntegerValue"); -ObservableListValue = Java.type("javafx.beans.value.ObservableListValue"); -ObservableLongValue = Java.type("javafx.beans.value.ObservableLongValue"); -ObservableMapValue = Java.type("javafx.beans.value.ObservableMapValue"); -ObservableNumberValue = Java.type("javafx.beans.value.ObservableNumberValue"); -ObservableObjectValue = Java.type("javafx.beans.value.ObservableObjectValue"); -ObservableSetValue = Java.type("javafx.beans.value.ObservableSetValue"); -ObservableStringValue = Java.type("javafx.beans.value.ObservableStringValue"); -ObservableValue = Java.type("javafx.beans.value.ObservableValue"); -ObservableValueBase = Java.type("javafx.beans.value.ObservableValueBase"); -WeakChangeListener = Java.type("javafx.beans.value.WeakChangeListener"); -WritableBooleanValue = Java.type("javafx.beans.value.WritableBooleanValue"); -WritableDoubleValue = Java.type("javafx.beans.value.WritableDoubleValue"); -WritableFloatValue = Java.type("javafx.beans.value.WritableFloatValue"); -WritableIntegerValue = Java.type("javafx.beans.value.WritableIntegerValue"); -WritableListValue = Java.type("javafx.beans.value.WritableListValue"); -WritableLongValue = Java.type("javafx.beans.value.WritableLongValue"); -WritableMapValue = Java.type("javafx.beans.value.WritableMapValue"); -WritableNumberValue = Java.type("javafx.beans.value.WritableNumberValue"); -WritableObjectValue = Java.type("javafx.beans.value.WritableObjectValue"); -WritableSetValue = Java.type("javafx.beans.value.WritableSetValue"); -WritableStringValue = Java.type("javafx.beans.value.WritableStringValue"); -WritableValue = Java.type("javafx.beans.value.WritableValue"); -WeakInvalidationListener = Java.type("javafx.beans.WeakInvalidationListener"); -WeakListener = Java.type("javafx.beans.WeakListener"); -FXCollections = Java.type("javafx.collections.FXCollections"); -ListChangeListener = Java.type("javafx.collections.ListChangeListener"); -ListChangeListener$Change = Java.type("javafx.collections.ListChangeListener$Change"); -MapChangeListener = Java.type("javafx.collections.MapChangeListener"); -MapChangeListener$Change = Java.type("javafx.collections.MapChangeListener$Change"); -ModifiableObservableListBase = Java.type("javafx.collections.ModifiableObservableListBase"); -ObservableList = Java.type("javafx.collections.ObservableList"); -ObservableListBase = Java.type("javafx.collections.ObservableListBase"); -ObservableMap = Java.type("javafx.collections.ObservableMap"); -ObservableSet = Java.type("javafx.collections.ObservableSet"); -SetChangeListener = Java.type("javafx.collections.SetChangeListener"); -SetChangeListener$Change = Java.type("javafx.collections.SetChangeListener$Change"); -WeakListChangeListener = Java.type("javafx.collections.WeakListChangeListener"); -WeakMapChangeListener = Java.type("javafx.collections.WeakMapChangeListener"); -WeakSetChangeListener = Java.type("javafx.collections.WeakSetChangeListener"); -ActionEvent = Java.type("javafx.event.ActionEvent"); -Event = Java.type("javafx.event.Event"); -EventDispatchChain = Java.type("javafx.event.EventDispatchChain"); -EventDispatcher = Java.type("javafx.event.EventDispatcher"); -EventHandler = Java.type("javafx.event.EventHandler"); -EventTarget = Java.type("javafx.event.EventTarget"); -EventType = Java.type("javafx.event.EventType"); -WeakEventHandler = Java.type("javafx.event.WeakEventHandler"); -Builder = Java.type("javafx.util.Builder"); -BuilderFactory = Java.type("javafx.util.BuilderFactory"); -Callback = Java.type("javafx.util.Callback"); -BigDecimalStringConverter = Java.type("javafx.util.converter.BigDecimalStringConverter"); -BigIntegerStringConverter = Java.type("javafx.util.converter.BigIntegerStringConverter"); -BooleanStringConverter = Java.type("javafx.util.converter.BooleanStringConverter"); -ByteStringConverter = Java.type("javafx.util.converter.ByteStringConverter"); -CharacterStringConverter = Java.type("javafx.util.converter.CharacterStringConverter"); -CurrencyStringConverter = Java.type("javafx.util.converter.CurrencyStringConverter"); -DateStringConverter = Java.type("javafx.util.converter.DateStringConverter"); -DateTimeStringConverter = Java.type("javafx.util.converter.DateTimeStringConverter"); -DefaultStringConverter = Java.type("javafx.util.converter.DefaultStringConverter"); -DoubleStringConverter = Java.type("javafx.util.converter.DoubleStringConverter"); -FloatStringConverter = Java.type("javafx.util.converter.FloatStringConverter"); -FormatStringConverter = Java.type("javafx.util.converter.FormatStringConverter"); -IntegerStringConverter = Java.type("javafx.util.converter.IntegerStringConverter"); -LongStringConverter = Java.type("javafx.util.converter.LongStringConverter"); -NumberStringConverter = Java.type("javafx.util.converter.NumberStringConverter"); -PercentageStringConverter = Java.type("javafx.util.converter.PercentageStringConverter"); -ShortStringConverter = Java.type("javafx.util.converter.ShortStringConverter"); -TimeStringConverter = Java.type("javafx.util.converter.TimeStringConverter"); -Duration = Java.type("javafx.util.Duration"); -Pair = Java.type("javafx.util.Pair"); -StringConverter = Java.type("javafx.util.StringConverter"); +function LOAD_FX_CLASSES(clsList) { + + for each (var cls in clsList) { + // Ex. Stage = Java.type("javafx.stage.Stage"); + this[cls[cls.length - 1]] = Java.type(cls.join(".")); + } +} + +(function() { + var System = Java.type("java.lang.System"); + var ZipFile = Java.type("java.util.zip.ZipFile"); + + var SUFFIX_LENGTH = ".class".length; + + try { + var jfxrtJar = new ZipFile(System.getProperty("java.home") + "/lib/ext/jfxrt.jar"); + } catch (ex) { + throw new Error("JavaFX runtime not found"); + } + + var entries = jfxrtJar.entries(); + + while (entries.hasMoreElements()) { + var entry = entries.nextElement(); + + if (entry.isDirectory()) { + continue; + } + + var name = entry.name; + + if (!name.endsWith(".class")) { + continue; + } + + name = name.substring(0, name.length - SUFFIX_LENGTH); + cls = name.split("/"); + + if (cls[0] != "javafx") { + continue; + } + + var last = cls[cls.length - 1]; + var nested = last.lastIndexOf("$"); + + // If class name ends with $nnn + if (nested != -1 && !(last.substring(nested) - 0)) { + continue; + } + + switch (cls[1]) { + case "stage": + if (cls[2] == "Stage") { + JFX_BASE_CLASSES.push(cls); + } else { + JFX_GRAPHICS_CLASSES.push(cls); + } + break; + + case "scene": + switch (cls[2]) { + case "Scene": + case "Group": + JFX_BASE_CLASSES.push(cls); + break; + + case "chart": + case "control": + JFX_CONTROLS_CLASSES.push(cls); + break; + + case "web": + JFX_WEB_CLASSES.push(cls); + break; + + case "media": + JFX_MEDIA_CLASSES.push(cls); + break; + + default: + JFX_GRAPHICS_CLASSES.push(cls); + break; + } + break; + + case "beans": + case "collections": + case "events": + case "util": + JFX_BASE_CLASSES.push(cls); + break; + + case "animation": + case "application": + case "concurrent": + case "css": + case "geometry": + JFX_GRAPHICS_CLASSES.push(cls); + break; + + case "fxml": + JFX_FXML_CLASSES.push(cls); + break; + + case "embed": + if (cls[2] == "swing") { + JFX_SWING_CLASSES.push(cls); + } else { + JFX_SWT_CLASSES.push(cls); + } + break; + } + } +})(); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/controls.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/controls.js index 6a2a89c400c..ca3f284c8e3 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/controls.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/controls.js @@ -23,242 +23,8 @@ * questions. */ -AreaChart = Java.type("javafx.scene.chart.AreaChart"); -AreaChartBuilder = Java.type("javafx.scene.chart.AreaChartBuilder"); -Axis = Java.type("javafx.scene.chart.Axis"); -Axis$TickMark = Java.type("javafx.scene.chart.Axis$TickMark"); -AxisBuilder = Java.type("javafx.scene.chart.AxisBuilder"); -BarChart = Java.type("javafx.scene.chart.BarChart"); -BarChartBuilder = Java.type("javafx.scene.chart.BarChartBuilder"); -BubbleChart = Java.type("javafx.scene.chart.BubbleChart"); -BubbleChartBuilder = Java.type("javafx.scene.chart.BubbleChartBuilder"); -CategoryAxis = Java.type("javafx.scene.chart.CategoryAxis"); -CategoryAxisBuilder = Java.type("javafx.scene.chart.CategoryAxisBuilder"); -Chart = Java.type("javafx.scene.chart.Chart"); -ChartBuilder = Java.type("javafx.scene.chart.ChartBuilder"); -LineChart = Java.type("javafx.scene.chart.LineChart"); -LineChartBuilder = Java.type("javafx.scene.chart.LineChartBuilder"); -NumberAxis = Java.type("javafx.scene.chart.NumberAxis"); -NumberAxis$DefaultFormatter = Java.type("javafx.scene.chart.NumberAxis$DefaultFormatter"); -NumberAxisBuilder = Java.type("javafx.scene.chart.NumberAxisBuilder"); -PieChart = Java.type("javafx.scene.chart.PieChart"); -PieChart$Data = Java.type("javafx.scene.chart.PieChart$Data"); -PieChartBuilder = Java.type("javafx.scene.chart.PieChartBuilder"); -ScatterChart = Java.type("javafx.scene.chart.ScatterChart"); -ScatterChartBuilder = Java.type("javafx.scene.chart.ScatterChartBuilder"); -StackedAreaChart = Java.type("javafx.scene.chart.StackedAreaChart"); -StackedAreaChartBuilder = Java.type("javafx.scene.chart.StackedAreaChartBuilder"); -StackedBarChart = Java.type("javafx.scene.chart.StackedBarChart"); -StackedBarChartBuilder = Java.type("javafx.scene.chart.StackedBarChartBuilder"); -ValueAxis = Java.type("javafx.scene.chart.ValueAxis"); -ValueAxisBuilder = Java.type("javafx.scene.chart.ValueAxisBuilder"); -XYChart = Java.type("javafx.scene.chart.XYChart"); -XYChart$Data = Java.type("javafx.scene.chart.XYChart$Data"); -XYChart$Series = Java.type("javafx.scene.chart.XYChart$Series"); -XYChartBuilder = Java.type("javafx.scene.chart.XYChartBuilder"); -Accordion = Java.type("javafx.scene.control.Accordion"); -AccordionBuilder = Java.type("javafx.scene.control.AccordionBuilder"); -Button = Java.type("javafx.scene.control.Button"); -ButtonBase = Java.type("javafx.scene.control.ButtonBase"); -ButtonBaseBuilder = Java.type("javafx.scene.control.ButtonBaseBuilder"); -ButtonBuilder = Java.type("javafx.scene.control.ButtonBuilder"); -Cell = Java.type("javafx.scene.control.Cell"); -CheckBoxListCell = Java.type("javafx.scene.control.cell.CheckBoxListCell"); -CheckBoxListCellBuilder = Java.type("javafx.scene.control.cell.CheckBoxListCellBuilder"); -CheckBoxTableCell = Java.type("javafx.scene.control.cell.CheckBoxTableCell"); -CheckBoxTableCellBuilder = Java.type("javafx.scene.control.cell.CheckBoxTableCellBuilder"); -CheckBoxTreeCell = Java.type("javafx.scene.control.cell.CheckBoxTreeCell"); -CheckBoxTreeCellBuilder = Java.type("javafx.scene.control.cell.CheckBoxTreeCellBuilder"); -CheckBoxTreeTableCell = Java.type("javafx.scene.control.cell.CheckBoxTreeTableCell"); -//CheckBoxTreeTableCellBuilder = Java.type("javafx.scene.control.cell.CheckBoxTreeTableCellBuilder"); -ChoiceBoxListCell = Java.type("javafx.scene.control.cell.ChoiceBoxListCell"); -ChoiceBoxListCellBuilder = Java.type("javafx.scene.control.cell.ChoiceBoxListCellBuilder"); -ChoiceBoxTableCell = Java.type("javafx.scene.control.cell.ChoiceBoxTableCell"); -ChoiceBoxTableCellBuilder = Java.type("javafx.scene.control.cell.ChoiceBoxTableCellBuilder"); -ChoiceBoxTreeCell = Java.type("javafx.scene.control.cell.ChoiceBoxTreeCell"); -ChoiceBoxTreeCellBuilder = Java.type("javafx.scene.control.cell.ChoiceBoxTreeCellBuilder"); -ChoiceBoxTreeTableCell = Java.type("javafx.scene.control.cell.ChoiceBoxTreeTableCell"); -//ChoiceBoxTreeTableCellBuilder = Java.type("javafx.scene.control.cell.ChoiceBoxTreeTableCellBuilder"); -ComboBoxListCell = Java.type("javafx.scene.control.cell.ComboBoxListCell"); -ComboBoxListCellBuilder = Java.type("javafx.scene.control.cell.ComboBoxListCellBuilder"); -ComboBoxTableCell = Java.type("javafx.scene.control.cell.ComboBoxTableCell"); -ComboBoxTableCellBuilder = Java.type("javafx.scene.control.cell.ComboBoxTableCellBuilder"); -ComboBoxTreeCell = Java.type("javafx.scene.control.cell.ComboBoxTreeCell"); -ComboBoxTreeCellBuilder = Java.type("javafx.scene.control.cell.ComboBoxTreeCellBuilder"); -ComboBoxTreeTableCell = Java.type("javafx.scene.control.cell.ComboBoxTreeTableCell"); -//ComboBoxTreeTableCellBuilder = Java.type("javafx.scene.control.cell.ComboBoxTreeTableCellBuilder"); -MapValueFactory = Java.type("javafx.scene.control.cell.MapValueFactory"); -ProgressBarTableCell = Java.type("javafx.scene.control.cell.ProgressBarTableCell"); -ProgressBarTreeTableCell = Java.type("javafx.scene.control.cell.ProgressBarTreeTableCell"); -PropertyValueFactory = Java.type("javafx.scene.control.cell.PropertyValueFactory"); -PropertyValueFactoryBuilder = Java.type("javafx.scene.control.cell.PropertyValueFactoryBuilder"); -TextFieldListCell = Java.type("javafx.scene.control.cell.TextFieldListCell"); -TextFieldListCellBuilder = Java.type("javafx.scene.control.cell.TextFieldListCellBuilder"); -TextFieldTableCell = Java.type("javafx.scene.control.cell.TextFieldTableCell"); -TextFieldTableCellBuilder = Java.type("javafx.scene.control.cell.TextFieldTableCellBuilder"); -TextFieldTreeCell = Java.type("javafx.scene.control.cell.TextFieldTreeCell"); -TextFieldTreeCellBuilder = Java.type("javafx.scene.control.cell.TextFieldTreeCellBuilder"); -TextFieldTreeTableCell = Java.type("javafx.scene.control.cell.TextFieldTreeTableCell"); -//TextFieldTreeTableCellBuilder = Java.type("javafx.scene.control.cell.TextFieldTreeTableCellBuilder"); -TreeItemPropertyValueFactory = Java.type("javafx.scene.control.cell.TreeItemPropertyValueFactory"); -//TreeItemPropertyValueFactoryBuilder = Java.type("javafx.scene.control.cell.TreeItemPropertyValueFactoryBuilder"); -CellBuilder = Java.type("javafx.scene.control.CellBuilder"); -CheckBox = Java.type("javafx.scene.control.CheckBox"); -CheckBoxBuilder = Java.type("javafx.scene.control.CheckBoxBuilder"); -CheckBoxTreeItem = Java.type("javafx.scene.control.CheckBoxTreeItem"); -CheckBoxTreeItem$TreeModificationEvent = Java.type("javafx.scene.control.CheckBoxTreeItem$TreeModificationEvent"); -CheckBoxTreeItemBuilder = Java.type("javafx.scene.control.CheckBoxTreeItemBuilder"); -CheckMenuItem = Java.type("javafx.scene.control.CheckMenuItem"); -CheckMenuItemBuilder = Java.type("javafx.scene.control.CheckMenuItemBuilder"); -ChoiceBox = Java.type("javafx.scene.control.ChoiceBox"); -ChoiceBoxBuilder = Java.type("javafx.scene.control.ChoiceBoxBuilder"); -ColorPicker = Java.type("javafx.scene.control.ColorPicker"); -ColorPickerBuilder = Java.type("javafx.scene.control.ColorPickerBuilder"); -ComboBox = Java.type("javafx.scene.control.ComboBox"); -ComboBoxBase = Java.type("javafx.scene.control.ComboBoxBase"); -ComboBoxBaseBuilder = Java.type("javafx.scene.control.ComboBoxBaseBuilder"); -ComboBoxBuilder = Java.type("javafx.scene.control.ComboBoxBuilder"); -ContentDisplay = Java.type("javafx.scene.control.ContentDisplay"); -ContextMenu = Java.type("javafx.scene.control.ContextMenu"); -ContextMenuBuilder = Java.type("javafx.scene.control.ContextMenuBuilder"); -Control = Java.type("javafx.scene.control.Control"); -ControlBuilder = Java.type("javafx.scene.control.ControlBuilder"); -CustomMenuItem = Java.type("javafx.scene.control.CustomMenuItem"); -CustomMenuItemBuilder = Java.type("javafx.scene.control.CustomMenuItemBuilder"); -FocusModel = Java.type("javafx.scene.control.FocusModel"); -Hyperlink = Java.type("javafx.scene.control.Hyperlink"); -HyperlinkBuilder = Java.type("javafx.scene.control.HyperlinkBuilder"); -IndexedCell = Java.type("javafx.scene.control.IndexedCell"); -IndexedCellBuilder = Java.type("javafx.scene.control.IndexedCellBuilder"); -IndexRange = Java.type("javafx.scene.control.IndexRange"); -IndexRangeBuilder = Java.type("javafx.scene.control.IndexRangeBuilder"); -Label = Java.type("javafx.scene.control.Label"); -LabelBuilder = Java.type("javafx.scene.control.LabelBuilder"); -Labeled = Java.type("javafx.scene.control.Labeled"); -LabeledBuilder = Java.type("javafx.scene.control.LabeledBuilder"); -ListCell = Java.type("javafx.scene.control.ListCell"); -ListCellBuilder = Java.type("javafx.scene.control.ListCellBuilder"); -ListView = Java.type("javafx.scene.control.ListView"); -ListView$EditEvent = Java.type("javafx.scene.control.ListView$EditEvent"); -ListViewBuilder = Java.type("javafx.scene.control.ListViewBuilder"); -Menu = Java.type("javafx.scene.control.Menu"); -MenuBar = Java.type("javafx.scene.control.MenuBar"); -MenuBarBuilder = Java.type("javafx.scene.control.MenuBarBuilder"); -MenuBuilder = Java.type("javafx.scene.control.MenuBuilder"); -MenuButton = Java.type("javafx.scene.control.MenuButton"); -MenuButtonBuilder = Java.type("javafx.scene.control.MenuButtonBuilder"); -MenuItem = Java.type("javafx.scene.control.MenuItem"); -MenuItemBuilder = Java.type("javafx.scene.control.MenuItemBuilder"); -MultipleSelectionModel = Java.type("javafx.scene.control.MultipleSelectionModel"); -MultipleSelectionModelBuilder = Java.type("javafx.scene.control.MultipleSelectionModelBuilder"); -OverrunStyle = Java.type("javafx.scene.control.OverrunStyle"); -Pagination = Java.type("javafx.scene.control.Pagination"); -PaginationBuilder = Java.type("javafx.scene.control.PaginationBuilder"); -PasswordField = Java.type("javafx.scene.control.PasswordField"); -PasswordFieldBuilder = Java.type("javafx.scene.control.PasswordFieldBuilder"); -PopupControl = Java.type("javafx.scene.control.PopupControl"); -PopupControlBuilder = Java.type("javafx.scene.control.PopupControlBuilder"); -ProgressBar = Java.type("javafx.scene.control.ProgressBar"); -ProgressBarBuilder = Java.type("javafx.scene.control.ProgressBarBuilder"); -ProgressIndicator = Java.type("javafx.scene.control.ProgressIndicator"); -ProgressIndicatorBuilder = Java.type("javafx.scene.control.ProgressIndicatorBuilder"); -RadioButton = Java.type("javafx.scene.control.RadioButton"); -RadioButtonBuilder = Java.type("javafx.scene.control.RadioButtonBuilder"); -RadioMenuItem = Java.type("javafx.scene.control.RadioMenuItem"); -RadioMenuItemBuilder = Java.type("javafx.scene.control.RadioMenuItemBuilder"); -ResizeFeaturesBase = Java.type("javafx.scene.control.ResizeFeaturesBase"); -//ResizeFeaturesBaseBuilder = Java.type("javafx.scene.control.ResizeFeaturesBaseBuilder"); -ScrollBar = Java.type("javafx.scene.control.ScrollBar"); -ScrollBarBuilder = Java.type("javafx.scene.control.ScrollBarBuilder"); -ScrollPane = Java.type("javafx.scene.control.ScrollPane"); -ScrollPane$ScrollBarPolicy = Java.type("javafx.scene.control.ScrollPane$ScrollBarPolicy"); -ScrollPaneBuilder = Java.type("javafx.scene.control.ScrollPaneBuilder"); -ScrollToEvent = Java.type("javafx.scene.control.ScrollToEvent"); -SelectionMode = Java.type("javafx.scene.control.SelectionMode"); -SelectionModel = Java.type("javafx.scene.control.SelectionModel"); -Separator = Java.type("javafx.scene.control.Separator"); -SeparatorBuilder = Java.type("javafx.scene.control.SeparatorBuilder"); -SeparatorMenuItem = Java.type("javafx.scene.control.SeparatorMenuItem"); -SeparatorMenuItemBuilder = Java.type("javafx.scene.control.SeparatorMenuItemBuilder"); -SingleSelectionModel = Java.type("javafx.scene.control.SingleSelectionModel"); -Skin = Java.type("javafx.scene.control.Skin"); -SkinBase = Java.type("javafx.scene.control.SkinBase"); -//SkinBaseBuilder = Java.type("javafx.scene.control.SkinBaseBuilder"); -Skinnable = Java.type("javafx.scene.control.Skinnable"); -Slider = Java.type("javafx.scene.control.Slider"); -SliderBuilder = Java.type("javafx.scene.control.SliderBuilder"); -SortEvent = Java.type("javafx.scene.control.SortEvent"); -SplitMenuButton = Java.type("javafx.scene.control.SplitMenuButton"); -SplitMenuButtonBuilder = Java.type("javafx.scene.control.SplitMenuButtonBuilder"); -SplitPane = Java.type("javafx.scene.control.SplitPane"); -SplitPane$Divider = Java.type("javafx.scene.control.SplitPane$Divider"); -SplitPaneBuilder = Java.type("javafx.scene.control.SplitPaneBuilder"); -Tab = Java.type("javafx.scene.control.Tab"); -TabBuilder = Java.type("javafx.scene.control.TabBuilder"); -TableCell = Java.type("javafx.scene.control.TableCell"); -TableCellBuilder = Java.type("javafx.scene.control.TableCellBuilder"); -TableColumn = Java.type("javafx.scene.control.TableColumn"); -TableColumn$CellDataFeatures = Java.type("javafx.scene.control.TableColumn$CellDataFeatures"); -TableColumn$CellEditEvent = Java.type("javafx.scene.control.TableColumn$CellEditEvent"); -TableColumn$SortType = Java.type("javafx.scene.control.TableColumn$SortType"); -TableColumnBase = Java.type("javafx.scene.control.TableColumnBase"); -//TableColumnBaseBuilder = Java.type("javafx.scene.control.TableColumnBaseBuilder"); -TableColumnBuilder = Java.type("javafx.scene.control.TableColumnBuilder"); -TableFocusModel = Java.type("javafx.scene.control.TableFocusModel"); -TablePosition = Java.type("javafx.scene.control.TablePosition"); -TablePositionBase = Java.type("javafx.scene.control.TablePositionBase"); -TableRow = Java.type("javafx.scene.control.TableRow"); -TableRowBuilder = Java.type("javafx.scene.control.TableRowBuilder"); -TableSelectionModel = Java.type("javafx.scene.control.TableSelectionModel"); -//TableSelectionModelBuilder = Java.type("javafx.scene.control.TableSelectionModelBuilder"); -TableView = Java.type("javafx.scene.control.TableView"); -TableView$ResizeFeatures = Java.type("javafx.scene.control.TableView$ResizeFeatures"); -TableView$TableViewFocusModel = Java.type("javafx.scene.control.TableView$TableViewFocusModel"); -TableView$TableViewSelectionModel = Java.type("javafx.scene.control.TableView$TableViewSelectionModel"); -TableViewBuilder = Java.type("javafx.scene.control.TableViewBuilder"); -TabPane = Java.type("javafx.scene.control.TabPane"); -TabPane$TabClosingPolicy = Java.type("javafx.scene.control.TabPane$TabClosingPolicy"); -TabPaneBuilder = Java.type("javafx.scene.control.TabPaneBuilder"); -TextArea = Java.type("javafx.scene.control.TextArea"); -TextAreaBuilder = Java.type("javafx.scene.control.TextAreaBuilder"); -TextField = Java.type("javafx.scene.control.TextField"); -TextFieldBuilder = Java.type("javafx.scene.control.TextFieldBuilder"); -TextInputControl = Java.type("javafx.scene.control.TextInputControl"); -TextInputControl$Content = Java.type("javafx.scene.control.TextInputControl$Content"); -TextInputControlBuilder = Java.type("javafx.scene.control.TextInputControlBuilder"); -TitledPane = Java.type("javafx.scene.control.TitledPane"); -TitledPaneBuilder = Java.type("javafx.scene.control.TitledPaneBuilder"); -Toggle = Java.type("javafx.scene.control.Toggle"); -ToggleButton = Java.type("javafx.scene.control.ToggleButton"); -ToggleButtonBuilder = Java.type("javafx.scene.control.ToggleButtonBuilder"); -ToggleGroup = Java.type("javafx.scene.control.ToggleGroup"); -ToggleGroupBuilder = Java.type("javafx.scene.control.ToggleGroupBuilder"); -ToolBar = Java.type("javafx.scene.control.ToolBar"); -ToolBarBuilder = Java.type("javafx.scene.control.ToolBarBuilder"); -Tooltip = Java.type("javafx.scene.control.Tooltip"); -TooltipBuilder = Java.type("javafx.scene.control.TooltipBuilder"); -TreeCell = Java.type("javafx.scene.control.TreeCell"); -TreeCellBuilder = Java.type("javafx.scene.control.TreeCellBuilder"); -TreeItem = Java.type("javafx.scene.control.TreeItem"); -TreeItem$TreeModificationEvent = Java.type("javafx.scene.control.TreeItem$TreeModificationEvent"); -TreeItemBuilder = Java.type("javafx.scene.control.TreeItemBuilder"); -TreeSortMode = Java.type("javafx.scene.control.TreeSortMode"); -TreeTableCell = Java.type("javafx.scene.control.TreeTableCell"); -//TreeTableCellBuilder = Java.type("javafx.scene.control.TreeTableCellBuilder"); -TreeTableColumn = Java.type("javafx.scene.control.TreeTableColumn"); -TreeTableColumn$CellDataFeatures = Java.type("javafx.scene.control.TreeTableColumn$CellDataFeatures"); -TreeTableColumn$CellEditEvent = Java.type("javafx.scene.control.TreeTableColumn$CellEditEvent"); -TreeTableColumn$SortType = Java.type("javafx.scene.control.TreeTableColumn$SortType"); -//TreeTableColumnBuilder = Java.type("javafx.scene.control.TreeTableColumnBuilder"); -TreeTablePosition = Java.type("javafx.scene.control.TreeTablePosition"); -TreeTableRow = Java.type("javafx.scene.control.TreeTableRow"); -//TreeTableRowBuilder = Java.type("javafx.scene.control.TreeTableRowBuilder"); -TreeTableView = Java.type("javafx.scene.control.TreeTableView"); -TreeTableView$EditEvent = Java.type("javafx.scene.control.TreeTableView$EditEvent"); -TreeTableView$ResizeFeatures = Java.type("javafx.scene.control.TreeTableView$ResizeFeatures"); -TreeTableView$TreeTableViewFocusModel = Java.type("javafx.scene.control.TreeTableView$TreeTableViewFocusModel"); -TreeTableView$TreeTableViewSelectionModel = Java.type("javafx.scene.control.TreeTableView$TreeTableViewSelectionModel"); -//TreeTableViewBuilder = Java.type("javafx.scene.control.TreeTableViewBuilder"); -TreeView = Java.type("javafx.scene.control.TreeView"); -TreeView$EditEvent = Java.type("javafx.scene.control.TreeView$EditEvent"); -TreeViewBuilder = Java.type("javafx.scene.control.TreeViewBuilder"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_CONTROLS_CLASSES); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/fxml.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/fxml.js index bc018a9ece3..0ce18168ce6 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/fxml.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/fxml.js @@ -23,8 +23,8 @@ * questions. */ -FXML = Java.type("javafx.fxml.FXML"); -FXMLLoader = Java.type("javafx.fxml.FXMLLoader"); -Initializable = Java.type("javafx.fxml.Initializable"); -JavaFXBuilderFactory = Java.type("javafx.fxml.JavaFXBuilderFactory"); -LoadException = Java.type("javafx.fxml.LoadException"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_FXML_CLASSES); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/graphics.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/graphics.js index 72f55cd1926..f41661fa9e1 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/graphics.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/graphics.js @@ -23,409 +23,10 @@ * questions. */ -Animation = Java.type("javafx.animation.Animation"); -Animation$Status = Java.type("javafx.animation.Animation$Status"); -AnimationBuilder = Java.type("javafx.animation.AnimationBuilder"); -AnimationTimer = Java.type("javafx.animation.AnimationTimer"); -FadeTransition = Java.type("javafx.animation.FadeTransition"); -FadeTransitionBuilder = Java.type("javafx.animation.FadeTransitionBuilder"); -FillTransition = Java.type("javafx.animation.FillTransition"); -FillTransitionBuilder = Java.type("javafx.animation.FillTransitionBuilder"); -Interpolatable = Java.type("javafx.animation.Interpolatable"); -Interpolator = Java.type("javafx.animation.Interpolator"); -KeyFrame = Java.type("javafx.animation.KeyFrame"); -KeyValue = Java.type("javafx.animation.KeyValue"); -ParallelTransition = Java.type("javafx.animation.ParallelTransition"); -ParallelTransitionBuilder = Java.type("javafx.animation.ParallelTransitionBuilder"); -PathTransition = Java.type("javafx.animation.PathTransition"); -PathTransition$OrientationType = Java.type("javafx.animation.PathTransition$OrientationType"); -PathTransitionBuilder = Java.type("javafx.animation.PathTransitionBuilder"); -PauseTransition = Java.type("javafx.animation.PauseTransition"); -PauseTransitionBuilder = Java.type("javafx.animation.PauseTransitionBuilder"); -RotateTransition = Java.type("javafx.animation.RotateTransition"); -RotateTransitionBuilder = Java.type("javafx.animation.RotateTransitionBuilder"); -ScaleTransition = Java.type("javafx.animation.ScaleTransition"); -ScaleTransitionBuilder = Java.type("javafx.animation.ScaleTransitionBuilder"); -SequentialTransition = Java.type("javafx.animation.SequentialTransition"); -SequentialTransitionBuilder = Java.type("javafx.animation.SequentialTransitionBuilder"); -StrokeTransition = Java.type("javafx.animation.StrokeTransition"); -StrokeTransitionBuilder = Java.type("javafx.animation.StrokeTransitionBuilder"); -Timeline = Java.type("javafx.animation.Timeline"); -TimelineBuilder = Java.type("javafx.animation.TimelineBuilder"); -Transition = Java.type("javafx.animation.Transition"); -TransitionBuilder = Java.type("javafx.animation.TransitionBuilder"); -TranslateTransition = Java.type("javafx.animation.TranslateTransition"); -TranslateTransitionBuilder = Java.type("javafx.animation.TranslateTransitionBuilder"); -Application = Java.type("javafx.application.Application"); -Application$Parameters = Java.type("javafx.application.Application$Parameters"); -ConditionalFeature = Java.type("javafx.application.ConditionalFeature"); -HostServices = Java.type("javafx.application.HostServices"); -Platform = Java.type("javafx.application.Platform"); -Preloader = Java.type("javafx.application.Preloader"); -Preloader$ErrorNotification = Java.type("javafx.application.Preloader$ErrorNotification"); -Preloader$PreloaderNotification = Java.type("javafx.application.Preloader$PreloaderNotification"); -Preloader$ProgressNotification = Java.type("javafx.application.Preloader$ProgressNotification"); -Preloader$StateChangeNotification = Java.type("javafx.application.Preloader$StateChangeNotification"); -Preloader$StateChangeNotification$Type = Java.type("javafx.application.Preloader$StateChangeNotification$Type"); -ScheduledService = Java.type("javafx.concurrent.ScheduledService"); -Service = Java.type("javafx.concurrent.Service"); -Task = Java.type("javafx.concurrent.Task"); -Worker = Java.type("javafx.concurrent.Worker"); -Worker$State = Java.type("javafx.concurrent.Worker$State"); -WorkerStateEvent = Java.type("javafx.concurrent.WorkerStateEvent"); -CssMetaData = Java.type("javafx.css.CssMetaData"); -FontCssMetaData = Java.type("javafx.css.FontCssMetaData"); -ParsedValue = Java.type("javafx.css.ParsedValue"); -PseudoClass = Java.type("javafx.css.PseudoClass"); -SimpleStyleableBooleanProperty = Java.type("javafx.css.SimpleStyleableBooleanProperty"); -SimpleStyleableDoubleProperty = Java.type("javafx.css.SimpleStyleableDoubleProperty"); -SimpleStyleableFloatProperty = Java.type("javafx.css.SimpleStyleableFloatProperty"); -SimpleStyleableIntegerProperty = Java.type("javafx.css.SimpleStyleableIntegerProperty"); -SimpleStyleableLongProperty = Java.type("javafx.css.SimpleStyleableLongProperty"); -SimpleStyleableObjectProperty = Java.type("javafx.css.SimpleStyleableObjectProperty"); -SimpleStyleableStringProperty = Java.type("javafx.css.SimpleStyleableStringProperty"); -Styleable = Java.type("javafx.css.Styleable"); -StyleableBooleanProperty = Java.type("javafx.css.StyleableBooleanProperty"); -StyleableDoubleProperty = Java.type("javafx.css.StyleableDoubleProperty"); -StyleableFloatProperty = Java.type("javafx.css.StyleableFloatProperty"); -StyleableIntegerProperty = Java.type("javafx.css.StyleableIntegerProperty"); -StyleableLongProperty = Java.type("javafx.css.StyleableLongProperty"); -StyleableObjectProperty = Java.type("javafx.css.StyleableObjectProperty"); -StyleableProperty = Java.type("javafx.css.StyleableProperty"); -StyleableStringProperty = Java.type("javafx.css.StyleableStringProperty"); -StyleConverter = Java.type("javafx.css.StyleConverter"); -StyleOrigin = Java.type("javafx.css.StyleOrigin"); -BoundingBox = Java.type("javafx.geometry.BoundingBox"); -BoundingBoxBuilder = Java.type("javafx.geometry.BoundingBoxBuilder"); -Bounds = Java.type("javafx.geometry.Bounds"); -Dimension2D = Java.type("javafx.geometry.Dimension2D"); -Dimension2DBuilder = Java.type("javafx.geometry.Dimension2DBuilder"); -HorizontalDirection = Java.type("javafx.geometry.HorizontalDirection"); -HPos = Java.type("javafx.geometry.HPos"); -Insets = Java.type("javafx.geometry.Insets"); -InsetsBuilder = Java.type("javafx.geometry.InsetsBuilder"); -NodeOrientation = Java.type("javafx.geometry.NodeOrientation"); -Orientation = Java.type("javafx.geometry.Orientation"); -Point2D = Java.type("javafx.geometry.Point2D"); -Point2DBuilder = Java.type("javafx.geometry.Point2DBuilder"); -Point3D = Java.type("javafx.geometry.Point3D"); -Point3DBuilder = Java.type("javafx.geometry.Point3DBuilder"); -Pos = Java.type("javafx.geometry.Pos"); -Rectangle2D = Java.type("javafx.geometry.Rectangle2D"); -Rectangle2DBuilder = Java.type("javafx.geometry.Rectangle2DBuilder"); -Side = Java.type("javafx.geometry.Side"); -VerticalDirection = Java.type("javafx.geometry.VerticalDirection"); -VPos = Java.type("javafx.geometry.VPos"); -Collation = Java.type("javafx.print.Collation"); -JobSettings = Java.type("javafx.print.JobSettings"); -PageLayout = Java.type("javafx.print.PageLayout"); -PageOrientation = Java.type("javafx.print.PageOrientation"); -PageRange = Java.type("javafx.print.PageRange"); -Paper = Java.type("javafx.print.Paper"); -Paper$Units = Java.type("javafx.print.Paper$Units"); -PaperSource = Java.type("javafx.print.PaperSource"); -PrintColor = Java.type("javafx.print.PrintColor"); -Printer = Java.type("javafx.print.Printer"); -Printer$MarginType = Java.type("javafx.print.Printer$MarginType"); -PrinterAttributes = Java.type("javafx.print.PrinterAttributes"); -PrinterJob = Java.type("javafx.print.PrinterJob"); -PrinterJob$JobStatus = Java.type("javafx.print.PrinterJob$JobStatus"); -PrintQuality = Java.type("javafx.print.PrintQuality"); -PrintResolution = Java.type("javafx.print.PrintResolution"); -PrintSides = Java.type("javafx.print.PrintSides"); -AmbientLight = Java.type("javafx.scene.AmbientLight"); -//AmbientLightBuilder = Java.type("javafx.scene.AmbientLightBuilder"); -CacheHint = Java.type("javafx.scene.CacheHint"); -Camera = Java.type("javafx.scene.Camera"); -//CameraBuilder = Java.type("javafx.scene.CameraBuilder"); -Canvas = Java.type("javafx.scene.canvas.Canvas"); -CanvasBuilder = Java.type("javafx.scene.canvas.CanvasBuilder"); -GraphicsContext = Java.type("javafx.scene.canvas.GraphicsContext"); -Cursor = Java.type("javafx.scene.Cursor"); -DepthTest = Java.type("javafx.scene.DepthTest"); -Blend = Java.type("javafx.scene.effect.Blend"); -BlendBuilder = Java.type("javafx.scene.effect.BlendBuilder"); -BlendMode = Java.type("javafx.scene.effect.BlendMode"); -Bloom = Java.type("javafx.scene.effect.Bloom"); -BloomBuilder = Java.type("javafx.scene.effect.BloomBuilder"); -BlurType = Java.type("javafx.scene.effect.BlurType"); -BoxBlur = Java.type("javafx.scene.effect.BoxBlur"); -BoxBlurBuilder = Java.type("javafx.scene.effect.BoxBlurBuilder"); -ColorAdjust = Java.type("javafx.scene.effect.ColorAdjust"); -ColorAdjustBuilder = Java.type("javafx.scene.effect.ColorAdjustBuilder"); -ColorInput = Java.type("javafx.scene.effect.ColorInput"); -ColorInputBuilder = Java.type("javafx.scene.effect.ColorInputBuilder"); -DisplacementMap = Java.type("javafx.scene.effect.DisplacementMap"); -DisplacementMapBuilder = Java.type("javafx.scene.effect.DisplacementMapBuilder"); -DropShadow = Java.type("javafx.scene.effect.DropShadow"); -DropShadowBuilder = Java.type("javafx.scene.effect.DropShadowBuilder"); -Effect = Java.type("javafx.scene.effect.Effect"); -FloatMap = Java.type("javafx.scene.effect.FloatMap"); -FloatMapBuilder = Java.type("javafx.scene.effect.FloatMapBuilder"); -GaussianBlur = Java.type("javafx.scene.effect.GaussianBlur"); -GaussianBlurBuilder = Java.type("javafx.scene.effect.GaussianBlurBuilder"); -Glow = Java.type("javafx.scene.effect.Glow"); -GlowBuilder = Java.type("javafx.scene.effect.GlowBuilder"); -ImageInput = Java.type("javafx.scene.effect.ImageInput"); -ImageInputBuilder = Java.type("javafx.scene.effect.ImageInputBuilder"); -InnerShadow = Java.type("javafx.scene.effect.InnerShadow"); -InnerShadowBuilder = Java.type("javafx.scene.effect.InnerShadowBuilder"); -Light = Java.type("javafx.scene.effect.Light"); -Light$Distant = Java.type("javafx.scene.effect.Light$Distant"); -Light$Point = Java.type("javafx.scene.effect.Light$Point"); -Light$Spot = Java.type("javafx.scene.effect.Light$Spot"); -LightBuilder = Java.type("javafx.scene.effect.LightBuilder"); -Lighting = Java.type("javafx.scene.effect.Lighting"); -LightingBuilder = Java.type("javafx.scene.effect.LightingBuilder"); -MotionBlur = Java.type("javafx.scene.effect.MotionBlur"); -MotionBlurBuilder = Java.type("javafx.scene.effect.MotionBlurBuilder"); -PerspectiveTransform = Java.type("javafx.scene.effect.PerspectiveTransform"); -PerspectiveTransformBuilder = Java.type("javafx.scene.effect.PerspectiveTransformBuilder"); -Reflection = Java.type("javafx.scene.effect.Reflection"); -ReflectionBuilder = Java.type("javafx.scene.effect.ReflectionBuilder"); -SepiaTone = Java.type("javafx.scene.effect.SepiaTone"); -SepiaToneBuilder = Java.type("javafx.scene.effect.SepiaToneBuilder"); -Shadow = Java.type("javafx.scene.effect.Shadow"); -ShadowBuilder = Java.type("javafx.scene.effect.ShadowBuilder"); -//Group = Java.type("javafx.scene.Group"); -GroupBuilder = Java.type("javafx.scene.GroupBuilder"); -Image = Java.type("javafx.scene.image.Image"); -ImageView = Java.type("javafx.scene.image.ImageView"); -ImageViewBuilder = Java.type("javafx.scene.image.ImageViewBuilder"); -PixelFormat = Java.type("javafx.scene.image.PixelFormat"); -PixelFormat$Type = Java.type("javafx.scene.image.PixelFormat$Type"); -PixelReader = Java.type("javafx.scene.image.PixelReader"); -PixelWriter = Java.type("javafx.scene.image.PixelWriter"); -WritableImage = Java.type("javafx.scene.image.WritableImage"); -WritablePixelFormat = Java.type("javafx.scene.image.WritablePixelFormat"); -ImageCursor = Java.type("javafx.scene.ImageCursor"); -ImageCursorBuilder = Java.type("javafx.scene.ImageCursorBuilder"); -Clipboard = Java.type("javafx.scene.input.Clipboard"); -ClipboardContent = Java.type("javafx.scene.input.ClipboardContent"); -ClipboardContentBuilder = Java.type("javafx.scene.input.ClipboardContentBuilder"); -ContextMenuEvent = Java.type("javafx.scene.input.ContextMenuEvent"); -DataFormat = Java.type("javafx.scene.input.DataFormat"); -Dragboard = Java.type("javafx.scene.input.Dragboard"); -DragEvent = Java.type("javafx.scene.input.DragEvent"); -GestureEvent = Java.type("javafx.scene.input.GestureEvent"); -InputEvent = Java.type("javafx.scene.input.InputEvent"); -//InputEventBuilder = Java.type("javafx.scene.input.InputEventBuilder"); -InputMethodEvent = Java.type("javafx.scene.input.InputMethodEvent"); -InputMethodHighlight = Java.type("javafx.scene.input.InputMethodHighlight"); -InputMethodRequests = Java.type("javafx.scene.input.InputMethodRequests"); -InputMethodTextRun = Java.type("javafx.scene.input.InputMethodTextRun"); -//InputMethodTextRunBuilder = Java.type("javafx.scene.input.InputMethodTextRunBuilder"); -KeyCharacterCombination = Java.type("javafx.scene.input.KeyCharacterCombination"); -KeyCharacterCombinationBuilder = Java.type("javafx.scene.input.KeyCharacterCombinationBuilder"); -KeyCode = Java.type("javafx.scene.input.KeyCode"); -KeyCodeCombination = Java.type("javafx.scene.input.KeyCodeCombination"); -KeyCodeCombinationBuilder = Java.type("javafx.scene.input.KeyCodeCombinationBuilder"); -KeyCombination = Java.type("javafx.scene.input.KeyCombination"); -KeyCombination$Modifier = Java.type("javafx.scene.input.KeyCombination$Modifier"); -KeyCombination$ModifierValue = Java.type("javafx.scene.input.KeyCombination$ModifierValue"); -KeyEvent = Java.type("javafx.scene.input.KeyEvent"); -Mnemonic = Java.type("javafx.scene.input.Mnemonic"); -MnemonicBuilder = Java.type("javafx.scene.input.MnemonicBuilder"); -MouseButton = Java.type("javafx.scene.input.MouseButton"); -MouseDragEvent = Java.type("javafx.scene.input.MouseDragEvent"); -MouseEvent = Java.type("javafx.scene.input.MouseEvent"); -PickResult = Java.type("javafx.scene.input.PickResult"); -RotateEvent = Java.type("javafx.scene.input.RotateEvent"); -ScrollEvent = Java.type("javafx.scene.input.ScrollEvent"); -ScrollEvent$HorizontalTextScrollUnits = Java.type("javafx.scene.input.ScrollEvent$HorizontalTextScrollUnits"); -ScrollEvent$VerticalTextScrollUnits = Java.type("javafx.scene.input.ScrollEvent$VerticalTextScrollUnits"); -SwipeEvent = Java.type("javafx.scene.input.SwipeEvent"); -TouchEvent = Java.type("javafx.scene.input.TouchEvent"); -TouchPoint = Java.type("javafx.scene.input.TouchPoint"); -TouchPoint$State = Java.type("javafx.scene.input.TouchPoint$State"); -//TouchPointBuilder = Java.type("javafx.scene.input.TouchPointBuilder"); -TransferMode = Java.type("javafx.scene.input.TransferMode"); -ZoomEvent = Java.type("javafx.scene.input.ZoomEvent"); -AnchorPane = Java.type("javafx.scene.layout.AnchorPane"); -AnchorPaneBuilder = Java.type("javafx.scene.layout.AnchorPaneBuilder"); -Background = Java.type("javafx.scene.layout.Background"); -//BackgroundBuilder = Java.type("javafx.scene.layout.BackgroundBuilder"); -BackgroundFill = Java.type("javafx.scene.layout.BackgroundFill"); -//BackgroundFillBuilder = Java.type("javafx.scene.layout.BackgroundFillBuilder"); -BackgroundImage = Java.type("javafx.scene.layout.BackgroundImage"); -//BackgroundImageBuilder = Java.type("javafx.scene.layout.BackgroundImageBuilder"); -BackgroundPosition = Java.type("javafx.scene.layout.BackgroundPosition"); -//BackgroundPositionBuilder = Java.type("javafx.scene.layout.BackgroundPositionBuilder"); -BackgroundRepeat = Java.type("javafx.scene.layout.BackgroundRepeat"); -BackgroundSize = Java.type("javafx.scene.layout.BackgroundSize"); -//BackgroundSizeBuilder = Java.type("javafx.scene.layout.BackgroundSizeBuilder"); -Border = Java.type("javafx.scene.layout.Border"); -//BorderBuilder = Java.type("javafx.scene.layout.BorderBuilder"); -BorderImage = Java.type("javafx.scene.layout.BorderImage"); -//BorderImageBuilder = Java.type("javafx.scene.layout.BorderImageBuilder"); -BorderPane = Java.type("javafx.scene.layout.BorderPane"); -BorderPaneBuilder = Java.type("javafx.scene.layout.BorderPaneBuilder"); -BorderRepeat = Java.type("javafx.scene.layout.BorderRepeat"); -BorderStroke = Java.type("javafx.scene.layout.BorderStroke"); -//BorderStrokeBuilder = Java.type("javafx.scene.layout.BorderStrokeBuilder"); -BorderStrokeStyle = Java.type("javafx.scene.layout.BorderStrokeStyle"); -//BorderStrokeStyleBuilder = Java.type("javafx.scene.layout.BorderStrokeStyleBuilder"); -BorderWidths = Java.type("javafx.scene.layout.BorderWidths"); -//BorderWidthsBuilder = Java.type("javafx.scene.layout.BorderWidthsBuilder"); -ColumnConstraints = Java.type("javafx.scene.layout.ColumnConstraints"); -ColumnConstraintsBuilder = Java.type("javafx.scene.layout.ColumnConstraintsBuilder"); -ConstraintsBase = Java.type("javafx.scene.layout.ConstraintsBase"); -CornerRadii = Java.type("javafx.scene.layout.CornerRadii"); -FlowPane = Java.type("javafx.scene.layout.FlowPane"); -FlowPaneBuilder = Java.type("javafx.scene.layout.FlowPaneBuilder"); -GridPane = Java.type("javafx.scene.layout.GridPane"); -GridPaneBuilder = Java.type("javafx.scene.layout.GridPaneBuilder"); -HBox = Java.type("javafx.scene.layout.HBox"); -HBoxBuilder = Java.type("javafx.scene.layout.HBoxBuilder"); -Pane = Java.type("javafx.scene.layout.Pane"); -PaneBuilder = Java.type("javafx.scene.layout.PaneBuilder"); -Priority = Java.type("javafx.scene.layout.Priority"); -Region = Java.type("javafx.scene.layout.Region"); -RegionBuilder = Java.type("javafx.scene.layout.RegionBuilder"); -RowConstraints = Java.type("javafx.scene.layout.RowConstraints"); -RowConstraintsBuilder = Java.type("javafx.scene.layout.RowConstraintsBuilder"); -StackPane = Java.type("javafx.scene.layout.StackPane"); -StackPaneBuilder = Java.type("javafx.scene.layout.StackPaneBuilder"); -TilePane = Java.type("javafx.scene.layout.TilePane"); -TilePaneBuilder = Java.type("javafx.scene.layout.TilePaneBuilder"); -VBox = Java.type("javafx.scene.layout.VBox"); -VBoxBuilder = Java.type("javafx.scene.layout.VBoxBuilder"); -LightBase = Java.type("javafx.scene.LightBase"); -//LightBaseBuilder = Java.type("javafx.scene.LightBaseBuilder"); -Node = Java.type("javafx.scene.Node"); -NodeBuilder = Java.type("javafx.scene.NodeBuilder"); -Color = Java.type("javafx.scene.paint.Color"); -ColorBuilder = Java.type("javafx.scene.paint.ColorBuilder"); -CycleMethod = Java.type("javafx.scene.paint.CycleMethod"); -ImagePattern = Java.type("javafx.scene.paint.ImagePattern"); -ImagePatternBuilder = Java.type("javafx.scene.paint.ImagePatternBuilder"); -LinearGradient = Java.type("javafx.scene.paint.LinearGradient"); -LinearGradientBuilder = Java.type("javafx.scene.paint.LinearGradientBuilder"); -Material = Java.type("javafx.scene.paint.Material"); -Paint = Java.type("javafx.scene.paint.Paint"); -PhongMaterial = Java.type("javafx.scene.paint.PhongMaterial"); -//PhongMaterialBuilder = Java.type("javafx.scene.paint.PhongMaterialBuilder"); -RadialGradient = Java.type("javafx.scene.paint.RadialGradient"); -RadialGradientBuilder = Java.type("javafx.scene.paint.RadialGradientBuilder"); -Stop = Java.type("javafx.scene.paint.Stop"); -StopBuilder = Java.type("javafx.scene.paint.StopBuilder"); -ParallelCamera = Java.type("javafx.scene.ParallelCamera"); -//ParallelCameraBuilder = Java.type("javafx.scene.ParallelCameraBuilder"); -Parent = Java.type("javafx.scene.Parent"); -ParentBuilder = Java.type("javafx.scene.ParentBuilder"); -PerspectiveCamera = Java.type("javafx.scene.PerspectiveCamera"); -PerspectiveCameraBuilder = Java.type("javafx.scene.PerspectiveCameraBuilder"); -PointLight = Java.type("javafx.scene.PointLight"); -//PointLightBuilder = Java.type("javafx.scene.PointLightBuilder"); -//Scene = Java.type("javafx.scene.Scene"); -SceneBuilder = Java.type("javafx.scene.SceneBuilder"); -Arc = Java.type("javafx.scene.shape.Arc"); -ArcBuilder = Java.type("javafx.scene.shape.ArcBuilder"); -ArcTo = Java.type("javafx.scene.shape.ArcTo"); -ArcToBuilder = Java.type("javafx.scene.shape.ArcToBuilder"); -ArcType = Java.type("javafx.scene.shape.ArcType"); -Box = Java.type("javafx.scene.shape.Box"); -//BoxBuilder = Java.type("javafx.scene.shape.BoxBuilder"); -Circle = Java.type("javafx.scene.shape.Circle"); -CircleBuilder = Java.type("javafx.scene.shape.CircleBuilder"); -ClosePath = Java.type("javafx.scene.shape.ClosePath"); -ClosePathBuilder = Java.type("javafx.scene.shape.ClosePathBuilder"); -CubicCurve = Java.type("javafx.scene.shape.CubicCurve"); -CubicCurveBuilder = Java.type("javafx.scene.shape.CubicCurveBuilder"); -CubicCurveTo = Java.type("javafx.scene.shape.CubicCurveTo"); -CubicCurveToBuilder = Java.type("javafx.scene.shape.CubicCurveToBuilder"); -CullFace = Java.type("javafx.scene.shape.CullFace"); -Cylinder = Java.type("javafx.scene.shape.Cylinder"); -//CylinderBuilder = Java.type("javafx.scene.shape.CylinderBuilder"); -DrawMode = Java.type("javafx.scene.shape.DrawMode"); -Ellipse = Java.type("javafx.scene.shape.Ellipse"); -EllipseBuilder = Java.type("javafx.scene.shape.EllipseBuilder"); -FillRule = Java.type("javafx.scene.shape.FillRule"); -HLineTo = Java.type("javafx.scene.shape.HLineTo"); -HLineToBuilder = Java.type("javafx.scene.shape.HLineToBuilder"); -Line = Java.type("javafx.scene.shape.Line"); -LineBuilder = Java.type("javafx.scene.shape.LineBuilder"); -LineTo = Java.type("javafx.scene.shape.LineTo"); -LineToBuilder = Java.type("javafx.scene.shape.LineToBuilder"); -Mesh = Java.type("javafx.scene.shape.Mesh"); -MeshView = Java.type("javafx.scene.shape.MeshView"); -//MeshViewBuilder = Java.type("javafx.scene.shape.MeshViewBuilder"); -MoveTo = Java.type("javafx.scene.shape.MoveTo"); -MoveToBuilder = Java.type("javafx.scene.shape.MoveToBuilder"); -Path = Java.type("javafx.scene.shape.Path"); -PathBuilder = Java.type("javafx.scene.shape.PathBuilder"); -PathElement = Java.type("javafx.scene.shape.PathElement"); -PathElementBuilder = Java.type("javafx.scene.shape.PathElementBuilder"); -Polygon = Java.type("javafx.scene.shape.Polygon"); -PolygonBuilder = Java.type("javafx.scene.shape.PolygonBuilder"); -Polyline = Java.type("javafx.scene.shape.Polyline"); -PolylineBuilder = Java.type("javafx.scene.shape.PolylineBuilder"); -QuadCurve = Java.type("javafx.scene.shape.QuadCurve"); -QuadCurveBuilder = Java.type("javafx.scene.shape.QuadCurveBuilder"); -QuadCurveTo = Java.type("javafx.scene.shape.QuadCurveTo"); -QuadCurveToBuilder = Java.type("javafx.scene.shape.QuadCurveToBuilder"); -Rectangle = Java.type("javafx.scene.shape.Rectangle"); -RectangleBuilder = Java.type("javafx.scene.shape.RectangleBuilder"); -Shape = Java.type("javafx.scene.shape.Shape"); -Shape3D = Java.type("javafx.scene.shape.Shape3D"); -//Shape3DBuilder = Java.type("javafx.scene.shape.Shape3DBuilder"); -ShapeBuilder = Java.type("javafx.scene.shape.ShapeBuilder"); -Sphere = Java.type("javafx.scene.shape.Sphere"); -//SphereBuilder = Java.type("javafx.scene.shape.SphereBuilder"); -StrokeLineCap = Java.type("javafx.scene.shape.StrokeLineCap"); -StrokeLineJoin = Java.type("javafx.scene.shape.StrokeLineJoin"); -StrokeType = Java.type("javafx.scene.shape.StrokeType"); -SVGPath = Java.type("javafx.scene.shape.SVGPath"); -SVGPathBuilder = Java.type("javafx.scene.shape.SVGPathBuilder"); -TriangleMesh = Java.type("javafx.scene.shape.TriangleMesh"); -VLineTo = Java.type("javafx.scene.shape.VLineTo"); -VLineToBuilder = Java.type("javafx.scene.shape.VLineToBuilder"); -SnapshotParameters = Java.type("javafx.scene.SnapshotParameters"); -SnapshotParametersBuilder = Java.type("javafx.scene.SnapshotParametersBuilder"); -SnapshotResult = Java.type("javafx.scene.SnapshotResult"); -SubScene = Java.type("javafx.scene.SubScene"); -//SubSceneBuilder = Java.type("javafx.scene.SubSceneBuilder"); -Font = Java.type("javafx.scene.text.Font"); -FontBuilder = Java.type("javafx.scene.text.FontBuilder"); -FontPosture = Java.type("javafx.scene.text.FontPosture"); -FontSmoothingType = Java.type("javafx.scene.text.FontSmoothingType"); -FontWeight = Java.type("javafx.scene.text.FontWeight"); -Text = Java.type("javafx.scene.text.Text"); -TextAlignment = Java.type("javafx.scene.text.TextAlignment"); -TextBoundsType = Java.type("javafx.scene.text.TextBoundsType"); -TextBuilder = Java.type("javafx.scene.text.TextBuilder"); -TextFlow = Java.type("javafx.scene.text.TextFlow"); -//TextFlowBuilder = Java.type("javafx.scene.text.TextFlowBuilder"); -Affine = Java.type("javafx.scene.transform.Affine"); -AffineBuilder = Java.type("javafx.scene.transform.AffineBuilder"); -MatrixType = Java.type("javafx.scene.transform.MatrixType"); -NonInvertibleTransformException = Java.type("javafx.scene.transform.NonInvertibleTransformException"); -Rotate = Java.type("javafx.scene.transform.Rotate"); -RotateBuilder = Java.type("javafx.scene.transform.RotateBuilder"); -Scale = Java.type("javafx.scene.transform.Scale"); -ScaleBuilder = Java.type("javafx.scene.transform.ScaleBuilder"); -Shear = Java.type("javafx.scene.transform.Shear"); -ShearBuilder = Java.type("javafx.scene.transform.ShearBuilder"); -Transform = Java.type("javafx.scene.transform.Transform"); -//TransformBuilder = Java.type("javafx.scene.transform.TransformBuilder"); -TransformChangedEvent = Java.type("javafx.scene.transform.TransformChangedEvent"); -Translate = Java.type("javafx.scene.transform.Translate"); -TranslateBuilder = Java.type("javafx.scene.transform.TranslateBuilder"); -DirectoryChooser = Java.type("javafx.stage.DirectoryChooser"); -DirectoryChooserBuilder = Java.type("javafx.stage.DirectoryChooserBuilder"); -FileChooser = Java.type("javafx.stage.FileChooser"); -FileChooser$ExtensionFilter = Java.type("javafx.stage.FileChooser$ExtensionFilter"); -FileChooserBuilder = Java.type("javafx.stage.FileChooserBuilder"); -Modality = Java.type("javafx.stage.Modality"); -Popup = Java.type("javafx.stage.Popup"); -PopupBuilder = Java.type("javafx.stage.PopupBuilder"); -PopupWindow = Java.type("javafx.stage.PopupWindow"); -PopupWindowBuilder = Java.type("javafx.stage.PopupWindowBuilder"); -Screen = Java.type("javafx.stage.Screen"); -//Stage = Java.type("javafx.stage.Stage"); -StageBuilder = Java.type("javafx.stage.StageBuilder"); -StageStyle = Java.type("javafx.stage.StageStyle"); -Window = Java.type("javafx.stage.Window"); -WindowBuilder = Java.type("javafx.stage.WindowBuilder"); -WindowEvent = Java.type("javafx.stage.WindowEvent"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_GRAPHICS_CLASSES); + diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/media.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/media.js index 7cc7887b3a8..29640255ba8 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/media.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/media.js @@ -23,23 +23,8 @@ * questions. */ -AudioClip = Java.type("javafx.scene.media.AudioClip"); -AudioClipBuilder = Java.type("javafx.scene.media.AudioClipBuilder"); -AudioEqualizer = Java.type("javafx.scene.media.AudioEqualizer"); -AudioSpectrumListener = Java.type("javafx.scene.media.AudioSpectrumListener"); -AudioTrack = Java.type("javafx.scene.media.AudioTrack"); -EqualizerBand = Java.type("javafx.scene.media.EqualizerBand"); -Media = Java.type("javafx.scene.media.Media"); -MediaBuilder = Java.type("javafx.scene.media.MediaBuilder"); -MediaErrorEvent = Java.type("javafx.scene.media.MediaErrorEvent"); -MediaException = Java.type("javafx.scene.media.MediaException"); -MediaException$Type = Java.type("javafx.scene.media.MediaException$Type"); -MediaMarkerEvent = Java.type("javafx.scene.media.MediaMarkerEvent"); -MediaPlayer = Java.type("javafx.scene.media.MediaPlayer"); -MediaPlayer$Status = Java.type("javafx.scene.media.MediaPlayer$Status"); -MediaPlayerBuilder = Java.type("javafx.scene.media.MediaPlayerBuilder"); -MediaView = Java.type("javafx.scene.media.MediaView"); -MediaViewBuilder = Java.type("javafx.scene.media.MediaViewBuilder"); -SubtitleTrack = Java.type("javafx.scene.media.SubtitleTrack"); -Track = Java.type("javafx.scene.media.Track"); -VideoTrack = Java.type("javafx.scene.media.VideoTrack"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_MEDIA_CLASSES); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swing.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swing.js index 241205d1282..e4021af9d49 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swing.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swing.js @@ -23,7 +23,8 @@ * questions. */ -JFXPanel = Java.type("javafx.embed.swing.JFXPanel"); -JFXPanelBuilder = Java.type("javafx.embed.swing.JFXPanelBuilder"); -SwingFXUtils = Java.type("javafx.embed.swing.SwingFXUtils"); -SwingNode = Java.type("javafx.embed.swing.SwingNode"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_SWING_CLASSES); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swt.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swt.js index 82197c71198..144bcd5de71 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swt.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/swt.js @@ -23,7 +23,8 @@ * questions. */ -CustomTransfer = Java.type("javafx.embed.swt.CustomTransfer"); -//CustomTransferBuilder = Java.type("javafx.embed.swt.CustomTransferBuilder"); -FXCanvas = Java.type("javafx.embed.swt.FXCanvas"); -SWTFXUtils = Java.type("javafx.embed.swt.SWTFXUtils"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_SWT_CLASSES); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/web.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/web.js index 606c3c315a9..fa66cb25788 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/web.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/fx/web.js @@ -23,14 +23,8 @@ * questions. */ -HTMLEditor = Java.type("javafx.scene.web.HTMLEditor"); -//HTMLEditorBuilder = Java.type("javafx.scene.web.HTMLEditorBuilder"); -PopupFeatures = Java.type("javafx.scene.web.PopupFeatures"); -PromptData = Java.type("javafx.scene.web.PromptData"); -//PromptDataBuilder = Java.type("javafx.scene.web.PromptDataBuilder"); -WebEngine = Java.type("javafx.scene.web.WebEngine"); -WebEngineBuilder = Java.type("javafx.scene.web.WebEngineBuilder"); -WebEvent = Java.type("javafx.scene.web.WebEvent"); -WebHistory = Java.type("javafx.scene.web.WebHistory"); -WebView = Java.type("javafx.scene.web.WebView"); -WebViewBuilder = Java.type("javafx.scene.web.WebViewBuilder"); +if (!this.JFX_BASE_CLASSES) { + load("fx:base.js") +} + +LOAD_FX_CLASSES(JFX_WEB_CLASSES); diff --git a/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js b/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js index 60bdc7b1ab0..6b934ad4b00 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/mozilla_compat.js @@ -137,17 +137,6 @@ Object.defineProperty(Object.prototype, "__lookupSetter__", { } }); -// Object.prototype.__proto__ (read-only) -Object.defineProperty(Object.prototype, "__proto__", { - configurable: true, enumerable: false, - get: function() { - return Object.getPrototypeOf(this); - }, - set: function(x) { - Object.setPrototypeOf(this, x); - } -}); - // Object.prototype.toSource Object.defineProperty(Object.prototype, "toSource", { configurable: true, enumerable: false, writable: true, diff --git a/nashorn/test/script/basic/8024180/global_var_delete.js b/nashorn/test/script/basic/8024180/global_var_delete.js new file mode 100644 index 00000000000..f099dd33f87 --- /dev/null +++ b/nashorn/test/script/basic/8024180/global_var_delete.js @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + + +this.x = 44; + +function func() { + with({ }) { + print(x); + } +} + +func(); + +// delete global 'x' +delete this.x; + +try { + func(); +} catch(e) { + // expect ReferenceError + print(e); +} diff --git a/nashorn/test/script/basic/8024180/global_var_delete.js.EXPECTED b/nashorn/test/script/basic/8024180/global_var_delete.js.EXPECTED new file mode 100644 index 00000000000..7e54b9e6a3c --- /dev/null +++ b/nashorn/test/script/basic/8024180/global_var_delete.js.EXPECTED @@ -0,0 +1,2 @@ +44 +ReferenceError: "x" is not defined diff --git a/nashorn/test/script/basic/8024180/global_var_shadow.js b/nashorn/test/script/basic/8024180/global_var_shadow.js new file mode 100644 index 00000000000..5ba5f5e2d1d --- /dev/null +++ b/nashorn/test/script/basic/8024180/global_var_shadow.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +// global variable is shadowed by with 'expression' property +var user = { name: 'foo' }; + +function func(locals) { + with (locals) { + print(user.name); + } +} + +// global user.name 'foo' printed +func({}); + +// local user.name 'toto' printed +func({ user: { name: 'toto' } }); + diff --git a/nashorn/test/script/basic/8024180/global_var_shadow.js.EXPECTED b/nashorn/test/script/basic/8024180/global_var_shadow.js.EXPECTED new file mode 100644 index 00000000000..7f1a102b9cc --- /dev/null +++ b/nashorn/test/script/basic/8024180/global_var_shadow.js.EXPECTED @@ -0,0 +1,2 @@ +foo +toto diff --git a/nashorn/test/script/basic/8024180/scope_no_such_prop.js b/nashorn/test/script/basic/8024180/scope_no_such_prop.js new file mode 100644 index 00000000000..5973c469e0d --- /dev/null +++ b/nashorn/test/script/basic/8024180/scope_no_such_prop.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +// __noSuchProperty__ defined here confuses 'with' +// results in ReferenceError even when 'with' expression has +// the property + +load("nashorn:mozilla_compat.js") + +function func(locals) { + with (locals) { + print(user.name); + } +} + +try { + func({}); +} catch (e) { + print(e); +} + +// 'toto' expected in the call below +func({ user: { name: 'toto' } }); + diff --git a/nashorn/test/script/basic/8024180/scope_no_such_prop.js.EXPECTED b/nashorn/test/script/basic/8024180/scope_no_such_prop.js.EXPECTED new file mode 100644 index 00000000000..ad4d247ea47 --- /dev/null +++ b/nashorn/test/script/basic/8024180/scope_no_such_prop.js.EXPECTED @@ -0,0 +1,2 @@ +ReferenceError: user is not defined +toto diff --git a/nashorn/test/script/basic/8024180/with_expr_prop_add.js b/nashorn/test/script/basic/8024180/with_expr_prop_add.js new file mode 100644 index 00000000000..7c3b3a546fb --- /dev/null +++ b/nashorn/test/script/basic/8024180/with_expr_prop_add.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +var obj = {}; +var x = "global x"; + +// adding property to 'with' xpression object should reflect +// as variable inside the 'with' block. +function func() { + with(obj) { + for (i = 0; i < 2; i++) { + print(x); + if (i == 0) { + obj.x = "obj.x"; + } + } + } +} + +func(); diff --git a/nashorn/test/script/basic/8024180/with_expr_prop_add.js.EXPECTED b/nashorn/test/script/basic/8024180/with_expr_prop_add.js.EXPECTED new file mode 100644 index 00000000000..4139e361961 --- /dev/null +++ b/nashorn/test/script/basic/8024180/with_expr_prop_add.js.EXPECTED @@ -0,0 +1,2 @@ +global x +obj.x diff --git a/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js b/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js new file mode 100644 index 00000000000..a6a17e7071b --- /dev/null +++ b/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +var p = { }; +var obj = Object.create(p); + +var x = "global x"; + +// adding property to __proto__ of 'with' expression should +// reflect as a variable immediately. +function func() { + with(obj) { + for (i = 0; i < 2; i++) { + print(x); + if (i == 0) { + p.x = "p.x"; + } + } + } +} + +func(); diff --git a/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js.EXPECTED b/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js.EXPECTED new file mode 100644 index 00000000000..aa6d3681c18 --- /dev/null +++ b/nashorn/test/script/basic/8024180/with_expr_proto_prop_add.js.EXPECTED @@ -0,0 +1,2 @@ +global x +p.x diff --git a/nashorn/test/script/basic/8024180/with_java_object.js b/nashorn/test/script/basic/8024180/with_java_object.js new file mode 100644 index 00000000000..32db2a5c3e0 --- /dev/null +++ b/nashorn/test/script/basic/8024180/with_java_object.js @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024180: Incorrect handling of expression and parent scope in 'with' statements + * + * @test + * @run + */ + +// TypeError for with expression being non script object +try { + with(new java.lang.Object()) {} +} catch (e) { + print(e); +} diff --git a/nashorn/test/script/basic/8024180/with_java_object.js.EXPECTED b/nashorn/test/script/basic/8024180/with_java_object.js.EXPECTED new file mode 100644 index 00000000000..3f0facfade1 --- /dev/null +++ b/nashorn/test/script/basic/8024180/with_java_object.js.EXPECTED @@ -0,0 +1 @@ +TypeError: Cannot apply "with" to non script object diff --git a/nashorn/test/script/basic/JDK-8023368.js b/nashorn/test/script/basic/JDK-8023368.js index 9f32805caa8..da034dbc566 100644 --- a/nashorn/test/script/basic/JDK-8023368.js +++ b/nashorn/test/script/basic/JDK-8023368.js @@ -28,8 +28,6 @@ * @run */ -load("nashorn:mozilla_compat.js"); - // function to force same callsites function check(obj) { print(obj.func()); diff --git a/nashorn/test/script/basic/JDK-8023368.js.EXPECTED b/nashorn/test/script/basic/JDK-8023368.js.EXPECTED index 4ca8d077d38..c116a6b7c10 100644 --- a/nashorn/test/script/basic/JDK-8023368.js.EXPECTED +++ b/nashorn/test/script/basic/JDK-8023368.js.EXPECTED @@ -4,15 +4,15 @@ hello Func.prototype.func hello [object Object] -obj.__proto__.func @ 57 +obj.__proto__.func @ 55 344 [object Object] -obj.__proto__.func @ 57 +obj.__proto__.func @ 55 344 [object Object] -obj.__proto__.func @ 57 +obj.__proto__.func @ 55 344 new object.toString -obj.__proto__.func @ 57 +obj.__proto__.func @ 55 344 new object.toString diff --git a/nashorn/test/script/basic/JDK-8024120.js b/nashorn/test/script/basic/JDK-8024120.js new file mode 100644 index 00000000000..0ac4ff98c15 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024120.js @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024120: Setting __proto__ to null removes the __proto__ property + * + * @test + * @run + */ + +var obj = {}; + +obj.__proto__ = null; + +if (obj.__proto__ !== null || typeof(obj.__proto__) != 'object') { + fail("obj.__proto__ is expected to be null"); +} + +var p = Object.getPrototypeOf(obj); +if (p !== null || typeof(p) != 'object') { + fail("Object.getPrototypeOf(obj) is expected to be null"); +} diff --git a/nashorn/test/script/basic/JDK-8024174.js b/nashorn/test/script/basic/JDK-8024174.js new file mode 100644 index 00000000000..5fd48e17bc3 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024174.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024174: Setting __proto__ property in Object literal should be supported * + * @test + * @run + */ + +var p = { foo: function() { print("p.foo"); } }; + +var obj = { + __proto__ : p, + bar: 44 +}; + +if (obj.__proto__ !== p || Object.getPrototypeOf(obj) !== p) { + fail("obj.__proto__ was not set inside literal"); +} + +if (typeof(obj.foo) !== 'function' || obj.foo !== p.foo) { + fail("'obj' failed to inherit 'foo' from 'p'"); +} + +var obj2 = { + __proto__: null +}; + +if (obj2.__proto__ !== null || Object.getPrototypeOf(obj2) !== null) { + fail("obj2.__proto__ was not set to null inside literal"); +} diff --git a/nashorn/test/script/basic/JDK-8024255.js b/nashorn/test/script/basic/JDK-8024255.js new file mode 100644 index 00000000000..54022a5cd1d --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024255.js @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024255: When a keyword is used as object property name, the property can not be deleted + * + * @test + * @run + */ + +function check(obj, name) { + var desc = Object.getOwnPropertyDescriptor(obj, name); + if (! desc.configurable) { + fail("Property " + name + " is not configurable"); + } + + if (! (delete obj[name])) { + fail("Property " + name + " can not be deleted"); + } +} + +var obj = { + default: 344, + in: 'hello', + if: false, + class: 4.223 +} + +for (var p in obj) { + check(obj, p); +} diff --git a/nashorn/test/script/basic/JDK-8024512.js b/nashorn/test/script/basic/JDK-8024512.js new file mode 100644 index 00000000000..c03ba212c14 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024512.js @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024512: Regex /[^\[]/ doesn't match + * + * @test + * @run + */ + +print("[M]".match(/(\[[^\[]*\])/)); +print("[[]".match(/(\[[^\[]*\])/)); + +print("[M]".match(/(\[[^\[^]*\])/)); +print("[[]".match(/(\[[^\[^]*\])/)); +print("[^]".match(/(\[[^\[^]*\])/)); + +print("[M]".match(/(\[[^\[]\])/)); +print("[[]".match(/(\[[^\[]\])/)); + +print("[M]".match(/(\[[^\[^]\])/)); +print("[[]".match(/(\[[^\[^]\])/)); +print("[^]".match(/(\[[^\[^]\])/)); + +print("M".match(/[^\[]/)); +print("[".match(/[^\[]/)); +print("^".match(/[^\[]/)); + +// Repeat above without escaping inner square bracket +print("[M]".match(/(\[[^[]\])/)); +print("[[]".match(/(\[[^[]\])/)); + +print("[M]".match(/(\[[^[^]\])/)); +print("[[]".match(/(\[[^[^]\])/)); +print("[^]".match(/(\[[^[^]\])/)); + +print("M".match(/[^[]/)); +print("[".match(/[^[]/)); +print("^".match(/[^[]/)); diff --git a/nashorn/test/script/basic/JDK-8024512.js.EXPECTED b/nashorn/test/script/basic/JDK-8024512.js.EXPECTED new file mode 100644 index 00000000000..9bb84de91dc --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024512.js.EXPECTED @@ -0,0 +1,21 @@ +[M],[M] +[],[] +[M],[M] +[],[] +null +[M],[M] +null +[M],[M] +null +null +M +null +^ +[M],[M] +null +[M],[M] +null +null +M +null +^ diff --git a/nashorn/test/script/basic/JDK-8024619.js b/nashorn/test/script/basic/JDK-8024619.js new file mode 100644 index 00000000000..064e0d7b676 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024619.js @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024619: JDBC java.sql.DriverManager is not usable from JS script + * + * @test + * @run + */ + +var DriverManager = Java.type("java.sql.DriverManager"); +var e = DriverManager.getDrivers(); + +var driverFound = false; +// check for Nashorn SQL driver +while (e.hasMoreElements()) { + var driver = e.nextElement(); + if (driver.acceptsURL("jdbc:nashorn:")) { + driverFound = true; + break; + } +} + +if (! driverFound) { + fail("Nashorn JDBC Driver not found!"); +} diff --git a/nashorn/test/script/basic/JDK-8024846.js b/nashorn/test/script/basic/JDK-8024846.js new file mode 100644 index 00000000000..ccdf8fcc9b6 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024846.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024846: keep separate internal arguments variable + * + * @test + */ + +function f() { print(arguments); } + +function func(obj) { + var arguments = obj; + for (var i in arguments) { + } + return obj; +} diff --git a/nashorn/test/script/basic/JDK-8024847.js b/nashorn/test/script/basic/JDK-8024847.js new file mode 100644 index 00000000000..4a671ecd9f0 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024847.js @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024847: Java.to should accept mirror and external JSObjects as array-like objects as well + * + * @test + * @run + */ + +var global = loadWithNewGlobal({ name: "test", script:"this" }); +var arr = new global.Array(2, 4, 6, 8); +var jarr = Java.to(arr, "int[]"); +for (var i in jarr) { + print(jarr[i]); +} + +arr = null; +jarr = null; + +// external JSObjects +var JSObject = Java.type("jdk.nashorn.api.scripting.JSObject"); +var arr = new JSObject() { + getMember: function(name) { + return name == "length"? 4 : undefined; + }, + + hasMember: function(name) { + return name == "length"; + }, + + getSlot: function(idx) { + return idx*idx; + }, + + hasSlot: function(idx) { + return true; + } +}; + +var jarr = Java.to(arr, "int[]"); +for (var i in jarr) { + print(jarr[i]); +} + +arr = null; +jarr = null; + +// List conversion +var arr = global.Array("hello", "world"); +var jlist = Java.to(arr, java.util.List); +print(jlist instanceof java.util.List); +print(jlist); + +arr = null; +jlist = null; + +// external JSObject +var __array__ = [ "nashorn", "js" ]; + +var obj = new JSObject() { + + hasMember: function(name) { + return name in __array__; + }, + + hasSlot: function(idx) { + return idx in __array__; + }, + + getMember: function(name) { + return __array__[name]; + }, + + getSlot: function(idx) { + return __array__[idx]; + } +} + +var jlist = Java.to(obj, java.util.List); +print(jlist instanceof java.util.List); +print(jlist); diff --git a/nashorn/test/script/basic/JDK-8024847.js.EXPECTED b/nashorn/test/script/basic/JDK-8024847.js.EXPECTED new file mode 100644 index 00000000000..015183a02a9 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024847.js.EXPECTED @@ -0,0 +1,12 @@ +2 +4 +6 +8 +0 +1 +4 +9 +true +[hello, world] +true +[nashorn, js] diff --git a/nashorn/test/script/basic/JDK-8024972.js b/nashorn/test/script/basic/JDK-8024972.js new file mode 100644 index 00000000000..2e940812cf6 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024972.js @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8024972: for (LeftHandSideExpression in Expression) crashes the compiler + * + * @test + * @run + */ + +var obj = {}; + +var arr = [2, 45, -1, 445]; +for (obj.x in arr) { + print(obj.x + "->"+ arr[obj.x]); +} + +var abc = { foo: 'bar', hello: 'world' }; +for (obj.x in abc) { + print(obj.x + "->" + abc[obj.x]); +} + +for (obj.x in 0) {} diff --git a/nashorn/test/script/basic/JDK-8024972.js.EXPECTED b/nashorn/test/script/basic/JDK-8024972.js.EXPECTED new file mode 100644 index 00000000000..aa4692fb2cc --- /dev/null +++ b/nashorn/test/script/basic/JDK-8024972.js.EXPECTED @@ -0,0 +1,6 @@ +0->2 +1->45 +2->-1 +3->445 +foo->bar +hello->world diff --git a/nashorn/test/script/basic/JDK-8025048-2.js b/nashorn/test/script/basic/JDK-8025048-2.js new file mode 100644 index 00000000000..c11816bad53 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025048-2.js @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025048: true as case label results in ClassCastException + * + * @test + * @run + */ + +function func(x) { + switch(x) { + case 8: break; case false: + } +} + diff --git a/nashorn/test/script/basic/JDK-8025048.js b/nashorn/test/script/basic/JDK-8025048.js new file mode 100644 index 00000000000..75838a987d6 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025048.js @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025048: true as case label results in ClassCastException + * + * @test + * @run + */ + +function func(x) { + switch(x) { + case 8: break; case true: + } +} + diff --git a/nashorn/test/script/basic/JDK-8025080.js b/nashorn/test/script/basic/JDK-8025080.js new file mode 100644 index 00000000000..1ea46efa530 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025080.js @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025080: Object literal getter, setter function with number format property name results in ClassFormatError + * + * @test + * @run + */ + +var obj = { + get 1e81() { print("1e81 getter"); }, + set 1e81(x) { print("1e81 setter"); }, + get 3.14e-2() { print("3.14e-2 getter");}, + set 3.14e-2(x) { print("3.14e-2 setter"); } +}; + +obj[1e81]; +obj[1e81] = 23; + +obj[3.14e-2]; +obj[3.14e-2] = 42; + diff --git a/nashorn/test/script/basic/JDK-8025080.js.EXPECTED b/nashorn/test/script/basic/JDK-8025080.js.EXPECTED new file mode 100644 index 00000000000..e19e8ae9621 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025080.js.EXPECTED @@ -0,0 +1,4 @@ +1e81 getter +1e81 setter +3.14e-2 getter +3.14e-2 setter diff --git a/nashorn/test/script/basic/JDK-8025090.js b/nashorn/test/script/basic/JDK-8025090.js new file mode 100644 index 00000000000..8e42099cf47 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025090.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025090: 'while' statement with 'test' using var before being declared in body results in VerifyError + * + * @test + * @run + */ + +// The following used to result in VerifyError +function f() { + while (x += 2) { var x = 44 } +} + diff --git a/nashorn/test/script/basic/JDK-8025111.js b/nashorn/test/script/basic/JDK-8025111.js new file mode 100644 index 00000000000..953f27c0d5a --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025111.js @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025111: undefined or null 'with' expression in empty with block should throw TypeError + * + * @test + * @run + */ + +function check(callback, arg) { + try { + callback(arg); + fail("should have thrown TypeError: " + callback + " on " + arg); + } catch (e) { + if (! (e instanceof TypeError)) { + fail("Expected TypeError, got " + e); + } + } +} + +function func(obj) { + with(obj) {} +} + +check(func); +check(func, undefined); +check(func, null); diff --git a/nashorn/test/script/basic/JDK-8025147.js b/nashorn/test/script/basic/JDK-8025147.js new file mode 100644 index 00000000000..905a1c9c320 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025147.js @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025147: Trailing comma is not allowed in JSONArray and JSONObject + * + * @test + * @run + */ + +function check(str) { + try { + JSON.parse(str); + fail("should have thrown SyntaxError for " + str); + } catch (e) { + print(e); + } +} + +check("{ \"a\": 333, }"); +check("[ 4343, ]"); diff --git a/nashorn/test/script/basic/JDK-8025147.js.EXPECTED b/nashorn/test/script/basic/JDK-8025147.js.EXPECTED new file mode 100644 index 00000000000..3afb20a8204 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025147.js.EXPECTED @@ -0,0 +1,6 @@ +SyntaxError: Invalid JSON: :1:12 Trailing comma is not allowed in JSON +{ "a": 333, } + ^ +SyntaxError: Invalid JSON: :1:8 Trailing comma is not allowed in JSON +[ 4343, ] + ^ diff --git a/nashorn/test/script/basic/JDK-8025149.js b/nashorn/test/script/basic/JDK-8025149.js new file mode 100644 index 00000000000..b1d33a1a3ce --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025149.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025149: JSON.stringify does not handle 'space' argument as per the spec. + * + * @test + * @run + */ + +print(JSON.stringify({ foo : 23, bar: { x : 22} }, undefined ,new Number(Infinity))); + +print(JSON.stringify({ foo : 23, bar: { x : 22} }, undefined ,new Number(-Infinity))); + +try { + JSON.stringify({},[], + (n = new Number(0), n.valueOf = function() { throw ("inside n.valueOf") }, n)); +} catch (e) { + print(e); +} + +try { + JSON.stringify({},[], + (s = new String(""), s.toString = function() { throw ("inside s.toString") }, s)); +} catch (e) { + print(e); +} diff --git a/nashorn/test/script/basic/JDK-8025149.js.EXPECTED b/nashorn/test/script/basic/JDK-8025149.js.EXPECTED new file mode 100644 index 00000000000..10fd8641cbc --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025149.js.EXPECTED @@ -0,0 +1,9 @@ +{ + "foo": 23, + "bar": { + "x": 22 + } +} +{"foo":23,"bar":{"x":22}} +inside n.valueOf +inside s.toString diff --git a/nashorn/test/script/basic/JDK-8025163.js b/nashorn/test/script/basic/JDK-8025163.js new file mode 100644 index 00000000000..1eaa98e82c2 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025163.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025163: Date methods should not return -0 + * + * @test + * @run + */ + +print(1 / (new Date(0, 0, 1)).getYear()); +print(1 / (new Date(1969, 1, 2)).getDay()); +print(1 / (new Date(1969, 0, 1)).getHours()); +print(1 / (new Date(1969, 0, 1)).getHours()); +print(1 / (new Date(1969, 0, 1)).getMinutes()); +print(1 / (new Date(1969, 0, 1)).getSeconds()); +print(1 / (new Date(1969, 0, 1)).getMilliseconds()); +print(1 / (new Date(1969, 0, 1)).getMilliseconds()); + diff --git a/nashorn/test/script/basic/JDK-8025163.js.EXPECTED b/nashorn/test/script/basic/JDK-8025163.js.EXPECTED new file mode 100644 index 00000000000..cde7e1933e7 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025163.js.EXPECTED @@ -0,0 +1,8 @@ +Infinity +Infinity +Infinity +Infinity +Infinity +Infinity +Infinity +Infinity diff --git a/nashorn/test/script/basic/JDK-8025197.js b/nashorn/test/script/basic/JDK-8025197.js new file mode 100644 index 00000000000..5099b673691 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025197.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025197: String replace method fails with regexp /$/gi + * + * @test + * @run + */ + +print('dog'.replace(/$/gi, 's')); +print('dog'.replace(/(?:g)$/gi, 's')); +print('dog'.replace(/(?:a)$/gi, 's')); +print('dog'.replace(/(?!g)$/gi, 's')); +print('dog'.replace(/(?!a)$/gi, 's')); +print('dog'.replace(/g?$/gi, 's')); +print('dog'.replace(/.?$/gi, 's')); diff --git a/nashorn/test/script/basic/JDK-8025197.js.EXPECTED b/nashorn/test/script/basic/JDK-8025197.js.EXPECTED new file mode 100644 index 00000000000..9f2a08f67e5 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025197.js.EXPECTED @@ -0,0 +1,7 @@ +dogs +dos +dog +dogs +dogs +doss +doss diff --git a/nashorn/test/script/basic/JDK-8025312.js b/nashorn/test/script/basic/JDK-8025312.js new file mode 100644 index 00000000000..6f2b42f38af --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025312.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025312: parseInt should convert 'radix' argument to ToInt32 even if empty string is parsed + * + * @test + * @run + */ + +parseInt("", { + valueOf: function() { + print("inside valueOf of 'radix'"); + } +}); diff --git a/nashorn/test/script/basic/JDK-8025312.js.EXPECTED b/nashorn/test/script/basic/JDK-8025312.js.EXPECTED new file mode 100644 index 00000000000..31ffef83890 --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025312.js.EXPECTED @@ -0,0 +1 @@ +inside valueOf of 'radix' diff --git a/nashorn/test/script/basic/JDK-8025325.js b/nashorn/test/script/basic/JDK-8025325.js new file mode 100644 index 00000000000..63dfef9d96e --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025325.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025325: parseFloat does not handle '.' in exponent part + * + * @test + * @run + */ + +print(parseFloat("2e2.")); +print(parseFloat("2e2.3")); +print(parseFloat("2e2.fdgdf")); +print(parseFloat("2e2. gdfgdf")); +print(parseFloat("2e2. ")); diff --git a/nashorn/test/script/basic/JDK-8025325.js.EXPECTED b/nashorn/test/script/basic/JDK-8025325.js.EXPECTED new file mode 100644 index 00000000000..4ddf679a54b --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025325.js.EXPECTED @@ -0,0 +1,5 @@ +200 +200 +200 +200 +200 diff --git a/nashorn/test/script/basic/JDK-8025434.js b/nashorn/test/script/basic/JDK-8025434.js new file mode 100644 index 00000000000..1d42959416d --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025434.js @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025434: RegExp lastIndex can exceed int range + * + * @test + * @run + */ + +var r = /a/g; + +r.lastIndex = 0x100000000; +if (r.test("a")) { + throw new Error("Expected no match"); +} + +r.lastIndex = 0x100000000000000; +if (r.test("a")) { + throw new Error("Expected no match"); +} + +r.lastIndex = -0x100000000; +if (r.test("a")) { + throw new Error("Expected match"); +} + +r.lastIndex = -0x100000000000000; +if (r.test("a")) { + throw new Error("Expected no match"); +} + +r.lastIndex = 1; +if (r.test("a")) { + throw new Error("Expected no match"); +} + +r.lastIndex = -1; +if (r.test("a")) { + throw new Error("Expected no match"); +} + +r.lastIndex = 0; +if (!r.test("a")) { + throw new Error("Expected match"); +} diff --git a/nashorn/test/script/basic/JDK-8025486.js b/nashorn/test/script/basic/JDK-8025486.js new file mode 100644 index 00000000000..8012f72383c --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025486.js @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * JDK-8025486: RegExp constructor arguments are not evaluated in right order + * + * @test + * @run + */ + +new RegExp({ + toString: function() { + print("source"); + return "a"; + } +}, { + toString: function() { + print("flags"); + return "g"; + } +}); + +try { + new RegExp(/asdf/, { + toString: function() { + fail("toString should not be called"); + } + }); + fail("expected TypeError"); +} catch (e) { + if (!(e instanceof TypeError)) { + fail("expected TypeError"); + } + print(e); +} diff --git a/nashorn/test/script/basic/JDK-8025486.js.EXPECTED b/nashorn/test/script/basic/JDK-8025486.js.EXPECTED new file mode 100644 index 00000000000..cf46bd7a29d --- /dev/null +++ b/nashorn/test/script/basic/JDK-8025486.js.EXPECTED @@ -0,0 +1,3 @@ +source +flags +TypeError: Cannot supply flags when constructing one RegExp from another diff --git a/nashorn/test/script/basic/NASHORN-737.js b/nashorn/test/script/basic/NASHORN-737.js index 44169d0435f..3db48918df1 100644 --- a/nashorn/test/script/basic/NASHORN-737.js +++ b/nashorn/test/script/basic/NASHORN-737.js @@ -30,4 +30,4 @@ load("nashorn:parser.js"); var ast = parse("label: while(true) break label;"); -print(JSON.stringify(ast)); +print(JSON.stringify(ast, null, " ")); diff --git a/nashorn/test/script/basic/NASHORN-737.js.EXPECTED b/nashorn/test/script/basic/NASHORN-737.js.EXPECTED index 8f828342948..77c796579f4 100644 --- a/nashorn/test/script/basic/NASHORN-737.js.EXPECTED +++ b/nashorn/test/script/basic/NASHORN-737.js.EXPECTED @@ -1 +1,36 @@ -{"type":"Program","rest":null,"body":[{"type":"LabeledStatement","label":{"type":"Identifier","name":"label"},"body":{"type":"BlockStatement","body":[{"type":"WhileStatement","test":{"type":"Literal","value":true},"block":{"type":"BlockStatement","body":[{"type":"BreakStatement","label":"label"}]}}]}}]} +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "label" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "BreakStatement", + "label": { + "type": "Identifier", + "name": "label" + } + } + ] + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/circular_proto.js b/nashorn/test/script/basic/circular_proto.js index 5ae8f9cd03b..b381b7cf2d7 100644 --- a/nashorn/test/script/basic/circular_proto.js +++ b/nashorn/test/script/basic/circular_proto.js @@ -29,7 +29,6 @@ */ // check that we cannot create __proto__ cycle -load("nashorn:mozilla_compat.js"); var obj = {}; var obj2 = Object.create(obj); diff --git a/nashorn/test/script/basic/nonextensible_proto_assign.js b/nashorn/test/script/basic/nonextensible_proto_assign.js index 0240420d332..10ce4f53e27 100644 --- a/nashorn/test/script/basic/nonextensible_proto_assign.js +++ b/nashorn/test/script/basic/nonextensible_proto_assign.js @@ -28,8 +28,6 @@ * @run */ -load("nashorn:mozilla_compat.js") - // check that we cannot assign to __proto__ of a non-extensible object try { var obj = {} diff --git a/nashorn/test/script/basic/parser/assignmentExpr.js b/nashorn/test/script/basic/parser/assignmentExpr.js new file mode 100644 index 00000000000..231e19fd9b1 --- /dev/null +++ b/nashorn/test/script/basic/parser/assignmentExpr.js @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check assignment e xyzpressions. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("xyz = 314"); +printParse("xyz += 314"); +printParse("xyz -= 314"); +printParse("xyz *= 314"); +printParse("xyz /= 314"); +printParse("xyz %= 314"); +printParse("xyz <<= 314"); +printParse("xyz >>= 314"); +printParse("xyz >>>= 314"); +printParse("xyz &= 314"); +printParse("xyz ^= 314"); +printParse("xyz |= 314"); diff --git a/nashorn/test/script/basic/parser/assignmentExpr.js.EXPECTED b/nashorn/test/script/basic/parser/assignmentExpr.js.EXPECTED new file mode 100644 index 00000000000..da6793afa55 --- /dev/null +++ b/nashorn/test/script/basic/parser/assignmentExpr.js.EXPECTED @@ -0,0 +1,240 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "+=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "-=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "*=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "/=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "%=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "<<=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": ">>=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": ">>>=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "&=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "^=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "|=", + "left": { + "type": "Identifier", + "name": "xyz" + }, + "right": { + "type": "Literal", + "value": 314 + } + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/binaryExpr.js b/nashorn/test/script/basic/parser/binaryExpr.js new file mode 100644 index 00000000000..a2b761da2f1 --- /dev/null +++ b/nashorn/test/script/basic/parser/binaryExpr.js @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check binary operators. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("a * b") +printParse("a / b"); +printParse("a % b"); +printParse("a + b"); +printParse("a - b"); +printParse("a << b"); +printParse("a >> b"); +printParse("a >>> b"); +printParse("a < b"); +printParse("a > b"); +printParse("a <= b"); +printParse("a >= b"); +printParse("a instanceof b"); +printParse("a == b"); +printParse("a != b"); +printParse("a === b"); +printParse("a !== b"); +printParse("a & b"); +printParse("a ^ b"); +printParse("a | b"); +printParse("a && b"); +printParse("a || b"); diff --git a/nashorn/test/script/basic/parser/binaryExpr.js.EXPECTED b/nashorn/test/script/basic/parser/binaryExpr.js.EXPECTED new file mode 100644 index 00000000000..dd75f4b6096 --- /dev/null +++ b/nashorn/test/script/basic/parser/binaryExpr.js.EXPECTED @@ -0,0 +1,440 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "*", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "/", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "%", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "-", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "<<", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": ">>", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": ">>>", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "<", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": ">", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "<=", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": ">=", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "instanceof", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "==", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "!=", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "===", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "!==", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "&", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "^", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "|", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "LogicalExpression", + "operator": "&&", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "LogicalExpression", + "operator": "||", + "left": { + "type": "Identifier", + "name": "a" + }, + "right": { + "type": "Identifier", + "name": "b" + } + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/breakStat.js b/nashorn/test/script/basic/parser/breakStat.js new file mode 100644 index 00000000000..1b16cc2ce75 --- /dev/null +++ b/nashorn/test/script/basic/parser/breakStat.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check 'break' statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("while (true) { break; }"); +printParse("loop: { while (true) { break loop } }"); +printParse("loop: { for (;;) { break loop } }"); diff --git a/nashorn/test/script/basic/parser/breakStat.js.EXPECTED b/nashorn/test/script/basic/parser/breakStat.js.EXPECTED new file mode 100644 index 00000000000..1d9fd079810 --- /dev/null +++ b/nashorn/test/script/basic/parser/breakStat.js.EXPECTED @@ -0,0 +1,92 @@ +{ + "type": "Program", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "BreakStatement", + "label": null + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "loop" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "BreakStatement", + "label": { + "type": "Identifier", + "name": "loop" + } + } + ] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "loop" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ForStatement", + "init": null, + "test": null, + "update": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "BreakStatement", + "label": { + "type": "Identifier", + "name": "loop" + } + } + ] + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/condExpr.js b/nashorn/test/script/basic/parser/condExpr.js new file mode 100644 index 00000000000..3644ff35e84 --- /dev/null +++ b/nashorn/test/script/basic/parser/condExpr.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check ternary operator. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("a? b : c"); diff --git a/nashorn/test/script/basic/parser/condExpr.js.EXPECTED b/nashorn/test/script/basic/parser/condExpr.js.EXPECTED new file mode 100644 index 00000000000..75c486fa85f --- /dev/null +++ b/nashorn/test/script/basic/parser/condExpr.js.EXPECTED @@ -0,0 +1,23 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ConditionalExpression", + "test": { + "type": "Identifier", + "name": "a" + }, + "consequent": { + "type": "Identifier", + "name": "b" + }, + "alternate": { + "type": "Identifier", + "name": "c" + } + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/continueStat.js b/nashorn/test/script/basic/parser/continueStat.js new file mode 100644 index 00000000000..22ddadd44e6 --- /dev/null +++ b/nashorn/test/script/basic/parser/continueStat.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check 'continue' statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("while (true) { continue; }"); +printParse("begin: { while (true) { continue begin; } }"); +printParse("start: { for(;;) { continue start; } }"); diff --git a/nashorn/test/script/basic/parser/continueStat.js.EXPECTED b/nashorn/test/script/basic/parser/continueStat.js.EXPECTED new file mode 100644 index 00000000000..cfd3114db3c --- /dev/null +++ b/nashorn/test/script/basic/parser/continueStat.js.EXPECTED @@ -0,0 +1,92 @@ +{ + "type": "Program", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ContinueStatement", + "label": null + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "begin" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ContinueStatement", + "label": { + "type": "Identifier", + "name": "begin" + } + } + ] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "start" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ForStatement", + "init": null, + "test": null, + "update": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ContinueStatement", + "label": { + "type": "Identifier", + "name": "start" + } + } + ] + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/debuggerStat.js b/nashorn/test/script/basic/parser/debuggerStat.js new file mode 100644 index 00000000000..60eab78fff0 --- /dev/null +++ b/nashorn/test/script/basic/parser/debuggerStat.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check debugger statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("debugger"); diff --git a/nashorn/test/script/basic/parser/debuggerStat.js.EXPECTED b/nashorn/test/script/basic/parser/debuggerStat.js.EXPECTED new file mode 100644 index 00000000000..7b954fc30ee --- /dev/null +++ b/nashorn/test/script/basic/parser/debuggerStat.js.EXPECTED @@ -0,0 +1,8 @@ +{ + "type": "Program", + "body": [ + { + "type": "DebuggerStatement" + } + ] +} diff --git a/nashorn/test/script/basic/parser/functions.js b/nashorn/test/script/basic/parser/functions.js new file mode 100644 index 00000000000..7b624b554be --- /dev/null +++ b/nashorn/test/script/basic/parser/functions.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check 'function' statements and expressions. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("function hello() { print('hello') }") +printParse("function hello(a) { print(a) }") +printParse("function hello(a, b) { print(a, b) }") +printParse("var hello = function() { print('hello') };") +printParse("var hello = function hello() { print('hello') };") +printParse("(function(){})") +printParse("function test() { 'use strict' }"); diff --git a/nashorn/test/script/basic/parser/functions.js.EXPECTED b/nashorn/test/script/basic/parser/functions.js.EXPECTED new file mode 100644 index 00000000000..59451d57942 --- /dev/null +++ b/nashorn/test/script/basic/parser/functions.js.EXPECTED @@ -0,0 +1,279 @@ +{ + "type": "Program", + "body": [ + { + "type": "FunctionDeclaration", + "id": { + "type": "Identifier", + "name": "hello" + }, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] + }, + "generator": false, + "expression": false + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "FunctionDeclaration", + "id": { + "type": "Identifier", + "name": "hello" + }, + "params": [ + { + "type": "Identifier", + "name": "a" + } + ], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Identifier", + "name": "a" + } + ] + } + } + ] + }, + "generator": false, + "expression": false + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "FunctionDeclaration", + "id": { + "type": "Identifier", + "name": "hello" + }, + "params": [ + { + "type": "Identifier", + "name": "a" + }, + { + "type": "Identifier", + "name": "b" + } + ], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Identifier", + "name": "a" + }, + { + "type": "Identifier", + "name": "b" + } + ] + } + } + ] + }, + "generator": false, + "expression": false + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "hello" + }, + "init": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] + }, + "generator": false, + "expression": false + } + } + ] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "hello" + }, + "init": { + "type": "FunctionExpression", + "id": { + "type": "Identifier", + "name": "hello" + }, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] + }, + "generator": false, + "expression": false + } + } + ] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [] + }, + "generator": false, + "expression": false + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "FunctionDeclaration", + "id": { + "type": "Identifier", + "name": "test" + }, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": "use strict" + } + } + ] + }, + "generator": false, + "expression": false + } + ] +} diff --git a/nashorn/test/script/basic/parser/ifStat.js b/nashorn/test/script/basic/parser/ifStat.js new file mode 100644 index 00000000000..5d1566686c2 --- /dev/null +++ b/nashorn/test/script/basic/parser/ifStat.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check 'if' statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("if (js) { nashorn() }"); +printParse("if (js) { nashorn() } else { java() }"); diff --git a/nashorn/test/script/basic/parser/ifStat.js.EXPECTED b/nashorn/test/script/basic/parser/ifStat.js.EXPECTED new file mode 100644 index 00000000000..3897dc14fca --- /dev/null +++ b/nashorn/test/script/basic/parser/ifStat.js.EXPECTED @@ -0,0 +1,73 @@ +{ + "type": "Program", + "body": [ + { + "type": "IfStatement", + "test": { + "type": "Identifier", + "name": "js" + }, + "consequent": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "nashorn" + }, + "arguments": [] + } + } + ] + }, + "alternate": null + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "IfStatement", + "test": { + "type": "Identifier", + "name": "js" + }, + "consequent": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "nashorn" + }, + "arguments": [] + } + } + ] + }, + "alternate": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "java" + }, + "arguments": [] + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/labelledStat.js b/nashorn/test/script/basic/parser/labelledStat.js new file mode 100644 index 00000000000..25829a4a755 --- /dev/null +++ b/nashorn/test/script/basic/parser/labelledStat.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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 for labelled statements. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("begin: { for (;;) break begin }"); +printParse("begin: { while (true) break begin }"); diff --git a/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED b/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED new file mode 100644 index 00000000000..fc5f37e8a3b --- /dev/null +++ b/nashorn/test/script/basic/parser/labelledStat.js.EXPECTED @@ -0,0 +1,71 @@ +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "begin" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ForStatement", + "init": null, + "test": null, + "update": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "BreakStatement", + "label": { + "type": "Identifier", + "name": "begin" + } + } + ] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "LabeledStatement", + "label": { + "type": "Identifier", + "name": "begin" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "BreakStatement", + "label": { + "type": "Identifier", + "name": "begin" + } + } + ] + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/lhsExpr.js b/nashorn/test/script/basic/parser/lhsExpr.js new file mode 100644 index 00000000000..68f4d6c3c46 --- /dev/null +++ b/nashorn/test/script/basic/parser/lhsExpr.js @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check left-hand-side expressions + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("a[3]"); +printParse("a[b]"); +printParse("a['foo']"); +printParse("obj.foo"); +printParse("obj.foo.bar"); +printParse("new Type"); +printParse("new Type()"); +printParse("new Type(a, 'hello')"); +printParse("new obj.Type"); +printParse("new obj.Type()"); +printParse("new obj.Type(a, 'hello')"); +printParse("foo()") +printParse("obj.foo()"); +printParse("foo(a,b)"); +printParse("obj.foo(a, b)"); diff --git a/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED b/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED new file mode 100644 index 00000000000..e61c6c8fc6a --- /dev/null +++ b/nashorn/test/script/basic/parser/lhsExpr.js.EXPECTED @@ -0,0 +1,344 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a" + }, + "property": { + "type": "Literal", + "value": 3 + }, + "computed": true + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a" + }, + "property": { + "type": "Identifier", + "name": "b" + }, + "computed": true + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "a" + }, + "property": { + "type": "Literal", + "value": "foo" + }, + "computed": true + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "foo" + }, + "computed": false + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "MemberExpression", + "object": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "foo" + }, + "computed": false + }, + "property": { + "type": "Identifier", + "name": "bar" + }, + "computed": false + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "NewExpression", + "callee": { + "type": "Identifier", + "name": "Type" + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "NewExpression", + "callee": { + "type": "Identifier", + "name": "Type" + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "NewExpression", + "callee": { + "type": "Identifier", + "name": "Type" + }, + "arguments": [ + { + "type": "Identifier", + "name": "a" + }, + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "NewExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "Type" + }, + "computed": false + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "NewExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "Type" + }, + "computed": false + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "NewExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "Type" + }, + "computed": false + }, + "arguments": [ + { + "type": "Identifier", + "name": "a" + }, + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo" + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "foo" + }, + "computed": false + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo" + }, + "arguments": [ + { + "type": "Identifier", + "name": "a" + }, + { + "type": "Identifier", + "name": "b" + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "foo" + }, + "computed": false + }, + "arguments": [ + { + "type": "Identifier", + "name": "a" + }, + { + "type": "Identifier", + "name": "b" + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/loopStat.js b/nashorn/test/script/basic/parser/loopStat.js new file mode 100644 index 00000000000..ba705568e8e --- /dev/null +++ b/nashorn/test/script/basic/parser/loopStat.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests for loop statements. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("while(true) { print('hello') }") +printParse("do { print('hello') } while(true)") +printParse("for (i in obj) { print(obj[i]) }") +printParse("for each (i in obj) { print(i) }") +printParse("for (i = 0; i < 10; i++) { print(i) }") diff --git a/nashorn/test/script/basic/parser/loopStat.js.EXPECTED b/nashorn/test/script/basic/parser/loopStat.js.EXPECTED new file mode 100644 index 00000000000..fd8ef838afc --- /dev/null +++ b/nashorn/test/script/basic/parser/loopStat.js.EXPECTED @@ -0,0 +1,212 @@ +{ + "type": "Program", + "body": [ + { + "type": "WhileStatement", + "test": { + "type": "Literal", + "value": true + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "DoWhileStatement", + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Literal", + "value": "hello" + } + ] + } + } + ] + }, + "test": { + "type": "Literal", + "value": true + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ForInStatement", + "left": { + "type": "Identifier", + "name": "i" + }, + "right": { + "type": "Identifier", + "name": "obj" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "MemberExpression", + "object": { + "type": "Identifier", + "name": "obj" + }, + "property": { + "type": "Identifier", + "name": "i" + }, + "computed": true + } + ] + } + } + ] + }, + "each": false + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ForInStatement", + "left": { + "type": "Identifier", + "name": "i" + }, + "right": { + "type": "Identifier", + "name": "obj" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Identifier", + "name": "i" + } + ] + } + } + ] + }, + "each": true + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ForStatement", + "init": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "i" + }, + "right": { + "type": "Literal", + "value": 0 + } + }, + "test": { + "type": "BinaryExpression", + "operator": "<", + "left": { + "type": "Identifier", + "name": "i" + }, + "right": { + "type": "Literal", + "value": 10 + } + }, + "update": { + "type": "UpdateExpression", + "operator": "++", + "prefix": false, + "argument": { + "type": "Identifier", + "name": "i" + } + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "print" + }, + "arguments": [ + { + "type": "Identifier", + "name": "i" + } + ] + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/objectLitExpr.js b/nashorn/test/script/basic/parser/objectLitExpr.js new file mode 100644 index 00000000000..bdecc7fa691 --- /dev/null +++ b/nashorn/test/script/basic/parser/objectLitExpr.js @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check assignment e xyzpressions. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("obj = {}"); +printParse("p = { x: 10, y: 2 }"); +printParse("p = { 'x': 10, 'y': 2 }"); +printParse("p = { get x() { return xValue }, get y() { return yValue } }"); diff --git a/nashorn/test/script/basic/parser/objectLitExpr.js.EXPECTED b/nashorn/test/script/basic/parser/objectLitExpr.js.EXPECTED new file mode 100644 index 00000000000..7968d9a4a0f --- /dev/null +++ b/nashorn/test/script/basic/parser/objectLitExpr.js.EXPECTED @@ -0,0 +1,183 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "obj" + }, + "right": { + "type": "ObjectExpression", + "properties": [] + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "p" + }, + "right": { + "type": "ObjectExpression", + "properties": [ + { + "key": { + "type": "Identifier", + "name": "x" + }, + "value": { + "type": "Literal", + "value": 10 + }, + "kind": "init" + }, + { + "key": { + "type": "Identifier", + "name": "y" + }, + "value": { + "type": "Literal", + "value": 2 + }, + "kind": "init" + } + ] + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "p" + }, + "right": { + "type": "ObjectExpression", + "properties": [ + { + "key": { + "type": "Literal", + "value": "x" + }, + "value": { + "type": "Literal", + "value": 10 + }, + "kind": "init" + }, + { + "key": { + "type": "Literal", + "value": "y" + }, + "value": { + "type": "Literal", + "value": 2 + }, + "kind": "init" + } + ] + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "p" + }, + "right": { + "type": "ObjectExpression", + "properties": [ + { + "key": { + "type": "Identifier", + "name": "x" + }, + "value": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "xValue" + } + } + ] + }, + "generator": false, + "expression": false + }, + "kind": "get" + }, + { + "key": { + "type": "Identifier", + "name": "y" + }, + "value": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "yValue" + } + } + ] + }, + "generator": false, + "expression": false + }, + "kind": "get" + } + ] + } + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/parenExpr.js b/nashorn/test/script/basic/parser/parenExpr.js new file mode 100644 index 00000000000..2d52a023034 --- /dev/null +++ b/nashorn/test/script/basic/parser/parenExpr.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests for parenthesis expressions. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("(2) + (1) + 4"); +printParse("3 + (7) << (5)"); diff --git a/nashorn/test/script/basic/parser/parenExpr.js.EXPECTED b/nashorn/test/script/basic/parser/parenExpr.js.EXPECTED new file mode 100644 index 00000000000..1e4a2306c71 --- /dev/null +++ b/nashorn/test/script/basic/parser/parenExpr.js.EXPECTED @@ -0,0 +1,56 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Literal", + "value": 2 + }, + "right": { + "type": "Literal", + "value": 1 + } + }, + "right": { + "type": "Literal", + "value": 4 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "<<", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Literal", + "value": 3 + }, + "right": { + "type": "Literal", + "value": 7 + } + }, + "right": { + "type": "Literal", + "value": 5 + } + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/primaryExpr.js b/nashorn/test/script/basic/parser/primaryExpr.js new file mode 100644 index 00000000000..950c47f3ea8 --- /dev/null +++ b/nashorn/test/script/basic/parser/primaryExpr.js @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check primary expressions. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("this"); +printParse("foo"); +printParse("null"); +printParse("true"); +printParse("false"); +printParse("33"); +printParse("3.14"); +printParse("(10 + 3)*2"); +printParse("({})"); +printParse("({ x: 3 })"); +printParse("[]"); +printParse("[,,]"); +printParse("[4, 5, 5]"); diff --git a/nashorn/test/script/basic/parser/primaryExpr.js.EXPECTED b/nashorn/test/script/basic/parser/primaryExpr.js.EXPECTED new file mode 100644 index 00000000000..fcb31d54cd5 --- /dev/null +++ b/nashorn/test/script/basic/parser/primaryExpr.js.EXPECTED @@ -0,0 +1,199 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ThisExpression" + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Identifier", + "name": "foo" + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": null + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": true + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": false + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": 33 + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": 3.14 + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "BinaryExpression", + "operator": "*", + "left": { + "type": "BinaryExpression", + "operator": "+", + "left": { + "type": "Literal", + "value": 10 + }, + "right": { + "type": "Literal", + "value": 3 + } + }, + "right": { + "type": "Literal", + "value": 2 + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ObjectExpression", + "properties": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ObjectExpression", + "properties": [ + { + "key": { + "type": "Identifier", + "name": "x" + }, + "value": { + "type": "Literal", + "value": 3 + }, + "kind": "init" + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ArrayExpression", + "elements": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ArrayExpression", + "elements": [ + null, + null + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "ArrayExpression", + "elements": [ + { + "type": "Literal", + "value": 4 + }, + { + "type": "Literal", + "value": 5 + }, + { + "type": "Literal", + "value": 5 + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/returnStat.js b/nashorn/test/script/basic/parser/returnStat.js new file mode 100644 index 00000000000..741a23403c4 --- /dev/null +++ b/nashorn/test/script/basic/parser/returnStat.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check 'return' statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("(function() { return })"); +printParse("(function() { return res })"); +printParse("(function() { return foo() })"); diff --git a/nashorn/test/script/basic/parser/returnStat.js.EXPECTED b/nashorn/test/script/basic/parser/returnStat.js.EXPECTED new file mode 100644 index 00000000000..149673c1d0f --- /dev/null +++ b/nashorn/test/script/basic/parser/returnStat.js.EXPECTED @@ -0,0 +1,88 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ReturnStatement", + "argument": null + } + ] + }, + "generator": false, + "expression": false + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ReturnStatement", + "argument": { + "type": "Identifier", + "name": "res" + } + } + ] + }, + "generator": false, + "expression": false + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "FunctionExpression", + "id": null, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ReturnStatement", + "argument": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "foo" + }, + "arguments": [] + } + } + ] + }, + "generator": false, + "expression": false + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/switchStat.js b/nashorn/test/script/basic/parser/switchStat.js new file mode 100644 index 00000000000..6f0dd75e741 --- /dev/null +++ b/nashorn/test/script/basic/parser/switchStat.js @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests for switch statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("switch (key) {}"); +printParse("switch (key) { case 2: hello(); break; }"); +printParse("switch (key) { case 4: hello(); break; case 2: world(); break; default: break }"); diff --git a/nashorn/test/script/basic/parser/switchStat.js.EXPECTED b/nashorn/test/script/basic/parser/switchStat.js.EXPECTED new file mode 100644 index 00000000000..6de4ba484b3 --- /dev/null +++ b/nashorn/test/script/basic/parser/switchStat.js.EXPECTED @@ -0,0 +1,123 @@ +{ + "type": "Program", + "body": [ + { + "type": "SwitchStatement", + "discriminant": { + "type": "Identifier", + "name": "key" + }, + "cases": [] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "SwitchStatement", + "discriminant": { + "type": "Identifier", + "name": "key" + }, + "cases": [ + { + "type": "SwitchCase", + "test": { + "type": "Literal", + "value": 2 + }, + "consequent": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "hello" + }, + "arguments": [] + } + }, + { + "type": "BreakStatement", + "label": null + } + ] + } + ] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "SwitchStatement", + "discriminant": { + "type": "Identifier", + "name": "key" + }, + "cases": [ + { + "type": "SwitchCase", + "test": { + "type": "Literal", + "value": 4 + }, + "consequent": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "hello" + }, + "arguments": [] + } + }, + { + "type": "BreakStatement", + "label": null + } + ] + }, + { + "type": "SwitchCase", + "test": { + "type": "Literal", + "value": 2 + }, + "consequent": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "world" + }, + "arguments": [] + } + }, + { + "type": "BreakStatement", + "label": null + } + ] + }, + { + "type": "SwitchCase", + "test": null, + "consequent": [ + { + "type": "BreakStatement", + "label": null + } + ] + } + ] + } + ] +} diff --git a/nashorn/test/script/basic/parser/throwStat.js b/nashorn/test/script/basic/parser/throwStat.js new file mode 100644 index 00000000000..345e3b8c7dc --- /dev/null +++ b/nashorn/test/script/basic/parser/throwStat.js @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests for throw statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("throw err"); +printParse("throw 'wrong'"); +printParse("throw new TypeError"); +printParse("throw new TypeError('not an array')"); +printParse("throw { msg: 'wrong!' }"); diff --git a/nashorn/test/script/basic/parser/throwStat.js.EXPECTED b/nashorn/test/script/basic/parser/throwStat.js.EXPECTED new file mode 100644 index 00000000000..d869cbda8df --- /dev/null +++ b/nashorn/test/script/basic/parser/throwStat.js.EXPECTED @@ -0,0 +1,85 @@ +{ + "type": "Program", + "body": [ + { + "type": "ThrowStatement", + "argument": { + "type": "Identifier", + "name": "err" + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ThrowStatement", + "argument": { + "type": "Literal", + "value": "wrong" + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ThrowStatement", + "argument": { + "type": "NewExpression", + "callee": { + "type": "Identifier", + "name": "TypeError" + }, + "arguments": [] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ThrowStatement", + "argument": { + "type": "NewExpression", + "callee": { + "type": "Identifier", + "name": "TypeError" + }, + "arguments": [ + { + "type": "Literal", + "value": "not an array" + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ThrowStatement", + "argument": { + "type": "ObjectExpression", + "properties": [ + { + "key": { + "type": "Identifier", + "name": "msg" + }, + "value": { + "type": "Literal", + "value": "wrong!" + }, + "kind": "init" + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/tryCatchStat.js b/nashorn/test/script/basic/parser/tryCatchStat.js new file mode 100644 index 00000000000..de1531338b0 --- /dev/null +++ b/nashorn/test/script/basic/parser/tryCatchStat.js @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check try..catch statements. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("try { } catch (e) { }"); +printParse("try { } catch (e) { } finally {}"); +printParse("try { } finally {}"); +printParse("try { } catch (e) { handle() }"); +printParse("try { that() } catch (e) { handle() } finally { clean() }"); +printParse("try { that() } catch (e if e instanceof TypeError) { handle() } catch (e) { rest() }"); diff --git a/nashorn/test/script/basic/parser/tryCatchStat.js.EXPECTED b/nashorn/test/script/basic/parser/tryCatchStat.js.EXPECTED new file mode 100644 index 00000000000..16075e15420 --- /dev/null +++ b/nashorn/test/script/basic/parser/tryCatchStat.js.EXPECTED @@ -0,0 +1,305 @@ +{ + "type": "Program", + "body": [ + { + "type": "BlockStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [] + }, + "guardedHandlers": [], + "handler": { + "type": "CatchClause", + "param": { + "type": "Identifier", + "name": "e" + }, + "body": { + "type": "BlockStatement", + "body": [] + } + }, + "finalizer": null + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "BlockStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [] + }, + "guardedHandlers": [], + "handler": { + "type": "CatchClause", + "param": { + "type": "Identifier", + "name": "e" + }, + "body": { + "type": "BlockStatement", + "body": [] + } + }, + "finalizer": { + "type": "BlockStatement", + "body": [] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "BlockStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [] + }, + "guardedHandlers": [], + "handler": null, + "finalizer": { + "type": "BlockStatement", + "body": [] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "BlockStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [] + }, + "guardedHandlers": [], + "handler": { + "type": "CatchClause", + "param": { + "type": "Identifier", + "name": "e" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "handle" + }, + "arguments": [] + } + } + ] + } + }, + "finalizer": null + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "BlockStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "that" + }, + "arguments": [] + } + } + ] + }, + "guardedHandlers": [], + "handler": { + "type": "CatchClause", + "param": { + "type": "Identifier", + "name": "e" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "handle" + }, + "arguments": [] + } + } + ] + } + }, + "finalizer": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "clean" + }, + "arguments": [] + } + } + ] + } + } + ] + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "BlockStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "TryStatement", + "block": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "that" + }, + "arguments": [] + } + } + ] + }, + "guardedHandlers": [ + { + "type": "CatchClause", + "param": { + "type": "Identifier", + "name": "e" + }, + "guard": { + "type": "BinaryExpression", + "operator": "instanceof", + "left": { + "type": "Identifier", + "name": "e" + }, + "right": { + "type": "Identifier", + "name": "TypeError" + } + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "handle" + }, + "arguments": [] + } + } + ] + } + } + ], + "handler": { + "type": "CatchClause", + "param": { + "type": "Identifier", + "name": "e" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "CallExpression", + "callee": { + "type": "Identifier", + "name": "rest" + }, + "arguments": [] + } + } + ] + } + }, + "finalizer": null + } + ] + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/unaryExpr.js b/nashorn/test/script/basic/parser/unaryExpr.js new file mode 100644 index 00000000000..e21b55f32fa --- /dev/null +++ b/nashorn/test/script/basic/parser/unaryExpr.js @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check unary operators. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("x++"); +printParse("x--"); +printParse("delete x"); +printParse("void x"); +printParse("typeof x"); +printParse("++x"); +printParse("--x"); +printParse("+x"); +printParse("-x"); +printParse("~x"); +printParse("!x"); diff --git a/nashorn/test/script/basic/parser/unaryExpr.js.EXPECTED b/nashorn/test/script/basic/parser/unaryExpr.js.EXPECTED new file mode 100644 index 00000000000..d7a9532b677 --- /dev/null +++ b/nashorn/test/script/basic/parser/unaryExpr.js.EXPECTED @@ -0,0 +1,187 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UpdateExpression", + "operator": "++", + "prefix": false, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UpdateExpression", + "operator": "--", + "prefix": false, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "delete", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "void", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "typeof", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UpdateExpression", + "operator": "++", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UpdateExpression", + "operator": "--", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "+", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "-", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "~", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "UnaryExpression", + "operator": "!", + "prefix": true, + "argument": { + "type": "Identifier", + "name": "x" + } + } + } + ] +} diff --git a/nashorn/test/script/basic/parser/useStrict.js b/nashorn/test/script/basic/parser/useStrict.js new file mode 100644 index 00000000000..4d1c7a94d09 --- /dev/null +++ b/nashorn/test/script/basic/parser/useStrict.js @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check if statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("'use strict'"); +printParse("function f() { 'use strict' }"); diff --git a/nashorn/test/script/basic/parser/useStrict.js.EXPECTED b/nashorn/test/script/basic/parser/useStrict.js.EXPECTED new file mode 100644 index 00000000000..870fbc24e04 --- /dev/null +++ b/nashorn/test/script/basic/parser/useStrict.js.EXPECTED @@ -0,0 +1,41 @@ +{ + "type": "Program", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": "use strict" + } + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "FunctionDeclaration", + "id": { + "type": "Identifier", + "name": "f" + }, + "params": [], + "defaults": [], + "rest": null, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "Literal", + "value": "use strict" + } + } + ] + }, + "generator": false, + "expression": false + } + ] +} diff --git a/nashorn/test/script/basic/parser/util.js b/nashorn/test/script/basic/parser/util.js new file mode 100644 index 00000000000..6170018b378 --- /dev/null +++ b/nashorn/test/script/basic/parser/util.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * @subtest + */ + +// utilitity for parser tests + +load("nashorn:parser.js"); +function printParse(code) { + print(JSON.stringify(parse(code), null, ' ')); +} diff --git a/nashorn/test/script/basic/parser/varDecl.js b/nashorn/test/script/basic/parser/varDecl.js new file mode 100644 index 00000000000..e505761be8e --- /dev/null +++ b/nashorn/test/script/basic/parser/varDecl.js @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests to check variable declarations. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +// no initialization +printParse("var a"); +printParse("var a, b"); + +// init single, multiple +printParse("var a = 'hello'"); +printParse("var a = 1, b = 2, c = 3"); diff --git a/nashorn/test/script/basic/parser/varDecl.js.EXPECTED b/nashorn/test/script/basic/parser/varDecl.js.EXPECTED new file mode 100644 index 00000000000..96e71cf6f13 --- /dev/null +++ b/nashorn/test/script/basic/parser/varDecl.js.EXPECTED @@ -0,0 +1,123 @@ +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a" + }, + "init": null + } + ] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a" + }, + "init": null + } + ] + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b" + }, + "init": null + } + ] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a" + }, + "init": { + "type": "Literal", + "value": "hello" + } + } + ] + } + ] +} +{ + "type": "Program", + "body": [ + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "a" + }, + "init": { + "type": "Literal", + "value": 1 + } + } + ] + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "b" + }, + "init": { + "type": "Literal", + "value": 2 + } + } + ] + }, + { + "type": "VariableDeclaration", + "declarations": [ + { + "type": "VariableDeclarator", + "id": { + "type": "Identifier", + "name": "c" + }, + "init": { + "type": "Literal", + "value": 3 + } + } + ] + } + ] +} diff --git a/nashorn/test/script/basic/parser/withStat.js b/nashorn/test/script/basic/parser/withStat.js new file mode 100644 index 00000000000..3f94c7f596f --- /dev/null +++ b/nashorn/test/script/basic/parser/withStat.js @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * 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. + */ + +/** + * Tests for 'with' statement. + * + * @test + * @run + */ + +load(__DIR__ + "util.js"); + +printParse("with (scope) { x = y }"); diff --git a/nashorn/test/script/basic/parser/withStat.js.EXPECTED b/nashorn/test/script/basic/parser/withStat.js.EXPECTED new file mode 100644 index 00000000000..46bea479a26 --- /dev/null +++ b/nashorn/test/script/basic/parser/withStat.js.EXPECTED @@ -0,0 +1,32 @@ +{ + "type": "Program", + "body": [ + { + "type": "WithStatement", + "object": { + "type": "Identifier", + "name": "scope" + }, + "body": { + "type": "BlockStatement", + "body": [ + { + "type": "ExpressionStatement", + "expression": { + "type": "AssignmentExpression", + "operator": "=", + "left": { + "type": "Identifier", + "name": "x" + }, + "right": { + "type": "Identifier", + "name": "y" + } + } + } + ] + } + } + ] +} diff --git a/nashorn/test/script/trusted/JDK-8008305.js b/nashorn/test/script/trusted/JDK-8008305.js index e4d052cbce8..d57b5208048 100644 --- a/nashorn/test/script/trusted/JDK-8008305.js +++ b/nashorn/test/script/trusted/JDK-8008305.js @@ -54,6 +54,6 @@ try { fail("Expected SecurityException from script!"); } catch (e) { if (! (e instanceof SecurityException)) { - faile("Expected SecurityException, but got " + e); + fail("Expected SecurityException, but got " + e); } } diff --git a/nashorn/test/src/META-INF/services/java.sql.Driver b/nashorn/test/src/META-INF/services/java.sql.Driver new file mode 100644 index 00000000000..295fe48075f --- /dev/null +++ b/nashorn/test/src/META-INF/services/java.sql.Driver @@ -0,0 +1 @@ +jdk.nashorn.api.NashornSQLDriver diff --git a/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java b/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java new file mode 100644 index 00000000000..2987b948548 --- /dev/null +++ b/nashorn/test/src/jdk/nashorn/api/NashornSQLDriver.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.api; + +import java.sql.*; +import java.util.Properties; +import java.util.logging.Logger; + +/** + * A dummy SQL driver for testing purpose. + */ +public final class NashornSQLDriver implements Driver { + static { + try { + DriverManager.registerDriver(new NashornSQLDriver(), null); + } catch (SQLException se) { + throw new RuntimeException(se); + } + } + + @Override + public boolean acceptsURL(String url) { + return url.startsWith("jdbc:nashorn:"); + } + + @Override + public Connection connect(String url, Properties info) { + throw new UnsupportedOperationException("I am a dummy!!"); + } + + @Override + public int getMajorVersion() { + return -1; + } + + @Override + public int getMinorVersion() { + return -1; + } + + @Override + public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) { + return new DriverPropertyInfo[0]; + } + + @Override + public boolean jdbcCompliant() { + // no way! + return false; + } + + @Override + public Logger getParentLogger() throws SQLFeatureNotSupportedException { + throw new SQLFeatureNotSupportedException(); + } +} diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java new file mode 100644 index 00000000000..acb57164029 --- /dev/null +++ b/nashorn/test/src/jdk/nashorn/api/scripting/PluggableJSObjectTest.java @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package jdk.nashorn.api.scripting; + +import java.nio.IntBuffer; +import java.util.Collection; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Set; +import javax.script.ScriptEngine; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.fail; +import org.testng.annotations.Test; + +/** + * Tests for pluggable external impls. of jdk.nashorn.api.scripting.JSObject. + * + * JDK-8024615: Refactor ScriptObjectMirror and JSObject to support external + * JSObject implementations. + */ +public class PluggableJSObjectTest { + public static class MapWrapperObject extends JSObject { + private final HashMap map = new LinkedHashMap<>(); + + public HashMap getMap() { + return map; + } + + @Override + public Object getMember(String name) { + return map.get(name); + } + + @Override + public void setMember(String name, Object value) { + map.put(name, value); + } + + @Override + public boolean hasMember(String name) { + return map.containsKey(name); + } + + @Override + public void removeMember(String name) { + map.remove(name); + } + + @Override + public Set keySet() { + return map.keySet(); + } + + @Override + public Collection values() { + return map.values(); + } + } + + @Test + // Named property access on a JSObject + public void namedAccessTest() { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + try { + final MapWrapperObject obj = new MapWrapperObject(); + e.put("obj", obj); + obj.getMap().put("foo", "bar"); + + // property-like access on MapWrapperObject objects + assertEquals(e.eval("obj.foo"), "bar"); + e.eval("obj.foo = 'hello'"); + assertEquals(e.eval("'foo' in obj"), Boolean.TRUE); + assertEquals(e.eval("obj.foo"), "hello"); + assertEquals(obj.getMap().get("foo"), "hello"); + e.eval("delete obj.foo"); + assertFalse(obj.getMap().containsKey("foo")); + assertEquals(e.eval("'foo' in obj"), Boolean.FALSE); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + } + + public static class BufferObject extends JSObject { + private final IntBuffer buf; + + public BufferObject(int size) { + buf = IntBuffer.allocate(size); + } + + public IntBuffer getBuffer() { + return buf; + } + + @Override + public Object getMember(String name) { + return name.equals("length")? buf.capacity() : null; + } + + @Override + public boolean hasSlot(int i) { + return i > -1 && i < buf.capacity(); + } + + @Override + public Object getSlot(int i) { + return buf.get(i); + } + + @Override + public void setSlot(int i, Object value) { + buf.put(i, ((Number)value).intValue()); + } + + @Override + public boolean isArray() { + return true; + } + } + + @Test + // array-like indexed access for a JSObject + public void indexedAccessTest() { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + try { + final BufferObject buf = new BufferObject(2); + e.put("buf", buf); + + // array-like access on BufferObject objects + assertEquals(e.eval("buf.length"), buf.getBuffer().capacity()); + e.eval("buf[0] = 23"); + assertEquals(buf.getBuffer().get(0), 23); + assertEquals(e.eval("buf[0]"), 23); + assertEquals(e.eval("buf[1]"), 0); + buf.getBuffer().put(1, 42); + assertEquals(e.eval("buf[1]"), 42); + assertEquals(e.eval("Array.isArray(buf)"), Boolean.TRUE); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + } + + public static class Adder extends JSObject { + @Override + public Object call(Object thiz, Object... args) { + double res = 0.0; + for (Object arg : args) { + res += ((Number)arg).doubleValue(); + } + return res; + } + + @Override + public boolean isFunction() { + return true; + } + } + + @Test + // a callable JSObject + public void callableJSObjectTest() { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + try { + e.put("sum", new Adder()); + // check callability of Adder objects + assertEquals(e.eval("typeof sum"), "function"); + assertEquals(((Number)e.eval("sum(1, 2, 3, 4, 5)")).intValue(), 15); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + } + + public static class Factory extends JSObject { + @Override + public Object newObject(Object... args) { + return new HashMap(); + } + + @Override + public boolean isFunction() { + return true; + } + } + + @Test + // a factory JSObject + public void factoryJSObjectTest() { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + try { + e.put("Factory", new Factory()); + + // check new on Factory + assertEquals(e.eval("typeof Factory"), "function"); + assertEquals(e.eval("typeof new Factory()"), "object"); + assertEquals(e.eval("(new Factory()) instanceof java.util.Map"), Boolean.TRUE); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + } + + @Test + // iteration tests + public void iteratingJSObjectTest() { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine e = m.getEngineByName("nashorn"); + try { + final MapWrapperObject obj = new MapWrapperObject(); + obj.setMember("foo", "hello"); + obj.setMember("bar", "world"); + e.put("obj", obj); + + // check for..in + Object val = e.eval("var str = ''; for (i in obj) str += i; str"); + assertEquals(val.toString(), "foobar"); + + // check for..each..in + val = e.eval("var str = ''; for each (i in obj) str += i; str"); + assertEquals(val.toString(), "helloworld"); + } catch (final Exception exp) { + exp.printStackTrace(); + fail(exp.getMessage()); + } + } +} diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java index 416669fbcf3..99207de0d6e 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptEngineTest.java @@ -37,10 +37,12 @@ import java.lang.reflect.Method; import java.util.concurrent.Callable; import javax.script.Compilable; import javax.script.CompiledScript; +import javax.script.ScriptContext; import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import javax.script.ScriptEngineManager; import javax.script.ScriptException; +import javax.script.SimpleScriptContext; import org.testng.annotations.Test; /** @@ -230,6 +232,17 @@ public class ScriptEngineTest { } } + @Test + public void compileAndEvalInDiffContextTest() throws ScriptException { + final ScriptEngineManager m = new ScriptEngineManager(); + final ScriptEngine engine = m.getEngineByName("js"); + final Compilable compilable = (Compilable) engine; + final CompiledScript compiledScript = compilable.compile("foo"); + final ScriptContext ctxt = new SimpleScriptContext(); + ctxt.setAttribute("foo", "hello", ScriptContext.ENGINE_SCOPE); + assertEquals(compiledScript.eval(ctxt), "hello"); + } + @Test public void accessGlobalTest() { final ScriptEngineManager m = new ScriptEngineManager(); diff --git a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java index 75f636ae6a0..c7b40c6367f 100644 --- a/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java +++ b/nashorn/test/src/jdk/nashorn/api/scripting/ScriptObjectMirrorTest.java @@ -140,8 +140,8 @@ public class ScriptObjectMirrorTest { fail("obj[1] != 'world'"); } - if (!obj.call("func", new Object[0]).equals("hello")) { - fail("obj.call('func') != 'hello'"); + if (!obj.callMember("func", new Object[0]).equals("hello")) { + fail("obj.func() != 'hello'"); } // try setting properties @@ -210,8 +210,8 @@ public class ScriptObjectMirrorTest { e.eval("function func() {}"); e2.put("foo", e.get("func")); - final Object e2global = e2.eval("this"); - final Object newObj = ((ScriptObjectMirror) e2global).newObject("foo"); + final ScriptObjectMirror e2global = (ScriptObjectMirror)e2.eval("this"); + final Object newObj = ((ScriptObjectMirror)e2global.getMember("foo")).newObject(); assertTrue(newObj instanceof ScriptObjectMirror); } @@ -223,8 +223,8 @@ public class ScriptObjectMirrorTest { e.eval("function func() {}"); e2.put("func", e.get("func")); - final Object e2obj = e2.eval("({ foo: func })"); - final Object newObj = ((ScriptObjectMirror) e2obj).newObject("foo"); + final ScriptObjectMirror e2obj = (ScriptObjectMirror)e2.eval("({ foo: func })"); + final Object newObj = ((ScriptObjectMirror)e2obj.getMember("foo")).newObject(); assertTrue(newObj instanceof ScriptObjectMirror); } } diff --git a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java index 16165ce704d..1b21c23f404 100644 --- a/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java +++ b/nashorn/test/src/jdk/nashorn/internal/runtime/ContextTest.java @@ -64,6 +64,7 @@ public class ContextTest { final Options options = new Options(""); final ErrorManager errors = new ErrorManager(); final Context cx = new Context(options, errors, Thread.currentThread().getContextClassLoader()); + final boolean strict = cx.getEnv()._strict; final ScriptObject oldGlobal = Context.getGlobal(); Context.setGlobal(cx.createGlobal()); @@ -95,7 +96,7 @@ public class ContextTest { assertEquals(sobj.size(), 2); // add property - sobj.put("zee", "hello"); + sobj.put("zee", "hello", strict); assertEquals(sobj.get("zee"), "hello"); assertEquals(sobj.size(), 3);