diff --git a/.hgtags b/.hgtags index b6f1545f2b7..2fc464b6481 100644 --- a/.hgtags +++ b/.hgtags @@ -227,3 +227,5 @@ bbe43d712fe08e650808d774861b256ccb34e500 jdk8-b102 30a1d677a20c6a95f98043d8f20ce570304e3818 jdk8-b103 b5ed503c26ad38869c247c5e32debec217fd056b jdk8-b104 589f4fdc584e373a47cde0162e9eceec9165c381 jdk8-b105 +514b0b69fb9683ef52062fd962a3e0644431f64d jdk8-b106 +892889f445755790ae90e61775bfb59ddc6182b5 jdk8-b107 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index 505ac39fd54..d83fa5ca611 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -227,3 +227,5 @@ d2dcb110e9dbaf9903c05b211df800e78e4b394e jdk8-b100 b7e64be81c8a7690703df5711f4fc2375da8a9cb jdk8-b103 96c1b9b7524b52c3fcefc90ffad4c767396727c8 jdk8-b104 5166118c59178b5d31001bc4058e92486ee07d9b jdk8-b105 +8e7b4d9fb00fdf1334376aeac050c9bca6d1b383 jdk8-b106 +0874bb4707b723d5bb108d379c557cf41529d1a7 jdk8-b107 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 63e9354611c..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=1377850299 +DATE_WHEN_GENERATED=1379504921 ############################################################################### # @@ -6775,6 +6775,18 @@ test -n "$target_alias" && VAR_CPU_BITS=64 VAR_CPU_ENDIAN=big ;; + s390) + VAR_CPU=s390 + VAR_CPU_ARCH=s390 + VAR_CPU_BITS=32 + VAR_CPU_ENDIAN=big + ;; + s390x) + VAR_CPU=s390x + VAR_CPU_ARCH=s390 + VAR_CPU_BITS=64 + VAR_CPU_ENDIAN=big + ;; sparc) VAR_CPU=sparc VAR_CPU_ARCH=sparc @@ -6883,6 +6895,18 @@ $as_echo "$OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" >&6; } VAR_CPU_BITS=64 VAR_CPU_ENDIAN=big ;; + s390) + VAR_CPU=s390 + VAR_CPU_ARCH=s390 + VAR_CPU_BITS=32 + VAR_CPU_ENDIAN=big + ;; + s390x) + VAR_CPU=s390x + VAR_CPU_ARCH=s390 + VAR_CPU_BITS=64 + VAR_CPU_ENDIAN=big + ;; sparc) VAR_CPU=sparc VAR_CPU_ARCH=sparc @@ -8328,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 @@ -8685,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 @@ -9039,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 @@ -9398,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 @@ -9751,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 @@ -11051,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 @@ -16078,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 @@ -16113,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 @@ -16175,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; @@ -16252,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 @@ -17062,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 @@ -17562,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 @@ -18116,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 @@ -18427,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 @@ -18733,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 @@ -19326,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 @@ -19762,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 @@ -20898,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 @@ -21334,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 @@ -22235,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 @@ -22616,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 @@ -22963,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 @@ -23300,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 @@ -23621,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 @@ -23996,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 @@ -24302,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 @@ -24713,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 @@ -25113,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 @@ -25442,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 @@ -25754,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 @@ -26060,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 @@ -26366,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 @@ -26672,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 @@ -27031,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 @@ -27391,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 @@ -27764,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 @@ -28135,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 @@ -28444,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 @@ -28806,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 @@ -33594,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 @@ -34875,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 ed2581c1005..96c710d8a18 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -60,6 +60,18 @@ AC_DEFUN([PLATFORM_EXTRACT_VARS_FROM_CPU], VAR_CPU_BITS=64 VAR_CPU_ENDIAN=big ;; + s390) + VAR_CPU=s390 + VAR_CPU_ARCH=s390 + VAR_CPU_BITS=32 + VAR_CPU_ENDIAN=big + ;; + s390x) + VAR_CPU=s390x + VAR_CPU_ARCH=s390 + VAR_CPU_BITS=64 + VAR_CPU_ENDIAN=big + ;; sparc) VAR_CPU=sparc VAR_CPU_ARCH=sparc @@ -410,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/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/corba/.hgtags b/corba/.hgtags index 8faf5f45228..e24845b3555 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -227,3 +227,5 @@ a013024b07475782f1fa8e196e950b34b4077663 jdk8-b101 49c4a777fdfd648d4c3fffc940fdb97a23108ca8 jdk8-b103 d411c60a8c2fe8fdc572af907775e90f7eefd513 jdk8-b104 4e38de7c767e34104fa147b5b346d9fe6b731279 jdk8-b105 +2e3a056c84a71eba78945c18b05397858ffd7ad0 jdk8-b106 +23fc34133152692b725db4bd617b4c8dfd6ccb05 jdk8-b107 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 56c23d248df..370ade6688d 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -373,3 +373,7 @@ c4697c1c448416108743b59118b4a2498b339d0c jdk8-b102 c1604d5885a6f2adc0bcea2fa142a8f6bafad2f0 hs25-b47 acac3bde66b2c22791c257a8d99611d6d08c6713 jdk8-b105 18b4798adbc42c6fa16f5ecb7d5cd3ca130754bf hs25-b48 +aed585cafc0d9655726af6d1e1081d1c94cb3b5c jdk8-b106 +50794d8ac11c9579b41dec4de23b808fef9f34a1 hs25-b49 +5b7f90aab3ad25a25b75b7b2bb18d5ae23d8231c jdk8-b107 +a09fe9d1e016c285307507a5793bc4fa6215e9c9 hs25-b50 diff --git a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java index 1cc2c8d910a..01104f59515 100644 --- a/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java +++ b/hotspot/agent/src/share/classes/sun/jvm/hotspot/oops/InstanceKlass.java @@ -354,9 +354,16 @@ public class InstanceKlass extends Klass { public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; } public long getVtableLen() { return vtableLen.getValue(this); } public long getItableLen() { return itableLen.getValue(this); } - public Symbol getGenericSignature() { return getConstants().getSymbolAt(genericSignatureIndex.getValue(this)); } public long majorVersion() { return majorVersion.getValue(this); } public long minorVersion() { return minorVersion.getValue(this); } + public Symbol getGenericSignature() { + long index = genericSignatureIndex.getValue(this); + if (index != 0) { + return getConstants().getSymbolAt(index); + } else { + return null; + } + } // "size helper" == instance size in words public long getSizeHelper() { diff --git a/hotspot/make/bsd/makefiles/gcc.make b/hotspot/make/bsd/makefiles/gcc.make index c2c96f9a18f..b98485f901d 100644 --- a/hotspot/make/bsd/makefiles/gcc.make +++ b/hotspot/make/bsd/makefiles/gcc.make @@ -129,16 +129,21 @@ ifeq ($(USE_CLANG), true) # We only use precompiled headers for the JVM build CFLAGS += $(VM_PCH_FLAG) - - # There are some files which don't like precompiled headers - # The following files are build with 'OPT_CFLAGS/NOOPT' (-O0) in the opt build. - # But Clang doesn't support a precompiled header which was compiled with -O3 - # to be used in a compilation unit which uses '-O0'. We could also prepare an - # extra '-O0' PCH file for the opt build and use it here, but it's probably - # not worth the effort as long as only two files need this special handling. + + # The following files are compiled at various optimization + # levels due to optimization issues encountered at the + # 'OPT_CFLAGS_DEFAULT' level. The Clang compiler issues a compile + # time error if there is an optimization level specification + # skew between the PCH file and the C++ file. Especially if the + # PCH file is compiled at a higher optimization level than + # the C++ file. One solution might be to prepare extra optimization + # level specific PCH files for the opt build and use them here, but + # it's probably not worth the effort as long as only a few files + # need this special handling. PCH_FLAG/loopTransform.o = $(PCH_FLAG/NO_PCH) PCH_FLAG/sharedRuntimeTrig.o = $(PCH_FLAG/NO_PCH) PCH_FLAG/sharedRuntimeTrans.o = $(PCH_FLAG/NO_PCH) + PCH_FLAG/unsafe.o = $(PCH_FLAG/NO_PCH) endif else # ($(USE_CLANG), true) @@ -306,6 +311,7 @@ OPT_CFLAGS/NOOPT=-O0 ifeq ($(USE_CLANG), true) ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 2), 1) OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT) + OPT_CFLAGS/unsafe.o += -O1 endif else # 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation. diff --git a/hotspot/make/hotspot_version b/hotspot/make/hotspot_version index a16ed251dc6..e1572121149 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=48 +HS_BUILD_NUMBER=50 JDK_MAJOR_VER=1 JDK_MINOR_VER=8 diff --git a/hotspot/make/windows/create.bat b/hotspot/make/windows/create.bat index 6e72fa9c9e9..a9a8acea6d2 100644 --- a/hotspot/make/windows/create.bat +++ b/hotspot/make/windows/create.bat @@ -82,6 +82,7 @@ for /F %%i in ('sh %HotSpotWorkSpace%/make/windows/get_msc_ver.sh') do set %%i echo ************************************************************** set ProjectFile=%HotSpotBuildSpace%\jvm.vcproj +echo MSC_VER = "%MSC_VER%" if "%MSC_VER%" == "1200" ( set ProjectFile=%HotSpotBuildSpace%\jvm.dsp echo Will generate VC6 project {unsupported} @@ -96,11 +97,17 @@ if "%MSC_VER%" == "1600" ( echo Will generate VC10 {Visual Studio 2010} set ProjectFile=%HotSpotBuildSpace%\jvm.vcxproj ) else ( +if "%MSC_VER%" == "1700" ( +echo Will generate VC10 {compatible with Visual Studio 2012} +echo After opening in VS 2012, click "Update" when prompted. +set ProjectFile=%HotSpotBuildSpace%\jvm.vcxproj +) else ( echo Will generate VC7 project {Visual Studio 2003 .NET} ) ) ) ) +) echo %ProjectFile% echo ************************************************************** diff --git a/hotspot/make/windows/makefiles/rules.make b/hotspot/make/windows/makefiles/rules.make index 693c1926526..d728263171b 100644 --- a/hotspot/make/windows/makefiles/rules.make +++ b/hotspot/make/windows/makefiles/rules.make @@ -69,6 +69,13 @@ VcVersion=VC9 VcVersion=VC10 ProjectFile=jvm.vcxproj +!elseif "$(MSC_VER)" == "1700" +# This is VS2012, but it loads VS10 projects just fine (and will +# upgrade them automatically to VS2012 format). + +VcVersion=VC10 +ProjectFile=jvm.vcxproj + !else VcVersion=VC7 diff --git a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp index 113665220ae..c6039055300 100644 --- a/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_CodeStubs_sparc.cpp @@ -307,7 +307,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { assert(a_byte == *start++, "should be the same code"); } #endif - } else if (_id == load_mirror_id) { + } else if (_id == load_mirror_id || _id == load_appendix_id) { // produce a copy of the load mirror instruction for use by the being initialized case #ifdef ASSERT address start = __ pc(); @@ -384,6 +384,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { case access_field_id: target = Runtime1::entry_for(Runtime1::access_field_patching_id); break; case load_klass_id: target = Runtime1::entry_for(Runtime1::load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; case load_mirror_id: target = Runtime1::entry_for(Runtime1::load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; + case load_appendix_id: target = Runtime1::entry_for(Runtime1::load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); } __ bind(call_patch); @@ -397,7 +398,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { ce->add_call_info_here(_info); __ br(Assembler::always, false, Assembler::pt, _patch_site_entry); __ delayed()->nop(); - if (_id == load_klass_id || _id == load_mirror_id) { + if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) { CodeSection* cs = __ code_section(); address pc = (address)_pc_start; RelocIterator iter(cs, pc, pc + 1); diff --git a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp index 64745015923..12d51571ccb 100644 --- a/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_LIRAssembler_sparc.cpp @@ -520,7 +520,7 @@ void LIR_Assembler::jobject2reg(jobject o, Register reg) { void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo *info) { // Allocate a new index in table to hold the object once it's been patched int oop_index = __ oop_recorder()->allocate_oop_index(NULL); - PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_mirror_id, oop_index); + PatchingStub* patch = new PatchingStub(_masm, patching_id(info), oop_index); AddressLiteral addrlit(NULL, oop_Relocation::spec(oop_index)); assert(addrlit.rspec().type() == relocInfo::oop_type, "must be an oop reloc"); diff --git a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp index be4ae63e6aa..bc633103586 100644 --- a/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/c1_Runtime1_sparc.cpp @@ -804,6 +804,12 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; + case load_appendix_patching_id: + { __ set_info("load_appendix_patching", dont_gc_arguments); + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); + } + break; + case dtrace_object_alloc_id: { // O0: object __ set_info("dtrace_object_alloc", dont_gc_arguments); 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/x86/vm/c1_CodeStubs_x86.cpp b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp index cef3cdbbeaa..1e0c3d9c55c 100644 --- a/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_CodeStubs_x86.cpp @@ -402,6 +402,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { case access_field_id: target = Runtime1::entry_for(Runtime1::access_field_patching_id); break; case load_klass_id: target = Runtime1::entry_for(Runtime1::load_klass_patching_id); reloc_type = relocInfo::metadata_type; break; case load_mirror_id: target = Runtime1::entry_for(Runtime1::load_mirror_patching_id); reloc_type = relocInfo::oop_type; break; + case load_appendix_id: target = Runtime1::entry_for(Runtime1::load_appendix_patching_id); reloc_type = relocInfo::oop_type; break; default: ShouldNotReachHere(); } __ bind(call_patch); @@ -419,7 +420,7 @@ void PatchingStub::emit_code(LIR_Assembler* ce) { for (int j = __ offset() ; j < jmp_off + 5 ; j++ ) { __ nop(); } - if (_id == load_klass_id || _id == load_mirror_id) { + if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) { CodeSection* cs = __ code_section(); RelocIterator iter(cs, (address)_pc_start, (address)(_pc_start + 1)); relocInfo::change_reloc_info_for_address(&iter, (address) _pc_start, reloc_type, relocInfo::none); diff --git a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp index b5bceeb60c6..334d0cc92db 100644 --- a/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_LIRAssembler_x86.cpp @@ -362,7 +362,7 @@ int LIR_Assembler::check_icache() { void LIR_Assembler::jobject2reg_with_patching(Register reg, CodeEmitInfo* info) { jobject o = NULL; - PatchingStub* patch = new PatchingStub(_masm, PatchingStub::load_mirror_id); + PatchingStub* patch = new PatchingStub(_masm, patching_id(info)); __ movoop(reg, o); patching_epilog(patch, lir_patch_normal, reg, info); } diff --git a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp index ff9c11d86f5..e4066e6b4db 100644 --- a/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp +++ b/hotspot/src/cpu/x86/vm/c1_Runtime1_x86.cpp @@ -1499,6 +1499,13 @@ OopMapSet* Runtime1::generate_code_for(StubID id, StubAssembler* sasm) { } break; + case load_appendix_patching_id: + { StubFrame f(sasm, "load_appendix_patching", dont_gc_arguments); + // we should set up register map + oop_maps = generate_patching(sasm, CAST_FROM_FN_PTR(address, move_appendix_patching)); + } + break; + case dtrace_object_alloc_id: { // rax,: object StubFrame f(sasm, "dtrace_object_alloc", dont_gc_arguments); 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/os/linux/vm/os_linux.cpp b/hotspot/src/os/linux/vm/os_linux.cpp index 23d3457046d..70837a850d8 100644 --- a/hotspot/src/os/linux/vm/os_linux.cpp +++ b/hotspot/src/os/linux/vm/os_linux.cpp @@ -2767,7 +2767,19 @@ void os::numa_make_global(char *addr, size_t bytes) { Linux::numa_interleave_memory(addr, bytes); } +// Define for numa_set_bind_policy(int). Setting the argument to 0 will set the +// bind policy to MPOL_PREFERRED for the current thread. +#define USE_MPOL_PREFERRED 0 + void os::numa_make_local(char *addr, size_t bytes, int lgrp_hint) { + // To make NUMA and large pages more robust when both enabled, we need to ease + // the requirements on where the memory should be allocated. MPOL_BIND is the + // default policy and it will force memory to be allocated on the specified + // node. Changing this to MPOL_PREFERRED will prefer to allocate the memory on + // the specified node, but will not force it. Using this policy will prevent + // getting SIGBUS when trying to allocate large pages on NUMA nodes with no + // free large pages. + Linux::numa_set_bind_policy(USE_MPOL_PREFERRED); Linux::numa_tonode_memory(addr, bytes, lgrp_hint); } @@ -2869,6 +2881,8 @@ bool os::Linux::libnuma_init() { libnuma_dlsym(handle, "numa_tonode_memory"))); set_numa_interleave_memory(CAST_TO_FN_PTR(numa_interleave_memory_func_t, libnuma_dlsym(handle, "numa_interleave_memory"))); + set_numa_set_bind_policy(CAST_TO_FN_PTR(numa_set_bind_policy_func_t, + libnuma_dlsym(handle, "numa_set_bind_policy"))); if (numa_available() != -1) { @@ -2935,6 +2949,7 @@ os::Linux::numa_max_node_func_t os::Linux::_numa_max_node; os::Linux::numa_available_func_t os::Linux::_numa_available; os::Linux::numa_tonode_memory_func_t os::Linux::_numa_tonode_memory; os::Linux::numa_interleave_memory_func_t os::Linux::_numa_interleave_memory; +os::Linux::numa_set_bind_policy_func_t os::Linux::_numa_set_bind_policy; unsigned long* os::Linux::_numa_all_nodes; bool os::pd_uncommit_memory(char* addr, size_t size) { @@ -2943,6 +2958,53 @@ bool os::pd_uncommit_memory(char* addr, size_t size) { return res != (uintptr_t) MAP_FAILED; } +static +address get_stack_commited_bottom(address bottom, size_t size) { + address nbot = bottom; + address ntop = bottom + size; + + size_t page_sz = os::vm_page_size(); + unsigned pages = size / page_sz; + + unsigned char vec[1]; + unsigned imin = 1, imax = pages + 1, imid; + int mincore_return_value; + + while (imin < imax) { + imid = (imax + imin) / 2; + nbot = ntop - (imid * page_sz); + + // Use a trick with mincore to check whether the page is mapped or not. + // mincore sets vec to 1 if page resides in memory and to 0 if page + // is swapped output but if page we are asking for is unmapped + // it returns -1,ENOMEM + mincore_return_value = mincore(nbot, page_sz, vec); + + if (mincore_return_value == -1) { + // Page is not mapped go up + // to find first mapped page + if (errno != EAGAIN) { + assert(errno == ENOMEM, "Unexpected mincore errno"); + imax = imid; + } + } else { + // Page is mapped go down + // to find first not mapped page + imin = imid + 1; + } + } + + nbot = nbot + page_sz; + + // Adjust stack bottom one page up if last checked page is not mapped + if (mincore_return_value == -1) { + nbot = nbot + page_sz; + } + + return nbot; +} + + // Linux uses a growable mapping for the stack, and if the mapping for // the stack guard pages is not removed when we detach a thread the // stack cannot grow beyond the pages where the stack guard was @@ -2957,59 +3019,37 @@ bool os::pd_uncommit_memory(char* addr, size_t size) { // So, we need to know the extent of the stack mapping when // create_stack_guard_pages() is called. -// Find the bounds of the stack mapping. Return true for success. -// // We only need this for stacks that are growable: at the time of // writing thread stacks don't use growable mappings (i.e. those // creeated with MAP_GROWSDOWN), and aren't marked "[stack]", so this // only applies to the main thread. -static -bool get_stack_bounds(uintptr_t *bottom, uintptr_t *top) { - - char buf[128]; - int fd, sz; - - if ((fd = ::open("/proc/self/maps", O_RDONLY)) < 0) { - return false; - } - - const char kw[] = "[stack]"; - const int kwlen = sizeof(kw)-1; - - // Address part of /proc/self/maps couldn't be more than 128 bytes - while ((sz = os::get_line_chars(fd, buf, sizeof(buf))) > 0) { - if (sz > kwlen && ::memcmp(buf+sz-kwlen, kw, kwlen) == 0) { - // Extract addresses - if (sscanf(buf, "%" SCNxPTR "-%" SCNxPTR, bottom, top) == 2) { - uintptr_t sp = (uintptr_t) __builtin_frame_address(0); - if (sp >= *bottom && sp <= *top) { - ::close(fd); - return true; - } - } - } - } - - ::close(fd); - return false; -} - - // If the (growable) stack mapping already extends beyond the point // where we're going to put our guard pages, truncate the mapping at // that point by munmap()ping it. This ensures that when we later // munmap() the guard pages we don't leave a hole in the stack -// mapping. This only affects the main/initial thread, but guard -// against future OS changes +// mapping. This only affects the main/initial thread + bool os::pd_create_stack_guard_pages(char* addr, size_t size) { - uintptr_t stack_extent, stack_base; - bool chk_bounds = NOT_DEBUG(os::Linux::is_initial_thread()) DEBUG_ONLY(true); - if (chk_bounds && get_stack_bounds(&stack_extent, &stack_base)) { - assert(os::Linux::is_initial_thread(), - "growable stack in non-initial thread"); - if (stack_extent < (uintptr_t)addr) - ::munmap((void*)stack_extent, (uintptr_t)addr - stack_extent); + + if (os::Linux::is_initial_thread()) { + // As we manually grow stack up to bottom inside create_attached_thread(), + // it's likely that os::Linux::initial_thread_stack_bottom is mapped and + // we don't need to do anything special. + // Check it first, before calling heavy function. + uintptr_t stack_extent = (uintptr_t) os::Linux::initial_thread_stack_bottom(); + unsigned char vec[1]; + + if (mincore((address)stack_extent, os::vm_page_size(), vec) == -1) { + // Fallback to slow path on all errors, including EAGAIN + stack_extent = (uintptr_t) get_stack_commited_bottom( + os::Linux::initial_thread_stack_bottom(), + (size_t)addr - stack_extent); + } + + if (stack_extent < (uintptr_t)addr) { + ::munmap((void*)stack_extent, (uintptr_t)(addr - stack_extent)); + } } return os::commit_memory(addr, size, !ExecMem); @@ -3018,13 +3058,13 @@ bool os::pd_create_stack_guard_pages(char* addr, size_t size) { // If this is a growable mapping, remove the guard pages entirely by // munmap()ping them. If not, just call uncommit_memory(). This only // affects the main/initial thread, but guard against future OS changes +// It's safe to always unmap guard pages for initial thread because we +// always place it right after end of the mapped region + bool os::remove_stack_guard_pages(char* addr, size_t size) { uintptr_t stack_extent, stack_base; - bool chk_bounds = NOT_DEBUG(os::Linux::is_initial_thread()) DEBUG_ONLY(true); - if (chk_bounds && get_stack_bounds(&stack_extent, &stack_base)) { - assert(os::Linux::is_initial_thread(), - "growable stack in non-initial thread"); + if (os::Linux::is_initial_thread()) { return ::munmap(addr, size) == 0; } diff --git a/hotspot/src/os/linux/vm/os_linux.hpp b/hotspot/src/os/linux/vm/os_linux.hpp index 5fa24499319..c824e8ad3fe 100644 --- a/hotspot/src/os/linux/vm/os_linux.hpp +++ b/hotspot/src/os/linux/vm/os_linux.hpp @@ -235,6 +235,7 @@ private: typedef int (*numa_available_func_t)(void); typedef int (*numa_tonode_memory_func_t)(void *start, size_t size, int node); typedef void (*numa_interleave_memory_func_t)(void *start, size_t size, unsigned long *nodemask); + typedef void (*numa_set_bind_policy_func_t)(int policy); static sched_getcpu_func_t _sched_getcpu; static numa_node_to_cpus_func_t _numa_node_to_cpus; @@ -242,6 +243,7 @@ private: static numa_available_func_t _numa_available; static numa_tonode_memory_func_t _numa_tonode_memory; static numa_interleave_memory_func_t _numa_interleave_memory; + static numa_set_bind_policy_func_t _numa_set_bind_policy; static unsigned long* _numa_all_nodes; static void set_sched_getcpu(sched_getcpu_func_t func) { _sched_getcpu = func; } @@ -250,6 +252,7 @@ private: static void set_numa_available(numa_available_func_t func) { _numa_available = func; } static void set_numa_tonode_memory(numa_tonode_memory_func_t func) { _numa_tonode_memory = func; } static void set_numa_interleave_memory(numa_interleave_memory_func_t func) { _numa_interleave_memory = func; } + static void set_numa_set_bind_policy(numa_set_bind_policy_func_t func) { _numa_set_bind_policy = func; } static void set_numa_all_nodes(unsigned long* ptr) { _numa_all_nodes = ptr; } static int sched_getcpu_syscall(void); public: @@ -267,6 +270,11 @@ public: _numa_interleave_memory(start, size, _numa_all_nodes); } } + static void numa_set_bind_policy(int policy) { + if (_numa_set_bind_policy != NULL) { + _numa_set_bind_policy(policy); + } + } static int get_node_by_cpu(int cpu_id); }; diff --git a/hotspot/src/os/posix/vm/os_posix.cpp b/hotspot/src/os/posix/vm/os_posix.cpp index d3ae881d931..6aae96e9b89 100644 --- a/hotspot/src/os/posix/vm/os_posix.cpp +++ b/hotspot/src/os/posix/vm/os_posix.cpp @@ -30,6 +30,8 @@ #include #include #include +#include +#include // Check core dump limit and report possible place where core can be found @@ -320,11 +322,17 @@ os::WatcherThreadCrashProtection::WatcherThreadCrashProtection() { * The callback is supposed to provide the method that should be protected. */ bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) { + sigset_t saved_sig_mask; + assert(Thread::current()->is_Watcher_thread(), "Only for WatcherThread"); assert(!WatcherThread::watcher_thread()->has_crash_protection(), "crash_protection already set?"); - if (sigsetjmp(_jmpbuf, 1) == 0) { + // we cannot rely on sigsetjmp/siglongjmp to save/restore the signal mask + // since on at least some systems (OS X) siglongjmp will restore the mask + // for the process, not the thread + pthread_sigmask(0, NULL, &saved_sig_mask); + if (sigsetjmp(_jmpbuf, 0) == 0) { // make sure we can see in the signal handler that we have crash protection // installed WatcherThread::watcher_thread()->set_crash_protection(this); @@ -334,6 +342,7 @@ bool os::WatcherThreadCrashProtection::call(os::CrashProtectionCallback& cb) { return true; } // this happens when we siglongjmp() back + pthread_sigmask(SIG_SETMASK, &saved_sig_mask, NULL); WatcherThread::watcher_thread()->set_crash_protection(NULL); return false; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp index 91a4336d903..c1f656b99f8 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/globals_solaris_x86.hpp @@ -44,6 +44,6 @@ define_pd_global(uintx,JVMInvokeMethodSlack, 10*K); define_pd_global(intx, CompilerThreadStackSize, 0); // Used on 64 bit platforms for UseCompressedOops base address -define_pd_global(uintx,HeapBaseMinAddress, 256*M); +define_pd_global(uintx,HeapBaseMinAddress, 2*G); #endif // OS_CPU_SOLARIS_X86_VM_GLOBALS_SOLARIS_X86_HPP diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java index 4870dffec2e..c4a77c02aac 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/CallSite.java @@ -106,10 +106,12 @@ public class CallSite { " (" + getMethod().getBytes() + " bytes) " + getReason()); } } + stream.printf(" (end time: %6.4f", getTimeStamp()); if (getEndNodes() > 0) { - stream.printf(" (end time: %6.4f nodes: %d live: %d)", getTimeStamp(), getEndNodes(), getEndLiveNodes()); + stream.printf(" nodes: %d live: %d", getEndNodes(), getEndLiveNodes()); } - stream.println(""); + stream.println(")"); + if (getReceiver() != null) { emit(stream, indent + 4); // stream.println("type profile " + method.holder + " -> " + receiver + " (" + diff --git a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java index 80a00364cc3..de80e9a1043 100644 --- a/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java +++ b/hotspot/src/share/tools/LogCompilation/src/com/sun/hotspot/tools/compiler/LogParser.java @@ -207,7 +207,12 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants } String search(Attributes attr, String name) { - return search(attr, name, null); + String result = attr.getValue(name); + if (result != null) { + return result; + } else { + throw new InternalError("can't find " + name); + } } String search(Attributes attr, String name, String defaultValue) { @@ -215,13 +220,7 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants if (result != null) { return result; } - if (defaultValue != null) { - return defaultValue; - } - for (int i = 0; i < attr.getLength(); i++) { - System.out.println(attr.getQName(i) + " " + attr.getValue(attr.getQName(i))); - } - throw new InternalError("can't find " + name); + return defaultValue; } int indent = 0; @@ -268,17 +267,18 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants Phase p = new Phase(search(atts, "name"), Double.parseDouble(search(atts, "stamp")), Integer.parseInt(search(atts, "nodes", "0")), - Integer.parseInt(search(atts, "live"))); + Integer.parseInt(search(atts, "live", "0"))); phaseStack.push(p); } else if (qname.equals("phase_done")) { Phase p = phaseStack.pop(); - if (! p.getId().equals(search(atts, "name"))) { + String phaseName = search(atts, "name", null); + if (phaseName != null && !p.getId().equals(phaseName)) { System.out.println("phase: " + p.getId()); throw new InternalError("phase name mismatch"); } p.setEnd(Double.parseDouble(search(atts, "stamp"))); p.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); - p.setEndLiveNodes(Integer.parseInt(search(atts, "live"))); + p.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0"))); compile.getPhases().add(p); } else if (qname.equals("task")) { compile = new Compilation(Integer.parseInt(search(atts, "compile_id", "-1"))); @@ -413,8 +413,8 @@ public class LogParser extends DefaultHandler implements ErrorHandler, Constants } } else if (qname.equals("parse_done")) { CallSite call = scopes.pop(); - call.setEndNodes(Integer.parseInt(search(atts, "nodes", "1"))); - call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "1"))); + call.setEndNodes(Integer.parseInt(search(atts, "nodes", "0"))); + call.setEndLiveNodes(Integer.parseInt(search(atts, "live", "0"))); call.setTimeStamp(Double.parseDouble(search(atts, "stamp"))); scopes.push(call); } diff --git a/hotspot/src/share/vm/adlc/arena.cpp b/hotspot/src/share/vm/adlc/arena.cpp index b8bb1a0bd8f..d7e4fc6eb44 100644 --- a/hotspot/src/share/vm/adlc/arena.cpp +++ b/hotspot/src/share/vm/adlc/arena.cpp @@ -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 @@ -24,7 +24,7 @@ #include "adlc.hpp" -void* Chunk::operator new(size_t requested_size, size_t length) { +void* Chunk::operator new(size_t requested_size, size_t length) throw() { return CHeapObj::operator new(requested_size + length); } @@ -163,7 +163,7 @@ bool Arena::contains( const void *ptr ) const { //----------------------------------------------------------------------------- // CHeapObj -void* CHeapObj::operator new(size_t size){ +void* CHeapObj::operator new(size_t size) throw() { return (void *) malloc(size); } diff --git a/hotspot/src/share/vm/adlc/arena.hpp b/hotspot/src/share/vm/adlc/arena.hpp index a92857e1311..7f09511d6ca 100644 --- a/hotspot/src/share/vm/adlc/arena.hpp +++ b/hotspot/src/share/vm/adlc/arena.hpp @@ -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 @@ -42,7 +42,7 @@ class CHeapObj { public: - void* operator new(size_t size); + void* operator new(size_t size) throw(); void operator delete(void* p); void* new_array(size_t size); }; @@ -53,7 +53,7 @@ class CHeapObj { class ValueObj { public: - void* operator new(size_t size); + void* operator new(size_t size) throw(); void operator delete(void* p); }; @@ -61,7 +61,7 @@ class ValueObj { class AllStatic { public: - void* operator new(size_t size); + void* operator new(size_t size) throw(); void operator delete(void* p); }; @@ -70,7 +70,7 @@ class AllStatic { // Linked list of raw memory chunks class Chunk: public CHeapObj { public: - void* operator new(size_t size, size_t length); + void* operator new(size_t size, size_t length) throw(); void operator delete(void* p, size_t length); Chunk(size_t length); diff --git a/hotspot/src/share/vm/adlc/main.cpp b/hotspot/src/share/vm/adlc/main.cpp index 4b812316381..b0035cbe7ef 100644 --- a/hotspot/src/share/vm/adlc/main.cpp +++ b/hotspot/src/share/vm/adlc/main.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 @@ -485,7 +485,7 @@ int get_legal_text(FileBuff &fbuf, char **legal_text) // VS2005 has its own definition, identical to this one. #if !defined(_WIN32) || defined(_WIN64) || _MSC_VER < 1400 -void *operator new( size_t size, int, const char *, int ) { +void *operator new( size_t size, int, const char *, int ) throw() { return ::operator new( size ); } #endif diff --git a/hotspot/src/share/vm/adlc/output_c.cpp b/hotspot/src/share/vm/adlc/output_c.cpp index a9bd95177eb..b8978591355 100644 --- a/hotspot/src/share/vm/adlc/output_c.cpp +++ b/hotspot/src/share/vm/adlc/output_c.cpp @@ -1095,7 +1095,7 @@ static void check_peepmatch_instruction_sequence(FILE *fp, PeepMatch *pmatch, Pe fprintf(fp, " // Identify previous instruction if inside this block\n"); fprintf(fp, " if( "); print_block_index(fp, inst_position); - fprintf(fp, " > 0 ) {\n Node *n = block->_nodes.at("); + fprintf(fp, " > 0 ) {\n Node *n = block->get_node("); print_block_index(fp, inst_position); fprintf(fp, ");\n inst%d = (n->is_Mach()) ? ", inst_position); fprintf(fp, "n->as_Mach() : NULL;\n }\n"); diff --git a/hotspot/src/share/vm/asm/codeBuffer.hpp b/hotspot/src/share/vm/asm/codeBuffer.hpp index 8ce94646d95..bcc5d51e7ad 100644 --- a/hotspot/src/share/vm/asm/codeBuffer.hpp +++ b/hotspot/src/share/vm/asm/codeBuffer.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 @@ -296,8 +296,8 @@ class CodeBuffer: public StackObj { // CodeBuffers must be allocated on the stack except for a single // special case during expansion which is handled internally. This // is done to guarantee proper cleanup of resources. - void* operator new(size_t size) { return ResourceObj::operator new(size); } - void operator delete(void* p) { ShouldNotCallThis(); } + void* operator new(size_t size) throw() { return ResourceObj::operator new(size); } + void operator delete(void* p) { ShouldNotCallThis(); } public: typedef int csize_t; // code size type; would be size_t except for history diff --git a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp index 7235cd6c38a..5f4a04c5b6c 100644 --- a/hotspot/src/share/vm/c1/c1_CodeStubs.hpp +++ b/hotspot/src/share/vm/c1/c1_CodeStubs.hpp @@ -364,7 +364,8 @@ class PatchingStub: public CodeStub { enum PatchID { access_field_id, load_klass_id, - load_mirror_id + load_mirror_id, + load_appendix_id }; enum constants { patch_info_size = 3 @@ -417,7 +418,7 @@ class PatchingStub: public CodeStub { } NativeMovRegMem* n_move = nativeMovRegMem_at(pc_start()); n_move->set_offset(field_offset); - } else if (_id == load_klass_id || _id == load_mirror_id) { + } else if (_id == load_klass_id || _id == load_mirror_id || _id == load_appendix_id) { assert(_obj != noreg, "must have register object for load_klass/load_mirror"); #ifdef ASSERT // verify that we're pointing at a NativeMovConstReg diff --git a/hotspot/src/share/vm/c1/c1_Compilation.cpp b/hotspot/src/share/vm/c1/c1_Compilation.cpp index a8effa4bccf..1cdcab542fa 100644 --- a/hotspot/src/share/vm/c1/c1_Compilation.cpp +++ b/hotspot/src/share/vm/c1/c1_Compilation.cpp @@ -74,16 +74,19 @@ class PhaseTraceTime: public TraceTime { private: JavaThread* _thread; CompileLog* _log; + TimerName _timer; public: PhaseTraceTime(TimerName timer) - : TraceTime("", &timers[timer], CITime || CITimeEach, Verbose), _log(NULL) { + : TraceTime("", &timers[timer], CITime || CITimeEach, Verbose), + _log(NULL), _timer(timer) + { if (Compilation::current() != NULL) { _log = Compilation::current()->log(); } if (_log != NULL) { - _log->begin_head("phase name='%s'", timer_name[timer]); + _log->begin_head("phase name='%s'", timer_name[_timer]); _log->stamp(); _log->end_head(); } @@ -91,7 +94,7 @@ class PhaseTraceTime: public TraceTime { ~PhaseTraceTime() { if (_log != NULL) - _log->done("phase"); + _log->done("phase name='%s'", timer_name[_timer]); } }; diff --git a/hotspot/src/share/vm/c1/c1_Compilation.hpp b/hotspot/src/share/vm/c1/c1_Compilation.hpp index 897da9762cb..f98ae97f309 100644 --- a/hotspot/src/share/vm/c1/c1_Compilation.hpp +++ b/hotspot/src/share/vm/c1/c1_Compilation.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 @@ -279,8 +279,8 @@ class InstructionMark: public StackObj { // Base class for objects allocated by the compiler in the compilation arena class CompilationResourceObj ALLOCATION_SUPER_CLASS_SPEC { public: - void* operator new(size_t size) { return Compilation::current()->arena()->Amalloc(size); } - void* operator new(size_t size, Arena* arena) { + void* operator new(size_t size) throw() { return Compilation::current()->arena()->Amalloc(size); } + void* operator new(size_t size, Arena* arena) throw() { return arena->Amalloc(size); } void operator delete(void* p) {} // nothing to do diff --git a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp index b84c8911e4c..b7ea6eebb26 100644 --- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1583,7 +1583,7 @@ void GraphBuilder::access_field(Bytecodes::Code code) { ObjectType* obj_type = obj->type()->as_ObjectType(); if (obj_type->is_constant() && !PatchALot) { ciObject* const_oop = obj_type->constant_value(); - if (!const_oop->is_null_object()) { + if (!const_oop->is_null_object() && const_oop->is_loaded()) { if (field->is_constant()) { ciConstant field_val = field->constant_value_of(const_oop); BasicType field_type = field_val.basic_type(); @@ -1667,9 +1667,8 @@ void GraphBuilder::invoke(Bytecodes::Code code) { const Bytecodes::Code bc_raw = stream()->cur_bc_raw(); assert(declared_signature != NULL, "cannot be null"); - // FIXME bail out for now - if (Bytecodes::has_optional_appendix(bc_raw) && !will_link) { - BAILOUT("unlinked call site (FIXME needs patching or recompile support)"); + if (!C1PatchInvokeDynamic && Bytecodes::has_optional_appendix(bc_raw) && !will_link) { + BAILOUT("unlinked call site (C1PatchInvokeDynamic is off)"); } // we have to make sure the argument size (incl. the receiver) @@ -1713,10 +1712,23 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial; break; } + } else { + if (bc_raw == Bytecodes::_invokehandle) { + assert(!will_link, "should come here only for unlinked call"); + code = Bytecodes::_invokespecial; + } } // Push appendix argument (MethodType, CallSite, etc.), if one. - if (stream()->has_appendix()) { + bool patch_for_appendix = false; + int patching_appendix_arg = 0; + if (C1PatchInvokeDynamic && + (Bytecodes::has_optional_appendix(bc_raw) && (!will_link || PatchALot))) { + Value arg = append(new Constant(new ObjectConstant(compilation()->env()->unloaded_ciinstance()), copy_state_before())); + apush(arg); + patch_for_appendix = true; + patching_appendix_arg = (will_link && stream()->has_appendix()) ? 0 : 1; + } else if (stream()->has_appendix()) { ciObject* appendix = stream()->get_appendix(); Value arg = append(new Constant(new ObjectConstant(appendix))); apush(arg); @@ -1732,7 +1744,8 @@ void GraphBuilder::invoke(Bytecodes::Code code) { if (UseCHA && DeoptC1 && klass->is_loaded() && target->is_loaded() && !(// %%% FIXME: Are both of these relevant? target->is_method_handle_intrinsic() || - target->is_compiled_lambda_form())) { + target->is_compiled_lambda_form()) && + !patch_for_appendix) { Value receiver = NULL; ciInstanceKlass* receiver_klass = NULL; bool type_is_exact = false; @@ -1850,7 +1863,8 @@ void GraphBuilder::invoke(Bytecodes::Code code) { // check if we could do inlining if (!PatchALot && Inline && klass->is_loaded() && (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized()) - && target->is_loaded()) { + && target->is_loaded() + && !patch_for_appendix) { // callee is known => check if we have static binding assert(target->is_loaded(), "callee must be known"); if (code == Bytecodes::_invokestatic || @@ -1901,7 +1915,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) { code == Bytecodes::_invokespecial || code == Bytecodes::_invokevirtual || code == Bytecodes::_invokeinterface; - Values* args = state()->pop_arguments(target->arg_size_no_receiver()); + Values* args = state()->pop_arguments(target->arg_size_no_receiver() + patching_appendix_arg); Value recv = has_receiver ? apop() : NULL; int vtable_index = Method::invalid_vtable_index; diff --git a/hotspot/src/share/vm/c1/c1_Instruction.hpp b/hotspot/src/share/vm/c1/c1_Instruction.hpp index 6b1f6ddd380..9563b720a10 100644 --- a/hotspot/src/share/vm/c1/c1_Instruction.hpp +++ b/hotspot/src/share/vm/c1/c1_Instruction.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 @@ -323,7 +323,7 @@ class Instruction: public CompilationResourceObj { } public: - void* operator new(size_t size) { + void* operator new(size_t size) throw() { Compilation* c = Compilation::current(); void* res = c->arena()->Amalloc(size); ((Instruction*)res)->_id = c->get_next_id(); @@ -1611,7 +1611,7 @@ LEAF(BlockBegin, StateSplit) friend class SuxAndWeightAdjuster; public: - void* operator new(size_t size) { + void* operator new(size_t size) throw() { Compilation* c = Compilation::current(); void* res = c->arena()->Amalloc(size); ((BlockBegin*)res)->_id = c->get_next_id(); diff --git a/hotspot/src/share/vm/c1/c1_LIR.hpp b/hotspot/src/share/vm/c1/c1_LIR.hpp index fab85e5750f..d0dca72f386 100644 --- a/hotspot/src/share/vm/c1/c1_LIR.hpp +++ b/hotspot/src/share/vm/c1/c1_LIR.hpp @@ -1211,8 +1211,6 @@ class LIR_OpJavaCall: public LIR_OpCall { bool is_invokedynamic() const { return code() == lir_dynamic_call; } bool is_method_handle_invoke() const { return - is_invokedynamic() // An invokedynamic is always a MethodHandle call site. - || method()->is_compiled_lambda_form() // Java-generated adapter || method()->is_method_handle_intrinsic(); // JVM-generated MH intrinsic diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index a76f5bb2ec3..9ae527054fe 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -93,12 +93,23 @@ void LIR_Assembler::patching_epilog(PatchingStub* patch, LIR_PatchCode patch_cod default: ShouldNotReachHere(); } + } else if (patch->id() == PatchingStub::load_appendix_id) { + Bytecodes::Code bc_raw = info->scope()->method()->raw_code_at_bci(info->stack()->bci()); + assert(Bytecodes::has_optional_appendix(bc_raw), "unexpected appendix resolution"); } else { ShouldNotReachHere(); } #endif } +PatchingStub::PatchID LIR_Assembler::patching_id(CodeEmitInfo* info) { + IRScope* scope = info->scope(); + Bytecodes::Code bc_raw = scope->method()->raw_code_at_bci(info->stack()->bci()); + if (Bytecodes::has_optional_appendix(bc_raw)) { + return PatchingStub::load_appendix_id; + } + return PatchingStub::load_mirror_id; +} //--------------------------------------------------------------- diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp index 4ced297c07b..57df2725ee2 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.hpp @@ -119,6 +119,8 @@ class LIR_Assembler: public CompilationResourceObj { void comp_op(LIR_Condition condition, LIR_Opr src, LIR_Opr result, LIR_Op2* op); + PatchingStub::PatchID patching_id(CodeEmitInfo* info); + public: LIR_Assembler(Compilation* c); ~LIR_Assembler(); diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.cpp b/hotspot/src/share/vm/c1/c1_Runtime1.cpp index 9a1c4cce21f..037bc31f658 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.cpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.cpp @@ -819,6 +819,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i KlassHandle init_klass(THREAD, NULL); // klass needed by load_klass_patching code KlassHandle load_klass(THREAD, NULL); // klass needed by load_klass_patching code Handle mirror(THREAD, NULL); // oop needed by load_mirror_patching code + Handle appendix(THREAD, NULL); // oop needed by appendix_patching code bool load_klass_or_mirror_patch_id = (stub_id == Runtime1::load_klass_patching_id || stub_id == Runtime1::load_mirror_patching_id); @@ -888,10 +889,32 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i mirror = Handle(THREAD, m); } break; - default: Unimplemented(); + default: fatal("unexpected bytecode for load_klass_or_mirror_patch_id"); } // convert to handle load_klass = KlassHandle(THREAD, k); + } else if (stub_id == load_appendix_patching_id) { + Bytecode_invoke bytecode(caller_method, bci); + Bytecodes::Code bc = bytecode.invoke_code(); + + CallInfo info; + constantPoolHandle pool(thread, caller_method->constants()); + int index = bytecode.index(); + LinkResolver::resolve_invoke(info, Handle(), pool, index, bc, CHECK); + appendix = info.resolved_appendix(); + switch (bc) { + case Bytecodes::_invokehandle: { + int cache_index = ConstantPool::decode_cpcache_index(index, true); + assert(cache_index >= 0 && cache_index < pool->cache()->length(), "unexpected cache index"); + pool->cache()->entry_at(cache_index)->set_method_handle(pool, info); + break; + } + case Bytecodes::_invokedynamic: { + pool->invokedynamic_cp_cache_entry_at(index)->set_dynamic_call(pool, info); + break; + } + default: fatal("unexpected bytecode for load_appendix_patching_id"); + } } else { ShouldNotReachHere(); } @@ -992,8 +1015,8 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i n_copy->data() == (intptr_t)Universe::non_oop_word(), "illegal init value"); if (stub_id == Runtime1::load_klass_patching_id) { - assert(load_klass() != NULL, "klass not set"); - n_copy->set_data((intx) (load_klass())); + assert(load_klass() != NULL, "klass not set"); + n_copy->set_data((intx) (load_klass())); } else { assert(mirror() != NULL, "klass not set"); n_copy->set_data((intx) (mirror())); @@ -1002,43 +1025,55 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i if (TracePatching) { Disassembler::decode(copy_buff, copy_buff + *byte_count, tty); } + } + } else if (stub_id == Runtime1::load_appendix_patching_id) { + NativeMovConstReg* n_copy = nativeMovConstReg_at(copy_buff); + assert(n_copy->data() == 0 || + n_copy->data() == (intptr_t)Universe::non_oop_word(), + "illegal init value"); + n_copy->set_data((intx) (appendix())); -#if defined(SPARC) || defined(PPC) - // Update the location in the nmethod with the proper - // metadata. When the code was generated, a NULL was stuffed - // in the metadata table and that table needs to be update to - // have the right value. On intel the value is kept - // directly in the instruction instead of in the metadata - // table, so set_data above effectively updated the value. - nmethod* nm = CodeCache::find_nmethod(instr_pc); - assert(nm != NULL, "invalid nmethod_pc"); - RelocIterator mds(nm, copy_buff, copy_buff + 1); - bool found = false; - while (mds.next() && !found) { - if (mds.type() == relocInfo::oop_type) { - assert(stub_id == Runtime1::load_mirror_patching_id, "wrong stub id"); - oop_Relocation* r = mds.oop_reloc(); - oop* oop_adr = r->oop_addr(); - *oop_adr = mirror(); - r->fix_oop_relocation(); - found = true; - } else if (mds.type() == relocInfo::metadata_type) { - assert(stub_id == Runtime1::load_klass_patching_id, "wrong stub id"); - metadata_Relocation* r = mds.metadata_reloc(); - Metadata** metadata_adr = r->metadata_addr(); - *metadata_adr = load_klass(); - r->fix_metadata_relocation(); - found = true; - } - } - assert(found, "the metadata must exist!"); -#endif - + if (TracePatching) { + Disassembler::decode(copy_buff, copy_buff + *byte_count, tty); } } else { ShouldNotReachHere(); } +#if defined(SPARC) || defined(PPC) + if (load_klass_or_mirror_patch_id || + stub_id == Runtime1::load_appendix_patching_id) { + // Update the location in the nmethod with the proper + // metadata. When the code was generated, a NULL was stuffed + // in the metadata table and that table needs to be update to + // have the right value. On intel the value is kept + // directly in the instruction instead of in the metadata + // table, so set_data above effectively updated the value. + nmethod* nm = CodeCache::find_nmethod(instr_pc); + assert(nm != NULL, "invalid nmethod_pc"); + RelocIterator mds(nm, copy_buff, copy_buff + 1); + bool found = false; + while (mds.next() && !found) { + if (mds.type() == relocInfo::oop_type) { + assert(stub_id == Runtime1::load_mirror_patching_id || + stub_id == Runtime1::load_appendix_patching_id, "wrong stub id"); + oop_Relocation* r = mds.oop_reloc(); + oop* oop_adr = r->oop_addr(); + *oop_adr = stub_id == Runtime1::load_mirror_patching_id ? mirror() : appendix(); + r->fix_oop_relocation(); + found = true; + } else if (mds.type() == relocInfo::metadata_type) { + assert(stub_id == Runtime1::load_klass_patching_id, "wrong stub id"); + metadata_Relocation* r = mds.metadata_reloc(); + Metadata** metadata_adr = r->metadata_addr(); + *metadata_adr = load_klass(); + r->fix_metadata_relocation(); + found = true; + } + } + assert(found, "the metadata must exist!"); + } +#endif if (do_patch) { // replace instructions // first replace the tail, then the call @@ -1077,7 +1112,8 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i ICache::invalidate_range(instr_pc, *byte_count); NativeGeneralJump::replace_mt_safe(instr_pc, copy_buff); - if (load_klass_or_mirror_patch_id) { + if (load_klass_or_mirror_patch_id || + stub_id == Runtime1::load_appendix_patching_id) { relocInfo::relocType rtype = (stub_id == Runtime1::load_klass_patching_id) ? relocInfo::metadata_type : @@ -1118,7 +1154,8 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i // If we are patching in a non-perm oop, make sure the nmethod // is on the right list. - if (ScavengeRootsInCode && mirror.not_null() && mirror()->is_scavengable()) { + if (ScavengeRootsInCode && ((mirror.not_null() && mirror()->is_scavengable()) || + (appendix.not_null() && appendix->is_scavengable()))) { MutexLockerEx ml_code (CodeCache_lock, Mutex::_no_safepoint_check_flag); nmethod* nm = CodeCache::find_nmethod(caller_frame.pc()); guarantee(nm != NULL, "only nmethods can contain non-perm oops"); @@ -1179,6 +1216,24 @@ int Runtime1::move_mirror_patching(JavaThread* thread) { return caller_is_deopted(); } +int Runtime1::move_appendix_patching(JavaThread* thread) { +// +// NOTE: we are still in Java +// + Thread* THREAD = thread; + debug_only(NoHandleMark nhm;) + { + // Enter VM mode + + ResetNoHandleMark rnhm; + patch_code(thread, load_appendix_patching_id); + } + // Back in JAVA, use no oops DON'T safepoint + + // Return true if calling code is deoptimized + + return caller_is_deopted(); +} // // Entry point for compiled code. We want to patch a nmethod. // We don't do a normal VM transition here because we want to diff --git a/hotspot/src/share/vm/c1/c1_Runtime1.hpp b/hotspot/src/share/vm/c1/c1_Runtime1.hpp index 9b12d26226e..e41f2f188dc 100644 --- a/hotspot/src/share/vm/c1/c1_Runtime1.hpp +++ b/hotspot/src/share/vm/c1/c1_Runtime1.hpp @@ -67,6 +67,7 @@ class StubAssembler; stub(access_field_patching) \ stub(load_klass_patching) \ stub(load_mirror_patching) \ + stub(load_appendix_patching) \ stub(g1_pre_barrier_slow) \ stub(g1_post_barrier_slow) \ stub(fpu2long_stub) \ @@ -160,6 +161,7 @@ class Runtime1: public AllStatic { static int access_field_patching(JavaThread* thread); static int move_klass_patching(JavaThread* thread); static int move_mirror_patching(JavaThread* thread); + static int move_appendix_patching(JavaThread* thread); static void patch_code(JavaThread* thread, StubID stub_id); diff --git a/hotspot/src/share/vm/c1/c1_globals.cpp b/hotspot/src/share/vm/c1/c1_globals.cpp index a611f033ee6..553b9aa4322 100644 --- a/hotspot/src/share/vm/c1/c1_globals.cpp +++ b/hotspot/src/share/vm/c1/c1_globals.cpp @@ -25,4 +25,4 @@ #include "precompiled.hpp" #include "c1/c1_globals.hpp" -C1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_NOTPRODUCT_FLAG) +C1_FLAGS(MATERIALIZE_DEVELOPER_FLAG, MATERIALIZE_PD_DEVELOPER_FLAG, MATERIALIZE_PRODUCT_FLAG, MATERIALIZE_PD_PRODUCT_FLAG, MATERIALIZE_DIAGNOSTIC_FLAG, MATERIALIZE_NOTPRODUCT_FLAG) diff --git a/hotspot/src/share/vm/c1/c1_globals.hpp b/hotspot/src/share/vm/c1/c1_globals.hpp index 844880be256..3dceebc9d5b 100644 --- a/hotspot/src/share/vm/c1/c1_globals.hpp +++ b/hotspot/src/share/vm/c1/c1_globals.hpp @@ -54,7 +54,7 @@ // // Defines all global flags used by the client compiler. // -#define C1_FLAGS(develop, develop_pd, product, product_pd, notproduct) \ +#define C1_FLAGS(develop, develop_pd, product, product_pd, diagnostic, notproduct) \ \ /* Printing */ \ notproduct(bool, PrintC1Statistics, false, \ @@ -333,15 +333,19 @@ "Use CHA and exact type results at call sites when updating MDOs")\ \ product(bool, C1UpdateMethodData, trueInTiered, \ - "Update MethodData*s in Tier1-generated code") \ + "Update MethodData*s in Tier1-generated code") \ \ develop(bool, PrintCFGToFile, false, \ "print control flow graph to a separate file during compilation") \ \ + diagnostic(bool, C1PatchInvokeDynamic, true, \ + "Patch invokedynamic appendix not known at compile time") \ + \ + \ // Read default values for c1 globals -C1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_NOTPRODUCT_FLAG) +C1_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_NOTPRODUCT_FLAG) #endif // SHARE_VM_C1_C1_GLOBALS_HPP 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/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 7776db5eb6d..0102b2b21f0 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -1150,6 +1150,10 @@ void ciEnv::record_out_of_memory_failure() { record_method_not_compilable("out of memory"); } +ciInstance* ciEnv::unloaded_ciinstance() { + GUARDED_VM_ENTRY(return _factory->get_unloaded_object_constant();) +} + void ciEnv::dump_replay_data(outputStream* out) { VM_ENTRY_MARK; MutexLocker ml(Compile_lock); diff --git a/hotspot/src/share/vm/ci/ciEnv.hpp b/hotspot/src/share/vm/ci/ciEnv.hpp index 45dd42eb25e..01f417d2f9d 100644 --- a/hotspot/src/share/vm/ci/ciEnv.hpp +++ b/hotspot/src/share/vm/ci/ciEnv.hpp @@ -400,6 +400,7 @@ public: static ciInstanceKlass* unloaded_ciinstance_klass() { return _unloaded_ciinstance_klass; } + ciInstance* unloaded_ciinstance(); ciKlass* find_system_klass(ciSymbol* klass_name); // Note: To find a class from its name string, use ciSymbol::make, diff --git a/hotspot/src/share/vm/ci/ciField.cpp b/hotspot/src/share/vm/ci/ciField.cpp index fe967554c3a..1a711ae522a 100644 --- a/hotspot/src/share/vm/ci/ciField.cpp +++ b/hotspot/src/share/vm/ci/ciField.cpp @@ -189,12 +189,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 +229,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 +274,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; } @@ -373,8 +380,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..81af9ca79a9 100644 --- a/hotspot/src/share/vm/ci/ciField.hpp +++ b/hotspot/src/share/vm/ci/ciField.hpp @@ -139,7 +139,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 +176,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 2d29c0dc8e2..8b48b1b3706 100644 --- a/hotspot/src/share/vm/ci/ciInstance.cpp +++ b/hotspot/src/share/vm/ci/ciInstance.cpp @@ -60,10 +60,10 @@ ciType* ciInstance::java_mirror_type() { // // Constant value of a field. ciConstant ciInstance::field_value(ciField* field) { - assert(is_loaded() && - field->holder()->is_loaded() && - klass()->is_subclass_of(field->holder()), - "invalid access"); + assert(is_loaded(), "invalid access - must be loaded"); + assert(field->holder()->is_loaded(), "invalid access - holder must be loaded"); + assert(klass()->is_subclass_of(field->holder()), "invalid access - must be subclass"); + VM_ENTRY_MARK; ciConstant result; Handle obj = get_oop(); @@ -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/ciMethod.hpp b/hotspot/src/share/vm/ci/ciMethod.hpp index 8305547c56f..ddff0ac9b9a 100644 --- a/hotspot/src/share/vm/ci/ciMethod.hpp +++ b/hotspot/src/share/vm/ci/ciMethod.hpp @@ -177,6 +177,10 @@ class ciMethod : public ciMetadata { address bcp = code() + bci; return Bytecodes::java_code_at(NULL, bcp); } + Bytecodes::Code raw_code_at_bci(int bci) { + address bcp = code() + bci; + return Bytecodes::code_at(NULL, bcp); + } BCEscapeAnalyzer *get_bcea(); ciMethodBlocks *get_method_blocks(); diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.cpp b/hotspot/src/share/vm/ci/ciObjectFactory.cpp index cc1be034dd9..a22fcf62c8c 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp @@ -563,7 +563,10 @@ ciInstance* ciObjectFactory::get_unloaded_method_type_constant(ciSymbol* signatu return get_unloaded_instance(ciEnv::_MethodType_klass->as_instance_klass()); } - +ciInstance* ciObjectFactory::get_unloaded_object_constant() { + if (ciEnv::_Object_klass == NULL) return NULL; + return get_unloaded_instance(ciEnv::_Object_klass->as_instance_klass()); +} //------------------------------------------------------------------ // ciObjectFactory::get_empty_methodData diff --git a/hotspot/src/share/vm/ci/ciObjectFactory.hpp b/hotspot/src/share/vm/ci/ciObjectFactory.hpp index 29de514b2ea..ba3d88c1202 100644 --- a/hotspot/src/share/vm/ci/ciObjectFactory.hpp +++ b/hotspot/src/share/vm/ci/ciObjectFactory.hpp @@ -131,6 +131,8 @@ public: ciInstance* get_unloaded_method_type_constant(ciSymbol* signature); + ciInstance* get_unloaded_object_constant(); + // Get the ciMethodData representing the methodData for a method // with none. ciMethodData* get_empty_methodData(); 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 507bb477a88..8972bceb434 100644 --- a/hotspot/src/share/vm/classfile/classFileParser.cpp +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp @@ -28,7 +28,6 @@ #include "classfile/classLoaderData.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/defaultMethods.hpp" -#include "classfile/genericSignatures.hpp" #include "classfile/javaClasses.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionary.hpp" @@ -1775,6 +1774,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 @@ -1787,6 +1790,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() { @@ -3039,35 +3044,6 @@ AnnotationArray* ClassFileParser::assemble_annotations(u1* runtime_visible_annot return annotations; } - -#ifdef ASSERT -static void parseAndPrintGenericSignatures( - instanceKlassHandle this_klass, TRAPS) { - assert(ParseAllGenericSignatures == true, "Shouldn't call otherwise"); - ResourceMark rm; - - if (this_klass->generic_signature() != NULL) { - using namespace generic; - ClassDescriptor* spec = ClassDescriptor::parse_generic_signature(this_klass(), CHECK); - - tty->print_cr("Parsing %s", this_klass->generic_signature()->as_C_string()); - spec->print_on(tty); - - for (int i = 0; i < this_klass->methods()->length(); ++i) { - Method* m = this_klass->methods()->at(i); - MethodDescriptor* method_spec = MethodDescriptor::parse_generic_signature(m, spec); - Symbol* sig = m->generic_signature(); - if (sig == NULL) { - sig = m->signature(); - } - tty->print_cr("Parsing %s", sig->as_C_string()); - method_spec->print_on(tty); - } - } -} -#endif // def ASSERT - - instanceKlassHandle ClassFileParser::parse_super_class(int super_class_index, TRAPS) { instanceKlassHandle super_klass; @@ -4060,12 +4036,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name, java_lang_Class::create_mirror(this_klass, protection_domain, CHECK_(nullHandle)); -#ifdef ASSERT - if (ParseAllGenericSignatures) { - parseAndPrintGenericSignatures(this_klass, CHECK_(nullHandle)); - } -#endif - // Generate any default methods - default methods are interface methods // that have a default implementation. This is new with Lambda project. if (has_default_methods && !access_flags.is_interface() && 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 32a4da05bb5..35055b4cb41 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.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 @@ -197,7 +197,7 @@ ClassPathDirEntry::ClassPathDirEntry(char* dir) : ClassPathEntry() { } -ClassFileStream* ClassPathDirEntry::open_stream(const char* name) { +ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) { // construct full path name char path[JVM_MAXPATHLEN]; if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) { @@ -240,7 +240,7 @@ ClassPathZipEntry::~ClassPathZipEntry() { FREE_C_HEAP_ARRAY(char, _zip_name, mtClass); } -ClassFileStream* ClassPathZipEntry::open_stream(const char* name) { +ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) { // enable call to C land JavaThread* thread = JavaThread::current(); ThreadToNativeFromVM ttn(thread); @@ -284,24 +284,24 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi } } -LazyClassPathEntry::LazyClassPathEntry(char* path, struct stat st) : ClassPathEntry() { +LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() { _path = strdup(path); - _st = st; + _st = *st; _meta_index = NULL; _resolved_entry = NULL; + _has_error = false; } bool LazyClassPathEntry::is_jar_file() { return ((_st.st_mode & S_IFREG) == S_IFREG); } -ClassPathEntry* LazyClassPathEntry::resolve_entry() { +ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) { if (_resolved_entry != NULL) { return (ClassPathEntry*) _resolved_entry; } ClassPathEntry* new_entry = NULL; - ClassLoader::create_class_path_entry(_path, _st, &new_entry, false); - assert(new_entry != NULL, "earlier code should have caught this"); + new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, CHECK_NULL); { ThreadCritical tc; if (_resolved_entry == NULL) { @@ -314,12 +314,21 @@ ClassPathEntry* LazyClassPathEntry::resolve_entry() { return (ClassPathEntry*) _resolved_entry; } -ClassFileStream* LazyClassPathEntry::open_stream(const char* name) { +ClassFileStream* LazyClassPathEntry::open_stream(const char* name, TRAPS) { if (_meta_index != NULL && !_meta_index->may_contain(name)) { return NULL; } - return resolve_entry()->open_stream(name); + if (_has_error) { + return NULL; + } + ClassPathEntry* cpe = resolve_entry(THREAD); + if (cpe == NULL) { + _has_error = true; + return NULL; + } else { + return cpe->open_stream(name, THREAD); + } } bool LazyClassPathEntry::is_lazy() { @@ -465,20 +474,19 @@ void ClassLoader::setup_bootstrap_search_path() { } } -void ClassLoader::create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy) { +ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) { JavaThread* thread = JavaThread::current(); if (lazy) { - *new_entry = new LazyClassPathEntry(path, st); - return; + return new LazyClassPathEntry(path, st); } - if ((st.st_mode & S_IFREG) == S_IFREG) { + ClassPathEntry* new_entry = NULL; + if ((st->st_mode & S_IFREG) == S_IFREG) { // Regular file, should be a zip file // Canonicalized filename char canonical_path[JVM_MAXPATHLEN]; if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) { // This matches the classic VM - EXCEPTION_MARK; - THROW_MSG(vmSymbols::java_io_IOException(), "Bad pathname"); + THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL); } char* error_msg = NULL; jzfile* zip; @@ -489,7 +497,7 @@ void ClassLoader::create_class_path_entry(char *path, struct stat st, ClassPathE zip = (*ZipOpen)(canonical_path, &error_msg); } if (zip != NULL && error_msg == NULL) { - *new_entry = new ClassPathZipEntry(zip, path); + new_entry = new ClassPathZipEntry(zip, path); if (TraceClassLoading) { tty->print_cr("[Opened %s]", path); } @@ -504,16 +512,16 @@ void ClassLoader::create_class_path_entry(char *path, struct stat st, ClassPathE msg = NEW_RESOURCE_ARRAY(char, len); ; jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path); } - EXCEPTION_MARK; - THROW_MSG(vmSymbols::java_lang_ClassNotFoundException(), msg); + THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL); } } else { // Directory - *new_entry = new ClassPathDirEntry(path); + new_entry = new ClassPathDirEntry(path); if (TraceClassLoading) { tty->print_cr("[Path %s]", path); } } + return new_entry; } @@ -572,13 +580,14 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) { } } -void ClassLoader::update_class_path_entry_list(const char *path, +void ClassLoader::update_class_path_entry_list(char *path, bool check_for_duplicates) { struct stat st; - if (os::stat((char *)path, &st) == 0) { + if (os::stat(path, &st) == 0) { // File or directory found ClassPathEntry* new_entry = NULL; - create_class_path_entry((char *)path, st, &new_entry, LazyBootClassLoader); + Thread* THREAD = Thread::current(); + new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, CHECK); // The kernel VM adds dynamically to the end of the classloader path and // doesn't reorder the bootclasspath which would break java.lang.Package // (see PackageInfo). @@ -897,7 +906,7 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) { PerfClassTraceTime::CLASS_LOAD); ClassPathEntry* e = _first_entry; while (e != NULL) { - stream = e->open_stream(name); + stream = e->open_stream(name, CHECK_NULL); if (stream != NULL) { break; } @@ -1257,11 +1266,16 @@ bool ClassPathZipEntry::is_rt_jar12() { } void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) { - resolve_entry()->compile_the_world(loader, CHECK); + ClassPathEntry* cpe = resolve_entry(THREAD); + if (cpe != NULL) { + cpe->compile_the_world(loader, CHECK); + } } bool LazyClassPathEntry::is_rt_jar() { - return resolve_entry()->is_rt_jar(); + Thread* THREAD = Thread::current(); + ClassPathEntry* cpe = resolve_entry(THREAD); + return (cpe != NULL) ? cpe->is_jar_file() : false; } void ClassLoader::compile_the_world() { diff --git a/hotspot/src/share/vm/classfile/classLoader.hpp b/hotspot/src/share/vm/classfile/classLoader.hpp index 786914cad22..e03cfad1b57 100644 --- a/hotspot/src/share/vm/classfile/classLoader.hpp +++ b/hotspot/src/share/vm/classfile/classLoader.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 @@ -63,7 +63,7 @@ class ClassPathEntry: public CHeapObj { ClassPathEntry(); // Attempt to locate file_name through this class path entry. // Returns a class file parsing stream if successfull. - virtual ClassFileStream* open_stream(const char* name) = 0; + virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0; // Debugging NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;) NOT_PRODUCT(virtual bool is_rt_jar() = 0;) @@ -77,7 +77,7 @@ class ClassPathDirEntry: public ClassPathEntry { bool is_jar_file() { return false; } const char* name() { return _dir; } ClassPathDirEntry(char* dir); - ClassFileStream* open_stream(const char* name); + ClassFileStream* open_stream(const char* name, TRAPS); // Debugging NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) NOT_PRODUCT(bool is_rt_jar();) @@ -107,7 +107,7 @@ class ClassPathZipEntry: public ClassPathEntry { const char* name() { return _zip_name; } ClassPathZipEntry(jzfile* zip, const char* zip_name); ~ClassPathZipEntry(); - ClassFileStream* open_stream(const char* name); + ClassFileStream* open_stream(const char* name, TRAPS); void contents_do(void f(const char* name, void* context), void* context); // Debugging NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);) @@ -125,13 +125,14 @@ class LazyClassPathEntry: public ClassPathEntry { char* _path; // dir or file struct stat _st; MetaIndex* _meta_index; + bool _has_error; volatile ClassPathEntry* _resolved_entry; - ClassPathEntry* resolve_entry(); + ClassPathEntry* resolve_entry(TRAPS); public: bool is_jar_file(); const char* name() { return _path; } - LazyClassPathEntry(char* path, struct stat st); - ClassFileStream* open_stream(const char* name); + LazyClassPathEntry(char* path, const struct stat* st); + ClassFileStream* open_stream(const char* name, TRAPS); void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; } virtual bool is_lazy(); // Debugging @@ -207,14 +208,15 @@ class ClassLoader: AllStatic { static void setup_meta_index(); static void setup_bootstrap_search_path(); static void load_zip_library(); - static void create_class_path_entry(char *path, struct stat st, ClassPathEntry **new_entry, bool lazy); + static ClassPathEntry* create_class_path_entry(char *path, const struct stat* st, + bool lazy, TRAPS); // Canonicalizes path names, so strcmp will work properly. This is mainly // to avoid confusing the zip library static bool get_canonical_path(char* orig, char* out, int len); public: // Used by the kernel jvm. - static void update_class_path_entry_list(const char *path, + static void update_class_path_entry_list(char *path, bool check_for_duplicates); static void print_bootclasspath(); diff --git a/hotspot/src/share/vm/classfile/defaultMethods.cpp b/hotspot/src/share/vm/classfile/defaultMethods.cpp index 3ff2996b3ed..b59fe66e062 100644 --- a/hotspot/src/share/vm/classfile/defaultMethods.cpp +++ b/hotspot/src/share/vm/classfile/defaultMethods.cpp @@ -25,7 +25,6 @@ #include "precompiled.hpp" #include "classfile/bytecodeAssembler.hpp" #include "classfile/defaultMethods.hpp" -#include "classfile/genericSignatures.hpp" #include "classfile/symbolTable.hpp" #include "memory/allocation.hpp" #include "memory/metadataFactory.hpp" @@ -75,14 +74,6 @@ class PseudoScope : public ResourceObj { } }; -class ContextMark : public PseudoScopeMark { - private: - generic::Context::Mark _mark; - public: - ContextMark(const generic::Context::Mark& cm) : _mark(cm) {} - virtual void destroy() { _mark.destroy(); } -}; - #ifndef PRODUCT static void print_slot(outputStream* str, Symbol* name, Symbol* signature) { ResourceMark rm; @@ -503,38 +494,6 @@ Symbol* MethodFamily::generate_conflicts_message(GrowableArray* methods return SymbolTable::new_symbol(ss.base(), (int)ss.size(), CHECK_NULL); } -// A generic method family contains a set of all methods that implement a single -// language-level method. Because of erasure, these methods may have different -// signatures. As members of the set are collected while walking over the -// hierarchy, they are tagged with a qualification state. The qualification -// state for an erased method is set to disqualified if there exists a path -// from the root of hierarchy to the method that contains an interleaving -// language-equivalent method defined in an interface. -class GenericMethodFamily : public MethodFamily { - private: - - generic::MethodDescriptor* _descriptor; // language-level description - - public: - - GenericMethodFamily(generic::MethodDescriptor* canonical_desc) - : _descriptor(canonical_desc) {} - - generic::MethodDescriptor* descriptor() const { return _descriptor; } - - bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) { - return descriptor()->covariant_match(md, ctx); - } - -#ifndef PRODUCT - Symbol* get_generic_sig() const { - - generic::Context ctx(NULL); // empty, as _descriptor already canonicalized - TempNewSymbol sig = descriptor()->reify_signature(&ctx, Thread::current()); - return sig; - } -#endif // ndef PRODUCT -}; class StateRestorer; @@ -571,26 +530,6 @@ class StatefulMethodFamily : public ResourceObj { StateRestorer* record_method_and_dq_further(Method* mo); }; - -// StatefulGenericMethodFamily is a wrapper around GenericMethodFamily that maintains the -// qualification state during hierarchy visitation, and applies that state -// when adding members to the GenericMethodFamily. -class StatefulGenericMethodFamily : public StatefulMethodFamily { - - public: - StatefulGenericMethodFamily(generic::MethodDescriptor* md, generic::Context* ctx) - : StatefulMethodFamily(new GenericMethodFamily(md->canonicalize(ctx))) { - - } - GenericMethodFamily* get_method_family() { - return (GenericMethodFamily*)_method_family; - } - - bool descriptor_matches(generic::MethodDescriptor* md, generic::Context* ctx) { - return get_method_family()->descriptor_matches(md, ctx); - } -}; - class StateRestorer : public PseudoScopeMark { private: StatefulMethodFamily* _method; @@ -616,39 +555,6 @@ StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) { return mark; } -class StatefulGenericMethodFamilies : public ResourceObj { - private: - GrowableArray _methods; - - public: - StatefulGenericMethodFamily* find_matching( - generic::MethodDescriptor* md, generic::Context* ctx) { - for (int i = 0; i < _methods.length(); ++i) { - StatefulGenericMethodFamily* existing = _methods.at(i); - if (existing->descriptor_matches(md, ctx)) { - return existing; - } - } - return NULL; - } - - StatefulGenericMethodFamily* find_matching_or_create( - generic::MethodDescriptor* md, generic::Context* ctx) { - StatefulGenericMethodFamily* method = find_matching(md, ctx); - if (method == NULL) { - method = new StatefulGenericMethodFamily(md, ctx); - _methods.append(method); - } - return method; - } - - void extract_families_into(GrowableArray* array) { - for (int i = 0; i < _methods.length(); ++i) { - array->append(_methods.at(i)->get_method_family()); - } - } -}; - // Represents a location corresponding to a vtable slot for methods that // neither the class nor any of it's ancestors provide an implementaion. // Default methods may be present to fill this slot. @@ -779,146 +685,11 @@ class FindMethodsByErasedSig : public HierarchyVisitor { }; -// Iterates over the type hierarchy looking for all methods with a specific -// method name. The result of this is a set of method families each of -// which is populated with a set of methods that implement the same -// language-level signature. -class FindMethodsByGenericSig : public HierarchyVisitor { - private: - // Context data - Thread* THREAD; - generic::DescriptorCache* _cache; - Symbol* _method_name; - generic::Context* _ctx; - StatefulGenericMethodFamilies _families; - public: - - FindMethodsByGenericSig(generic::DescriptorCache* cache, Symbol* name, - generic::Context* ctx, Thread* thread) : - _cache(cache), _method_name(name), _ctx(ctx), THREAD(thread) {} - - void get_discovered_families(GrowableArray* methods) { - _families.extract_families_into(methods); - } - - void* new_node_data(InstanceKlass* cls) { return new PseudoScope(); } - void free_node_data(void* node_data) { - PseudoScope::cast(node_data)->destroy(); - } - - bool visit() { - PseudoScope* scope = PseudoScope::cast(current_data()); - InstanceKlass* klass = current_class(); - InstanceKlass* sub = current_depth() > 0 ? class_at_depth(1) : NULL; - - ContextMark* cm = new ContextMark(_ctx->mark()); - scope->add_mark(cm); // will restore context when scope is freed - - _ctx->apply_type_arguments(sub, klass, THREAD); - - int start, end = 0; - start = klass->find_method_by_name(_method_name, &end); - if (start != -1) { - for (int i = start; i < end; ++i) { - Method* m = klass->methods()->at(i); - // This gets the method's parameter list with its generic type - // parameters resolved - generic::MethodDescriptor* md = _cache->descriptor_for(m, THREAD); - - // Find all methods on this hierarchy that match this method - // (name, signature). This class collects other families of this - // method name. - StatefulGenericMethodFamily* family = - _families.find_matching_or_create(md, _ctx); - - if (klass->is_interface()) { - // ??? - StateRestorer* restorer = family->record_method_and_dq_further(m); - scope->add_mark(restorer); - } else { - // This is the rule that methods in classes "win" (bad word) over - // methods in interfaces. This works because of single inheritance - family->set_target_if_empty(m); - } - } - } - return true; - } -}; - -#ifndef PRODUCT -static void print_generic_families( - GrowableArray* methods, Symbol* match) { - streamIndentor si(tty, 4); - if (methods->length() == 0) { - tty->indent(); - tty->print_cr("No Logical Method found"); - } - for (int i = 0; i < methods->length(); ++i) { - tty->indent(); - GenericMethodFamily* lm = methods->at(i); - if (lm->contains_signature(match)) { - tty->print_cr(""); - } else { - tty->print_cr(""); - } - lm->print_sig_on(tty, lm->get_generic_sig(), 1); - } -} -#endif // ndef PRODUCT static void create_overpasses( GrowableArray* slots, InstanceKlass* klass, TRAPS); -static void generate_generic_defaults( - InstanceKlass* klass, GrowableArray* empty_slots, - EmptyVtableSlot* slot, int current_slot_index, TRAPS) { - - if (slot->is_bound()) { -#ifndef PRODUCT - if (TraceDefaultMethods) { - streamIndentor si(tty, 4); - tty->indent().print_cr("Already bound to logical method:"); - GenericMethodFamily* lm = (GenericMethodFamily*)(slot->get_binding()); - lm->print_sig_on(tty, lm->get_generic_sig(), 1); - } -#endif // ndef PRODUCT - return; // covered by previous processing - } - - generic::DescriptorCache cache; - - generic::Context ctx(&cache); - FindMethodsByGenericSig visitor(&cache, slot->name(), &ctx, CHECK); - visitor.run(klass); - - GrowableArray discovered_families; - visitor.get_discovered_families(&discovered_families); - -#ifndef PRODUCT - if (TraceDefaultMethods) { - print_generic_families(&discovered_families, slot->signature()); - } -#endif // ndef PRODUCT - - // Find and populate any other slots that match the discovered families - for (int j = current_slot_index; j < empty_slots->length(); ++j) { - EmptyVtableSlot* open_slot = empty_slots->at(j); - - if (slot->name() == open_slot->name()) { - for (int k = 0; k < discovered_families.length(); ++k) { - GenericMethodFamily* lm = discovered_families.at(k); - - if (lm->contains_signature(open_slot->signature())) { - lm->determine_target(klass, CHECK); - open_slot->bind_family(lm); - } - } - } - } -} - static void generate_erased_defaults( InstanceKlass* klass, GrowableArray* empty_slots, EmptyVtableSlot* slot, TRAPS) { @@ -943,21 +714,14 @@ static void merge_in_new_methods(InstanceKlass* klass, // // First if finds any name/signature slots that need any implementation (either // because they are miranda or a superclass's implementation is an overpass -// itself). For each slot, iterate over the hierarchy, using generic signature -// information to partition any methods that match the name into method families -// where each family contains methods whose signatures are equivalent at the -// language level (i.e., their reified parameters match and return values are -// covariant). Check those sets to see if they contain a signature that matches -// the slot we're looking at (if we're lucky, there might be other empty slots -// that we can fill using the same analysis). +// itself). For each slot, iterate over the hierarchy, to see if they contain a +// signature that matches the slot we are looking at. // // For each slot filled, we generate an overpass method that either calls the // unique default method candidate using invokespecial, or throws an exception // (in the case of no default method candidates, or more than one valid -// candidate). These methods are then added to the class's method list. If -// the method set we're using contains methods (qualified or not) with a -// different runtime signature than the method we're creating, then we have to -// create bridges with those signatures too. +// candidate). These methods are then added to the class's method list. +// The JVM does not create bridges nor handle generic signatures here. void DefaultMethods::generate_default_methods( InstanceKlass* klass, GrowableArray* mirandas, TRAPS) { @@ -997,11 +761,7 @@ void DefaultMethods::generate_default_methods( } #endif // ndef PRODUCT - if (ParseGenericDefaults) { - generate_generic_defaults(klass, empty_slots, slot, i, CHECK); - } else { - generate_erased_defaults(klass, empty_slots, slot, CHECK); - } + generate_erased_defaults(klass, empty_slots, slot, CHECK); } #ifndef PRODUCT if (TraceDefaultMethods) { @@ -1019,13 +779,13 @@ void DefaultMethods::generate_default_methods( } /** - * Generic analysis was used upon interface '_target' and found a unique - * default method candidate with generic signature '_method_desc'. This + * Interface inheritance rules were used to find a unique default method + * candidate for the resolved class. This * method is only viable if it would also be in the set of default method * candidates if we ran a full analysis on the current class. * * The only reason that the method would not be in the set of candidates for - * the current class is if that there's another covariantly matching method + * the current class is if that there's another matching method * which is "more specific" than the found method -- i.e., one could find a * path in the interface hierarchy in which the matching method appears * before we get to '_target'. @@ -1110,49 +870,6 @@ class ErasedShadowChecker : public ShadowChecker { : ShadowChecker(thread, name, holder, target) {} }; -class GenericShadowChecker : public ShadowChecker { - private: - generic::DescriptorCache* _cache; - generic::MethodDescriptor* _method_desc; - - bool path_has_shadow() { - generic::Context ctx(_cache); - - for (int i = current_depth() - 1; i > 0; --i) { - InstanceKlass* ik = class_at_depth(i); - InstanceKlass* sub = class_at_depth(i + 1); - ctx.apply_type_arguments(sub, ik, THREAD); - - if (ik->is_interface()) { - int end; - int start = ik->find_method_by_name(_method_name, &end); - if (start != -1) { - for (int j = start; j < end; ++j) { - Method* mo = ik->methods()->at(j); - generic::MethodDescriptor* md = _cache->descriptor_for(mo, THREAD); - if (_method_desc->covariant_match(md, &ctx)) { - return true; - } - } - } - } - } - return false; - } - - public: - - GenericShadowChecker(generic::DescriptorCache* cache, Thread* thread, - Symbol* name, InstanceKlass* holder, generic::MethodDescriptor* desc, - InstanceKlass* target) - : ShadowChecker(thread, name, holder, target) { - _cache = cache; - _method_desc = desc; - } -}; - - - // Find the unique qualified candidate from the perspective of the super_class // which is the resolved_klass, which must be an immediate superinterface // of klass @@ -1166,103 +883,48 @@ Method* find_erased_super_default(InstanceKlass* current_class, InstanceKlass* s if (family != NULL) { family->determine_target(current_class, CHECK_NULL); // get target from current_class - } - if (family->has_target()) { - Method* target = family->get_selected_target(); - InstanceKlass* holder = InstanceKlass::cast(target->method_holder()); + if (family->has_target()) { + Method* target = family->get_selected_target(); + InstanceKlass* holder = InstanceKlass::cast(target->method_holder()); - // Verify that the identified method is valid from the context of - // the current class, which is the caller class for invokespecial - // link resolution, i.e. ensure there it is not shadowed. - // You can use invokespecial to disambiguate interface methods, but - // you can not use it to skip over an interface method that would shadow it. - ErasedShadowChecker checker(THREAD, target->name(), holder, super_class); - checker.run(current_class); + // Verify that the identified method is valid from the context of + // the current class, which is the caller class for invokespecial + // link resolution, i.e. ensure there it is not shadowed. + // You can use invokespecial to disambiguate interface methods, but + // you can not use it to skip over an interface method that would shadow it. + ErasedShadowChecker checker(THREAD, target->name(), holder, super_class); + checker.run(current_class); - if (checker.found_shadow()) { + if (checker.found_shadow()) { #ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr(" Only candidate found was shadowed."); - } + if (TraceDefaultMethods) { + tty->print_cr(" Only candidate found was shadowed."); + } #endif // ndef PRODUCT - THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), - "Accessible default method not found", NULL); + THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), + "Accessible default method not found", NULL); + } else { +#ifndef PRODUCT + if (TraceDefaultMethods) { + family->print_sig_on(tty, target->signature(), 1); + } +#endif // ndef PRODUCT + return target; + } } else { -#ifndef PRODUCT - if (TraceDefaultMethods) { - family->print_sig_on(tty, target->signature(), 1); - } -#endif // ndef PRODUCT - return target; - } + assert(family->throws_exception(), "must have target or throw"); + THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), + family->get_exception_message()->as_C_string(), NULL); + } } else { - assert(family->throws_exception(), "must have target or throw"); - THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), - family->get_exception_message()->as_C_string(), NULL); + // no method found + ResourceMark rm(THREAD); + THROW_MSG_(vmSymbols::java_lang_NoSuchMethodError(), + Method::name_and_sig_as_C_string(current_class, + method_name, sig), NULL); } } - -// super_class is assumed to be the direct super of current_class -Method* find_generic_super_default( InstanceKlass* current_class, - InstanceKlass* super_class, - Symbol* method_name, Symbol* sig, TRAPS) { - generic::DescriptorCache cache; - generic::Context ctx(&cache); - - // Prime the initial generic context for current -> super_class - ctx.apply_type_arguments(current_class, super_class, CHECK_NULL); - - FindMethodsByGenericSig visitor(&cache, method_name, &ctx, CHECK_NULL); - visitor.run(super_class); - - GrowableArray families; - visitor.get_discovered_families(&families); - -#ifndef PRODUCT - if (TraceDefaultMethods) { - print_generic_families(&families, sig); - } -#endif // ndef PRODUCT - - GenericMethodFamily* selected_family = NULL; - - for (int i = 0; i < families.length(); ++i) { - GenericMethodFamily* lm = families.at(i); - if (lm->contains_signature(sig)) { - lm->determine_target(current_class, CHECK_NULL); - selected_family = lm; - } - } - - if (selected_family->has_target()) { - Method* target = selected_family->get_selected_target(); - InstanceKlass* holder = InstanceKlass::cast(target->method_holder()); - - // Verify that the identified method is valid from the context of - // the current class - GenericShadowChecker checker(&cache, THREAD, target->name(), - holder, selected_family->descriptor(), super_class); - checker.run(current_class); - - if (checker.found_shadow()) { -#ifndef PRODUCT - if (TraceDefaultMethods) { - tty->print_cr(" Only candidate found was shadowed."); - } -#endif // ndef PRODUCT - THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), - "Accessible default method not found", NULL); - } else { - return target; - } - } else { - assert(selected_family->throws_exception(), "must have target or throw"); - THROW_MSG_(vmSymbols::java_lang_AbstractMethodError(), - selected_family->get_exception_message()->as_C_string(), NULL); - } -} - // This is called during linktime when we find an invokespecial call that // refers to a direct superinterface. It indicates that we should find the // default method in the hierarchy of that superinterface, and if that method @@ -1296,13 +958,8 @@ Method* DefaultMethods::find_super_default( assert(super_class->is_interface(), "only call for default methods"); Method* target = NULL; - if (ParseGenericDefaults) { - target = find_generic_super_default(current_class, super_class, - method_name, sig, CHECK_NULL); - } else { - target = find_erased_super_default(current_class, super_class, - method_name, sig, CHECK_NULL); - } + target = find_erased_super_default(current_class, super_class, + method_name, sig, CHECK_NULL); #ifndef PRODUCT if (target != NULL) { diff --git a/hotspot/src/share/vm/classfile/genericSignatures.cpp b/hotspot/src/share/vm/classfile/genericSignatures.cpp deleted file mode 100644 index 3bbce2f8ce7..00000000000 --- a/hotspot/src/share/vm/classfile/genericSignatures.cpp +++ /dev/null @@ -1,1279 +0,0 @@ -/* - * 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. - * - */ - -#include "precompiled.hpp" - -#include "classfile/genericSignatures.hpp" -#include "classfile/symbolTable.hpp" -#include "classfile/systemDictionary.hpp" -#include "memory/resourceArea.hpp" - -namespace generic { - -// Helper class for parsing the generic signature Symbol in klass and methods -class DescriptorStream : public ResourceObj { - private: - Symbol* _symbol; - int _offset; - int _mark; - const char* _parse_error; - - void set_parse_error(const char* error) { - assert(error != NULL, "Can't set NULL error string"); - _parse_error = error; - } - - public: - DescriptorStream(Symbol* sym) - : _symbol(sym), _offset(0), _mark(-1), _parse_error(NULL) {} - - const char* parse_error() const { - return _parse_error; - } - - bool at_end() { return _offset >= _symbol->utf8_length(); } - - char peek() { - if (at_end()) { - set_parse_error("Peeking past end of signature"); - return '\0'; - } else { - return _symbol->byte_at(_offset); - } - } - - char read() { - if (at_end()) { - set_parse_error("Reading past end of signature"); - return '\0'; - } else { - return _symbol->byte_at(_offset++); - } - } - - void read(char expected) { - char c = read(); - assert_char(c, expected, 0); - } - - void assert_char(char c, char expected, int pos = -1) { - if (c != expected) { - const char* fmt = "Parse error at %d: expected %c but got %c"; - size_t len = strlen(fmt) + 5; - char* buffer = NEW_RESOURCE_ARRAY(char, len); - jio_snprintf(buffer, len, fmt, _offset + pos, expected, c); - set_parse_error(buffer); - } - } - - void push(char c) { - assert(c == _symbol->byte_at(_offset - 1), "Pushing back wrong value"); - --_offset; - } - - void expect_end() { - if (!at_end()) { - set_parse_error("Unexpected data trailing signature"); - } - } - - bool has_mark() { return _mark != -1; } - - void set_mark() { - _mark = _offset; - } - - Identifier* identifier_from_mark() { - assert(has_mark(), "Mark should be set"); - if (!has_mark()) { - set_parse_error("Expected mark to be set"); - return NULL; - } else { - Identifier* id = new Identifier(_symbol, _mark, _offset - 1); - _mark = -1; - return id; - } - } -}; - - -#define CHECK_FOR_PARSE_ERROR() \ - if (STREAM->parse_error() != NULL) { \ - if (VerifyGenericSignatures) { \ - fatal(STREAM->parse_error()); \ - } \ - return NULL; \ - } (void)0 - -#define READ() STREAM->read(); CHECK_FOR_PARSE_ERROR() -#define PEEK() STREAM->peek(); CHECK_FOR_PARSE_ERROR() -#define PUSH(c) STREAM->push(c) -#define EXPECT(c) STREAM->read(c); CHECK_FOR_PARSE_ERROR() -#define EXPECTED(c, ch) STREAM->assert_char(c, ch); CHECK_FOR_PARSE_ERROR() -#define EXPECT_END() STREAM->expect_end(); CHECK_FOR_PARSE_ERROR() - -#define CHECK_STREAM STREAM); CHECK_FOR_PARSE_ERROR(); ((void)0 - -#ifndef PRODUCT -void Identifier::print_on(outputStream* str) const { - for (int i = _begin; i < _end; ++i) { - str->print("%c", (char)_sym->byte_at(i)); - } -} -#endif // ndef PRODUCT - -bool Identifier::equals(Identifier* other) { - if (_sym == other->_sym && _begin == other->_begin && _end == other->_end) { - return true; - } else if (_end - _begin != other->_end - other->_begin) { - return false; - } else { - size_t len = _end - _begin; - char* addr = ((char*)_sym->bytes()) + _begin; - char* oaddr = ((char*)other->_sym->bytes()) + other->_begin; - return strncmp(addr, oaddr, len) == 0; - } -} - -bool Identifier::equals(Symbol* sym) { - Identifier id(sym, 0, sym->utf8_length()); - return equals(&id); -} - -/** - * A formal type parameter may be found in the the enclosing class, but it could - * also come from an enclosing method or outer class, in the case of inner-outer - * classes or anonymous classes. For example: - * - * class Outer { - * class Inner { - * void m(T t, V v, W w); - * } - * } - * - * In this case, the type variables in m()'s signature are not all found in the - * immediate enclosing class (Inner). class Inner has only type parameter W, - * but it's outer_class field will reference Outer's descriptor which contains - * T & V (no outer_method in this case). - * - * If you have an anonymous class, it has both an enclosing method *and* an - * enclosing class where type parameters can be declared: - * - * class MOuter { - * void bar(V v) { - * Runnable r = new Runnable() { - * public void run() {} - * public void foo(T t, V v) { ... } - * }; - * } - * } - * - * In this case, foo will be a member of some class, Runnable$1, which has no - * formal parameters itself, but has an outer_method (bar()) which provides - * type parameter V, and an outer class MOuter with type parameter T. - * - * It is also possible that the outer class is itself an inner class to some - * other class (or an anonymous class with an enclosing method), so we need to - * follow the outer_class/outer_method chain to it's end when looking for a - * type parameter. - */ -TypeParameter* Descriptor::find_type_parameter(Identifier* id, int* depth) { - - int current_depth = 0; - - MethodDescriptor* outer_method = as_method_signature(); - ClassDescriptor* outer_class = as_class_signature(); - - if (outer_class == NULL) { // 'this' is a method signature; use the holder - outer_class = outer_method->outer_class(); - } - - while (outer_method != NULL || outer_class != NULL) { - if (outer_method != NULL) { - for (int i = 0; i < outer_method->type_parameters().length(); ++i) { - TypeParameter* p = outer_method->type_parameters().at(i); - if (p->identifier()->equals(id)) { - *depth = -1; // indicates this this is a method parameter - return p; - } - } - } - if (outer_class != NULL) { - for (int i = 0; i < outer_class->type_parameters().length(); ++i) { - TypeParameter* p = outer_class->type_parameters().at(i); - if (p->identifier()->equals(id)) { - *depth = current_depth; - return p; - } - } - outer_method = outer_class->outer_method(); - outer_class = outer_class->outer_class(); - ++current_depth; - } - } - - if (VerifyGenericSignatures) { - fatal("Could not resolve identifier"); - } - - return NULL; -} - -ClassDescriptor* ClassDescriptor::parse_generic_signature(Klass* klass, TRAPS) { - return parse_generic_signature(klass, NULL, CHECK_NULL); -} - -ClassDescriptor* ClassDescriptor::parse_generic_signature( - Klass* klass, Symbol* original_name, TRAPS) { - - InstanceKlass* ik = InstanceKlass::cast(klass); - Symbol* sym = ik->generic_signature(); - - ClassDescriptor* spec; - - if (sym == NULL || (spec = ClassDescriptor::parse_generic_signature(sym)) == NULL) { - spec = ClassDescriptor::placeholder(ik); - } - - u2 outer_index = get_outer_class_index(ik, CHECK_NULL); - if (outer_index != 0) { - if (original_name == NULL) { - original_name = ik->name(); - } - Handle class_loader = Handle(THREAD, ik->class_loader()); - Handle protection_domain = Handle(THREAD, ik->protection_domain()); - - Symbol* outer_name = ik->constants()->klass_name_at(outer_index); - Klass* outer = SystemDictionary::find( - outer_name, class_loader, protection_domain, CHECK_NULL); - if (outer == NULL && !THREAD->is_Compiler_thread()) { - if (outer_name == ik->super()->name()) { - outer = SystemDictionary::resolve_super_or_fail(original_name, outer_name, - class_loader, protection_domain, - false, CHECK_NULL); - } - else { - outer = SystemDictionary::resolve_or_fail(outer_name, class_loader, - protection_domain, false, CHECK_NULL); - } - } - - InstanceKlass* outer_ik; - ClassDescriptor* outer_spec = NULL; - if (outer == NULL) { - outer_spec = ClassDescriptor::placeholder(ik); - assert(false, "Outer class not loaded and not loadable from here"); - } else { - outer_ik = InstanceKlass::cast(outer); - outer_spec = parse_generic_signature(outer, original_name, CHECK_NULL); - } - spec->set_outer_class(outer_spec); - - u2 encl_method_idx = ik->enclosing_method_method_index(); - if (encl_method_idx != 0 && outer_ik != NULL) { - ConstantPool* cp = ik->constants(); - u2 name_index = cp->name_ref_index_at(encl_method_idx); - u2 sig_index = cp->signature_ref_index_at(encl_method_idx); - Symbol* name = cp->symbol_at(name_index); - Symbol* sig = cp->symbol_at(sig_index); - Method* m = outer_ik->find_method(name, sig); - if (m != NULL) { - Symbol* gsig = m->generic_signature(); - if (gsig != NULL) { - MethodDescriptor* gms = MethodDescriptor::parse_generic_signature(gsig, outer_spec); - spec->set_outer_method(gms); - } - } else if (VerifyGenericSignatures) { - ResourceMark rm; - stringStream ss; - ss.print("Could not find method %s %s in class %s", - name->as_C_string(), sig->as_C_string(), outer_name->as_C_string()); - fatal(ss.as_string()); - } - } - } - - spec->bind_variables_to_parameters(); - return spec; -} - -ClassDescriptor* ClassDescriptor::placeholder(InstanceKlass* klass) { - GrowableArray formals; - GrowableArray interfaces; - ClassType* super_type = NULL; - - Klass* super_klass = klass->super(); - if (super_klass != NULL) { - InstanceKlass* super = InstanceKlass::cast(super_klass); - super_type = ClassType::from_symbol(super->name()); - } - - for (int i = 0; i < klass->local_interfaces()->length(); ++i) { - InstanceKlass* iface = InstanceKlass::cast(klass->local_interfaces()->at(i)); - interfaces.append(ClassType::from_symbol(iface->name())); - } - return new ClassDescriptor(formals, super_type, interfaces); -} - -ClassDescriptor* ClassDescriptor::parse_generic_signature(Symbol* sym) { - - DescriptorStream ds(sym); - DescriptorStream* STREAM = &ds; - - GrowableArray parameters(8); - char c = READ(); - if (c == '<') { - c = READ(); - while (c != '>') { - PUSH(c); - TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM); - parameters.append(ftp); - c = READ(); - } - } else { - PUSH(c); - } - - EXPECT('L'); - ClassType* super = ClassType::parse_generic_signature(CHECK_STREAM); - - GrowableArray signatures(2); - while (!STREAM->at_end()) { - EXPECT('L'); - ClassType* iface = ClassType::parse_generic_signature(CHECK_STREAM); - signatures.append(iface); - } - - EXPECT_END(); - - return new ClassDescriptor(parameters, super, signatures); -} - -#ifndef PRODUCT -void ClassDescriptor::print_on(outputStream* str) const { - str->indent().print_cr("ClassDescriptor {"); - { - streamIndentor si(str); - if (_type_parameters.length() > 0) { - str->indent().print_cr("Formals {"); - { - streamIndentor si(str); - for (int i = 0; i < _type_parameters.length(); ++i) { - _type_parameters.at(i)->print_on(str); - } - } - str->indent().print_cr("}"); - } - if (_super != NULL) { - str->indent().print_cr("Superclass: "); - { - streamIndentor si(str); - _super->print_on(str); - } - } - if (_interfaces.length() > 0) { - str->indent().print_cr("SuperInterfaces: {"); - { - streamIndentor si(str); - for (int i = 0; i < _interfaces.length(); ++i) { - _interfaces.at(i)->print_on(str); - } - } - str->indent().print_cr("}"); - } - if (_outer_method != NULL) { - str->indent().print_cr("Outer Method: {"); - { - streamIndentor si(str); - _outer_method->print_on(str); - } - str->indent().print_cr("}"); - } - if (_outer_class != NULL) { - str->indent().print_cr("Outer Class: {"); - { - streamIndentor si(str); - _outer_class->print_on(str); - } - str->indent().print_cr("}"); - } - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -ClassType* ClassDescriptor::interface_desc(Symbol* sym) { - for (int i = 0; i < _interfaces.length(); ++i) { - if (_interfaces.at(i)->identifier()->equals(sym)) { - return _interfaces.at(i); - } - } - if (VerifyGenericSignatures) { - fatal("Did not find expected interface"); - } - return NULL; -} - -void ClassDescriptor::bind_variables_to_parameters() { - if (_outer_class != NULL) { - _outer_class->bind_variables_to_parameters(); - } - if (_outer_method != NULL) { - _outer_method->bind_variables_to_parameters(); - } - for (int i = 0; i < _type_parameters.length(); ++i) { - _type_parameters.at(i)->bind_variables_to_parameters(this, i); - } - if (_super != NULL) { - _super->bind_variables_to_parameters(this); - } - for (int i = 0; i < _interfaces.length(); ++i) { - _interfaces.at(i)->bind_variables_to_parameters(this); - } -} - -ClassDescriptor* ClassDescriptor::canonicalize(Context* ctx) { - - GrowableArray type_params(_type_parameters.length()); - for (int i = 0; i < _type_parameters.length(); ++i) { - type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0)); - } - - ClassDescriptor* outer = _outer_class == NULL ? NULL : - _outer_class->canonicalize(ctx); - - ClassType* super = _super == NULL ? NULL : _super->canonicalize(ctx, 0); - - GrowableArray interfaces(_interfaces.length()); - for (int i = 0; i < _interfaces.length(); ++i) { - interfaces.append(_interfaces.at(i)->canonicalize(ctx, 0)); - } - - MethodDescriptor* md = _outer_method == NULL ? NULL : - _outer_method->canonicalize(ctx); - - return new ClassDescriptor(type_params, super, interfaces, outer, md); -} - -u2 ClassDescriptor::get_outer_class_index(InstanceKlass* klass, TRAPS) { - int inner_index = InstanceKlass::inner_class_inner_class_info_offset; - int outer_index = InstanceKlass::inner_class_outer_class_info_offset; - int name_offset = InstanceKlass::inner_class_inner_name_offset; - int next_offset = InstanceKlass::inner_class_next_offset; - - if (klass->inner_classes() == NULL || klass->inner_classes()->length() == 0) { - // No inner class info => no declaring class - return 0; - } - - Array* i_icls = klass->inner_classes(); - ConstantPool* i_cp = klass->constants(); - int i_length = i_icls->length(); - - // Find inner_klass attribute - for (int i = 0; i + next_offset < i_length; i += next_offset) { - u2 ioff = i_icls->at(i + inner_index); - u2 ooff = i_icls->at(i + outer_index); - u2 noff = i_icls->at(i + name_offset); - if (ioff != 0) { - // Check to see if the name matches the class we're looking for - // before attempting to find the class. - if (i_cp->klass_name_at_matches(klass, ioff) && ooff != 0) { - return ooff; - } - } - } - - // It may be anonymous; try for that. - u2 encl_method_class_idx = klass->enclosing_method_class_index(); - if (encl_method_class_idx != 0) { - return encl_method_class_idx; - } - - return 0; -} - -MethodDescriptor* MethodDescriptor::parse_generic_signature(Method* m, ClassDescriptor* outer) { - Symbol* generic_sig = m->generic_signature(); - MethodDescriptor* md = NULL; - if (generic_sig == NULL || (md = parse_generic_signature(generic_sig, outer)) == NULL) { - md = parse_generic_signature(m->signature(), outer); - } - assert(md != NULL, "Could not parse method signature"); - md->bind_variables_to_parameters(); - return md; -} - -MethodDescriptor* MethodDescriptor::parse_generic_signature(Symbol* sym, ClassDescriptor* outer) { - - DescriptorStream ds(sym); - DescriptorStream* STREAM = &ds; - - GrowableArray params(8); - char c = READ(); - if (c == '<') { - c = READ(); - while (c != '>') { - PUSH(c); - TypeParameter* ftp = TypeParameter::parse_generic_signature(CHECK_STREAM); - params.append(ftp); - c = READ(); - } - } else { - PUSH(c); - } - - EXPECT('('); - - GrowableArray parameters(8); - c = READ(); - while (c != ')') { - PUSH(c); - Type* arg = Type::parse_generic_signature(CHECK_STREAM); - parameters.append(arg); - c = READ(); - } - - Type* rt = Type::parse_generic_signature(CHECK_STREAM); - - GrowableArray throws; - while (!STREAM->at_end()) { - EXPECT('^'); - Type* spec = Type::parse_generic_signature(CHECK_STREAM); - throws.append(spec); - } - - return new MethodDescriptor(params, outer, parameters, rt, throws); -} - -void MethodDescriptor::bind_variables_to_parameters() { - for (int i = 0; i < _type_parameters.length(); ++i) { - _type_parameters.at(i)->bind_variables_to_parameters(this, i); - } - for (int i = 0; i < _parameters.length(); ++i) { - _parameters.at(i)->bind_variables_to_parameters(this); - } - _return_type->bind_variables_to_parameters(this); - for (int i = 0; i < _throws.length(); ++i) { - _throws.at(i)->bind_variables_to_parameters(this); - } -} - -bool MethodDescriptor::covariant_match(MethodDescriptor* other, Context* ctx) { - - if (_parameters.length() == other->_parameters.length()) { - for (int i = 0; i < _parameters.length(); ++i) { - if (!_parameters.at(i)->covariant_match(other->_parameters.at(i), ctx)) { - return false; - } - } - - if (_return_type->as_primitive() != NULL) { - return _return_type->covariant_match(other->_return_type, ctx); - } else { - // return type is a reference - return other->_return_type->as_class() != NULL || - other->_return_type->as_variable() != NULL || - other->_return_type->as_array() != NULL; - } - } else { - return false; - } -} - -MethodDescriptor* MethodDescriptor::canonicalize(Context* ctx) { - - GrowableArray type_params(_type_parameters.length()); - for (int i = 0; i < _type_parameters.length(); ++i) { - type_params.append(_type_parameters.at(i)->canonicalize(ctx, 0)); - } - - ClassDescriptor* outer = _outer_class == NULL ? NULL : - _outer_class->canonicalize(ctx); - - GrowableArray params(_parameters.length()); - for (int i = 0; i < _parameters.length(); ++i) { - params.append(_parameters.at(i)->canonicalize(ctx, 0)); - } - - Type* rt = _return_type->canonicalize(ctx, 0); - - GrowableArray throws(_throws.length()); - for (int i = 0; i < _throws.length(); ++i) { - throws.append(_throws.at(i)->canonicalize(ctx, 0)); - } - - return new MethodDescriptor(type_params, outer, params, rt, throws); -} - -#ifndef PRODUCT -TempNewSymbol MethodDescriptor::reify_signature(Context* ctx, TRAPS) { - stringStream ss(256); - - ss.print("("); - for (int i = 0; i < _parameters.length(); ++i) { - _parameters.at(i)->reify_signature(&ss, ctx); - } - ss.print(")"); - _return_type->reify_signature(&ss, ctx); - return SymbolTable::new_symbol(ss.base(), (int)ss.size(), THREAD); -} - -void MethodDescriptor::print_on(outputStream* str) const { - str->indent().print_cr("MethodDescriptor {"); - { - streamIndentor si(str); - if (_type_parameters.length() > 0) { - str->indent().print_cr("Formals: {"); - { - streamIndentor si(str); - for (int i = 0; i < _type_parameters.length(); ++i) { - _type_parameters.at(i)->print_on(str); - } - } - str->indent().print_cr("}"); - } - str->indent().print_cr("Parameters: {"); - { - streamIndentor si(str); - for (int i = 0; i < _parameters.length(); ++i) { - _parameters.at(i)->print_on(str); - } - } - str->indent().print_cr("}"); - str->indent().print_cr("Return Type: "); - { - streamIndentor si(str); - _return_type->print_on(str); - } - - if (_throws.length() > 0) { - str->indent().print_cr("Throws: {"); - { - streamIndentor si(str); - for (int i = 0; i < _throws.length(); ++i) { - _throws.at(i)->print_on(str); - } - } - str->indent().print_cr("}"); - } - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -TypeParameter* TypeParameter::parse_generic_signature(DescriptorStream* STREAM) { - STREAM->set_mark(); - char c = READ(); - while (c != ':') { - c = READ(); - } - - Identifier* id = STREAM->identifier_from_mark(); - - ClassType* class_bound = NULL; - GrowableArray interface_bounds(8); - - c = READ(); - if (c != '>') { - if (c != ':') { - EXPECTED(c, 'L'); - class_bound = ClassType::parse_generic_signature(CHECK_STREAM); - c = READ(); - } - - while (c == ':') { - EXPECT('L'); - ClassType* fts = ClassType::parse_generic_signature(CHECK_STREAM); - interface_bounds.append(fts); - c = READ(); - } - } - PUSH(c); - - return new TypeParameter(id, class_bound, interface_bounds); -} - -void TypeParameter::bind_variables_to_parameters(Descriptor* sig, int position) { - if (_class_bound != NULL) { - _class_bound->bind_variables_to_parameters(sig); - } - for (int i = 0; i < _interface_bounds.length(); ++i) { - _interface_bounds.at(i)->bind_variables_to_parameters(sig); - } - _position = position; -} - -Type* TypeParameter::resolve( - Context* ctx, int inner_depth, int ctx_depth) { - - if (inner_depth == -1) { - // This indicates that the parameter is a method type parameter, which - // isn't resolveable using the class hierarchy context - return bound(); - } - - ClassType* provider = ctx->at_depth(ctx_depth); - if (provider != NULL) { - for (int i = 0; i < inner_depth && provider != NULL; ++i) { - provider = provider->outer_class(); - } - if (provider != NULL) { - TypeArgument* arg = provider->type_argument_at(_position); - if (arg != NULL) { - Type* value = arg->lower_bound(); - return value->canonicalize(ctx, ctx_depth + 1); - } - } - } - - return bound(); -} - -TypeParameter* TypeParameter::canonicalize(Context* ctx, int ctx_depth) { - ClassType* bound = _class_bound == NULL ? NULL : - _class_bound->canonicalize(ctx, ctx_depth); - - GrowableArray ifaces(_interface_bounds.length()); - for (int i = 0; i < _interface_bounds.length(); ++i) { - ifaces.append(_interface_bounds.at(i)->canonicalize(ctx, ctx_depth)); - } - - TypeParameter* ret = new TypeParameter(_identifier, bound, ifaces); - ret->_position = _position; - return ret; -} - -ClassType* TypeParameter::bound() { - if (_class_bound != NULL) { - return _class_bound; - } - - if (_interface_bounds.length() == 1) { - return _interface_bounds.at(0); - } - - return ClassType::java_lang_Object(); // TODO: investigate this case -} - -#ifndef PRODUCT -void TypeParameter::print_on(outputStream* str) const { - str->indent().print_cr("Formal: {"); - { - streamIndentor si(str); - - str->indent().print("Identifier: "); - _identifier->print_on(str); - str->print_cr(""); - if (_class_bound != NULL) { - str->indent().print_cr("Class Bound: "); - streamIndentor si(str); - _class_bound->print_on(str); - } - if (_interface_bounds.length() > 0) { - str->indent().print_cr("Interface Bounds: {"); - { - streamIndentor si(str); - for (int i = 0; i < _interface_bounds.length(); ++i) { - _interface_bounds.at(i)->print_on(str); - } - } - str->indent().print_cr("}"); - } - str->indent().print_cr("Ordinal Position: %d", _position); - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -Type* Type::parse_generic_signature(DescriptorStream* STREAM) { - char c = READ(); - switch (c) { - case 'L': - return ClassType::parse_generic_signature(CHECK_STREAM); - case 'T': - return TypeVariable::parse_generic_signature(CHECK_STREAM); - case '[': - return ArrayType::parse_generic_signature(CHECK_STREAM); - default: - return new PrimitiveType(c); - } -} - -Identifier* ClassType::parse_generic_signature_simple(GrowableArray* args, - bool* has_inner, DescriptorStream* STREAM) { - STREAM->set_mark(); - - char c = READ(); - while (c != ';' && c != '.' && c != '<') { c = READ(); } - Identifier* id = STREAM->identifier_from_mark(); - - if (c == '<') { - c = READ(); - while (c != '>') { - PUSH(c); - TypeArgument* arg = TypeArgument::parse_generic_signature(CHECK_STREAM); - args->append(arg); - c = READ(); - } - c = READ(); - } - - *has_inner = (c == '.'); - if (!(*has_inner)) { - EXPECTED(c, ';'); - } - - return id; -} - -ClassType* ClassType::parse_generic_signature(DescriptorStream* STREAM) { - return parse_generic_signature(NULL, CHECK_STREAM); -} - -ClassType* ClassType::parse_generic_signature(ClassType* outer, DescriptorStream* STREAM) { - GrowableArray args; - ClassType* gct = NULL; - bool has_inner = false; - - Identifier* id = parse_generic_signature_simple(&args, &has_inner, STREAM); - if (id != NULL) { - gct = new ClassType(id, args, outer); - - if (has_inner) { - gct = parse_generic_signature(gct, CHECK_STREAM); - } - } - return gct; -} - -ClassType* ClassType::from_symbol(Symbol* sym) { - assert(sym != NULL, "Must not be null"); - GrowableArray args; - Identifier* id = new Identifier(sym, 0, sym->utf8_length()); - return new ClassType(id, args, NULL); -} - -ClassType* ClassType::java_lang_Object() { - return from_symbol(vmSymbols::java_lang_Object()); -} - -void ClassType::bind_variables_to_parameters(Descriptor* sig) { - for (int i = 0; i < _type_arguments.length(); ++i) { - _type_arguments.at(i)->bind_variables_to_parameters(sig); - } - if (_outer_class != NULL) { - _outer_class->bind_variables_to_parameters(sig); - } -} - -TypeArgument* ClassType::type_argument_at(int i) { - if (i >= 0 && i < _type_arguments.length()) { - return _type_arguments.at(i); - } else { - return NULL; - } -} - -#ifndef PRODUCT -void ClassType::reify_signature(stringStream* ss, Context* ctx) { - ss->print("L"); - _identifier->print_on(ss); - ss->print(";"); -} - -void ClassType::print_on(outputStream* str) const { - str->indent().print_cr("Class {"); - { - streamIndentor si(str); - str->indent().print("Name: "); - _identifier->print_on(str); - str->print_cr(""); - if (_type_arguments.length() != 0) { - str->indent().print_cr("Type Arguments: {"); - { - streamIndentor si(str); - for (int j = 0; j < _type_arguments.length(); ++j) { - _type_arguments.at(j)->print_on(str); - } - } - str->indent().print_cr("}"); - } - if (_outer_class != NULL) { - str->indent().print_cr("Outer Class: "); - streamIndentor sir(str); - _outer_class->print_on(str); - } - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -bool ClassType::covariant_match(Type* other, Context* ctx) { - - if (other == this) { - return true; - } - - TypeVariable* variable = other->as_variable(); - if (variable != NULL) { - other = variable->resolve(ctx, 0); - } - - ClassType* outer = outer_class(); - ClassType* other_class = other->as_class(); - - if (other_class == NULL || - (outer == NULL) != (other_class->outer_class() == NULL)) { - return false; - } - - if (!_identifier->equals(other_class->_identifier)) { - return false; - } - - if (outer != NULL && !outer->covariant_match(other_class->outer_class(), ctx)) { - return false; - } - - return true; -} - -ClassType* ClassType::canonicalize(Context* ctx, int ctx_depth) { - - GrowableArray args(_type_arguments.length()); - for (int i = 0; i < _type_arguments.length(); ++i) { - args.append(_type_arguments.at(i)->canonicalize(ctx, ctx_depth)); - } - - ClassType* outer = _outer_class == NULL ? NULL : - _outer_class->canonicalize(ctx, ctx_depth); - - return new ClassType(_identifier, args, outer); -} - -TypeVariable* TypeVariable::parse_generic_signature(DescriptorStream* STREAM) { - STREAM->set_mark(); - char c = READ(); - while (c != ';') { - c = READ(); - } - Identifier* id = STREAM->identifier_from_mark(); - - return new TypeVariable(id); -} - -void TypeVariable::bind_variables_to_parameters(Descriptor* sig) { - _parameter = sig->find_type_parameter(_id, &_inner_depth); - if (VerifyGenericSignatures && _parameter == NULL) { - fatal("Could not find formal parameter"); - } -} - -Type* TypeVariable::resolve(Context* ctx, int ctx_depth) { - if (parameter() != NULL) { - return parameter()->resolve(ctx, inner_depth(), ctx_depth); - } else { - if (VerifyGenericSignatures) { - fatal("Type variable matches no parameter"); - } - return NULL; - } -} - -bool TypeVariable::covariant_match(Type* other, Context* ctx) { - - if (other == this) { - return true; - } - - Context my_context(NULL); // empty, results in erasure - Type* my_type = resolve(&my_context, 0); - if (my_type == NULL) { - return false; - } - - return my_type->covariant_match(other, ctx); -} - -Type* TypeVariable::canonicalize(Context* ctx, int ctx_depth) { - return resolve(ctx, ctx_depth); -} - -#ifndef PRODUCT -void TypeVariable::reify_signature(stringStream* ss, Context* ctx) { - Type* type = resolve(ctx, 0); - if (type != NULL) { - type->reify_signature(ss, ctx); - } -} - -void TypeVariable::print_on(outputStream* str) const { - str->indent().print_cr("Type Variable {"); - { - streamIndentor si(str); - str->indent().print("Name: "); - _id->print_on(str); - str->print_cr(""); - str->indent().print_cr("Inner depth: %d", _inner_depth); - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -ArrayType* ArrayType::parse_generic_signature(DescriptorStream* STREAM) { - Type* base = Type::parse_generic_signature(CHECK_STREAM); - return new ArrayType(base); -} - -void ArrayType::bind_variables_to_parameters(Descriptor* sig) { - assert(_base != NULL, "Invalid base"); - _base->bind_variables_to_parameters(sig); -} - -bool ArrayType::covariant_match(Type* other, Context* ctx) { - assert(_base != NULL, "Invalid base"); - - if (other == this) { - return true; - } - - ArrayType* other_array = other->as_array(); - return (other_array != NULL && _base->covariant_match(other_array->_base, ctx)); -} - -ArrayType* ArrayType::canonicalize(Context* ctx, int ctx_depth) { - assert(_base != NULL, "Invalid base"); - return new ArrayType(_base->canonicalize(ctx, ctx_depth)); -} - -#ifndef PRODUCT -void ArrayType::reify_signature(stringStream* ss, Context* ctx) { - assert(_base != NULL, "Invalid base"); - ss->print("["); - _base->reify_signature(ss, ctx); -} - -void ArrayType::print_on(outputStream* str) const { - str->indent().print_cr("Array {"); - { - streamIndentor si(str); - _base->print_on(str); - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -bool PrimitiveType::covariant_match(Type* other, Context* ctx) { - - PrimitiveType* other_prim = other->as_primitive(); - return (other_prim != NULL && _type == other_prim->_type); -} - -PrimitiveType* PrimitiveType::canonicalize(Context* ctx, int ctxd) { - return this; -} - -#ifndef PRODUCT -void PrimitiveType::reify_signature(stringStream* ss, Context* ctx) { - ss->print("%c", _type); -} - -void PrimitiveType::print_on(outputStream* str) const { - str->indent().print_cr("Primitive: '%c'", _type); -} -#endif // ndef PRODUCT - -void PrimitiveType::bind_variables_to_parameters(Descriptor* sig) { -} - -TypeArgument* TypeArgument::parse_generic_signature(DescriptorStream* STREAM) { - char c = READ(); - Type* type = NULL; - - switch (c) { - case '*': - return new TypeArgument(ClassType::java_lang_Object(), NULL); - break; - default: - PUSH(c); - // fall-through - case '+': - case '-': - type = Type::parse_generic_signature(CHECK_STREAM); - if (c == '+') { - return new TypeArgument(type, NULL); - } else if (c == '-') { - return new TypeArgument(ClassType::java_lang_Object(), type); - } else { - return new TypeArgument(type, type); - } - } -} - -void TypeArgument::bind_variables_to_parameters(Descriptor* sig) { - assert(_lower_bound != NULL, "Invalid lower bound"); - _lower_bound->bind_variables_to_parameters(sig); - if (_upper_bound != NULL && _upper_bound != _lower_bound) { - _upper_bound->bind_variables_to_parameters(sig); - } -} - -bool TypeArgument::covariant_match(TypeArgument* other, Context* ctx) { - assert(_lower_bound != NULL, "Invalid lower bound"); - - if (other == this) { - return true; - } - - if (!_lower_bound->covariant_match(other->lower_bound(), ctx)) { - return false; - } - return true; -} - -TypeArgument* TypeArgument::canonicalize(Context* ctx, int ctx_depth) { - assert(_lower_bound != NULL, "Invalid lower bound"); - Type* lower = _lower_bound->canonicalize(ctx, ctx_depth); - Type* upper = NULL; - - if (_upper_bound == _lower_bound) { - upper = lower; - } else if (_upper_bound != NULL) { - upper = _upper_bound->canonicalize(ctx, ctx_depth); - } - - return new TypeArgument(lower, upper); -} - -#ifndef PRODUCT -void TypeArgument::print_on(outputStream* str) const { - str->indent().print_cr("TypeArgument {"); - { - streamIndentor si(str); - if (_lower_bound != NULL) { - str->indent().print("Lower bound: "); - _lower_bound->print_on(str); - } - if (_upper_bound != NULL) { - str->indent().print("Upper bound: "); - _upper_bound->print_on(str); - } - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -void Context::Mark::destroy() { - if (is_active()) { - _context->reset_to_mark(_marked_size); - } - deactivate(); -} - -void Context::apply_type_arguments( - InstanceKlass* current, InstanceKlass* super, TRAPS) { - assert(_cache != NULL, "Cannot use an empty context"); - ClassType* spec = NULL; - if (current != NULL) { - ClassDescriptor* descriptor = _cache->descriptor_for(current, CHECK); - if (super == current->super()) { - spec = descriptor->super(); - } else { - spec = descriptor->interface_desc(super->name()); - } - if (spec != NULL) { - _type_arguments.push(spec); - } - } -} - -void Context::reset_to_mark(int size) { - _type_arguments.trunc_to(size); -} - -ClassType* Context::at_depth(int i) const { - if (i < _type_arguments.length()) { - return _type_arguments.at(_type_arguments.length() - 1 - i); - } - return NULL; -} - -#ifndef PRODUCT -void Context::print_on(outputStream* str) const { - str->indent().print_cr("Context {"); - for (int i = 0; i < _type_arguments.length(); ++i) { - streamIndentor si(str); - str->indent().print("leval %d: ", i); - ClassType* ct = at_depth(i); - if (ct == NULL) { - str->print_cr(""); - continue; - } else { - str->print_cr("{"); - } - - for (int j = 0; j < ct->type_arguments_length(); ++j) { - streamIndentor si(str); - TypeArgument* ta = ct->type_argument_at(j); - Type* bound = ta->lower_bound(); - bound->print_on(str); - } - str->indent().print_cr("}"); - } - str->indent().print_cr("}"); -} -#endif // ndef PRODUCT - -ClassDescriptor* DescriptorCache::descriptor_for(InstanceKlass* ik, TRAPS) { - - ClassDescriptor** existing = _class_descriptors.get(ik); - if (existing == NULL) { - ClassDescriptor* cd = ClassDescriptor::parse_generic_signature(ik, CHECK_NULL); - _class_descriptors.put(ik, cd); - return cd; - } else { - return *existing; - } -} - -MethodDescriptor* DescriptorCache::descriptor_for( - Method* mh, ClassDescriptor* cd, TRAPS) { - assert(mh != NULL && cd != NULL, "Should not be NULL"); - MethodDescriptor** existing = _method_descriptors.get(mh); - if (existing == NULL) { - MethodDescriptor* md = MethodDescriptor::parse_generic_signature(mh, cd); - _method_descriptors.put(mh, md); - return md; - } else { - return *existing; - } -} -MethodDescriptor* DescriptorCache::descriptor_for(Method* mh, TRAPS) { - ClassDescriptor* cd = descriptor_for( - InstanceKlass::cast(mh->method_holder()), CHECK_NULL); - return descriptor_for(mh, cd, THREAD); -} - -} // namespace generic diff --git a/hotspot/src/share/vm/classfile/genericSignatures.hpp b/hotspot/src/share/vm/classfile/genericSignatures.hpp deleted file mode 100644 index 07eb4759357..00000000000 --- a/hotspot/src/share/vm/classfile/genericSignatures.hpp +++ /dev/null @@ -1,467 +0,0 @@ -/* - * 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. - * - */ - -#ifndef SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP -#define SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP - -#include "classfile/symbolTable.hpp" -#include "memory/allocation.hpp" -#include "runtime/signature.hpp" -#include "utilities/growableArray.hpp" -#include "utilities/resourceHash.hpp" - -class stringStream; - -namespace generic { - -class Identifier; -class ClassDescriptor; -class MethodDescriptor; - -class TypeParameter; // a formal type parameter declared in generic signatures -class TypeArgument; // The "type value" passed to fill parameters in supertypes -class TypeVariable; // A usage of a type parameter as a value -/** - * Example: - * - * class Foo extends Bar { int m(V v) {} } - * ^^^^^^ ^^^^^^ ^^ - * type parameters type argument type variable - * - * Note that a type variable could be passed as an argument too: - * class Foo extends Bar { int m(V v) {} } - * ^^^ - * type argument's value is a type variable - */ - - -class Type; -class ClassType; -class ArrayType; -class PrimitiveType; -class Context; -class DescriptorCache; - -class DescriptorStream; - -class Identifier : public ResourceObj { - private: - Symbol* _sym; - int _begin; - int _end; - - public: - Identifier(Symbol* sym, int begin, int end) : - _sym(sym), _begin(begin), _end(end) {} - - bool equals(Identifier* other); - bool equals(Symbol* sym); - -#ifndef PRODUCT - void print_on(outputStream* str) const; -#endif // ndef PRODUCT -}; - -class Descriptor : public ResourceObj { - protected: - GrowableArray _type_parameters; - ClassDescriptor* _outer_class; - - Descriptor(GrowableArray& params, - ClassDescriptor* outer) - : _type_parameters(params), _outer_class(outer) {} - - public: - - ClassDescriptor* outer_class() { return _outer_class; } - void set_outer_class(ClassDescriptor* sig) { _outer_class = sig; } - - virtual ClassDescriptor* as_class_signature() { return NULL; } - virtual MethodDescriptor* as_method_signature() { return NULL; } - - bool is_class_signature() { return as_class_signature() != NULL; } - bool is_method_signature() { return as_method_signature() != NULL; } - - GrowableArray& type_parameters() { - return _type_parameters; - } - - TypeParameter* find_type_parameter(Identifier* id, int* param_depth); - - virtual void bind_variables_to_parameters() = 0; - -#ifndef PRODUCT - virtual void print_on(outputStream* str) const = 0; -#endif -}; - -class ClassDescriptor : public Descriptor { - private: - ClassType* _super; - GrowableArray _interfaces; - MethodDescriptor* _outer_method; - - ClassDescriptor(GrowableArray& ftp, ClassType* scs, - GrowableArray& sis, ClassDescriptor* outer_class = NULL, - MethodDescriptor* outer_method = NULL) - : Descriptor(ftp, outer_class), _super(scs), _interfaces(sis), - _outer_method(outer_method) {} - - static u2 get_outer_class_index(InstanceKlass* k, TRAPS); - static ClassDescriptor* parse_generic_signature(Klass* k, Symbol* original_name, TRAPS); - - public: - - virtual ClassDescriptor* as_class_signature() { return this; } - - MethodDescriptor* outer_method() { return _outer_method; } - void set_outer_method(MethodDescriptor* m) { _outer_method = m; } - - ClassType* super() { return _super; } - ClassType* interface_desc(Symbol* sym); - - static ClassDescriptor* parse_generic_signature(Klass* k, TRAPS); - static ClassDescriptor* parse_generic_signature(Symbol* sym); - - // For use in superclass chains in positions where this is no generic info - static ClassDescriptor* placeholder(InstanceKlass* klass); - -#ifndef PRODUCT - void print_on(outputStream* str) const; -#endif - - ClassDescriptor* canonicalize(Context* ctx); - - // Linking sets the position index in any contained TypeVariable type - // to correspond to the location of that identifier in the formal type - // parameters. - void bind_variables_to_parameters(); -}; - -class MethodDescriptor : public Descriptor { - private: - GrowableArray _parameters; - Type* _return_type; - GrowableArray _throws; - - MethodDescriptor(GrowableArray& ftp, ClassDescriptor* outer, - GrowableArray& sigs, Type* rt, GrowableArray& throws) - : Descriptor(ftp, outer), _parameters(sigs), _return_type(rt), - _throws(throws) {} - - public: - - static MethodDescriptor* parse_generic_signature(Method* m, ClassDescriptor* outer); - static MethodDescriptor* parse_generic_signature(Symbol* sym, ClassDescriptor* outer); - - MethodDescriptor* as_method_signature() { return this; } - - // Performs generic analysis on the method parameters to determine - // if both methods refer to the same argument types. - bool covariant_match(MethodDescriptor* other, Context* ctx); - - // Returns a new method descriptor with all generic variables - // removed and replaced with whatever is indicated using the Context. - MethodDescriptor* canonicalize(Context* ctx); - - void bind_variables_to_parameters(); - -#ifndef PRODUCT - TempNewSymbol reify_signature(Context* ctx, TRAPS); - void print_on(outputStream* str) const; -#endif -}; - -class TypeParameter : public ResourceObj { - private: - Identifier* _identifier; - ClassType* _class_bound; - GrowableArray _interface_bounds; - - // The position is the ordinal location of the parameter within the - // formal parameter list (excluding outer classes). It is only set for - // formal type parameters that are associated with a class -- method - // type parameters are left as -1. When resolving a generic variable to - // find the actual type, this index is used to access the generic type - // argument in the provided context object. - int _position; // Assigned during variable linking - - TypeParameter(Identifier* id, ClassType* class_bound, - GrowableArray& interface_bounds) : - _identifier(id), _class_bound(class_bound), - _interface_bounds(interface_bounds), _position(-1) {} - - public: - static TypeParameter* parse_generic_signature(DescriptorStream* str); - - ClassType* bound(); - int position() { return _position; } - - void bind_variables_to_parameters(Descriptor* sig, int position); - Identifier* identifier() { return _identifier; } - - Type* resolve(Context* ctx, int inner_depth, int ctx_depth); - TypeParameter* canonicalize(Context* ctx, int ctx_depth); - -#ifndef PRODUCT - void print_on(outputStream* str) const; -#endif -}; - -class Type : public ResourceObj { - public: - static Type* parse_generic_signature(DescriptorStream* str); - - virtual ClassType* as_class() { return NULL; } - virtual TypeVariable* as_variable() { return NULL; } - virtual ArrayType* as_array() { return NULL; } - virtual PrimitiveType* as_primitive() { return NULL; } - - virtual bool covariant_match(Type* gt, Context* ctx) = 0; - virtual Type* canonicalize(Context* ctx, int ctx_depth) = 0; - - virtual void bind_variables_to_parameters(Descriptor* sig) = 0; - -#ifndef PRODUCT - virtual void reify_signature(stringStream* ss, Context* ctx) = 0; - virtual void print_on(outputStream* str) const = 0; -#endif -}; - -class ClassType : public Type { - friend class ClassDescriptor; - protected: - Identifier* _identifier; - GrowableArray _type_arguments; - ClassType* _outer_class; - - ClassType(Identifier* identifier, - GrowableArray& args, - ClassType* outer) - : _identifier(identifier), _type_arguments(args), _outer_class(outer) {} - - // Returns true if there are inner classes to read - static Identifier* parse_generic_signature_simple( - GrowableArray* args, - bool* has_inner, DescriptorStream* str); - - static ClassType* parse_generic_signature(ClassType* outer, - DescriptorStream* str); - static ClassType* from_symbol(Symbol* sym); - - public: - ClassType* as_class() { return this; } - - static ClassType* parse_generic_signature(DescriptorStream* str); - static ClassType* java_lang_Object(); - - Identifier* identifier() { return _identifier; } - int type_arguments_length() { return _type_arguments.length(); } - TypeArgument* type_argument_at(int i); - - virtual ClassType* outer_class() { return _outer_class; } - - bool covariant_match(Type* gt, Context* ctx); - ClassType* canonicalize(Context* ctx, int context_depth); - - void bind_variables_to_parameters(Descriptor* sig); - -#ifndef PRODUCT - void reify_signature(stringStream* ss, Context* ctx); - void print_on(outputStream* str) const; -#endif -}; - -class TypeVariable : public Type { - private: - Identifier* _id; - TypeParameter* _parameter; // assigned during linking - - // how many steps "out" from inner classes, -1 if method - int _inner_depth; - - TypeVariable(Identifier* id) - : _id(id), _parameter(NULL), _inner_depth(0) {} - - public: - TypeVariable* as_variable() { return this; } - - static TypeVariable* parse_generic_signature(DescriptorStream* str); - - Identifier* identifier() { return _id; } - TypeParameter* parameter() { return _parameter; } - int inner_depth() { return _inner_depth; } - - void bind_variables_to_parameters(Descriptor* sig); - - Type* resolve(Context* ctx, int ctx_depth); - bool covariant_match(Type* gt, Context* ctx); - Type* canonicalize(Context* ctx, int ctx_depth); - -#ifndef PRODUCT - void reify_signature(stringStream* ss, Context* ctx); - void print_on(outputStream* str) const; -#endif -}; - -class ArrayType : public Type { - private: - Type* _base; - - ArrayType(Type* base) : _base(base) {} - - public: - ArrayType* as_array() { return this; } - - static ArrayType* parse_generic_signature(DescriptorStream* str); - - bool covariant_match(Type* gt, Context* ctx); - ArrayType* canonicalize(Context* ctx, int ctx_depth); - - void bind_variables_to_parameters(Descriptor* sig); - -#ifndef PRODUCT - void reify_signature(stringStream* ss, Context* ctx); - void print_on(outputStream* str) const; -#endif -}; - -class PrimitiveType : public Type { - friend class Type; - private: - char _type; // includes V for void - - PrimitiveType(char& type) : _type(type) {} - - public: - PrimitiveType* as_primitive() { return this; } - - bool covariant_match(Type* gt, Context* ctx); - PrimitiveType* canonicalize(Context* ctx, int ctx_depth); - - void bind_variables_to_parameters(Descriptor* sig); - -#ifndef PRODUCT - void reify_signature(stringStream* ss, Context* ctx); - void print_on(outputStream* str) const; -#endif -}; - -class TypeArgument : public ResourceObj { - private: - Type* _lower_bound; - Type* _upper_bound; // may be null or == _lower_bound - - TypeArgument(Type* lower_bound, Type* upper_bound) - : _lower_bound(lower_bound), _upper_bound(upper_bound) {} - - public: - - static TypeArgument* parse_generic_signature(DescriptorStream* str); - - Type* lower_bound() { return _lower_bound; } - Type* upper_bound() { return _upper_bound; } - - void bind_variables_to_parameters(Descriptor* sig); - TypeArgument* canonicalize(Context* ctx, int ctx_depth); - - bool covariant_match(TypeArgument* a, Context* ctx); - -#ifndef PRODUCT - void print_on(outputStream* str) const; -#endif -}; - - -class Context : public ResourceObj { - private: - DescriptorCache* _cache; - GrowableArray _type_arguments; - - void reset_to_mark(int size); - - public: - // When this object goes out of scope or 'destroy' is - // called, then the application of the type to the - // context is wound-back (unless it's been deactivated). - class Mark : public StackObj { - private: - mutable Context* _context; - int _marked_size; - - bool is_active() const { return _context != NULL; } - void deactivate() const { _context = NULL; } - - public: - Mark() : _context(NULL), _marked_size(0) {} - Mark(Context* ctx, int sz) : _context(ctx), _marked_size(sz) {} - Mark(const Mark& m) : _context(m._context), _marked_size(m._marked_size) { - m.deactivate(); // Ownership is transferred - } - - Mark& operator=(const Mark& cm) { - destroy(); - _context = cm._context; - _marked_size = cm._marked_size; - cm.deactivate(); - return *this; - } - - void destroy(); - ~Mark() { destroy(); } - }; - - Context(DescriptorCache* cache) : _cache(cache) {} - - Mark mark() { return Mark(this, _type_arguments.length()); } - void apply_type_arguments(InstanceKlass* current, InstanceKlass* super,TRAPS); - - ClassType* at_depth(int i) const; - -#ifndef PRODUCT - void print_on(outputStream* str) const; -#endif -}; - -/** - * Contains a cache of descriptors for classes and methods so they can be - * looked-up instead of reparsing each time they are needed. - */ -class DescriptorCache : public ResourceObj { - private: - ResourceHashtable _class_descriptors; - ResourceHashtable _method_descriptors; - - public: - ClassDescriptor* descriptor_for(InstanceKlass* ikh, TRAPS); - - MethodDescriptor* descriptor_for(Method* mh, ClassDescriptor* cd, TRAPS); - // Class descriptor derived from method holder - MethodDescriptor* descriptor_for(Method* mh, TRAPS); -}; - -} // namespace generic - -#endif // SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP - diff --git a/hotspot/src/share/vm/classfile/verifier.cpp b/hotspot/src/share/vm/classfile/verifier.cpp index 015b8093d21..7134e7cdb26 100644 --- a/hotspot/src/share/vm/classfile/verifier.cpp +++ b/hotspot/src/share/vm/classfile/verifier.cpp @@ -188,6 +188,10 @@ bool Verifier::verify(instanceKlassHandle klass, Verifier::Mode mode, bool shoul bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class) { Symbol* name = klass->name(); Klass* refl_magic_klass = SystemDictionary::reflect_MagicAccessorImpl_klass(); + Klass* lambda_magic_klass = SystemDictionary::lambda_MagicLambdaImpl_klass(); + + bool is_reflect = refl_magic_klass != NULL && klass->is_subtype_of(refl_magic_klass); + bool is_lambda = lambda_magic_klass != NULL && klass->is_subtype_of(lambda_magic_klass); return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class @@ -210,9 +214,9 @@ bool Verifier::is_eligible_for_verification(instanceKlassHandle klass, bool shou // sun/reflect/SerializationConstructorAccessor. // NOTE: this is called too early in the bootstrapping process to be // guarded by Universe::is_gte_jdk14x_version()/UseNewReflection. - (refl_magic_klass == NULL || - !klass->is_subtype_of(refl_magic_klass) || - VerifyReflectionBytecodes) + // Also for lambda generated code, gte jdk8 + (!is_reflect || VerifyReflectionBytecodes) && + (!is_lambda || VerifyLambdaBytecodes) ); } @@ -2318,9 +2322,6 @@ void ClassVerifier::verify_invoke_instructions( types = 1 << JVM_CONSTANT_InvokeDynamic; break; case Bytecodes::_invokespecial: - types = (1 << JVM_CONSTANT_InterfaceMethodref) | - (1 << JVM_CONSTANT_Methodref); - break; case Bytecodes::_invokestatic: types = (_klass->major_version() < STATIC_METHOD_IN_INTERFACE_MAJOR_VERSION) ? (1 << JVM_CONSTANT_Methodref) : 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/codeBlob.cpp b/hotspot/src/share/vm/code/codeBlob.cpp index a855ade0f5f..e377f893ee1 100644 --- a/hotspot/src/share/vm/code/codeBlob.cpp +++ b/hotspot/src/share/vm/code/codeBlob.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, 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 @@ -245,7 +245,7 @@ BufferBlob* BufferBlob::create(const char* name, CodeBuffer* cb) { } -void* BufferBlob::operator new(size_t s, unsigned size) { +void* BufferBlob::operator new(size_t s, unsigned size) throw() { void* p = CodeCache::allocate(size); return p; } @@ -347,14 +347,14 @@ RuntimeStub* RuntimeStub::new_runtime_stub(const char* stub_name, } -void* RuntimeStub::operator new(size_t s, unsigned size) { +void* RuntimeStub::operator new(size_t s, unsigned size) throw() { void* p = CodeCache::allocate(size, true); if (!p) fatal("Initial size of CodeCache is too small"); return p; } // operator new shared by all singletons: -void* SingletonBlob::operator new(size_t s, unsigned size) { +void* SingletonBlob::operator new(size_t s, unsigned size) throw() { void* p = CodeCache::allocate(size, true); if (!p) fatal("Initial size of CodeCache is too small"); return p; diff --git a/hotspot/src/share/vm/code/codeBlob.hpp b/hotspot/src/share/vm/code/codeBlob.hpp index e59ae7f1f89..6587b2d2e51 100644 --- a/hotspot/src/share/vm/code/codeBlob.hpp +++ b/hotspot/src/share/vm/code/codeBlob.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, 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 @@ -209,7 +209,7 @@ class BufferBlob: public CodeBlob { BufferBlob(const char* name, int size); BufferBlob(const char* name, int size, CodeBuffer* cb); - void* operator new(size_t s, unsigned size); + void* operator new(size_t s, unsigned size) throw(); public: // Creation @@ -283,7 +283,7 @@ class RuntimeStub: public CodeBlob { bool caller_must_gc_arguments ); - void* operator new(size_t s, unsigned size); + void* operator new(size_t s, unsigned size) throw(); public: // Creation @@ -321,7 +321,7 @@ class SingletonBlob: public CodeBlob { friend class VMStructs; protected: - void* operator new(size_t s, unsigned size); + void* operator new(size_t s, unsigned size) throw(); public: SingletonBlob( diff --git a/hotspot/src/share/vm/code/debugInfoRec.cpp b/hotspot/src/share/vm/code/debugInfoRec.cpp index eaa7188758d..fa0cb70fc94 100644 --- a/hotspot/src/share/vm/code/debugInfoRec.cpp +++ b/hotspot/src/share/vm/code/debugInfoRec.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, 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 @@ -38,7 +38,7 @@ class DIR_Chunk { int _length; // number of bytes in the stream int _hash; // hash of stream bytes (for quicker reuse) - void* operator new(size_t ignore, DebugInformationRecorder* dir) { + void* operator new(size_t ignore, DebugInformationRecorder* dir) throw() { assert(ignore == sizeof(DIR_Chunk), ""); if (dir->_next_chunk >= dir->_next_chunk_limit) { const int CHUNK = 100; diff --git a/hotspot/src/share/vm/code/nmethod.cpp b/hotspot/src/share/vm/code/nmethod.cpp index 9412feff709..4f8608f08a0 100644 --- a/hotspot/src/share/vm/code/nmethod.cpp +++ b/hotspot/src/share/vm/code/nmethod.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 @@ -93,18 +93,21 @@ HS_DTRACE_PROBE_DECL6(hotspot, compiled__method__unload, #endif bool nmethod::is_compiled_by_c1() const { - if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing - if (is_native_method()) return false; + if (compiler() == NULL) { + return false; + } return compiler()->is_c1(); } bool nmethod::is_compiled_by_c2() const { - if (compiler() == NULL || method() == NULL) return false; // can happen during debug printing - if (is_native_method()) return false; + if (compiler() == NULL) { + return false; + } return compiler()->is_c2(); } bool nmethod::is_compiled_by_shark() const { - if (is_native_method()) return false; - assert(compiler() != NULL, "must be"); + if (compiler() == NULL) { + return false; + } return compiler()->is_shark(); } @@ -800,7 +803,7 @@ nmethod::nmethod( } #endif // def HAVE_DTRACE_H -void* nmethod::operator new(size_t size, int nmethod_size) throw () { +void* nmethod::operator new(size_t size, int nmethod_size) throw() { // Not critical, may return null if there is too little continuous memory return CodeCache::allocate(nmethod_size); } @@ -1401,6 +1404,9 @@ bool nmethod::make_not_entrant_or_zombie(unsigned int state) { // nmethods aren't scanned for GC. _oops_are_stale = true; #endif + // the Method may be reclaimed by class unloading now that the + // nmethod is in zombie state + set_method(NULL); } else { assert(state == not_entrant, "other cases may need to be handled differently"); } diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index 3178e90d98a..4929ea820c0 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.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 @@ -265,7 +265,7 @@ class nmethod : public CodeBlob { int comp_level); // helper methods - void* operator new(size_t size, int nmethod_size); + void* operator new(size_t size, int nmethod_size) throw(); const char* reloc_string_for(u_char* begin, u_char* end); // Returns true if this thread changed the state of the nmethod or diff --git a/hotspot/src/share/vm/code/relocInfo.hpp b/hotspot/src/share/vm/code/relocInfo.hpp index 68a7f3a5889..b6adcf68302 100644 --- a/hotspot/src/share/vm/code/relocInfo.hpp +++ b/hotspot/src/share/vm/code/relocInfo.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 @@ -677,7 +677,7 @@ class Relocation VALUE_OBJ_CLASS_SPEC { } public: - void* operator new(size_t size, const RelocationHolder& holder) { + void* operator new(size_t size, const RelocationHolder& holder) throw() { if (size > sizeof(holder._relocbuf)) guarantee_size(); assert((void* const *)holder.reloc() == &holder._relocbuf[0], "ptrs must agree"); return holder.reloc(); diff --git a/hotspot/src/share/vm/code/vtableStubs.cpp b/hotspot/src/share/vm/code/vtableStubs.cpp index b0807145330..0d7b39a0241 100644 --- a/hotspot/src/share/vm/code/vtableStubs.cpp +++ b/hotspot/src/share/vm/code/vtableStubs.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 @@ -49,7 +49,7 @@ VMReg VtableStub::_receiver_location = VMRegImpl::Bad(); static int num_vtable_chunks = 0; -void* VtableStub::operator new(size_t size, int code_size) { +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) diff --git a/hotspot/src/share/vm/code/vtableStubs.hpp b/hotspot/src/share/vm/code/vtableStubs.hpp index d6e755a6ec8..aa95fee763c 100644 --- a/hotspot/src/share/vm/code/vtableStubs.hpp +++ b/hotspot/src/share/vm/code/vtableStubs.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 @@ -46,7 +46,7 @@ class VtableStub { bool _is_vtable_stub; // True if vtable stub, false, is itable stub /* code follows here */ // The vtableStub code - void* operator new(size_t size, int code_size); + void* operator new(size_t size, int code_size) throw(); VtableStub(bool is_vtable_stub, int index) : _next(NULL), _is_vtable_stub(is_vtable_stub), diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 685cd74c70a..e8f57b24e19 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -1718,7 +1718,7 @@ static void codecache_print(bool detailed) CodeCache::print_summary(&s, detailed); } ttyLocker ttyl; - tty->print_cr(s.as_string()); + tty->print(s.as_string()); } // ------------------------------------------------------------------ diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp index eb249a68a34..bd01ec3b602 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectedHeap.cpp @@ -2493,11 +2493,11 @@ void G1CollectedHeap::register_concurrent_cycle_start(jlong start_time) { void G1CollectedHeap::register_concurrent_cycle_end() { if (_concurrent_cycle_started) { - _gc_timer_cm->register_gc_end(os::elapsed_counter()); - if (_cm->has_aborted()) { _gc_tracer_cm->report_concurrent_mode_failure(); } + + _gc_timer_cm->register_gc_end(os::elapsed_counter()); _gc_tracer_cm->report_gc_end(_gc_timer_cm->gc_end(), _gc_timer_cm->time_partitions()); _concurrent_cycle_started = false; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp index 75497e7c37f..178acd26afd 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CollectorPolicy.cpp @@ -168,7 +168,15 @@ G1CollectorPolicy::G1CollectorPolicy() : // Set up the region size and associated fields. Given that the // policy is created before the heap, we have to set this up here, // so it's done as soon as possible. - HeapRegion::setup_heap_region_size(Arguments::min_heap_size()); + + // It would have been natural to pass initial_heap_byte_size() and + // max_heap_byte_size() to setup_heap_region_size() but those have + // not been set up at this point since they should be aligned with + // the region size. So, there is a circular dependency here. We base + // the region size on the heap size, but the heap size should be + // aligned with the region size. To get around this we use the + // unaligned values for the heap. + HeapRegion::setup_heap_region_size(InitialHeapSize, MaxHeapSize); HeapRegionRemSet::setup_remset_size(); G1ErgoVerbose::initialize(); diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index 3a3c99a5edd..e66268885e3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -149,18 +149,11 @@ 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 -void HeapRegion::setup_heap_region_size(uintx min_heap_size) { - // region_size in bytes +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)) { - // We base the automatic calculation on the min heap size. This - // can be problematic if the spread between min and max is quite - // wide, imagine -Xms128m -Xmx32g. But, if we decided it based on - // the max size, the region size might be way too large for the - // min size. Either way, some users might have to set the region - // size manually for some -Xms / -Xmx combos. - - region_size = MAX2(min_heap_size / TARGET_REGION_NUMBER, + size_t average_heap_size = (initial_heap_size + max_heap_size) / 2; + region_size = MAX2(average_heap_size / TARGET_REGION_NUMBER, (uintx) MIN_REGION_SIZE); } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp index 68e58d680c9..097c0b54380 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.hpp @@ -361,7 +361,7 @@ class HeapRegion: public G1OffsetTableContigSpace { // CardsPerRegion). All those fields are considered constant // throughout the JVM's execution, therefore they should only be set // up once during initialization time. - static void setup_heap_region_size(uintx min_heap_size); + static void setup_heap_region_size(size_t initial_heap_size, size_t max_heap_size); enum ClaimValues { InitialClaimValue = 0, diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp index da0c3856dd6..f08b7d1c52e 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcTraceSend.cpp @@ -28,6 +28,7 @@ #include "gc_implementation/shared/gcTrace.hpp" #include "gc_implementation/shared/gcWhen.hpp" #include "gc_implementation/shared/copyFailedInfo.hpp" +#include "runtime/os.hpp" #include "trace/tracing.hpp" #include "trace/traceBackend.hpp" #if INCLUDE_ALL_GCS @@ -54,11 +55,12 @@ void GCTracer::send_garbage_collection_event() const { } void GCTracer::send_reference_stats_event(ReferenceType type, size_t count) const { - EventGCReferenceStatistics e; + EventGCReferenceStatistics e(UNTIMED); if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_type((u1)type); e.set_count(count); + e.set_endtime(os::elapsed_counter()); e.commit(); } } @@ -105,20 +107,22 @@ static TraceStructCopyFailed to_trace_struct(const CopyFailedInfo& cf_info) { } void YoungGCTracer::send_promotion_failed_event(const PromotionFailedInfo& pf_info) const { - EventPromotionFailed e; + EventPromotionFailed e(UNTIMED); if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_data(to_trace_struct(pf_info)); e.set_thread(pf_info.thread()->thread_id()); + e.set_endtime(os::elapsed_counter()); e.commit(); } } // Common to CMS and G1 void OldGCTracer::send_concurrent_mode_failure_event() { - EventConcurrentModeFailure e; + EventConcurrentModeFailure e(UNTIMED); if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); + e.set_endtime(os::elapsed_counter()); e.commit(); } } @@ -136,7 +140,7 @@ void G1NewTracer::send_g1_young_gc_event() { } void G1NewTracer::send_evacuation_info_event(EvacuationInfo* info) { - EventEvacuationInfo e; + EventEvacuationInfo e(UNTIMED); if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_cSetRegions(info->collectionset_regions()); @@ -147,15 +151,17 @@ void G1NewTracer::send_evacuation_info_event(EvacuationInfo* info) { e.set_allocRegionsUsedAfter(info->alloc_regions_used_before() + info->bytes_copied()); e.set_bytesCopied(info->bytes_copied()); e.set_regionsFreed(info->regions_freed()); + e.set_endtime(os::elapsed_counter()); e.commit(); } } void G1NewTracer::send_evacuation_failed_event(const EvacuationFailedInfo& ef_info) const { - EventEvacuationFailed e; + EventEvacuationFailed e(UNTIMED); if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_data(to_trace_struct(ef_info)); + e.set_endtime(os::elapsed_counter()); e.commit(); } } @@ -189,12 +195,13 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { void visit(const GCHeapSummary* heap_summary) const { const VirtualSpaceSummary& heap_space = heap_summary->heap(); - EventGCHeapSummary e; + EventGCHeapSummary e(UNTIMED); if (e.should_commit()) { e.set_gcId(_id); e.set_when((u1)_when); e.set_heapSpace(to_trace_struct(heap_space)); e.set_heapUsed(heap_summary->used()); + e.set_endtime(os::elapsed_counter()); e.commit(); } } @@ -209,7 +216,7 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { const SpaceSummary& from_space = ps_heap_summary->from(); const SpaceSummary& to_space = ps_heap_summary->to(); - EventPSHeapSummary e; + EventPSHeapSummary e(UNTIMED); if (e.should_commit()) { e.set_gcId(_id); e.set_when((u1)_when); @@ -220,6 +227,7 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { e.set_edenSpace(to_trace_struct(ps_heap_summary->eden())); e.set_fromSpace(to_trace_struct(ps_heap_summary->from())); e.set_toSpace(to_trace_struct(ps_heap_summary->to())); + e.set_endtime(os::elapsed_counter()); e.commit(); } } @@ -241,13 +249,14 @@ static TraceStructMetaspaceSizes to_trace_struct(const MetaspaceSizes& sizes) { } void GCTracer::send_meta_space_summary_event(GCWhen::Type when, const MetaspaceSummary& meta_space_summary) const { - EventMetaspaceSummary e; + EventMetaspaceSummary e(UNTIMED); if (e.should_commit()) { e.set_gcId(_shared_gc_info.id()); e.set_when((u1) when); e.set_metaspace(to_trace_struct(meta_space_summary.meta_space())); e.set_dataSpace(to_trace_struct(meta_space_summary.data_space())); e.set_classSpace(to_trace_struct(meta_space_summary.class_space())); + e.set_endtime(os::elapsed_counter()); e.commit(); } } @@ -282,8 +291,6 @@ class PhaseSender : public PhaseVisitor { default: /* Ignore sending this phase */ break; } } - -#undef send_phase }; void GCTracer::send_phase_events(TimePartitions* time_partitions) const { diff --git a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp index a01115d06ef..ad3075c9023 100644 --- a/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp +++ b/hotspot/src/share/vm/gc_implementation/shared/gcUtil.hpp @@ -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 @@ -144,9 +144,9 @@ class AdaptivePaddedAverage : public AdaptiveWeightedAverage { _padded_avg(0.0), _deviation(0.0), _padding(padding) {} // Placement support - void* operator new(size_t ignored, void* p) { return p; } + void* operator new(size_t ignored, void* p) throw() { return p; } // Allocator - void* operator new(size_t size) { return CHeapObj::operator new(size); } + void* operator new(size_t size) throw() { return CHeapObj::operator new(size); } // Accessor float padded_average() const { return _padded_avg; } diff --git a/hotspot/src/share/vm/libadt/port.hpp b/hotspot/src/share/vm/libadt/port.hpp index ad7e77c1a9a..5f712a40222 100644 --- a/hotspot/src/share/vm/libadt/port.hpp +++ b/hotspot/src/share/vm/libadt/port.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, 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 @@ -163,8 +163,8 @@ extern void safe_free (const char *file, unsigned line, void *ptr); extern void *safe_calloc (const char *file, unsigned line, unsigned nitems, unsigned size); extern void *safe_realloc(const char *file, unsigned line, void *ptr, unsigned size); extern char *safe_strdup (const char *file, unsigned line, const char *src); -inline void *operator new( size_t size ) { return malloc(size); } -inline void operator delete( void *ptr ) { free(ptr); } +inline void *operator new( size_t size ) throw() { return malloc(size); } +inline void operator delete( void *ptr ) { free(ptr); } #endif //----------------------------------------------------------------------------- diff --git a/hotspot/src/share/vm/memory/allocation.cpp b/hotspot/src/share/vm/memory/allocation.cpp index 6a80c47385e..36c0d06c3fd 100644 --- a/hotspot/src/share/vm/memory/allocation.cpp +++ b/hotspot/src/share/vm/memory/allocation.cpp @@ -49,19 +49,19 @@ # include "os_bsd.inline.hpp" #endif -void* StackObj::operator new(size_t size) { ShouldNotCallThis(); return 0; } -void StackObj::operator delete(void* p) { ShouldNotCallThis(); } -void* StackObj::operator new [](size_t size) { ShouldNotCallThis(); return 0; } -void StackObj::operator delete [](void* p) { ShouldNotCallThis(); } +void* StackObj::operator new(size_t size) throw() { ShouldNotCallThis(); return 0; } +void StackObj::operator delete(void* p) { ShouldNotCallThis(); } +void* StackObj::operator new [](size_t size) throw() { ShouldNotCallThis(); return 0; } +void StackObj::operator delete [](void* p) { ShouldNotCallThis(); } -void* _ValueObj::operator new(size_t size) { ShouldNotCallThis(); return 0; } -void _ValueObj::operator delete(void* p) { ShouldNotCallThis(); } -void* _ValueObj::operator new [](size_t size) { ShouldNotCallThis(); return 0; } -void _ValueObj::operator delete [](void* p) { ShouldNotCallThis(); } +void* _ValueObj::operator new(size_t size) throw() { ShouldNotCallThis(); return 0; } +void _ValueObj::operator delete(void* p) { ShouldNotCallThis(); } +void* _ValueObj::operator new [](size_t size) throw() { ShouldNotCallThis(); return 0; } +void _ValueObj::operator delete [](void* p) { ShouldNotCallThis(); } void* MetaspaceObj::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, bool read_only, - MetaspaceObj::Type type, TRAPS) { + MetaspaceObj::Type type, TRAPS) throw() { // Klass has it's own operator new return Metaspace::allocate(loader_data, word_size, read_only, type, CHECK_NULL); @@ -80,7 +80,7 @@ void MetaspaceObj::print_address_on(outputStream* st) const { st->print(" {"INTPTR_FORMAT"}", this); } -void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) { +void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flags) throw() { address res; switch (type) { case C_HEAP: @@ -97,12 +97,12 @@ void* ResourceObj::operator new(size_t size, allocation_type type, MEMFLAGS flag return res; } -void* ResourceObj::operator new [](size_t size, allocation_type type, MEMFLAGS flags) { +void* ResourceObj::operator new [](size_t size, allocation_type type, MEMFLAGS flags) throw() { return (address) operator new(size, type, flags); } void* ResourceObj::operator new(size_t size, const std::nothrow_t& nothrow_constant, - allocation_type type, MEMFLAGS flags) { + allocation_type type, MEMFLAGS flags) throw() { //should only call this with std::nothrow, use other operator new() otherwise address res; switch (type) { @@ -121,7 +121,7 @@ void* ResourceObj::operator new(size_t size, const std::nothrow_t& nothrow_cons } void* ResourceObj::operator new [](size_t size, const std::nothrow_t& nothrow_constant, - allocation_type type, MEMFLAGS flags) { + allocation_type type, MEMFLAGS flags) throw() { return (address)operator new(size, nothrow_constant, type, flags); } @@ -370,7 +370,7 @@ class ChunkPoolCleaner : public PeriodicTask { //-------------------------------------------------------------------------------------- // Chunk implementation -void* Chunk::operator new (size_t requested_size, AllocFailType alloc_failmode, size_t length) { +void* Chunk::operator new (size_t requested_size, AllocFailType alloc_failmode, size_t length) throw() { // requested_size is equal to sizeof(Chunk) but in order for the arena // allocations to come out aligned as expected the size must be aligned // to expected arena alignment. @@ -478,18 +478,18 @@ Arena::~Arena() { NOT_PRODUCT(Atomic::dec(&_instance_count);) } -void* Arena::operator new(size_t size) { +void* Arena::operator new(size_t size) throw() { assert(false, "Use dynamic memory type binding"); return NULL; } -void* Arena::operator new (size_t size, const std::nothrow_t& nothrow_constant) { +void* Arena::operator new (size_t size, const std::nothrow_t& nothrow_constant) throw() { assert(false, "Use dynamic memory type binding"); return NULL; } // dynamic memory type binding -void* Arena::operator new(size_t size, MEMFLAGS flags) { +void* Arena::operator new(size_t size, MEMFLAGS flags) throw() { #ifdef ASSERT void* p = (void*)AllocateHeap(size, flags|otArena, CALLER_PC); if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p); @@ -499,7 +499,7 @@ void* Arena::operator new(size_t size, MEMFLAGS flags) { #endif } -void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) { +void* Arena::operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw() { #ifdef ASSERT void* p = os::malloc(size, flags|otArena, CALLER_PC); if (PrintMallocFree) trace_heap_malloc(size, "Arena-new", p); @@ -688,22 +688,22 @@ void* Arena::internal_malloc_4(size_t x) { // define ALLOW_OPERATOR_NEW_USAGE for platform on which global operator new allowed. // #ifndef ALLOW_OPERATOR_NEW_USAGE -void* operator new(size_t size){ +void* operator new(size_t size) throw() { assert(false, "Should not call global operator new"); return 0; } -void* operator new [](size_t size){ +void* operator new [](size_t size) throw() { assert(false, "Should not call global operator new[]"); return 0; } -void* operator new(size_t size, const std::nothrow_t& nothrow_constant){ +void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { assert(false, "Should not call global operator new"); return 0; } -void* operator new [](size_t size, std::nothrow_t& nothrow_constant){ +void* operator new [](size_t size, std::nothrow_t& nothrow_constant) throw() { assert(false, "Should not call global operator new[]"); return 0; } diff --git a/hotspot/src/share/vm/memory/allocation.hpp b/hotspot/src/share/vm/memory/allocation.hpp index d61bc7dcea5..739753311c5 100644 --- a/hotspot/src/share/vm/memory/allocation.hpp +++ b/hotspot/src/share/vm/memory/allocation.hpp @@ -204,12 +204,12 @@ const bool NMT_track_callsite = false; template class CHeapObj ALLOCATION_SUPER_CLASS_SPEC { public: - _NOINLINE_ void* operator new(size_t size, address caller_pc = 0); + _NOINLINE_ void* operator new(size_t size, address caller_pc = 0) throw(); _NOINLINE_ void* operator new (size_t size, const std::nothrow_t& nothrow_constant, - address caller_pc = 0); - _NOINLINE_ void* operator new [](size_t size, address caller_pc = 0); + address caller_pc = 0) throw(); + _NOINLINE_ void* operator new [](size_t size, address caller_pc = 0) throw(); _NOINLINE_ void* operator new [](size_t size, const std::nothrow_t& nothrow_constant, - address caller_pc = 0); + address caller_pc = 0) throw(); void operator delete(void* p); void operator delete [] (void* p); }; @@ -219,9 +219,9 @@ template class CHeapObj ALLOCATION_SUPER_CLASS_SPEC { class StackObj ALLOCATION_SUPER_CLASS_SPEC { private: - void* operator new(size_t size); + void* operator new(size_t size) throw(); void operator delete(void* p); - void* operator new [](size_t size); + void* operator new [](size_t size) throw(); void operator delete [](void* p); }; @@ -245,9 +245,9 @@ class StackObj ALLOCATION_SUPER_CLASS_SPEC { // class _ValueObj { private: - void* operator new(size_t size); + void* operator new(size_t size) throw(); void operator delete(void* p); - void* operator new [](size_t size); + void* operator new [](size_t size) throw(); void operator delete [](void* p); }; @@ -316,7 +316,7 @@ class MetaspaceObj { void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, bool read_only, - Type type, Thread* thread); + Type type, Thread* thread) throw(); // can't use TRAPS from this header file. void operator delete(void* p) { ShouldNotCallThis(); } }; @@ -339,7 +339,7 @@ class Chunk: CHeapObj { Chunk* _next; // Next Chunk in list const size_t _len; // Size of this Chunk public: - void* operator new(size_t size, AllocFailType alloc_failmode, size_t length); + void* operator new(size_t size, AllocFailType alloc_failmode, size_t length) throw(); void operator delete(void* p); Chunk(size_t length); @@ -422,12 +422,12 @@ protected: char* hwm() const { return _hwm; } // new operators - void* operator new (size_t size); - void* operator new (size_t size, const std::nothrow_t& nothrow_constant); + void* operator new (size_t size) throw(); + void* operator new (size_t size, const std::nothrow_t& nothrow_constant) throw(); // dynamic memory type tagging - void* operator new(size_t size, MEMFLAGS flags); - void* operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags); + void* operator new(size_t size, MEMFLAGS flags) throw(); + void* operator new(size_t size, const std::nothrow_t& nothrow_constant, MEMFLAGS flags) throw(); void operator delete(void* p); // Fast allocate in the arena. Common case is: pointer test + increment. @@ -583,44 +583,44 @@ class ResourceObj ALLOCATION_SUPER_CLASS_SPEC { #endif // ASSERT public: - void* operator new(size_t size, allocation_type type, MEMFLAGS flags); - void* operator new [](size_t size, allocation_type type, MEMFLAGS flags); + void* operator new(size_t size, allocation_type type, MEMFLAGS flags) throw(); + void* operator new [](size_t size, allocation_type type, MEMFLAGS flags) throw(); void* operator new(size_t size, const std::nothrow_t& nothrow_constant, - allocation_type type, MEMFLAGS flags); + allocation_type type, MEMFLAGS flags) throw(); void* operator new [](size_t size, const std::nothrow_t& nothrow_constant, - allocation_type type, MEMFLAGS flags); + allocation_type type, MEMFLAGS flags) throw(); - void* operator new(size_t size, Arena *arena) { + void* operator new(size_t size, Arena *arena) throw() { address res = (address)arena->Amalloc(size); DEBUG_ONLY(set_allocation_type(res, ARENA);) return res; } - void* operator new [](size_t size, Arena *arena) { + void* operator new [](size_t size, Arena *arena) throw() { address res = (address)arena->Amalloc(size); DEBUG_ONLY(set_allocation_type(res, ARENA);) return res; } - void* operator new(size_t size) { + void* operator new(size_t size) throw() { address res = (address)resource_allocate_bytes(size); DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);) return res; } - void* operator new(size_t size, const std::nothrow_t& nothrow_constant) { + void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { address res = (address)resource_allocate_bytes(size, AllocFailStrategy::RETURN_NULL); DEBUG_ONLY(if (res != NULL) set_allocation_type(res, RESOURCE_AREA);) return res; } - void* operator new [](size_t size) { + void* operator new [](size_t size) throw() { address res = (address)resource_allocate_bytes(size); DEBUG_ONLY(set_allocation_type(res, RESOURCE_AREA);) return res; } - void* operator new [](size_t size, const std::nothrow_t& nothrow_constant) { + void* operator new [](size_t size, const std::nothrow_t& nothrow_constant) throw() { address res = (address)resource_allocate_bytes(size, AllocFailStrategy::RETURN_NULL); DEBUG_ONLY(if (res != NULL) set_allocation_type(res, RESOURCE_AREA);) return res; diff --git a/hotspot/src/share/vm/memory/allocation.inline.hpp b/hotspot/src/share/vm/memory/allocation.inline.hpp index f59ae5b4f0e..d8f1940a6d4 100644 --- a/hotspot/src/share/vm/memory/allocation.inline.hpp +++ b/hotspot/src/share/vm/memory/allocation.inline.hpp @@ -85,7 +85,7 @@ inline void FreeHeap(void* p, MEMFLAGS memflags = mtInternal) { template void* CHeapObj::operator new(size_t size, - address caller_pc){ + address caller_pc) throw() { void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC)); #ifdef ASSERT if (PrintMallocFree) trace_heap_malloc(size, "CHeapObj-new", p); @@ -94,7 +94,7 @@ template void* CHeapObj::operator new(size_t size, } template void* CHeapObj::operator new (size_t size, - const std::nothrow_t& nothrow_constant, address caller_pc) { + const std::nothrow_t& nothrow_constant, address caller_pc) throw() { void* p = (void*)AllocateHeap(size, F, (caller_pc != 0 ? caller_pc : CALLER_PC), AllocFailStrategy::RETURN_NULL); #ifdef ASSERT @@ -104,12 +104,12 @@ template void* CHeapObj::operator new (size_t size, } template void* CHeapObj::operator new [](size_t size, - address caller_pc){ + address caller_pc) throw() { return CHeapObj::operator new(size, caller_pc); } template void* CHeapObj::operator new [](size_t size, - const std::nothrow_t& nothrow_constant, address caller_pc) { + const std::nothrow_t& nothrow_constant, address caller_pc) throw() { return CHeapObj::operator new(size, nothrow_constant, caller_pc); } diff --git a/hotspot/src/share/vm/memory/filemap.cpp b/hotspot/src/share/vm/memory/filemap.cpp index d036266b00f..8eb5f452495 100644 --- a/hotspot/src/share/vm/memory/filemap.cpp +++ b/hotspot/src/share/vm/memory/filemap.cpp @@ -55,6 +55,7 @@ static void fail(const char *msg, va_list ap) { " shared archive file.\n"); jio_vfprintf(defaultStream::error_stream(), msg, ap); jio_fprintf(defaultStream::error_stream(), "\n"); + // Do not change the text of the below message because some tests check for it. vm_exit_during_initialization("Unable to use shared archive.", NULL); } diff --git a/hotspot/src/share/vm/memory/memRegion.cpp b/hotspot/src/share/vm/memory/memRegion.cpp index baabdb8781c..9eb2be56930 100644 --- a/hotspot/src/share/vm/memory/memRegion.cpp +++ b/hotspot/src/share/vm/memory/memRegion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, 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 @@ -102,11 +102,11 @@ MemRegion MemRegion::minus(const MemRegion mr2) const { return MemRegion(); } -void* MemRegion::operator new(size_t size) { +void* MemRegion::operator new(size_t size) throw() { return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL); } -void* MemRegion::operator new [](size_t size) { +void* MemRegion::operator new [](size_t size) throw() { return (address)AllocateHeap(size, mtGC, 0, AllocFailStrategy::RETURN_NULL); } void MemRegion::operator delete(void* p) { diff --git a/hotspot/src/share/vm/memory/memRegion.hpp b/hotspot/src/share/vm/memory/memRegion.hpp index 600d27533e8..9a72fac756e 100644 --- a/hotspot/src/share/vm/memory/memRegion.hpp +++ b/hotspot/src/share/vm/memory/memRegion.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 @@ -94,8 +94,8 @@ public: size_t word_size() const { return _word_size; } bool is_empty() const { return word_size() == 0; } - void* operator new(size_t size); - void* operator new [](size_t size); + void* operator new(size_t size) throw(); + void* operator new [](size_t size) throw(); void operator delete(void* p); void operator delete [](void* p); }; @@ -111,13 +111,13 @@ public: class MemRegionClosureRO: public MemRegionClosure { public: - void* operator new(size_t size, ResourceObj::allocation_type type, MEMFLAGS flags) { + void* operator new(size_t size, ResourceObj::allocation_type type, MEMFLAGS flags) throw() { return ResourceObj::operator new(size, type, flags); } - void* operator new(size_t size, Arena *arena) { + void* operator new(size_t size, Arena *arena) throw() { return ResourceObj::operator new(size, arena); } - void* operator new(size_t size) { + void* operator new(size_t size) throw() { return ResourceObj::operator new(size); } 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/klass.cpp b/hotspot/src/share/vm/oops/klass.cpp index 41d5ec31c73..cf24783fbf8 100644 --- a/hotspot/src/share/vm/oops/klass.cpp +++ b/hotspot/src/share/vm/oops/klass.cpp @@ -139,7 +139,7 @@ Method* Klass::uncached_lookup_method(Symbol* name, Symbol* signature) const { return NULL; } -void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) { +void* Klass::operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw() { return Metaspace::allocate(loader_data, word_size, /*read_only*/false, MetaspaceObj::ClassType, CHECK_NULL); } diff --git a/hotspot/src/share/vm/oops/klass.hpp b/hotspot/src/share/vm/oops/klass.hpp index 9e96dafe235..83bf44561b2 100644 --- a/hotspot/src/share/vm/oops/klass.hpp +++ b/hotspot/src/share/vm/oops/klass.hpp @@ -179,7 +179,7 @@ class Klass : public Metadata { // Constructor Klass(); - void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS); + void* operator new(size_t size, ClassLoaderData* loader_data, size_t word_size, TRAPS) throw(); public: bool is_klass() const volatile { return true; } diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 7082e72510e..b8e60a774f3 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -720,11 +720,22 @@ void Method::print_made_not_compilable(int comp_level, bool is_osr, bool report, } } +bool Method::is_always_compilable() const { + // Generated adapters must be compiled + if (is_method_handle_intrinsic() && is_synthetic()) { + assert(!is_not_c1_compilable(), "sanity check"); + assert(!is_not_c2_compilable(), "sanity check"); + return true; + } + + return false; +} + bool Method::is_not_compilable(int comp_level) const { if (number_of_breakpoints() > 0) return true; - if (is_method_handle_intrinsic()) - return !is_synthetic(); // the generated adapters must be compiled + if (is_always_compilable()) + return false; if (comp_level == CompLevel_any) return is_not_c1_compilable() || is_not_c2_compilable(); if (is_c1_compile(comp_level)) @@ -736,6 +747,10 @@ bool Method::is_not_compilable(int comp_level) const { // call this when compiler finds that this method is not compilable void Method::set_not_compilable(int comp_level, bool report, const char* reason) { + if (is_always_compilable()) { + // Don't mark a method which should be always compilable + return; + } print_made_not_compilable(comp_level, /*is_osr*/ false, report, reason); if (comp_level == CompLevel_all) { set_not_c1_compilable(); diff --git a/hotspot/src/share/vm/oops/method.hpp b/hotspot/src/share/vm/oops/method.hpp index 250d5c0d65f..faaf5105994 100644 --- a/hotspot/src/share/vm/oops/method.hpp +++ b/hotspot/src/share/vm/oops/method.hpp @@ -796,6 +796,7 @@ class Method : public Metadata { void set_not_osr_compilable_quietly(int comp_level = CompLevel_all) { set_not_osr_compilable(comp_level, false); } + bool is_always_compilable() const; private: void print_made_not_compilable(int comp_level, bool is_osr, bool report, const char* reason); diff --git a/hotspot/src/share/vm/oops/symbol.cpp b/hotspot/src/share/vm/oops/symbol.cpp index f5fdfec9974..2a2c975b6ef 100644 --- a/hotspot/src/share/vm/oops/symbol.cpp +++ b/hotspot/src/share/vm/oops/symbol.cpp @@ -41,19 +41,19 @@ Symbol::Symbol(const u1* name, int length, int refcount) { } } -void* Symbol::operator new(size_t sz, int len, TRAPS) { +void* Symbol::operator new(size_t sz, int len, TRAPS) throw() { int alloc_size = size(len)*HeapWordSize; address res = (address) AllocateHeap(alloc_size, mtSymbol); return res; } -void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) { +void* Symbol::operator new(size_t sz, int len, Arena* arena, TRAPS) throw() { int alloc_size = size(len)*HeapWordSize; address res = (address)arena->Amalloc(alloc_size); return res; } -void* Symbol::operator new(size_t sz, int len, ClassLoaderData* loader_data, TRAPS) { +void* Symbol::operator new(size_t sz, int len, ClassLoaderData* loader_data, TRAPS) throw() { address res; int alloc_size = size(len)*HeapWordSize; res = (address) Metaspace::allocate(loader_data, size(len), true, diff --git a/hotspot/src/share/vm/oops/symbol.hpp b/hotspot/src/share/vm/oops/symbol.hpp index a71bdd454c3..f9db8d39974 100644 --- a/hotspot/src/share/vm/oops/symbol.hpp +++ b/hotspot/src/share/vm/oops/symbol.hpp @@ -136,9 +136,9 @@ class Symbol : private SymbolBase { } Symbol(const u1* name, int length, int refcount); - void* operator new(size_t size, int len, TRAPS); - void* operator new(size_t size, int len, Arena* arena, TRAPS); - void* operator new(size_t size, int len, ClassLoaderData* loader_data, TRAPS); + void* operator new(size_t size, int len, TRAPS) throw(); + void* operator new(size_t size, int len, Arena* arena, TRAPS) throw(); + void* operator new(size_t size, int len, ClassLoaderData* loader_data, TRAPS) throw(); void operator delete(void* p); diff --git a/hotspot/src/share/vm/opto/block.cpp b/hotspot/src/share/vm/opto/block.cpp index 5a6b791b24a..fade19bdb6b 100644 --- a/hotspot/src/share/vm/opto/block.cpp +++ b/hotspot/src/share/vm/opto/block.cpp @@ -112,9 +112,9 @@ uint Block::compute_loop_alignment() { // exceeds OptoLoopAlignment. uint Block::compute_first_inst_size(uint& sum_size, uint inst_cnt, PhaseRegAlloc* ra) { - uint last_inst = _nodes.size(); + uint last_inst = number_of_nodes(); for( uint j = 0; j < last_inst && inst_cnt > 0; j++ ) { - uint inst_size = _nodes[j]->size(ra); + uint inst_size = get_node(j)->size(ra); if( inst_size > 0 ) { inst_cnt--; uint sz = sum_size + inst_size; @@ -131,8 +131,8 @@ uint Block::compute_first_inst_size(uint& sum_size, uint inst_cnt, } uint Block::find_node( const Node *n ) const { - for( uint i = 0; i < _nodes.size(); i++ ) { - if( _nodes[i] == n ) + for( uint i = 0; i < number_of_nodes(); i++ ) { + if( get_node(i) == n ) return i; } ShouldNotReachHere(); @@ -141,7 +141,7 @@ uint Block::find_node( const Node *n ) const { // Find and remove n from block list void Block::find_remove( const Node *n ) { - _nodes.remove(find_node(n)); + remove_node(find_node(n)); } // Return empty status of a block. Empty blocks contain only the head, other @@ -154,10 +154,10 @@ int Block::is_Empty() const { } int success_result = completely_empty; - int end_idx = _nodes.size()-1; + int end_idx = number_of_nodes() - 1; // Check for ending goto - if ((end_idx > 0) && (_nodes[end_idx]->is_MachGoto())) { + if ((end_idx > 0) && (get_node(end_idx)->is_MachGoto())) { success_result = empty_with_goto; end_idx--; } @@ -170,7 +170,7 @@ int Block::is_Empty() const { // Ideal nodes are allowable in empty blocks: skip them Only MachNodes // turn directly into code, because only MachNodes have non-trivial // emit() functions. - while ((end_idx > 0) && !_nodes[end_idx]->is_Mach()) { + while ((end_idx > 0) && !get_node(end_idx)->is_Mach()) { end_idx--; } @@ -209,15 +209,15 @@ bool Block::has_uncommon_code() const { // True if block is low enough frequency or guarded by a test which // mostly does not go here. -bool Block::is_uncommon(PhaseCFG* cfg) const { +bool PhaseCFG::is_uncommon(const Block* block) { // Initial blocks must never be moved, so are never uncommon. - if (head()->is_Root() || head()->is_Start()) return false; + if (block->head()->is_Root() || block->head()->is_Start()) return false; // Check for way-low freq - if( _freq < BLOCK_FREQUENCY(0.00001f) ) return true; + if(block->_freq < BLOCK_FREQUENCY(0.00001f) ) return true; // Look for code shape indicating uncommon_trap or slow path - if (has_uncommon_code()) return true; + if (block->has_uncommon_code()) return true; const float epsilon = 0.05f; const float guard_factor = PROB_UNLIKELY_MAG(4) / (1.f - epsilon); @@ -225,8 +225,8 @@ bool Block::is_uncommon(PhaseCFG* cfg) const { uint freq_preds = 0; uint uncommon_for_freq_preds = 0; - for( uint i=1; iget_block_for_node(pred(i)); + for( uint i=1; i< block->num_preds(); i++ ) { + Block* guard = get_block_for_node(block->pred(i)); // Check to see if this block follows its guard 1 time out of 10000 // or less. // @@ -244,14 +244,14 @@ bool Block::is_uncommon(PhaseCFG* cfg) const { uncommon_preds++; } else { freq_preds++; - if( _freq < guard->_freq * guard_factor ) { + if(block->_freq < guard->_freq * guard_factor ) { uncommon_for_freq_preds++; } } } - if( num_preds() > 1 && + if( block->num_preds() > 1 && // The block is uncommon if all preds are uncommon or - (uncommon_preds == (num_preds()-1) || + (uncommon_preds == (block->num_preds()-1) || // it is uncommon for all frequent preds. uncommon_for_freq_preds == freq_preds) ) { return true; @@ -344,8 +344,8 @@ void Block::dump() const { void Block::dump(const PhaseCFG* cfg) const { dump_head(cfg); - for (uint i=0; i< _nodes.size(); i++) { - _nodes[i]->dump(); + for (uint i=0; i< number_of_nodes(); i++) { + get_node(i)->dump(); } tty->print("\n"); } @@ -434,7 +434,7 @@ uint PhaseCFG::build_cfg() { map_node_to_block(p, bb); map_node_to_block(x, bb); if( x != p ) { // Only for root is x == p - bb->_nodes.push((Node*)x); + bb->push_node((Node*)x); } // Now handle predecessors ++sum; // Count 1 for self block @@ -469,11 +469,11 @@ uint PhaseCFG::build_cfg() { assert( x != proj, "" ); // Map basic block of projection map_node_to_block(proj, pb); - pb->_nodes.push(proj); + pb->push_node(proj); } // Insert self as a child of my predecessor block pb->_succs.map(pb->_num_succs++, get_block_for_node(np)); - assert( pb->_nodes[ pb->_nodes.size() - pb->_num_succs ]->is_block_proj(), + assert( pb->get_node(pb->number_of_nodes() - pb->_num_succs)->is_block_proj(), "too many control users, not a CFG?" ); } } @@ -495,7 +495,7 @@ void PhaseCFG::insert_goto_at(uint block_no, uint succ_no) { // surrounding blocks. float freq = in->_freq * in->succ_prob(succ_no); // get ProjNode corresponding to the succ_no'th successor of the in block - ProjNode* proj = in->_nodes[in->_nodes.size() - in->_num_succs + succ_no]->as_Proj(); + ProjNode* proj = in->get_node(in->number_of_nodes() - in->_num_succs + succ_no)->as_Proj(); // create region for basic block RegionNode* region = new (C) RegionNode(2); region->init_req(1, proj); @@ -507,7 +507,7 @@ void PhaseCFG::insert_goto_at(uint block_no, uint succ_no) { Node* gto = _goto->clone(); // get a new goto node gto->set_req(0, region); // add it to the basic block - block->_nodes.push(gto); + block->push_node(gto); map_node_to_block(gto, block); C->regalloc()->set_bad(gto->_idx); // hook up successor block @@ -527,9 +527,9 @@ void PhaseCFG::insert_goto_at(uint block_no, uint succ_no) { // Does this block end in a multiway branch that cannot have the default case // flipped for another case? static bool no_flip_branch( Block *b ) { - int branch_idx = b->_nodes.size() - b->_num_succs-1; + int branch_idx = b->number_of_nodes() - b->_num_succs-1; if( branch_idx < 1 ) return false; - Node *bra = b->_nodes[branch_idx]; + Node *bra = b->get_node(branch_idx); if( bra->is_Catch() ) return true; if( bra->is_Mach() ) { @@ -550,16 +550,16 @@ static bool no_flip_branch( Block *b ) { void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) { // Find true target int end_idx = b->end_idx(); - int idx = b->_nodes[end_idx+1]->as_Proj()->_con; + int idx = b->get_node(end_idx+1)->as_Proj()->_con; Block *succ = b->_succs[idx]; Node* gto = _goto->clone(); // get a new goto node gto->set_req(0, b->head()); - Node *bp = b->_nodes[end_idx]; - b->_nodes.map(end_idx,gto); // Slam over NeverBranch + Node *bp = b->get_node(end_idx); + b->map_node(gto, end_idx); // Slam over NeverBranch map_node_to_block(gto, b); C->regalloc()->set_bad(gto->_idx); - b->_nodes.pop(); // Yank projections - b->_nodes.pop(); // Yank projections + b->pop_node(); // Yank projections + b->pop_node(); // Yank projections b->_succs.map(0,succ); // Map only successor b->_num_succs = 1; // remap successor's predecessors if necessary @@ -575,8 +575,8 @@ void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) { // Scan through block, yanking dead path from // all regions and phis. dead->head()->del_req(j); - for( int k = 1; dead->_nodes[k]->is_Phi(); k++ ) - dead->_nodes[k]->del_req(j); + for( int k = 1; dead->get_node(k)->is_Phi(); k++ ) + dead->get_node(k)->del_req(j); } // Helper function to move block bx to the slot following b_index. Return @@ -620,7 +620,7 @@ void PhaseCFG::move_to_end(Block *b, uint i) { if (e != Block::not_empty) { if (e == Block::empty_with_goto) { // Remove the goto, but leave the block. - b->_nodes.pop(); + b->pop_node(); } // Mark this block as a connector block, which will cause it to be // ignored in certain functions such as non_connector_successor(). @@ -663,13 +663,13 @@ void PhaseCFG::remove_empty_blocks() { // to give a fake exit path to infinite loops. At this late stage they // need to turn into Goto's so that when you enter the infinite loop you // indeed hang. - if (block->_nodes[block->end_idx()]->Opcode() == Op_NeverBranch) { + if (block->get_node(block->end_idx())->Opcode() == Op_NeverBranch) { convert_NeverBranch_to_Goto(block); } // Look for uncommon blocks and move to end. if (!C->do_freq_based_layout()) { - if (block->is_uncommon(this)) { + if (is_uncommon(block)) { move_to_end(block, i); last--; // No longer check for being uncommon! if (no_flip_branch(block)) { // Fall-thru case must follow? @@ -720,9 +720,9 @@ void PhaseCFG::fixup_flow() { // exchange the true and false targets. if (no_flip_branch(block)) { // Find fall through case - if must fall into its target - int branch_idx = block->_nodes.size() - block->_num_succs; + int branch_idx = block->number_of_nodes() - block->_num_succs; for (uint j2 = 0; j2 < block->_num_succs; j2++) { - const ProjNode* p = block->_nodes[branch_idx + j2]->as_Proj(); + const ProjNode* p = block->get_node(branch_idx + j2)->as_Proj(); if (p->_con == 0) { // successor j2 is fall through case if (block->non_connector_successor(j2) != bnext) { @@ -743,14 +743,14 @@ void PhaseCFG::fixup_flow() { // Remove all CatchProjs for (uint j = 0; j < block->_num_succs; j++) { - block->_nodes.pop(); + block->pop_node(); } } else if (block->_num_succs == 1) { // Block ends in a Goto? if (bnext == bs0) { // We fall into next block; remove the Goto - block->_nodes.pop(); + block->pop_node(); } } else if(block->_num_succs == 2) { // Block ends in a If? @@ -759,9 +759,9 @@ void PhaseCFG::fixup_flow() { // be projections (in any order), the 3rd last node must be // the IfNode (we have excluded other 2-way exits such as // CatchNodes already). - MachNode* iff = block->_nodes[block->_nodes.size() - 3]->as_Mach(); - ProjNode* proj0 = block->_nodes[block->_nodes.size() - 2]->as_Proj(); - ProjNode* proj1 = block->_nodes[block->_nodes.size() - 1]->as_Proj(); + MachNode* iff = block->get_node(block->number_of_nodes() - 3)->as_Mach(); + ProjNode* proj0 = block->get_node(block->number_of_nodes() - 2)->as_Proj(); + ProjNode* proj1 = block->get_node(block->number_of_nodes() - 1)->as_Proj(); // Assert that proj0 and succs[0] match up. Similarly for proj1 and succs[1]. assert(proj0->raw_out(0) == block->_succs[0]->head(), "Mismatch successor 0"); @@ -833,8 +833,8 @@ void PhaseCFG::fixup_flow() { iff->as_MachIf()->negate(); } - block->_nodes.pop(); // Remove IfFalse & IfTrue projections - block->_nodes.pop(); + block->pop_node(); // Remove IfFalse & IfTrue projections + block->pop_node(); } else { // Multi-exit block, e.g. a switch statement @@ -895,13 +895,13 @@ void PhaseCFG::verify() const { // Verify sane CFG for (uint i = 0; i < number_of_blocks(); i++) { Block* block = get_block(i); - uint cnt = block->_nodes.size(); + uint cnt = block->number_of_nodes(); uint j; for (j = 0; j < cnt; j++) { - Node *n = block->_nodes[j]; + Node *n = block->get_node(j); assert(get_block_for_node(n) == block, ""); if (j >= 1 && n->is_Mach() && n->as_Mach()->ideal_Opcode() == Op_CreateEx) { - assert(j == 1 || block->_nodes[j-1]->is_Phi(), "CreateEx must be first instruction in block"); + assert(j == 1 || block->get_node(j-1)->is_Phi(), "CreateEx must be first instruction in block"); } for (uint k = 0; k < n->req(); k++) { Node *def = n->in(k); @@ -930,14 +930,14 @@ void PhaseCFG::verify() const { } j = block->end_idx(); - Node* bp = (Node*)block->_nodes[block->_nodes.size() - 1]->is_block_proj(); + Node* bp = (Node*)block->get_node(block->number_of_nodes() - 1)->is_block_proj(); assert(bp, "last instruction must be a block proj"); - assert(bp == block->_nodes[j], "wrong number of successors for this block"); + assert(bp == block->get_node(j), "wrong number of successors for this block"); if (bp->is_Catch()) { - while (block->_nodes[--j]->is_MachProj()) { + while (block->get_node(--j)->is_MachProj()) { ; } - assert(block->_nodes[j]->is_MachCall(), "CatchProj must follow call"); + assert(block->get_node(j)->is_MachCall(), "CatchProj must follow call"); } else if (bp->is_Mach() && bp->as_Mach()->ideal_Opcode() == Op_If) { assert(block->_num_succs == 2, "Conditional branch must have two targets"); } @@ -1440,9 +1440,9 @@ void Trace::fixup_blocks(PhaseCFG &cfg) { Block *bnext = next(b); Block *bs0 = b->non_connector_successor(0); - MachNode *iff = b->_nodes[b->_nodes.size()-3]->as_Mach(); - ProjNode *proj0 = b->_nodes[b->_nodes.size()-2]->as_Proj(); - ProjNode *proj1 = b->_nodes[b->_nodes.size()-1]->as_Proj(); + MachNode *iff = b->get_node(b->number_of_nodes() - 3)->as_Mach(); + ProjNode *proj0 = b->get_node(b->number_of_nodes() - 2)->as_Proj(); + ProjNode *proj1 = b->get_node(b->number_of_nodes() - 1)->as_Proj(); if (bnext == bs0) { // Fall-thru case in succs[0], should be in succs[1] @@ -1454,8 +1454,8 @@ void Trace::fixup_blocks(PhaseCFG &cfg) { b->_succs.map( 1, tbs0 ); // Flip projections to match targets - b->_nodes.map(b->_nodes.size()-2, proj1); - b->_nodes.map(b->_nodes.size()-1, proj0); + b->map_node(proj1, b->number_of_nodes() - 2); + b->map_node(proj0, b->number_of_nodes() - 1); } } } diff --git a/hotspot/src/share/vm/opto/block.hpp b/hotspot/src/share/vm/opto/block.hpp index 7cc566cf007..e1574691849 100644 --- a/hotspot/src/share/vm/opto/block.hpp +++ b/hotspot/src/share/vm/opto/block.hpp @@ -105,15 +105,53 @@ class CFGElement : public ResourceObj { // any optimization pass. They are created late in the game. class Block : public CFGElement { friend class VMStructs; - public: + +private: // Nodes in this block, in order Node_List _nodes; +public: + + // Get the node at index 'at_index', if 'at_index' is out of bounds return NULL + Node* get_node(uint at_index) const { + return _nodes[at_index]; + } + + // Get the number of nodes in this block + uint number_of_nodes() const { + return _nodes.size(); + } + + // Map a node 'node' to index 'to_index' in the block, if the index is out of bounds the size of the node list is increased + void map_node(Node* node, uint to_index) { + _nodes.map(to_index, node); + } + + // Insert a node 'node' at index 'at_index', moving all nodes that are on a higher index one step, if 'at_index' is out of bounds we crash + void insert_node(Node* node, uint at_index) { + _nodes.insert(at_index, node); + } + + // Remove a node at index 'at_index' + void remove_node(uint at_index) { + _nodes.remove(at_index); + } + + // Push a node 'node' onto the node list + void push_node(Node* node) { + _nodes.push(node); + } + + // Pop the last node off the node list + Node* pop_node() { + return _nodes.pop(); + } + // Basic blocks have a Node which defines Control for all Nodes pinned in // this block. This Node is a RegionNode. Exception-causing Nodes // (division, subroutines) and Phi functions are always pinned. Later, // every Node will get pinned to some block. - Node *head() const { return _nodes[0]; } + Node *head() const { return get_node(0); } // CAUTION: num_preds() is ONE based, so that predecessor numbers match // input edges to Regions and Phis. @@ -274,29 +312,12 @@ class Block : public CFGElement { // Add an instruction to an existing block. It must go after the head // instruction and before the end instruction. - void add_inst( Node *n ) { _nodes.insert(end_idx(),n); } + void add_inst( Node *n ) { insert_node(n, end_idx()); } // Find node in block uint find_node( const Node *n ) const; // Find and remove n from block list void find_remove( const Node *n ); - // helper function that adds caller save registers to MachProjNode - void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe); - // Schedule a call next in the block - uint sched_call(Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_List &worklist, GrowableArray &ready_cnt, MachCallNode *mcall, VectorSet &next_call); - - // Perform basic-block local scheduling - Node *select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &ready_cnt, VectorSet &next_call, uint sched_slot); - void set_next_call( Node *n, VectorSet &next_call, PhaseCFG* cfg); - void needed_for_next_call(Node *this_call, VectorSet &next_call, PhaseCFG* cfg); - bool schedule_local(PhaseCFG *cfg, Matcher &m, GrowableArray &ready_cnt, VectorSet &next_call); - // Cleanup if any code lands between a Call and his Catch - void call_catch_cleanup(PhaseCFG* cfg, Compile *C); - // Detect implicit-null-check opportunities. Basically, find NULL checks - // with suitable memory ops nearby. Use the memory op to do the NULL check. - // I can generate a memory op if there is not one nearby. - void implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowed_reasons); - // Return the empty status of a block enum { not_empty, empty_with_goto, completely_empty }; int is_Empty() const; @@ -328,10 +349,6 @@ class Block : public CFGElement { // Examine block's code shape to predict if it is not commonly executed. bool has_uncommon_code() const; - // Use frequency calculations and code shape to predict if the block - // is uncommon. - bool is_uncommon(PhaseCFG* cfg) const; - #ifndef PRODUCT // Debugging print of basic block void dump_bidx(const Block* orig, outputStream* st = tty) const; @@ -414,6 +431,27 @@ class PhaseCFG : public Phase { // to late. Helper for schedule_late. Block* hoist_to_cheaper_block(Block* LCA, Block* early, Node* self); + bool schedule_local(Block* block, GrowableArray& ready_cnt, VectorSet& next_call); + void set_next_call(Block* block, Node* n, VectorSet& next_call); + void needed_for_next_call(Block* block, Node* this_call, VectorSet& next_call); + + // Perform basic-block local scheduling + Node* select(Block* block, Node_List& worklist, GrowableArray& ready_cnt, VectorSet& next_call, uint sched_slot); + + // Schedule a call next in the block + uint sched_call(Block* block, uint node_cnt, Node_List& worklist, GrowableArray& ready_cnt, MachCallNode* mcall, VectorSet& next_call); + + // Cleanup if any code lands between a Call and his Catch + void call_catch_cleanup(Block* block); + + Node* catch_cleanup_find_cloned_def(Block* use_blk, Node* def, Block* def_blk, int n_clone_idx); + void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Block *def_blk, int n_clone_idx); + + // Detect implicit-null-check opportunities. Basically, find NULL checks + // with suitable memory ops nearby. Use the memory op to do the NULL check. + // I can generate a memory op if there is not one nearby. + void implicit_null_check(Block* block, Node *proj, Node *val, int allowed_reasons); + // Perform a Depth First Search (DFS). // Setup 'vertex' as DFS to vertex mapping. // Setup 'semi' as vertex to DFS mapping. @@ -530,6 +568,10 @@ class PhaseCFG : public Phase { return (_node_to_block_mapping.lookup(node->_idx) != NULL); } + // Use frequency calculations and code shape to predict if the block + // is uncommon. + bool is_uncommon(const Block* block); + #ifdef ASSERT Unique_Node_List _raw_oops; #endif @@ -550,7 +592,7 @@ class PhaseCFG : public Phase { // Insert a node into a block at index and map the node to the block void insert(Block *b, uint idx, Node *n) { - b->_nodes.insert( idx, n ); + b->insert_node(n , idx); map_node_to_block(n, b); } diff --git a/hotspot/src/share/vm/opto/buildOopMap.cpp b/hotspot/src/share/vm/opto/buildOopMap.cpp index 746511114a7..e63be38ed11 100644 --- a/hotspot/src/share/vm/opto/buildOopMap.cpp +++ b/hotspot/src/share/vm/opto/buildOopMap.cpp @@ -121,8 +121,8 @@ struct OopFlow : public ResourceObj { // Given reaching-defs for this block start, compute it for this block end void OopFlow::compute_reach( PhaseRegAlloc *regalloc, int max_reg, Dict *safehash ) { - for( uint i=0; i<_b->_nodes.size(); i++ ) { - Node *n = _b->_nodes[i]; + for( uint i=0; i<_b->number_of_nodes(); i++ ) { + Node *n = _b->get_node(i); if( n->jvms() ) { // Build an OopMap here? JVMState *jvms = n->jvms(); @@ -447,8 +447,8 @@ static void do_liveness(PhaseRegAlloc* regalloc, PhaseCFG* cfg, Block_List* work } // Now walk tmp_live up the block backwards, computing live - for( int k=b->_nodes.size()-1; k>=0; k-- ) { - Node *n = b->_nodes[k]; + for( int k=b->number_of_nodes()-1; k>=0; k-- ) { + Node *n = b->get_node(k); // KILL def'd bits int first = regalloc->get_reg_first(n); int second = regalloc->get_reg_second(n); @@ -544,12 +544,12 @@ static void do_liveness(PhaseRegAlloc* regalloc, PhaseCFG* cfg, Block_List* work for (i = 1; i < cfg->number_of_blocks(); i++) { Block* block = cfg->get_block(i); uint j; - for (j = 1; j < block->_nodes.size(); j++) { - if (block->_nodes[j]->jvms() && (*safehash)[block->_nodes[j]] == NULL) { + for (j = 1; j < block->number_of_nodes(); j++) { + if (block->get_node(j)->jvms() && (*safehash)[block->get_node(j)] == NULL) { break; } } - if (j < block->_nodes.size()) { + if (j < block->number_of_nodes()) { break; } } 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 8cdc4e827cd..0f6b2d16590 100644 --- a/hotspot/src/share/vm/opto/callGenerator.hpp +++ b/hotspot/src/share/vm/opto/callGenerator.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 @@ -260,7 +260,7 @@ class WarmCallInfo : public ResourceObj { // Because WarmInfo objects live over the entire lifetime of the // Compile object, they are allocated into the comp_arena, which // does not get resource marked or reset during the compile process - void *operator new( size_t x, Compile* C ) { return C->comp_arena()->Amalloc(x); } + void *operator new( size_t x, Compile* C ) throw() { return C->comp_arena()->Amalloc(x); } void operator delete( void * ) { } // fast deallocation static WarmCallInfo* always_hot(); diff --git a/hotspot/src/share/vm/opto/callnode.cpp b/hotspot/src/share/vm/opto/callnode.cpp index cce6c5f29b4..594b650decb 100644 --- a/hotspot/src/share/vm/opto/callnode.cpp +++ b/hotspot/src/share/vm/opto/callnode.cpp @@ -458,7 +458,7 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) st->print("={"); uint nf = spobj->n_fields(); if (nf > 0) { - uint first_ind = spobj->first_index(); + uint first_ind = spobj->first_index(mcall->jvms()); Node* fld_node = mcall->in(first_ind); ciField* cifield; if (iklass != NULL) { @@ -1063,7 +1063,6 @@ void SafePointNode::grow_stack(JVMState* jvms, uint grow_by) { int scloff = jvms->scloff(); int endoff = jvms->endoff(); assert(endoff == (int)req(), "no other states or debug info after me"); - assert(jvms->scl_size() == 0, "parsed code should not have scalar objects"); Node* top = Compile::current()->top(); for (uint i = 0; i < grow_by; i++) { ins_req(monoff, top); @@ -1079,32 +1078,31 @@ void SafePointNode::push_monitor(const FastLockNode *lock) { const int MonitorEdges = 2; assert(JVMState::logMonitorEdges == exact_log2(MonitorEdges), "correct MonitorEdges"); assert(req() == jvms()->endoff(), "correct sizing"); - assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects"); int nextmon = jvms()->scloff(); if (GenerateSynchronizationCode) { - add_req(lock->box_node()); - add_req(lock->obj_node()); + ins_req(nextmon, lock->box_node()); + ins_req(nextmon+1, lock->obj_node()); } else { Node* top = Compile::current()->top(); - add_req(top); - add_req(top); + ins_req(nextmon, top); + ins_req(nextmon, top); } - jvms()->set_scloff(nextmon+MonitorEdges); + jvms()->set_scloff(nextmon + MonitorEdges); jvms()->set_endoff(req()); } void SafePointNode::pop_monitor() { // Delete last monitor from debug info - assert((jvms()->scl_size() == 0), "parsed code should not have scalar objects"); debug_only(int num_before_pop = jvms()->nof_monitors()); - const int MonitorEdges = (1<scloff(); int endoff = jvms()->endoff(); int new_scloff = scloff - MonitorEdges; int new_endoff = endoff - MonitorEdges; jvms()->set_scloff(new_scloff); jvms()->set_endoff(new_endoff); - while (scloff > new_scloff) del_req(--scloff); + while (scloff > new_scloff) del_req_ordered(--scloff); assert(jvms()->nof_monitors() == num_before_pop-1, ""); } @@ -1169,13 +1167,12 @@ uint SafePointScalarObjectNode::match_edge(uint idx) const { } SafePointScalarObjectNode* -SafePointScalarObjectNode::clone(int jvms_adj, Dict* sosn_map) const { +SafePointScalarObjectNode::clone(Dict* sosn_map) const { void* cached = (*sosn_map)[(void*)this]; if (cached != NULL) { return (SafePointScalarObjectNode*)cached; } SafePointScalarObjectNode* res = (SafePointScalarObjectNode*)Node::clone(); - res->_first_index += jvms_adj; sosn_map->Insert((void*)this, (void*)res); return res; } diff --git a/hotspot/src/share/vm/opto/callnode.hpp b/hotspot/src/share/vm/opto/callnode.hpp index ebcca023315..699f7e7d0fd 100644 --- a/hotspot/src/share/vm/opto/callnode.hpp +++ b/hotspot/src/share/vm/opto/callnode.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 @@ -216,7 +216,7 @@ public: // Because JVMState objects live over the entire lifetime of the // Compile object, they are allocated into the comp_arena, which // does not get resource marked or reset during the compile process - void *operator new( size_t x, Compile* C ) { return C->comp_arena()->Amalloc(x); } + void *operator new( size_t x, Compile* C ) throw() { return C->comp_arena()->Amalloc(x); } void operator delete( void * ) { } // fast deallocation // Create a new JVMState, ready for abstract interpretation. @@ -449,14 +449,17 @@ public: // at a safepoint. class SafePointScalarObjectNode: public TypeNode { - uint _first_index; // First input edge index of a SafePoint node where + uint _first_index; // First input edge relative index of a SafePoint node where // states of the scalarized object fields are collected. + // It is relative to the last (youngest) jvms->_scloff. uint _n_fields; // Number of non-static fields of the scalarized object. DEBUG_ONLY(AllocateNode* _alloc;) virtual uint hash() const ; // { return NO_HASH; } virtual uint cmp( const Node &n ) const; + uint first_index() const { return _first_index; } + public: SafePointScalarObjectNode(const TypeOopPtr* tp, #ifdef ASSERT @@ -469,7 +472,10 @@ public: virtual const RegMask &out_RegMask() const; virtual uint match_edge(uint idx) const; - uint first_index() const { return _first_index; } + uint first_index(JVMState* jvms) const { + assert(jvms != NULL, "missed JVMS"); + return jvms->scloff() + _first_index; + } uint n_fields() const { return _n_fields; } #ifdef ASSERT @@ -485,7 +491,7 @@ public: // corresponds appropriately to "this" in "new_call". Assumes that // "sosn_map" is a map, specific to the translation of "s" to "new_call", // mapping old SafePointScalarObjectNodes to new, to avoid multiple copies. - SafePointScalarObjectNode* clone(int jvms_adj, Dict* sosn_map) const; + SafePointScalarObjectNode* clone(Dict* sosn_map) const; #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; diff --git a/hotspot/src/share/vm/opto/chaitin.cpp b/hotspot/src/share/vm/opto/chaitin.cpp index c2f8d40b202..a1a0e1c1fb7 100644 --- a/hotspot/src/share/vm/opto/chaitin.cpp +++ b/hotspot/src/share/vm/opto/chaitin.cpp @@ -301,7 +301,7 @@ int PhaseChaitin::clone_projs(Block* b, uint idx, Node* orig, Node* copy, uint& // Copy kill projections after the cloned node Node* kills = proj->clone(); kills->set_req(0, copy); - b->_nodes.insert(idx++, kills); + b->insert_node(kills, idx++); _cfg.map_node_to_block(kills, b); new_lrg(kills, max_lrg_id++); } @@ -682,11 +682,11 @@ void PhaseChaitin::de_ssa() { uint lr_counter = 1; for( uint i = 0; i < _cfg.number_of_blocks(); i++ ) { Block* block = _cfg.get_block(i); - uint cnt = block->_nodes.size(); + uint cnt = block->number_of_nodes(); // Handle all the normal Nodes in the block for( uint j = 0; j < cnt; j++ ) { - Node *n = block->_nodes[j]; + Node *n = block->get_node(j); // Pre-color to the zero live range, or pick virtual register const RegMask &rm = n->out_RegMask(); _lrg_map.map(n->_idx, rm.is_NotEmpty() ? lr_counter++ : 0); @@ -710,8 +710,8 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { Block* block = _cfg.get_block(i); // For all instructions - for (uint j = 1; j < block->_nodes.size(); j++) { - Node* n = block->_nodes[j]; + for (uint j = 1; j < block->number_of_nodes(); j++) { + Node* n = block->get_node(j); uint input_edge_start =1; // Skip control most nodes if (n->is_Mach()) { input_edge_start = n->as_Mach()->oper_input_base(); @@ -1604,7 +1604,7 @@ void PhaseChaitin::fixup_spills() { // For all instructions in block uint last_inst = block->end_idx(); for (uint j = 1; j <= last_inst; j++) { - Node* n = block->_nodes[j]; + Node* n = block->get_node(j); // Dead instruction??? assert( n->outcnt() != 0 ||// Nothing dead after post alloc @@ -1641,7 +1641,7 @@ void PhaseChaitin::fixup_spills() { assert( cisc->oper_input_base() == 2, "Only adding one edge"); cisc->ins_req(1,src); // Requires a memory edge } - block->_nodes.map(j,cisc); // Insert into basic block + block->map_node(cisc, j); // Insert into basic block n->subsume_by(cisc, C); // Correct graph // ++_used_cisc_instructions; @@ -1698,7 +1698,7 @@ Node *PhaseChaitin::find_base_for_derived( Node **derived_base_map, Node *derive // (where top() node is placed). base->init_req(0, _cfg.get_root_node()); Block *startb = _cfg.get_block_for_node(C->top()); - startb->_nodes.insert(startb->find_node(C->top()), base ); + startb->insert_node(base, startb->find_node(C->top())); _cfg.map_node_to_block(base, startb); assert(_lrg_map.live_range_id(base) == 0, "should not have LRG yet"); } @@ -1743,9 +1743,9 @@ Node *PhaseChaitin::find_base_for_derived( Node **derived_base_map, Node *derive // Search the current block for an existing base-Phi Block *b = _cfg.get_block_for_node(derived); for( i = 1; i <= b->end_idx(); i++ ) {// Search for matching Phi - Node *phi = b->_nodes[i]; + Node *phi = b->get_node(i); if( !phi->is_Phi() ) { // Found end of Phis with no match? - b->_nodes.insert( i, base ); // Must insert created Phi here as base + b->insert_node(base, i); // Must insert created Phi here as base _cfg.map_node_to_block(base, b); new_lrg(base,maxlrg++); break; @@ -1786,7 +1786,7 @@ bool PhaseChaitin::stretch_base_pointer_live_ranges(ResourceArea *a) { IndexSet liveout(_live->live(block)); for (uint j = block->end_idx() + 1; j > 1; j--) { - Node* n = block->_nodes[j - 1]; + Node* n = block->get_node(j - 1); // Pre-split compares of loop-phis. Loop-phis form a cycle we would // like to see in the same register. Compare uses the loop-phi and so @@ -1979,8 +1979,8 @@ void PhaseChaitin::dump(const Block *b) const { b->dump_head(&_cfg); // For all instructions - for( uint j = 0; j < b->_nodes.size(); j++ ) - dump(b->_nodes[j]); + for( uint j = 0; j < b->number_of_nodes(); j++ ) + dump(b->get_node(j)); // Print live-out info at end of block if( _live ) { tty->print("Liveout: "); @@ -2271,8 +2271,8 @@ void PhaseChaitin::dump_lrg( uint lidx, bool defs_only ) const { int dump_once = 0; // For all instructions - for( uint j = 0; j < block->_nodes.size(); j++ ) { - Node *n = block->_nodes[j]; + for( uint j = 0; j < block->number_of_nodes(); j++ ) { + Node *n = block->get_node(j); if (_lrg_map.find_const(n) == lidx) { if (!dump_once++) { tty->cr(); diff --git a/hotspot/src/share/vm/opto/coalesce.cpp b/hotspot/src/share/vm/opto/coalesce.cpp index 66fd988c273..bd207b584a1 100644 --- a/hotspot/src/share/vm/opto/coalesce.cpp +++ b/hotspot/src/share/vm/opto/coalesce.cpp @@ -54,9 +54,9 @@ void PhaseCoalesce::dump() const { for( j=0; j_num_succs; j++ ) tty->print("B%d ",b->_succs[j]->_pre_order); tty->print(" IDom: B%d/#%d\n", b->_idom ? b->_idom->_pre_order : 0, b->_dom_depth); - uint cnt = b->_nodes.size(); + uint cnt = b->number_of_nodes(); for( j=0; j_nodes[j]; + Node *n = b->get_node(j); dump( n ); tty->print("\t%s\t",n->Name()); @@ -152,7 +152,7 @@ void PhaseAggressiveCoalesce::insert_copy_with_overlap( Block *b, Node *copy, ui // after the last use. Last use is really first-use on a backwards scan. uint i = b->end_idx()-1; while(1) { - Node *n = b->_nodes[i]; + Node *n = b->get_node(i); // Check for end of virtual copies; this is also the end of the // parallel renaming effort. if (n->_idx < _unique) { @@ -174,7 +174,7 @@ void PhaseAggressiveCoalesce::insert_copy_with_overlap( Block *b, Node *copy, ui // the last kill. Thus it is the first kill on a backwards scan. i = b->end_idx()-1; while (1) { - Node *n = b->_nodes[i]; + Node *n = b->get_node(i); // Check for end of virtual copies; this is also the end of the // parallel renaming effort. if (n->_idx < _unique) { @@ -200,13 +200,13 @@ void PhaseAggressiveCoalesce::insert_copy_with_overlap( Block *b, Node *copy, ui tmp ->set_req(idx,copy->in(idx)); copy->set_req(idx,tmp); // Save source in temp early, before source is killed - b->_nodes.insert(kill_src_idx,tmp); + b->insert_node(tmp, kill_src_idx); _phc._cfg.map_node_to_block(tmp, b); last_use_idx++; } // Insert just after last use - b->_nodes.insert(last_use_idx+1,copy); + b->insert_node(copy, last_use_idx + 1); } void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { @@ -237,8 +237,8 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { Block *b = _phc._cfg.get_block(i); uint cnt = b->num_preds(); // Number of inputs to the Phi - for( uint l = 1; l_nodes.size(); l++ ) { - Node *n = b->_nodes[l]; + for( uint l = 1; lnumber_of_nodes(); l++ ) { + Node *n = b->get_node(l); // Do not use removed-copies, use copied value instead uint ncnt = n->req(); @@ -260,7 +260,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { if (_phc._lrg_map.find(n) == _phc._lrg_map.find(def)) { n->replace_by(def); n->set_req(cidx,NULL); - b->_nodes.remove(l); + b->remove_node(l); l--; continue; } @@ -321,13 +321,13 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { m->as_Mach()->rematerialize()) { copy = m->clone(); // Insert the copy in the basic block, just before us - b->_nodes.insert(l++, copy); + b->insert_node(copy, l++); l += _phc.clone_projs(b, l, m, copy, _phc._lrg_map); } else { const RegMask *rm = C->matcher()->idealreg2spillmask[m->ideal_reg()]; copy = new (C) MachSpillCopyNode(m, *rm, *rm); // Insert the copy in the basic block, just before us - b->_nodes.insert(l++, copy); + b->insert_node(copy, l++); } // Insert the copy in the use-def chain n->set_req(idx, copy); @@ -339,7 +339,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { } // End of is two-adr // Insert a copy at a debug use for a lrg which has high frequency - if (b->_freq < OPTO_DEBUG_SPLIT_FREQ || b->is_uncommon(&_phc._cfg)) { + if (b->_freq < OPTO_DEBUG_SPLIT_FREQ || _phc._cfg.is_uncommon(b)) { // Walk the debug inputs to the node and check for lrg freq JVMState* jvms = n->jvms(); uint debug_start = jvms ? jvms->debug_start() : 999999; @@ -376,7 +376,7 @@ void PhaseAggressiveCoalesce::insert_copies( Matcher &matcher ) { // Insert the copy in the use-def chain n->set_req(inpidx, copy ); // Insert the copy in the basic block, just before us - b->_nodes.insert( l++, copy ); + b->insert_node(copy, l++); // Extend ("register allocate") the names array for the copy. uint max_lrg_id = _phc._lrg_map.max_lrg_id(); _phc.new_lrg(copy, max_lrg_id); @@ -431,8 +431,8 @@ void PhaseAggressiveCoalesce::coalesce( Block *b ) { } // Visit all the Phis in successor block - for( uint k = 1; k_nodes.size(); k++ ) { - Node *n = bs->_nodes[k]; + for( uint k = 1; knumber_of_nodes(); k++ ) { + Node *n = bs->get_node(k); if( !n->is_Phi() ) break; combine_these_two( n, n->in(j) ); } @@ -442,7 +442,7 @@ void PhaseAggressiveCoalesce::coalesce( Block *b ) { // Check _this_ block for 2-address instructions and copies. uint cnt = b->end_idx(); for( i = 1; i_nodes[i]; + Node *n = b->get_node(i); uint idx; // 2-address instructions have a virtual Copy matching their input // to their output @@ -490,10 +490,10 @@ void PhaseConservativeCoalesce::union_helper( Node *lr1_node, Node *lr2_node, ui dst_copy->set_req( didx, src_def ); // Add copy to free list // _phc.free_spillcopy(b->_nodes[bindex]); - assert( b->_nodes[bindex] == dst_copy, "" ); + assert( b->get_node(bindex) == dst_copy, "" ); dst_copy->replace_by( dst_copy->in(didx) ); dst_copy->set_req( didx, NULL); - b->_nodes.remove(bindex); + b->remove_node(bindex); if( bindex < b->_ihrp_index ) b->_ihrp_index--; if( bindex < b->_fhrp_index ) b->_fhrp_index--; @@ -523,8 +523,8 @@ uint PhaseConservativeCoalesce::compute_separating_interferences(Node *dst_copy, bindex2 = b2->end_idx()-1; } // Get prior instruction - assert(bindex2 < b2->_nodes.size(), "index out of bounds"); - Node *x = b2->_nodes[bindex2]; + assert(bindex2 < b2->number_of_nodes(), "index out of bounds"); + Node *x = b2->get_node(bindex2); if( x == prev_copy ) { // Previous copy in copy chain? if( prev_copy == src_copy)// Found end of chain and all interferences break; // So break out of loop @@ -769,14 +769,14 @@ bool PhaseConservativeCoalesce::copy_copy(Node *dst_copy, Node *src_copy, Block // Conservative (but pessimistic) copy coalescing of a single block void PhaseConservativeCoalesce::coalesce( Block *b ) { // Bail out on infrequent blocks - if (b->is_uncommon(&_phc._cfg)) { + if (_phc._cfg.is_uncommon(b)) { return; } // Check this block for copies. for( uint i = 1; iend_idx(); i++ ) { // Check for actual copies on inputs. Coalesce a copy into its // input if use and copy's input are compatible. - Node *copy1 = b->_nodes[i]; + Node *copy1 = b->get_node(i); uint idx1 = copy1->is_Copy(); if( !idx1 ) continue; // Not a copy diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index 39ebf9d0483..8d7e6c9e102 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -1297,6 +1297,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 +1501,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 +1620,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 +1692,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; } @@ -2258,7 +2273,7 @@ void Compile::dump_asm(int *pcs, uint pc_limit) { if (block->is_connector() && !Verbose) { continue; } - n = block->_nodes[0]; + n = block->head(); if (pcs && n->_idx < pc_limit) { tty->print("%3.3x ", pcs[n->_idx]); } else { @@ -2273,12 +2288,12 @@ void Compile::dump_asm(int *pcs, uint pc_limit) { // For all instructions Node *delay = NULL; - for (uint j = 0; j < block->_nodes.size(); j++) { + for (uint j = 0; j < block->number_of_nodes(); j++) { if (VMThread::should_terminate()) { cut_short = true; break; } - n = block->_nodes[j]; + n = block->get_node(j); if (valid_bundle_info(n)) { Bundle* bundle = node_bundling(n); if (bundle->used_in_unconditional_delay()) { diff --git a/hotspot/src/share/vm/opto/compile.hpp b/hotspot/src/share/vm/opto/compile.hpp index 60787464bd0..8d862c24125 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; diff --git a/hotspot/src/share/vm/opto/domgraph.cpp b/hotspot/src/share/vm/opto/domgraph.cpp index 9a98aef28e9..5e1886c24f0 100644 --- a/hotspot/src/share/vm/opto/domgraph.cpp +++ b/hotspot/src/share/vm/opto/domgraph.cpp @@ -211,21 +211,21 @@ class Block_Stack { uint Block_Stack::most_frequent_successor( Block *b ) { uint freq_idx = 0; int eidx = b->end_idx(); - Node *n = b->_nodes[eidx]; + Node *n = b->get_node(eidx); int op = n->is_Mach() ? n->as_Mach()->ideal_Opcode() : n->Opcode(); switch( op ) { case Op_CountedLoopEnd: case Op_If: { // Split frequency amongst children float prob = n->as_MachIf()->_prob; // Is succ[0] the TRUE branch or the FALSE branch? - if( b->_nodes[eidx+1]->Opcode() == Op_IfFalse ) + if( b->get_node(eidx+1)->Opcode() == Op_IfFalse ) prob = 1.0f - prob; freq_idx = prob < PROB_FAIR; // freq=1 for succ[0] < 0.5 prob break; } case Op_Catch: // Split frequency amongst children for( freq_idx = 0; freq_idx < b->_num_succs; freq_idx++ ) - if( b->_nodes[eidx+1+freq_idx]->as_CatchProj()->_con == CatchProjNode::fall_through_index ) + if( b->get_node(eidx+1+freq_idx)->as_CatchProj()->_con == CatchProjNode::fall_through_index ) break; // Handle case of no fall-thru (e.g., check-cast MUST throw an exception) if( freq_idx == b->_num_succs ) freq_idx = 0; diff --git a/hotspot/src/share/vm/opto/gcm.cpp b/hotspot/src/share/vm/opto/gcm.cpp index 3e95535b73e..db60d4d1e60 100644 --- a/hotspot/src/share/vm/opto/gcm.cpp +++ b/hotspot/src/share/vm/opto/gcm.cpp @@ -102,12 +102,12 @@ void PhaseCFG::replace_block_proj_ctrl( Node *n ) { uint j = 0; if (pb->_num_succs != 1) { // More then 1 successor? // Search for successor - uint max = pb->_nodes.size(); + uint max = pb->number_of_nodes(); assert( max > 1, "" ); uint start = max - pb->_num_succs; // Find which output path belongs to projection for (j = start; j < max; j++) { - if( pb->_nodes[j] == in0 ) + if( pb->get_node(j) == in0 ) break; } assert( j < max, "must find" ); @@ -1027,8 +1027,8 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) { Block* least = LCA; double least_freq = least->_freq; uint target = get_latency_for_node(self); - uint start_latency = get_latency_for_node(LCA->_nodes[0]); - uint end_latency = get_latency_for_node(LCA->_nodes[LCA->end_idx()]); + uint start_latency = get_latency_for_node(LCA->head()); + uint end_latency = get_latency_for_node(LCA->get_node(LCA->end_idx())); bool in_latency = (target <= start_latency); const Block* root_block = get_block_for_node(_root); @@ -1049,9 +1049,9 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) { self->dump(); tty->print_cr("# B%d: start latency for [%4d]=%d, end latency for [%4d]=%d, freq=%g", LCA->_pre_order, - LCA->_nodes[0]->_idx, + LCA->head()->_idx, start_latency, - LCA->_nodes[LCA->end_idx()]->_idx, + LCA->get_node(LCA->end_idx())->_idx, end_latency, least_freq); } @@ -1074,14 +1074,14 @@ Block* PhaseCFG::hoist_to_cheaper_block(Block* LCA, Block* early, Node* self) { if (mach && LCA == root_block) break; - uint start_lat = get_latency_for_node(LCA->_nodes[0]); + uint start_lat = get_latency_for_node(LCA->head()); uint end_idx = LCA->end_idx(); - uint end_lat = get_latency_for_node(LCA->_nodes[end_idx]); + uint end_lat = get_latency_for_node(LCA->get_node(end_idx)); double LCA_freq = LCA->_freq; #ifndef PRODUCT if (trace_opto_pipelining()) { tty->print_cr("# B%d: start latency for [%4d]=%d, end latency for [%4d]=%d, freq=%g", - LCA->_pre_order, LCA->_nodes[0]->_idx, start_lat, end_idx, end_lat, LCA_freq); + LCA->_pre_order, LCA->head()->_idx, start_lat, end_idx, end_lat, LCA_freq); } #endif cand_cnt++; @@ -1342,7 +1342,7 @@ void PhaseCFG::global_code_motion() { Node* proj = _matcher._null_check_tests[i]; Node* val = _matcher._null_check_tests[i + 1]; Block* block = get_block_for_node(proj); - block->implicit_null_check(this, proj, val, allowed_reasons); + implicit_null_check(block, proj, val, allowed_reasons); // The implicit_null_check will only perform the transformation // if the null branch is truly uncommon, *and* it leads to an // uncommon trap. Combined with the too_many_traps guards @@ -1363,7 +1363,7 @@ void PhaseCFG::global_code_motion() { visited.Clear(); for (uint i = 0; i < number_of_blocks(); i++) { Block* block = get_block(i); - if (!block->schedule_local(this, _matcher, ready_cnt, visited)) { + if (!schedule_local(block, ready_cnt, visited)) { if (!C->failure_reason_is(C2Compiler::retry_no_subsuming_loads())) { C->record_method_not_compilable("local schedule failed"); } @@ -1375,7 +1375,7 @@ void PhaseCFG::global_code_motion() { // clone the instructions on all paths below the Catch. for (uint i = 0; i < number_of_blocks(); i++) { Block* block = get_block(i); - block->call_catch_cleanup(this, C); + call_catch_cleanup(block); } #ifndef PRODUCT @@ -1726,7 +1726,7 @@ void CFGLoop::compute_freq() { // Determine the probability of reaching successor 'i' from the receiver block. float Block::succ_prob(uint i) { int eidx = end_idx(); - Node *n = _nodes[eidx]; // Get ending Node + Node *n = get_node(eidx); // Get ending Node int op = n->Opcode(); if (n->is_Mach()) { @@ -1761,7 +1761,7 @@ float Block::succ_prob(uint i) { float prob = n->as_MachIf()->_prob; assert(prob >= 0.0 && prob <= 1.0, "out of range probability"); // If succ[i] is the FALSE branch, invert path info - if( _nodes[i + eidx + 1]->Opcode() == Op_IfFalse ) { + if( get_node(i + eidx + 1)->Opcode() == Op_IfFalse ) { return 1.0f - prob; // not taken } else { return prob; // taken @@ -1773,7 +1773,7 @@ float Block::succ_prob(uint i) { return 1.0f/_num_succs; case Op_Catch: { - const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj(); + const CatchProjNode *ci = get_node(i + eidx + 1)->as_CatchProj(); if (ci->_con == CatchProjNode::fall_through_index) { // Fall-thru path gets the lion's share. return 1.0f - PROB_UNLIKELY_MAG(5)*_num_succs; @@ -1810,7 +1810,7 @@ float Block::succ_prob(uint i) { // Return the number of fall-through candidates for a block int Block::num_fall_throughs() { int eidx = end_idx(); - Node *n = _nodes[eidx]; // Get ending Node + Node *n = get_node(eidx); // Get ending Node int op = n->Opcode(); if (n->is_Mach()) { @@ -1834,7 +1834,7 @@ int Block::num_fall_throughs() { case Op_Catch: { for (uint i = 0; i < _num_succs; i++) { - const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj(); + const CatchProjNode *ci = get_node(i + eidx + 1)->as_CatchProj(); if (ci->_con == CatchProjNode::fall_through_index) { return 1; } @@ -1862,14 +1862,14 @@ int Block::num_fall_throughs() { // Return true if a specific successor could be fall-through target. bool Block::succ_fall_through(uint i) { int eidx = end_idx(); - Node *n = _nodes[eidx]; // Get ending Node + Node *n = get_node(eidx); // Get ending Node int op = n->Opcode(); if (n->is_Mach()) { if (n->is_MachNullCheck()) { // In theory, either side can fall-thru, for simplicity sake, // let's say only the false branch can now. - return _nodes[i + eidx + 1]->Opcode() == Op_IfFalse; + return get_node(i + eidx + 1)->Opcode() == Op_IfFalse; } op = n->as_Mach()->ideal_Opcode(); } @@ -1883,7 +1883,7 @@ bool Block::succ_fall_through(uint i) { return true; case Op_Catch: { - const CatchProjNode *ci = _nodes[i + eidx + 1]->as_CatchProj(); + const CatchProjNode *ci = get_node(i + eidx + 1)->as_CatchProj(); return ci->_con == CatchProjNode::fall_through_index; } @@ -1907,7 +1907,7 @@ bool Block::succ_fall_through(uint i) { // Update the probability of a two-branch to be uncommon void Block::update_uncommon_branch(Block* ub) { int eidx = end_idx(); - Node *n = _nodes[eidx]; // Get ending Node + Node *n = get_node(eidx); // Get ending Node int op = n->as_Mach()->ideal_Opcode(); @@ -1923,7 +1923,7 @@ void Block::update_uncommon_branch(Block* ub) { // If ub is the true path, make the proability small, else // ub is the false path, and make the probability large - bool invert = (_nodes[s + eidx + 1]->Opcode() == Op_IfFalse); + bool invert = (get_node(s + eidx + 1)->Opcode() == Op_IfFalse); // Get existing probability float p = n->as_MachIf()->_prob; diff --git a/hotspot/src/share/vm/opto/generateOptoStub.cpp b/hotspot/src/share/vm/opto/generateOptoStub.cpp index c5ebd5ad524..9b64d1f10e2 100644 --- a/hotspot/src/share/vm/opto/generateOptoStub.cpp +++ b/hotspot/src/share/vm/opto/generateOptoStub.cpp @@ -61,6 +61,7 @@ void GraphKit::gen_stub(address C_function, JVMState* jvms = new (C) JVMState(0); jvms->set_bci(InvocationEntryBci); jvms->set_monoff(max_map); + jvms->set_scloff(max_map); jvms->set_endoff(max_map); { SafePointNode *map = new (C) SafePointNode( max_map, jvms ); diff --git a/hotspot/src/share/vm/opto/graphKit.cpp b/hotspot/src/share/vm/opto/graphKit.cpp index a363b11a5b8..dcdd104ee72 100644 --- a/hotspot/src/share/vm/opto/graphKit.cpp +++ b/hotspot/src/share/vm/opto/graphKit.cpp @@ -1501,6 +1501,25 @@ void GraphKit::pre_barrier(bool do_load, } } +bool GraphKit::can_move_pre_barrier() const { + BarrierSet* bs = Universe::heap()->barrier_set(); + switch (bs->kind()) { + case BarrierSet::G1SATBCT: + case BarrierSet::G1SATBCTLogging: + return true; // Can move it if no safepoint + + case BarrierSet::CardTableModRef: + case BarrierSet::CardTableExtension: + case BarrierSet::ModRef: + return true; // There is no pre-barrier + + case BarrierSet::Other: + default : + ShouldNotReachHere(); + } + return false; +} + void GraphKit::post_barrier(Node* ctl, Node* store, Node* obj, @@ -3551,6 +3570,8 @@ void GraphKit::g1_write_barrier_pre(bool do_load, } else { // In this case both val_type and alias_idx are unused. assert(pre_val != NULL, "must be loaded already"); + // Nothing to be done if pre_val is null. + if (pre_val->bottom_type() == TypePtr::NULL_PTR) return; assert(pre_val->bottom_type()->basic_type() == T_OBJECT, "or we shouldn't be here"); } assert(bt == T_OBJECT, "or we shouldn't be here"); @@ -3595,7 +3616,7 @@ void GraphKit::g1_write_barrier_pre(bool do_load, if (do_load) { // load original value // alias_idx correct?? - pre_val = __ load(no_ctrl, adr, val_type, bt, alias_idx); + pre_val = __ load(__ ctrl(), adr, val_type, bt, alias_idx); } // if (pre_val != NULL) @@ -3804,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) { @@ -3823,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); @@ -3840,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 4d7d96178ae..1fd4e86d2e7 100644 --- a/hotspot/src/share/vm/opto/graphKit.hpp +++ b/hotspot/src/share/vm/opto/graphKit.hpp @@ -695,6 +695,10 @@ class GraphKit : public Phase { void write_barrier_post(Node *store, Node* obj, Node* adr, uint adr_idx, Node* val, bool use_precise); + // Allow reordering of pre-barrier with oop store and/or post-barrier. + // Used for load_store operations which loads old value. + bool can_move_pre_barrier() const; + // G1 pre/post barriers void g1_write_barrier_pre(bool do_load, Node* obj, @@ -832,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/idealGraphPrinter.cpp b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp index 06cecaddbdc..9f67a652eec 100644 --- a/hotspot/src/share/vm/opto/idealGraphPrinter.cpp +++ b/hotspot/src/share/vm/opto/idealGraphPrinter.cpp @@ -639,8 +639,8 @@ void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) // reachable but are in the CFG so add them here. for (uint i = 0; i < C->cfg()->number_of_blocks(); i++) { Block* block = C->cfg()->get_block(i); - for (uint s = 0; s < block->_nodes.size(); s++) { - nodeStack.push(block->_nodes[s]); + for (uint s = 0; s < block->number_of_nodes(); s++) { + nodeStack.push(block->get_node(s)); } } } @@ -713,9 +713,9 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in tail(SUCCESSORS_ELEMENT); head(NODES_ELEMENT); - for (uint s = 0; s < block->_nodes.size(); s++) { + for (uint s = 0; s < block->number_of_nodes(); s++) { begin_elem(NODE_ELEMENT); - print_attr(NODE_ID_PROPERTY, get_node_id(block->_nodes[s])); + print_attr(NODE_ID_PROPERTY, get_node_id(block->get_node(s))); end_elem(); } tail(NODES_ELEMENT); diff --git a/hotspot/src/share/vm/opto/ifg.cpp b/hotspot/src/share/vm/opto/ifg.cpp index 4455cd4571f..db8dbea84d7 100644 --- a/hotspot/src/share/vm/opto/ifg.cpp +++ b/hotspot/src/share/vm/opto/ifg.cpp @@ -319,7 +319,7 @@ void PhaseChaitin::build_ifg_virtual( ) { // value is then removed from the live-ness set and it's inputs are // added to the live-ness set. for (uint j = block->end_idx() + 1; j > 1; j--) { - Node* n = block->_nodes[j - 1]; + Node* n = block->get_node(j - 1); // Get value being defined uint r = _lrg_map.live_range_id(n); @@ -456,7 +456,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // Compute first nonphi node index uint first_inst; for (first_inst = 1; first_inst < last_inst; first_inst++) { - if (!block->_nodes[first_inst]->is_Phi()) { + if (!block->get_node(first_inst)->is_Phi()) { break; } } @@ -464,15 +464,15 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // Spills could be inserted before CreateEx node which should be // first instruction in block after Phis. Move CreateEx up. for (uint insidx = first_inst; insidx < last_inst; insidx++) { - Node *ex = block->_nodes[insidx]; + Node *ex = block->get_node(insidx); if (ex->is_SpillCopy()) { continue; } if (insidx > first_inst && ex->is_Mach() && ex->as_Mach()->ideal_Opcode() == Op_CreateEx) { // If the CreateEx isn't above all the MachSpillCopies // then move it to the top. - block->_nodes.remove(insidx); - block->_nodes.insert(first_inst, ex); + block->remove_node(insidx); + block->insert_node(ex, first_inst); } // Stop once a CreateEx or any other node is found break; @@ -523,7 +523,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // to the live-ness set. uint j; for (j = last_inst + 1; j > 1; j--) { - Node* n = block->_nodes[j - 1]; + Node* n = block->get_node(j - 1); // Get value being defined uint r = _lrg_map.live_range_id(n); @@ -541,7 +541,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { if( !n->is_Proj() || // Could also be a flags-projection of a dead ADD or such. (_lrg_map.live_range_id(def) && !liveout.member(_lrg_map.live_range_id(def)))) { - block->_nodes.remove(j - 1); + block->remove_node(j - 1); if (lrgs(r)._def == n) { lrgs(r)._def = 0; } @@ -605,7 +605,7 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // (j - 1) is index for current instruction 'n' Node *m = n; for (uint i = j; i <= last_inst && m->is_SpillCopy(); ++i) { - m = block->_nodes[i]; + m = block->get_node(i); } if (m == single_use) { lrgs(r)._area = 0.0; @@ -772,20 +772,20 @@ uint PhaseChaitin::build_ifg_physical( ResourceArea *a ) { // Compute high pressure indice; avoid landing in the middle of projnodes j = hrp_index[0]; - if (j < block->_nodes.size() && j < block->end_idx() + 1) { - Node* cur = block->_nodes[j]; + if (j < block->number_of_nodes() && j < block->end_idx() + 1) { + Node* cur = block->get_node(j); while (cur->is_Proj() || (cur->is_MachNullCheck()) || cur->is_Catch()) { j--; - cur = block->_nodes[j]; + cur = block->get_node(j); } } block->_ihrp_index = j; j = hrp_index[1]; - if (j < block->_nodes.size() && j < block->end_idx() + 1) { - Node* cur = block->_nodes[j]; + if (j < block->number_of_nodes() && j < block->end_idx() + 1) { + Node* cur = block->get_node(j); while (cur->is_Proj() || (cur->is_MachNullCheck()) || cur->is_Catch()) { j--; - cur = block->_nodes[j]; + cur = block->get_node(j); } } block->_fhrp_index = j; diff --git a/hotspot/src/share/vm/opto/lcm.cpp b/hotspot/src/share/vm/opto/lcm.cpp index 8d9daa54b86..63deec31b3f 100644 --- a/hotspot/src/share/vm/opto/lcm.cpp +++ b/hotspot/src/share/vm/opto/lcm.cpp @@ -58,14 +58,14 @@ // The proj is the control projection for the not-null case. // The val is the pointer being checked for nullness or // decodeHeapOop_not_null node if it did not fold into address. -void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowed_reasons) { +void PhaseCFG::implicit_null_check(Block* block, Node *proj, Node *val, int allowed_reasons) { // Assume if null check need for 0 offset then always needed // Intel solaris doesn't support any null checks yet and no // mechanism exists (yet) to set the switches at an os_cpu level if( !ImplicitNullChecks || MacroAssembler::needs_explicit_null_check(0)) return; // Make sure the ptr-is-null path appears to be uncommon! - float f = end()->as_MachIf()->_prob; + float f = block->end()->as_MachIf()->_prob; if( proj->Opcode() == Op_IfTrue ) f = 1.0f - f; if( f > PROB_UNLIKELY_MAG(4) ) return; @@ -75,13 +75,13 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // Get the successor block for if the test ptr is non-null Block* not_null_block; // this one goes with the proj Block* null_block; - if (_nodes[_nodes.size()-1] == proj) { - null_block = _succs[0]; - not_null_block = _succs[1]; + if (block->get_node(block->number_of_nodes()-1) == proj) { + null_block = block->_succs[0]; + not_null_block = block->_succs[1]; } else { - assert(_nodes[_nodes.size()-2] == proj, "proj is one or the other"); - not_null_block = _succs[0]; - null_block = _succs[1]; + assert(block->get_node(block->number_of_nodes()-2) == proj, "proj is one or the other"); + not_null_block = block->_succs[0]; + null_block = block->_succs[1]; } while (null_block->is_Empty() == Block::empty_with_goto) { null_block = null_block->_succs[0]; @@ -93,8 +93,8 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // detect failure of this optimization, as in 6366351.) { bool found_trap = false; - for (uint i1 = 0; i1 < null_block->_nodes.size(); i1++) { - Node* nn = null_block->_nodes[i1]; + for (uint i1 = 0; i1 < null_block->number_of_nodes(); i1++) { + Node* nn = null_block->get_node(i1); if (nn->is_MachCall() && nn->as_MachCall()->entry_point() == SharedRuntime::uncommon_trap_blob()->entry_point()) { const Type* trtype = nn->in(TypeFunc::Parms)->bottom_type(); @@ -237,20 +237,20 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe } // Check ctrl input to see if the null-check dominates the memory op - Block *cb = cfg->get_block_for_node(mach); + Block *cb = get_block_for_node(mach); cb = cb->_idom; // Always hoist at least 1 block if( !was_store ) { // Stores can be hoisted only one block - while( cb->_dom_depth > (_dom_depth + 1)) + while( cb->_dom_depth > (block->_dom_depth + 1)) cb = cb->_idom; // Hoist loads as far as we want // The non-null-block should dominate the memory op, too. Live // range spilling will insert a spill in the non-null-block if it is // needs to spill the memory op for an implicit null check. - if (cb->_dom_depth == (_dom_depth + 1)) { + if (cb->_dom_depth == (block->_dom_depth + 1)) { if (cb != not_null_block) continue; cb = cb->_idom; } } - if( cb != this ) continue; + if( cb != block ) continue; // Found a memory user; see if it can be hoisted to check-block uint vidx = 0; // Capture index of value into memop @@ -262,8 +262,8 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe if( is_decoden ) continue; } // Block of memory-op input - Block *inb = cfg->get_block_for_node(mach->in(j)); - Block *b = this; // Start from nul check + Block *inb = get_block_for_node(mach->in(j)); + Block *b = block; // Start from nul check while( b != inb && b->_dom_depth > inb->_dom_depth ) b = b->_idom; // search upwards for input // See if input dominates null check @@ -272,28 +272,28 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe } if( j > 0 ) continue; - Block *mb = cfg->get_block_for_node(mach); + Block *mb = get_block_for_node(mach); // Hoisting stores requires more checks for the anti-dependence case. // Give up hoisting if we have to move the store past any load. if( was_store ) { Block *b = mb; // Start searching here for a local load // mach use (faulting) trying to hoist // n might be blocker to hoisting - while( b != this ) { + while( b != block ) { uint k; - for( k = 1; k < b->_nodes.size(); k++ ) { - Node *n = b->_nodes[k]; + for( k = 1; k < b->number_of_nodes(); k++ ) { + Node *n = b->get_node(k); if( n->needs_anti_dependence_check() && n->in(LoadNode::Memory) == mach->in(StoreNode::Memory) ) break; // Found anti-dependent load } - if( k < b->_nodes.size() ) + if( k < b->number_of_nodes() ) break; // Found anti-dependent load // Make sure control does not do a merge (would have to check allpaths) if( b->num_preds() != 2 ) break; - b = cfg->get_block_for_node(b->pred(1)); // Move up to predecessor block + b = get_block_for_node(b->pred(1)); // Move up to predecessor block } - if( b != this ) continue; + if( b != block ) continue; } // Make sure this memory op is not already being used for a NullCheck @@ -303,7 +303,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // Found a candidate! Pick one with least dom depth - the highest // in the dom tree should be closest to the null check. - if (best == NULL || cfg->get_block_for_node(mach)->_dom_depth < cfg->get_block_for_node(best)->_dom_depth) { + if (best == NULL || get_block_for_node(mach)->_dom_depth < get_block_for_node(best)->_dom_depth) { best = mach; bidx = vidx; } @@ -319,46 +319,45 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe if( is_decoden ) { // Check if we need to hoist decodeHeapOop_not_null first. - Block *valb = cfg->get_block_for_node(val); - if( this != valb && this->_dom_depth < valb->_dom_depth ) { + Block *valb = get_block_for_node(val); + if( block != valb && block->_dom_depth < valb->_dom_depth ) { // Hoist it up to the end of the test block. valb->find_remove(val); - this->add_inst(val); - cfg->map_node_to_block(val, this); + block->add_inst(val); + map_node_to_block(val, block); // DecodeN on x86 may kill flags. Check for flag-killing projections // that also need to be hoisted. for (DUIterator_Fast jmax, j = val->fast_outs(jmax); j < jmax; j++) { Node* n = val->fast_out(j); if( n->is_MachProj() ) { - cfg->get_block_for_node(n)->find_remove(n); - this->add_inst(n); - cfg->map_node_to_block(n, this); + get_block_for_node(n)->find_remove(n); + block->add_inst(n); + map_node_to_block(n, block); } } } } // Hoist the memory candidate up to the end of the test block. - Block *old_block = cfg->get_block_for_node(best); + Block *old_block = get_block_for_node(best); old_block->find_remove(best); - add_inst(best); - cfg->map_node_to_block(best, this); + block->add_inst(best); + map_node_to_block(best, block); // Move the control dependence - if (best->in(0) && best->in(0) == old_block->_nodes[0]) - best->set_req(0, _nodes[0]); + if (best->in(0) && best->in(0) == old_block->head()) + best->set_req(0, block->head()); // Check for flag-killing projections that also need to be hoisted // Should be DU safe because no edge updates. for (DUIterator_Fast jmax, j = best->fast_outs(jmax); j < jmax; j++) { Node* n = best->fast_out(j); if( n->is_MachProj() ) { - cfg->get_block_for_node(n)->find_remove(n); - add_inst(n); - cfg->map_node_to_block(n, this); + get_block_for_node(n)->find_remove(n); + block->add_inst(n); + map_node_to_block(n, block); } } - Compile *C = cfg->C; // proj==Op_True --> ne test; proj==Op_False --> eq test. // One of two graph shapes got matched: // (IfTrue (If (Bool NE (CmpP ptr NULL)))) @@ -368,10 +367,10 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // We need to flip the projections to keep the same semantics. if( proj->Opcode() == Op_IfTrue ) { // Swap order of projections in basic block to swap branch targets - Node *tmp1 = _nodes[end_idx()+1]; - Node *tmp2 = _nodes[end_idx()+2]; - _nodes.map(end_idx()+1, tmp2); - _nodes.map(end_idx()+2, tmp1); + Node *tmp1 = block->get_node(block->end_idx()+1); + Node *tmp2 = block->get_node(block->end_idx()+2); + block->map_node(tmp2, block->end_idx()+1); + block->map_node(tmp1, block->end_idx()+2); Node *tmp = new (C) Node(C->top()); // Use not NULL input tmp1->replace_by(tmp); tmp2->replace_by(tmp1); @@ -384,8 +383,8 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // it as well. Node *old_tst = proj->in(0); MachNode *nul_chk = new (C) MachNullCheckNode(old_tst->in(0),best,bidx); - _nodes.map(end_idx(),nul_chk); - cfg->map_node_to_block(nul_chk, this); + block->map_node(nul_chk, block->end_idx()); + map_node_to_block(nul_chk, block); // Redirect users of old_test to nul_chk for (DUIterator_Last i2min, i2 = old_tst->last_outs(i2min); i2 >= i2min; --i2) old_tst->last_out(i2)->set_req(0, nul_chk); @@ -393,8 +392,8 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe for (uint i3 = 0; i3 < old_tst->req(); i3++) old_tst->set_req(i3, NULL); - cfg->latency_from_uses(nul_chk); - cfg->latency_from_uses(best); + latency_from_uses(nul_chk); + latency_from_uses(best); } @@ -408,7 +407,7 @@ void Block::implicit_null_check(PhaseCFG *cfg, Node *proj, Node *val, int allowe // remaining cases (most), choose the instruction with the greatest latency // (that is, the most number of pseudo-cycles required to the end of the // routine). If there is a tie, choose the instruction with the most inputs. -Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &ready_cnt, VectorSet &next_call, uint sched_slot) { +Node* PhaseCFG::select(Block* block, Node_List &worklist, GrowableArray &ready_cnt, VectorSet &next_call, uint sched_slot) { // If only a single entry on the stack, use it uint cnt = worklist.size(); @@ -442,7 +441,7 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &read } // Final call in a block must be adjacent to 'catch' - Node *e = end(); + Node *e = block->end(); if( e->is_Catch() && e->in(0)->in(0) == n ) continue; @@ -468,7 +467,7 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &read Node* use = n->fast_out(j); // The use is a conditional branch, make them adjacent - if (use->is_MachIf() && cfg->get_block_for_node(use) == this) { + if (use->is_MachIf() && get_block_for_node(use) == block) { found_machif = true; break; } @@ -501,7 +500,7 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &read n_choice = 1; } - uint n_latency = cfg->get_latency_for_node(n); + uint n_latency = get_latency_for_node(n); uint n_score = n->req(); // Many inputs get high score to break ties // Keep best latency found @@ -529,13 +528,13 @@ Node *Block::select(PhaseCFG *cfg, Node_List &worklist, GrowableArray &read //------------------------------set_next_call---------------------------------- -void Block::set_next_call( Node *n, VectorSet &next_call, PhaseCFG* cfg) { +void PhaseCFG::set_next_call(Block* block, Node* n, VectorSet& next_call) { if( next_call.test_set(n->_idx) ) return; for( uint i=0; ilen(); i++ ) { Node *m = n->in(i); if( !m ) continue; // must see all nodes in block that precede call - if (cfg->get_block_for_node(m) == this) { - set_next_call(m, next_call, cfg); + if (get_block_for_node(m) == block) { + set_next_call(block, m, next_call); } } } @@ -546,24 +545,26 @@ void Block::set_next_call( Node *n, VectorSet &next_call, PhaseCFG* cfg) { // next subroutine call get priority - basically it moves things NOT needed // for the next call till after the call. This prevents me from trying to // carry lots of stuff live across a call. -void Block::needed_for_next_call(Node *this_call, VectorSet &next_call, PhaseCFG* cfg) { +void PhaseCFG::needed_for_next_call(Block* block, Node* this_call, VectorSet& next_call) { // Find the next control-defining Node in this block Node* call = NULL; for (DUIterator_Fast imax, i = this_call->fast_outs(imax); i < imax; i++) { Node* m = this_call->fast_out(i); - if(cfg->get_block_for_node(m) == this && // Local-block user + if (get_block_for_node(m) == block && // Local-block user m != this_call && // Not self-start node - m->is_MachCall() ) + m->is_MachCall()) { call = m; break; + } } if (call == NULL) return; // No next call (e.g., block end is near) // Set next-call for all inputs to this call - set_next_call(call, next_call, cfg); + set_next_call(block, call, next_call); } //------------------------------add_call_kills------------------------------------- -void Block::add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe) { +// helper function that adds caller save registers to MachProjNode +static void add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_policy, bool exclude_soe) { // Fill in the kill mask for the call for( OptoReg::Name r = OptoReg::Name(0); r < _last_Mach_Reg; r=OptoReg::add(r,1) ) { if( !regs.Member(r) ) { // Not already defined by the call @@ -579,7 +580,7 @@ void Block::add_call_kills(MachProjNode *proj, RegMask& regs, const char* save_p //------------------------------sched_call------------------------------------- -uint Block::sched_call( Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_List &worklist, GrowableArray &ready_cnt, MachCallNode *mcall, VectorSet &next_call ) { +uint PhaseCFG::sched_call(Block* block, uint node_cnt, Node_List& worklist, GrowableArray& ready_cnt, MachCallNode* mcall, VectorSet& next_call) { RegMask regs; // Schedule all the users of the call right now. All the users are @@ -592,18 +593,18 @@ uint Block::sched_call( Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_Lis ready_cnt.at_put(n->_idx, n_cnt); assert( n_cnt == 0, "" ); // Schedule next to call - _nodes.map(node_cnt++, n); + block->map_node(n, node_cnt++); // Collect defined registers regs.OR(n->out_RegMask()); // Check for scheduling the next control-definer if( n->bottom_type() == Type::CONTROL ) // Warm up next pile of heuristic bits - needed_for_next_call(n, next_call, cfg); + needed_for_next_call(block, n, next_call); // Children of projections are now all ready for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* m = n->fast_out(j); // Get user - if(cfg->get_block_for_node(m) != this) { + if(get_block_for_node(m) != block) { continue; } if( m->is_Phi() ) continue; @@ -617,14 +618,14 @@ uint Block::sched_call( Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_Lis // Act as if the call defines the Frame Pointer. // Certainly the FP is alive and well after the call. - regs.Insert(matcher.c_frame_pointer()); + regs.Insert(_matcher.c_frame_pointer()); // Set all registers killed and not already defined by the call. uint r_cnt = mcall->tf()->range()->cnt(); int op = mcall->ideal_Opcode(); - MachProjNode *proj = new (matcher.C) MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj ); - cfg->map_node_to_block(proj, this); - _nodes.insert(node_cnt++, proj); + MachProjNode *proj = new (C) MachProjNode( mcall, r_cnt+1, RegMask::Empty, MachProjNode::fat_proj ); + map_node_to_block(proj, block); + block->insert_node(proj, node_cnt++); // Select the right register save policy. const char * save_policy; @@ -633,13 +634,13 @@ uint Block::sched_call( Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_Lis case Op_CallLeaf: case Op_CallLeafNoFP: // Calling C code so use C calling convention - save_policy = matcher._c_reg_save_policy; + save_policy = _matcher._c_reg_save_policy; break; case Op_CallStaticJava: case Op_CallDynamicJava: // Calling Java code so use Java calling convention - save_policy = matcher._register_save_policy; + save_policy = _matcher._register_save_policy; break; default: @@ -674,44 +675,46 @@ uint Block::sched_call( Matcher &matcher, PhaseCFG* cfg, uint node_cnt, Node_Lis //------------------------------schedule_local--------------------------------- // Topological sort within a block. Someday become a real scheduler. -bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray &ready_cnt, VectorSet &next_call) { +bool PhaseCFG::schedule_local(Block* block, GrowableArray& ready_cnt, VectorSet& next_call) { // Already "sorted" are the block start Node (as the first entry), and // the block-ending Node and any trailing control projections. We leave // these alone. PhiNodes and ParmNodes are made to follow the block start // Node. Everything else gets topo-sorted. #ifndef PRODUCT - if (cfg->trace_opto_pipelining()) { - tty->print_cr("# --- schedule_local B%d, before: ---", _pre_order); - for (uint i = 0;i < _nodes.size();i++) { + if (trace_opto_pipelining()) { + tty->print_cr("# --- schedule_local B%d, before: ---", block->_pre_order); + for (uint i = 0;i < block->number_of_nodes(); i++) { tty->print("# "); - _nodes[i]->fast_dump(); + block->get_node(i)->fast_dump(); } tty->print_cr("#"); } #endif // RootNode is already sorted - if( _nodes.size() == 1 ) return true; + if (block->number_of_nodes() == 1) { + return true; + } // Move PhiNodes and ParmNodes from 1 to cnt up to the start - uint node_cnt = end_idx(); + uint node_cnt = block->end_idx(); uint phi_cnt = 1; uint i; for( i = 1; iget_node(i); if( n->is_Phi() || // Found a PhiNode or ParmNode - (n->is_Proj() && n->in(0) == head()) ) { + (n->is_Proj() && n->in(0) == block->head()) ) { // Move guy at 'phi_cnt' to the end; makes a hole at phi_cnt - _nodes.map(i,_nodes[phi_cnt]); - _nodes.map(phi_cnt++,n); // swap Phi/Parm up front + block->map_node(block->get_node(phi_cnt), i); + block->map_node(n, phi_cnt++); // swap Phi/Parm up front } else { // All others // Count block-local inputs to 'n' uint cnt = n->len(); // Input count uint local = 0; for( uint j=0; jin(j); - if( m && cfg->get_block_for_node(m) == this && !m->is_top() ) + if( m && get_block_for_node(m) == block && !m->is_top() ) local++; // One more block-local input } ready_cnt.at_put(n->_idx, local); // Count em up @@ -723,7 +726,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & for (uint prec = n->req(); prec < n->len(); prec++) { Node* oop_store = n->in(prec); if (oop_store != NULL) { - assert(cfg->get_block_for_node(oop_store)->_dom_depth <= this->_dom_depth, "oop_store must dominate card-mark"); + assert(get_block_for_node(oop_store)->_dom_depth <= block->_dom_depth, "oop_store must dominate card-mark"); } } } @@ -747,16 +750,16 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & } } } - for(uint i2=i; i2<_nodes.size(); i2++ ) // Trailing guys get zapped count - ready_cnt.at_put(_nodes[i2]->_idx, 0); + for(uint i2=i; i2< block->number_of_nodes(); i2++ ) // Trailing guys get zapped count + ready_cnt.at_put(block->get_node(i2)->_idx, 0); // All the prescheduled guys do not hold back internal nodes uint i3; for(i3 = 0; i3get_node(i3); // Get pre-scheduled for (DUIterator_Fast jmax, j = n->fast_outs(jmax); j < jmax; j++) { Node* m = n->fast_out(j); - if (cfg->get_block_for_node(m) == this) { // Local-block user + if (get_block_for_node(m) == block) { // Local-block user int m_cnt = ready_cnt.at(m->_idx)-1; ready_cnt.at_put(m->_idx, m_cnt); // Fix ready count } @@ -767,7 +770,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & // Make a worklist Node_List worklist; for(uint i4=i3; i4get_node(i4); if( !ready_cnt.at(m->_idx) ) { // Zero ready count? if (m->is_iteratively_computed()) { // Push induction variable increments last to allow other uses @@ -789,15 +792,15 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & } // Warm up the 'next_call' heuristic bits - needed_for_next_call(_nodes[0], next_call, cfg); + needed_for_next_call(block, block->head(), next_call); #ifndef PRODUCT - if (cfg->trace_opto_pipelining()) { - for (uint j=0; j<_nodes.size(); j++) { - Node *n = _nodes[j]; + if (trace_opto_pipelining()) { + for (uint j=0; j< block->number_of_nodes(); j++) { + Node *n = block->get_node(j); int idx = n->_idx; tty->print("# ready cnt:%3d ", ready_cnt.at(idx)); - tty->print("latency:%3d ", cfg->get_latency_for_node(n)); + tty->print("latency:%3d ", get_latency_for_node(n)); tty->print("%4d: %s\n", idx, n->Name()); } } @@ -808,7 +811,7 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & while( worklist.size() ) { // Worklist is not ready #ifndef PRODUCT - if (cfg->trace_opto_pipelining()) { + if (trace_opto_pipelining()) { tty->print("# ready list:"); for( uint i=0; i & #endif // Select and pop a ready guy from worklist - Node* n = select(cfg, worklist, ready_cnt, next_call, phi_cnt); - _nodes.map(phi_cnt++,n); // Schedule him next + Node* n = select(block, worklist, ready_cnt, next_call, phi_cnt); + block->map_node(n, phi_cnt++); // Schedule him next #ifndef PRODUCT - if (cfg->trace_opto_pipelining()) { + if (trace_opto_pipelining()) { tty->print("# select %d: %s", n->_idx, n->Name()); - tty->print(", latency:%d", cfg->get_latency_for_node(n)); + tty->print(", latency:%d", get_latency_for_node(n)); n->dump(); if (Verbose) { tty->print("# ready list:"); @@ -840,26 +843,26 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & #endif if( n->is_MachCall() ) { MachCallNode *mcall = n->as_MachCall(); - phi_cnt = sched_call(matcher, cfg, phi_cnt, worklist, ready_cnt, mcall, next_call); + phi_cnt = sched_call(block, phi_cnt, worklist, ready_cnt, mcall, next_call); continue; } if (n->is_Mach() && n->as_Mach()->has_call()) { RegMask regs; - regs.Insert(matcher.c_frame_pointer()); + regs.Insert(_matcher.c_frame_pointer()); regs.OR(n->out_RegMask()); - MachProjNode *proj = new (matcher.C) MachProjNode( n, 1, RegMask::Empty, MachProjNode::fat_proj ); - cfg->map_node_to_block(proj, this); - _nodes.insert(phi_cnt++, proj); + MachProjNode *proj = new (C) MachProjNode( n, 1, RegMask::Empty, MachProjNode::fat_proj ); + map_node_to_block(proj, block); + block->insert_node(proj, phi_cnt++); - add_call_kills(proj, regs, matcher._c_reg_save_policy, false); + add_call_kills(proj, regs, _matcher._c_reg_save_policy, false); } // Children are now all ready for (DUIterator_Fast i5max, i5 = n->fast_outs(i5max); i5 < i5max; i5++) { Node* m = n->fast_out(i5); // Get user - if (cfg->get_block_for_node(m) != this) { + if (get_block_for_node(m) != block) { continue; } if( m->is_Phi() ) continue; @@ -874,9 +877,8 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & } } - if( phi_cnt != end_idx() ) { + if( phi_cnt != block->end_idx() ) { // did not schedule all. Retry, Bailout, or Die - Compile* C = matcher.C; if (C->subsume_loads() == true && !C->failing()) { // Retry with subsume_loads == false // If this is the first failure, the sentinel string will "stick" @@ -888,12 +890,12 @@ bool Block::schedule_local(PhaseCFG *cfg, Matcher &matcher, GrowableArray & } #ifndef PRODUCT - if (cfg->trace_opto_pipelining()) { + if (trace_opto_pipelining()) { tty->print_cr("#"); tty->print_cr("# after schedule_local"); - for (uint i = 0;i < _nodes.size();i++) { + for (uint i = 0;i < block->number_of_nodes();i++) { tty->print("# "); - _nodes[i]->fast_dump(); + block->get_node(i)->fast_dump(); } tty->cr(); } @@ -919,7 +921,7 @@ static void catch_cleanup_fix_all_inputs(Node *use, Node *old_def, Node *new_def } //------------------------------catch_cleanup_find_cloned_def------------------ -static Node *catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block *def_blk, PhaseCFG* cfg, int n_clone_idx) { +Node* PhaseCFG::catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block *def_blk, int n_clone_idx) { assert( use_blk != def_blk, "Inter-block cleanup only"); // The use is some block below the Catch. Find and return the clone of the def @@ -945,14 +947,14 @@ static Node *catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block *def // PhiNode, the PhiNode uses from the def and IT's uses need fixup. Node_Array inputs = new Node_List(Thread::current()->resource_area()); for(uint k = 1; k < use_blk->num_preds(); k++) { - Block* block = cfg->get_block_for_node(use_blk->pred(k)); - inputs.map(k, catch_cleanup_find_cloned_def(block, def, def_blk, cfg, n_clone_idx)); + Block* block = get_block_for_node(use_blk->pred(k)); + inputs.map(k, catch_cleanup_find_cloned_def(block, def, def_blk, n_clone_idx)); } // Check to see if the use_blk already has an identical phi inserted. // If it exists, it will be at the first position since all uses of a // def are processed together. - Node *phi = use_blk->_nodes[1]; + Node *phi = use_blk->get_node(1); if( phi->is_Phi() ) { fixup = phi; for (uint k = 1; k < use_blk->num_preds(); k++) { @@ -967,8 +969,8 @@ static Node *catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block *def // If an existing PhiNode was not found, make a new one. if (fixup == NULL) { Node *new_phi = PhiNode::make(use_blk->head(), def); - use_blk->_nodes.insert(1, new_phi); - cfg->map_node_to_block(new_phi, use_blk); + use_blk->insert_node(new_phi, 1); + map_node_to_block(new_phi, use_blk); for (uint k = 1; k < use_blk->num_preds(); k++) { new_phi->set_req(k, inputs[k]); } @@ -977,7 +979,7 @@ static Node *catch_cleanup_find_cloned_def(Block *use_blk, Node *def, Block *def } else { // Found the use just below the Catch. Make it use the clone. - fixup = use_blk->_nodes[n_clone_idx]; + fixup = use_blk->get_node(n_clone_idx); } return fixup; @@ -997,36 +999,36 @@ static void catch_cleanup_intra_block(Node *use, Node *def, Block *blk, int beg, for( uint k = 0; k < blk->_num_succs; k++ ) { // Get clone in each successor block Block *sb = blk->_succs[k]; - Node *clone = sb->_nodes[offset_idx+1]; + Node *clone = sb->get_node(offset_idx+1); assert( clone->Opcode() == use->Opcode(), "" ); // Make use-clone reference the def-clone - catch_cleanup_fix_all_inputs(clone, def, sb->_nodes[n_clone_idx]); + catch_cleanup_fix_all_inputs(clone, def, sb->get_node(n_clone_idx)); } } //------------------------------catch_cleanup_inter_block--------------------- // Fix all input edges in use that reference "def". The use is in a different // block than the def. -static void catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Block *def_blk, PhaseCFG* cfg, int n_clone_idx) { +void PhaseCFG::catch_cleanup_inter_block(Node *use, Block *use_blk, Node *def, Block *def_blk, int n_clone_idx) { if( !use_blk ) return; // Can happen if the use is a precedence edge - Node *new_def = catch_cleanup_find_cloned_def(use_blk, def, def_blk, cfg, n_clone_idx); + Node *new_def = catch_cleanup_find_cloned_def(use_blk, def, def_blk, n_clone_idx); catch_cleanup_fix_all_inputs(use, def, new_def); } //------------------------------call_catch_cleanup----------------------------- // If we inserted any instructions between a Call and his CatchNode, // clone the instructions on all paths below the Catch. -void Block::call_catch_cleanup(PhaseCFG* cfg, Compile* C) { +void PhaseCFG::call_catch_cleanup(Block* block) { // End of region to clone - uint end = end_idx(); - if( !_nodes[end]->is_Catch() ) return; + uint end = block->end_idx(); + if( !block->get_node(end)->is_Catch() ) return; // Start of region to clone uint beg = end; - while(!_nodes[beg-1]->is_MachProj() || - !_nodes[beg-1]->in(0)->is_MachCall() ) { + while(!block->get_node(beg-1)->is_MachProj() || + !block->get_node(beg-1)->in(0)->is_MachCall() ) { beg--; assert(beg > 0,"Catch cleanup walking beyond block boundary"); } @@ -1035,15 +1037,15 @@ void Block::call_catch_cleanup(PhaseCFG* cfg, Compile* C) { // Clone along all Catch output paths. Clone area between the 'beg' and // 'end' indices. - for( uint i = 0; i < _num_succs; i++ ) { - Block *sb = _succs[i]; + for( uint i = 0; i < block->_num_succs; i++ ) { + Block *sb = block->_succs[i]; // Clone the entire area; ignoring the edge fixup for now. for( uint j = end; j > beg; j-- ) { // It is safe here to clone a node with anti_dependence // since clones dominate on each path. - Node *clone = _nodes[j-1]->clone(); - sb->_nodes.insert( 1, clone ); - cfg->map_node_to_block(clone, sb); + Node *clone = block->get_node(j-1)->clone(); + sb->insert_node(clone, 1); + map_node_to_block(clone, sb); } } @@ -1051,7 +1053,7 @@ void Block::call_catch_cleanup(PhaseCFG* cfg, Compile* C) { // Fixup edges. Check the def-use info per cloned Node for(uint i2 = beg; i2 < end; i2++ ) { uint n_clone_idx = i2-beg+1; // Index of clone of n in each successor block - Node *n = _nodes[i2]; // Node that got cloned + Node *n = block->get_node(i2); // Node that got cloned // Need DU safe iterator because of edge manipulation in calls. Unique_Node_List *out = new Unique_Node_List(Thread::current()->resource_area()); for (DUIterator_Fast j1max, j1 = n->fast_outs(j1max); j1 < j1max; j1++) { @@ -1060,19 +1062,19 @@ void Block::call_catch_cleanup(PhaseCFG* cfg, Compile* C) { uint max = out->size(); for (uint j = 0; j < max; j++) {// For all users Node *use = out->pop(); - Block *buse = cfg->get_block_for_node(use); + Block *buse = get_block_for_node(use); if( use->is_Phi() ) { for( uint k = 1; k < use->req(); k++ ) if( use->in(k) == n ) { - Block* block = cfg->get_block_for_node(buse->pred(k)); - Node *fixup = catch_cleanup_find_cloned_def(block, n, this, cfg, n_clone_idx); + Block* b = get_block_for_node(buse->pred(k)); + Node *fixup = catch_cleanup_find_cloned_def(b, n, block, n_clone_idx); use->set_req(k, fixup); } } else { - if (this == buse) { - catch_cleanup_intra_block(use, n, this, beg, n_clone_idx); + if (block == buse) { + catch_cleanup_intra_block(use, n, block, beg, n_clone_idx); } else { - catch_cleanup_inter_block(use, buse, n, this, cfg, n_clone_idx); + catch_cleanup_inter_block(use, buse, n, block, n_clone_idx); } } } // End for all users @@ -1081,30 +1083,30 @@ void Block::call_catch_cleanup(PhaseCFG* cfg, Compile* C) { // Remove the now-dead cloned ops for(uint i3 = beg; i3 < end; i3++ ) { - _nodes[beg]->disconnect_inputs(NULL, C); - _nodes.remove(beg); + block->get_node(beg)->disconnect_inputs(NULL, C); + block->remove_node(beg); } // If the successor blocks have a CreateEx node, move it back to the top - for(uint i4 = 0; i4 < _num_succs; i4++ ) { - Block *sb = _succs[i4]; + for(uint i4 = 0; i4 < block->_num_succs; i4++ ) { + Block *sb = block->_succs[i4]; uint new_cnt = end - beg; // Remove any newly created, but dead, nodes. for( uint j = new_cnt; j > 0; j-- ) { - Node *n = sb->_nodes[j]; + Node *n = sb->get_node(j); if (n->outcnt() == 0 && (!n->is_Proj() || n->as_Proj()->in(0)->outcnt() == 1) ){ n->disconnect_inputs(NULL, C); - sb->_nodes.remove(j); + sb->remove_node(j); new_cnt--; } } // If any newly created nodes remain, move the CreateEx node to the top if (new_cnt > 0) { - Node *cex = sb->_nodes[1+new_cnt]; + Node *cex = sb->get_node(1+new_cnt); if( cex->is_Mach() && cex->as_Mach()->ideal_Opcode() == Op_CreateEx ) { - sb->_nodes.remove(1+new_cnt); - sb->_nodes.insert(1,cex); + sb->remove_node(1+new_cnt); + sb->insert_node(cex, 1); } } } diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 22deebb5a83..f7e09c3f89f 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -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); @@ -2756,10 +2761,28 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind newval = _gvn.makecon(TypePtr::NULL_PTR); // Reference stores need a store barrier. - pre_barrier(true /* do_load*/, - control(), base, adr, alias_idx, newval, value_type->make_oopptr(), - NULL /* pre_val*/, - T_OBJECT); + if (kind == LS_xchg) { + // If pre-barrier must execute before the oop store, old value will require do_load here. + if (!can_move_pre_barrier()) { + pre_barrier(true /* do_load*/, + control(), base, adr, alias_idx, newval, value_type->make_oopptr(), + NULL /* pre_val*/, + T_OBJECT); + } // Else move pre_barrier to use load_store value, see below. + } else if (kind == LS_cmpxchg) { + // Same as for newval above: + if (_gvn.type(oldval) == TypePtr::NULL_PTR) { + oldval = _gvn.makecon(TypePtr::NULL_PTR); + } + // The only known value which might get overwritten is oldval. + pre_barrier(false /* do_load */, + control(), NULL, NULL, max_juint, NULL, NULL, + oldval /* pre_val */, + T_OBJECT); + } else { + ShouldNotReachHere(); + } + #ifdef _LP64 if (adr->bottom_type()->is_ptr_to_narrowoop()) { Node *newval_enc = _gvn.transform(new (C) EncodePNode(newval, newval->bottom_type()->make_narrowoop())); @@ -2795,16 +2818,27 @@ bool LibraryCallKit::inline_unsafe_load_store(BasicType type, LoadStoreKind kind Node* proj = _gvn.transform(new (C) SCMemProjNode(load_store)); set_memory(proj, alias_idx); + if (type == T_OBJECT && kind == LS_xchg) { +#ifdef _LP64 + if (adr->bottom_type()->is_ptr_to_narrowoop()) { + load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type())); + } +#endif + if (can_move_pre_barrier()) { + // Don't need to load pre_val. The old value is returned by load_store. + // The pre_barrier can execute after the xchg as long as no safepoint + // gets inserted between them. + pre_barrier(false /* do_load */, + control(), NULL, NULL, max_juint, NULL, NULL, + load_store /* pre_val */, + T_OBJECT); + } + } + // Add the trailing membar surrounding the access insert_mem_bar(Op_MemBarCPUOrder); insert_mem_bar(Op_MemBarAcquire); -#ifdef _LP64 - if (type == T_OBJECT && adr->bottom_type()->is_ptr_to_narrowoop() && kind == LS_xchg) { - load_store = _gvn.transform(new (C) DecodeNNode(load_store, load_store->get_ptr_type())); - } -#endif - assert(type2size[load_store->bottom_type()->basic_type()] == type2size[rtype], "result type should match"); set_result(load_store); return true; diff --git a/hotspot/src/share/vm/opto/live.cpp b/hotspot/src/share/vm/opto/live.cpp index ab7381b639d..280d22204c2 100644 --- a/hotspot/src/share/vm/opto/live.cpp +++ b/hotspot/src/share/vm/opto/live.cpp @@ -85,8 +85,8 @@ void PhaseLive::compute(uint maxlrg) { IndexSet* def = &_defs[block->_pre_order-1]; DEBUG_ONLY(IndexSet *def_outside = getfreeset();) uint i; - for (i = block->_nodes.size(); i > 1; i--) { - Node* n = block->_nodes[i-1]; + for (i = block->number_of_nodes(); i > 1; i--) { + Node* n = block->get_node(i-1); if (n->is_Phi()) { break; } @@ -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->_nodes[k - 1]->_idx]; + uint r = _names[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->_nodes[k-1]->in(l)->_idx], first_pass); + add_liveout(p, _names[block->get_node(k-1)->in(l)->_idx], first_pass); } } freeset(block); @@ -254,10 +254,10 @@ void PhaseLive::add_liveout( Block *p, IndexSet *lo, VectorSet &first_pass ) { void PhaseLive::dump( const Block *b ) const { tty->print("Block %d: ",b->_pre_order); tty->print("LiveOut: "); _live[b->_pre_order-1].dump(); - uint cnt = b->_nodes.size(); + uint cnt = b->number_of_nodes(); for( uint i=0; iprint("L%d/", _names[b->_nodes[i]->_idx] ); - b->_nodes[i]->dump(); + tty->print("L%d/", _names[b->get_node(i)->_idx] ); + b->get_node(i)->dump(); } tty->print("\n"); } @@ -269,7 +269,7 @@ void PhaseChaitin::verify_base_ptrs( ResourceArea *a ) const { for (uint i = 0; i < _cfg.number_of_blocks(); i++) { Block* block = _cfg.get_block(i); for (uint j = block->end_idx() + 1; j > 1; j--) { - Node* n = block->_nodes[j-1]; + Node* n = block->get_node(j-1); if (n->is_Phi()) { break; } diff --git a/hotspot/src/share/vm/opto/machnode.hpp b/hotspot/src/share/vm/opto/machnode.hpp index 5b630e45c84..525135d949b 100644 --- a/hotspot/src/share/vm/opto/machnode.hpp +++ b/hotspot/src/share/vm/opto/machnode.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 @@ -58,7 +58,7 @@ class State; class MachOper : public ResourceObj { public: // Allocate right next to the MachNodes in the same arena - void *operator new( size_t x, Compile* C ) { return C->node_arena()->Amalloc_D(x); } + void *operator new( size_t x, Compile* C ) throw() { return C->node_arena()->Amalloc_D(x); } // Opcode virtual uint opcode() const = 0; diff --git a/hotspot/src/share/vm/opto/macro.cpp b/hotspot/src/share/vm/opto/macro.cpp index 56b9c939147..137c529ed0c 100644 --- a/hotspot/src/share/vm/opto/macro.cpp +++ b/hotspot/src/share/vm/opto/macro.cpp @@ -72,6 +72,8 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal int jvms_adj = new_dbg_start - old_dbg_start; assert (new_dbg_start == newcall->req(), "argument count mismatch"); + // SafePointScalarObject node could be referenced several times in debug info. + // Use Dict to record cloned nodes. Dict* sosn_map = new Dict(cmpkey,hashkey); for (uint i = old_dbg_start; i < oldcall->req(); i++) { Node* old_in = oldcall->in(i); @@ -79,8 +81,8 @@ void PhaseMacroExpand::copy_call_debug_info(CallNode *oldcall, CallNode * newcal if (old_in != NULL && old_in->is_SafePointScalarObject()) { SafePointScalarObjectNode* old_sosn = old_in->as_SafePointScalarObject(); uint old_unique = C->unique(); - Node* new_in = old_sosn->clone(jvms_adj, sosn_map); - if (old_unique != C->unique()) { + Node* new_in = old_sosn->clone(sosn_map); + if (old_unique != C->unique()) { // New node? new_in->set_req(0, C->root()); // reset control edge new_in = transform_later(new_in); // Register new node. } @@ -725,7 +727,11 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray 0) { SafePointNode* sfpt = safepoints.pop(); Node* mem = sfpt->memory(); - uint first_ind = sfpt->req(); + assert(sfpt->jvms() != NULL, "missed JVMS"); + // Fields of scalar objs are referenced only at the end + // of regular debuginfo at the last (youngest) JVMS. + // Record relative start index. + uint first_ind = (sfpt->req() - sfpt->jvms()->scloff()); SafePointScalarObjectNode* sobj = new (C) SafePointScalarObjectNode(res_type, #ifdef ASSERT alloc, @@ -799,7 +805,7 @@ bool PhaseMacroExpand::scalar_replacement(AllocateNode *alloc, GrowableArray in(i)->is_SafePointScalarObject()) { SafePointScalarObjectNode* scobj = sfpt_done->in(i)->as_SafePointScalarObject(); - if (scobj->first_index() == sfpt_done->req() && + if (scobj->first_index(jvms) == sfpt_done->req() && scobj->n_fields() == (uint)nfields) { assert(scobj->alloc() == alloc, "sanity"); sfpt_done->set_req(i, res); diff --git a/hotspot/src/share/vm/opto/memnode.cpp b/hotspot/src/share/vm/opto/memnode.cpp index aa03b5ff6c5..a91c63abc9b 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()) { diff --git a/hotspot/src/share/vm/opto/node.cpp b/hotspot/src/share/vm/opto/node.cpp index f2100040ffe..1df5eb51a8c 100644 --- a/hotspot/src/share/vm/opto/node.cpp +++ b/hotspot/src/share/vm/opto/node.cpp @@ -773,6 +773,21 @@ void Node::del_req( uint idx ) { _in[_cnt] = NULL; // NULL out emptied slot } +//------------------------------del_req_ordered-------------------------------- +// Delete the required edge and compact the edge array with preserved order +void Node::del_req_ordered( uint idx ) { + assert( idx < _cnt, "oob"); + assert( !VerifyHashTableKeys || _hash_lock == 0, + "remove node from hash table before modifying it"); + // First remove corresponding def-use edge + Node *n = in(idx); + if (n != NULL) n->del_out((Node *)this); + if (idx < _cnt - 1) { // Not last edge ? + Copy::conjoint_words_to_lower((HeapWord*)&_in[idx+1], (HeapWord*)&_in[idx], ((_cnt-idx-1)*sizeof(Node*))); + } + _in[--_cnt] = NULL; // NULL out emptied slot +} + //------------------------------ins_req---------------------------------------- // Insert a new required input at the end void Node::ins_req( uint idx, Node *n ) { diff --git a/hotspot/src/share/vm/opto/node.hpp b/hotspot/src/share/vm/opto/node.hpp index 0690d21b122..1c695f5660b 100644 --- a/hotspot/src/share/vm/opto/node.hpp +++ b/hotspot/src/share/vm/opto/node.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 @@ -211,7 +211,7 @@ public: // New Operator that takes a Compile pointer, this will eventually // be the "new" New operator. - inline void* operator new( size_t x, Compile* C) { + inline void* operator new( size_t x, Compile* C) throw() { Node* n = (Node*)C->node_arena()->Amalloc_D(x); #ifdef ASSERT n->_in = (Node**)n; // magic cookie for assertion check @@ -384,6 +384,7 @@ protected: void add_req( Node *n ); // Append a NEW required input void add_req_batch( Node* n, uint m ); // Append m NEW required inputs (all n). void del_req( uint idx ); // Delete required edge & compact + void del_req_ordered( uint idx ); // Delete required edge & compact with preserved order void ins_req( uint i, Node *n ); // Insert a NEW required input void set_req( uint i, Node *n ) { assert( is_not_dead(n), "can not use dead node"); diff --git a/hotspot/src/share/vm/opto/output.cpp b/hotspot/src/share/vm/opto/output.cpp index 8a06acdc983..6232c41f0b1 100644 --- a/hotspot/src/share/vm/opto/output.cpp +++ b/hotspot/src/share/vm/opto/output.cpp @@ -57,7 +57,7 @@ extern int emit_deopt_handler(CodeBuffer &cbuf); // Convert Nodes to instruction bits and pass off to the VM void Compile::Output() { // RootNode goes - assert( _cfg->get_root_block()->_nodes.size() == 0, "" ); + assert( _cfg->get_root_block()->number_of_nodes() == 0, "" ); // The number of new nodes (mostly MachNop) is proportional to // the number of java calls and inner loops which are aligned. @@ -70,11 +70,11 @@ void Compile::Output() { Block *entry = _cfg->get_block(1); Block *broot = _cfg->get_root_block(); - const StartNode *start = entry->_nodes[0]->as_Start(); + const StartNode *start = entry->head()->as_Start(); // Replace StartNode with prolog MachPrologNode *prolog = new (this) MachPrologNode(); - entry->_nodes.map( 0, prolog ); + entry->map_node(prolog, 0); _cfg->map_node_to_block(prolog, entry); _cfg->unmap_node_from_block(start); // start is no longer in any block @@ -144,8 +144,8 @@ void Compile::Output() { for (uint i = 0; i < _cfg->number_of_blocks(); i++) { tty->print("\nBB#%03d:\n", i); Block* block = _cfg->get_block(i); - for (uint j = 0; j < block->_nodes.size(); j++) { - Node* n = block->_nodes[j]; + for (uint j = 0; j < block->number_of_nodes(); j++) { + Node* n = block->get_node(j); OptoReg::Name reg = _regalloc->get_reg_first(n); tty->print(" %-6s ", reg >= 0 && reg < REG_COUNT ? Matcher::regName[reg] : ""); n->dump(); @@ -226,8 +226,8 @@ void Compile::Insert_zap_nodes() { // Insert call to zap runtime stub before every node with an oop map for( uint i=0; i<_cfg->number_of_blocks(); i++ ) { Block *b = _cfg->get_block(i); - for ( uint j = 0; j < b->_nodes.size(); ++j ) { - Node *n = b->_nodes[j]; + for ( uint j = 0; j < b->number_of_nodes(); ++j ) { + Node *n = b->get_node(j); // Determining if we should insert a zap-a-lot node in output. // We do that for all nodes that has oopmap info, except for calls @@ -256,7 +256,7 @@ void Compile::Insert_zap_nodes() { } if (insert) { Node *zap = call_zap_node(n->as_MachSafePoint(), i); - b->_nodes.insert( j, zap ); + b->insert_node(zap, j); _cfg->map_node_to_block(zap, b); ++j; } @@ -379,10 +379,10 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size DEBUG_ONLY( jmp_rule[i] = 0; ) // Sum all instruction sizes to compute block size - uint last_inst = block->_nodes.size(); + uint last_inst = block->number_of_nodes(); uint blk_size = 0; for (uint j = 0; j < last_inst; j++) { - Node* nj = block->_nodes[j]; + Node* nj = block->get_node(j); // Handle machine instruction nodes if (nj->is_Mach()) { MachNode *mach = nj->as_Mach(); @@ -477,18 +477,18 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size for (uint i = 0; i < nblocks; i++) { Block* block = _cfg->get_block(i); int idx = jmp_nidx[i]; - MachNode* mach = (idx == -1) ? NULL: block->_nodes[idx]->as_Mach(); + MachNode* mach = (idx == -1) ? NULL: block->get_node(idx)->as_Mach(); if (mach != NULL && mach->may_be_short_branch()) { #ifdef ASSERT assert(jmp_size[i] > 0 && mach->is_MachBranch(), "sanity"); int j; // Find the branch; ignore trailing NOPs. - for (j = block->_nodes.size()-1; j>=0; j--) { - Node* n = block->_nodes[j]; + for (j = block->number_of_nodes()-1; j>=0; j--) { + Node* n = block->get_node(j); if (!n->is_Mach() || n->as_Mach()->ideal_Opcode() != Op_Con) break; } - assert(j >= 0 && j == idx && block->_nodes[j] == (Node*)mach, "sanity"); + assert(j >= 0 && j == idx && block->get_node(j) == (Node*)mach, "sanity"); #endif int br_size = jmp_size[i]; int br_offs = blk_starts[i] + jmp_offset[i]; @@ -522,7 +522,7 @@ void Compile::shorten_branches(uint* blk_starts, int& code_size, int& reloc_size diff -= nop_size; } adjust_block_start += diff; - block->_nodes.map(idx, replacement); + block->map_node(replacement, idx); mach->subsume_by(replacement, C); mach = replacement; progress = true; @@ -639,7 +639,7 @@ void Compile::FillLocArray( int idx, MachSafePointNode* sfpt, Node *local, new ConstantOopWriteValue(cik->java_mirror()->constant_encoding())); Compile::set_sv_for_object_node(objs, sv); - uint first_ind = spobj->first_index(); + uint first_ind = spobj->first_index(sfpt->jvms()); for (uint i = 0; i < spobj->n_fields(); i++) { Node* fld_node = sfpt->in(first_ind+i); (void)FillLocArray(sv->field_values()->length(), sfpt, fld_node, sv->field_values(), objs); @@ -894,7 +894,7 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { GrowableArray *monarray = new GrowableArray(num_mon); // Loop over monitors and insert into array - for(idx = 0; idx < num_mon; idx++) { + for (idx = 0; idx < num_mon; idx++) { // Grab the node that defines this monitor Node* box_node = sfn->monitor_box(jvms, idx); Node* obj_node = sfn->monitor_obj(jvms, idx); @@ -902,11 +902,11 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { // Create ScopeValue for object ScopeValue *scval = NULL; - if( obj_node->is_SafePointScalarObject() ) { + if (obj_node->is_SafePointScalarObject()) { SafePointScalarObjectNode* spobj = obj_node->as_SafePointScalarObject(); scval = Compile::sv_for_node_id(objs, spobj->_idx); if (scval == NULL) { - const Type *t = obj_node->bottom_type(); + const Type *t = spobj->bottom_type(); ciKlass* cik = t->is_oopptr()->klass(); assert(cik->is_instance_klass() || cik->is_array_klass(), "Not supported allocation."); @@ -914,14 +914,14 @@ void Compile::Process_OopMap_Node(MachNode *mach, int current_offset) { new ConstantOopWriteValue(cik->java_mirror()->constant_encoding())); Compile::set_sv_for_object_node(objs, sv); - uint first_ind = spobj->first_index(); + uint first_ind = spobj->first_index(youngest_jvms); for (uint i = 0; i < spobj->n_fields(); i++) { Node* fld_node = sfn->in(first_ind+i); (void)FillLocArray(sv->field_values()->length(), sfn, fld_node, sv->field_values(), objs); } scval = sv; } - } else if( !obj_node->is_Con() ) { + } else if (!obj_node->is_Con()) { OptoReg::Name obj_reg = _regalloc->get_reg_first(obj_node); if( obj_node->bottom_type()->base() == Type::NarrowOop ) { scval = new_loc_value( _regalloc, obj_reg, Location::narrowoop ); @@ -1088,8 +1088,8 @@ CodeBuffer* Compile::init_buffer(uint* blk_starts) { for (uint i = 0; i < _cfg->number_of_blocks(); i++) { Block* b = _cfg->get_block(i); - for (uint j = 0; j < b->_nodes.size(); j++) { - Node* n = b->_nodes[j]; + for (uint j = 0; j < b->number_of_nodes(); j++) { + Node* n = b->get_node(j); // If the node is a MachConstantNode evaluate the constant // value section. @@ -1247,14 +1247,14 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { // Define the label at the beginning of the basic block MacroAssembler(cb).bind(blk_labels[block->_pre_order]); - uint last_inst = block->_nodes.size(); + uint last_inst = block->number_of_nodes(); // Emit block normally, except for last instruction. // Emit means "dump code bits into code buffer". for (uint j = 0; j_nodes[j]; + Node* n = block->get_node(j); // See if delay slots are supported if (valid_bundle_info(n) && @@ -1308,7 +1308,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { assert((padding % nop_size) == 0, "padding is not a multiple of NOP size"); int nops_cnt = padding / nop_size; MachNode *nop = new (this) MachNopNode(nops_cnt); - block->_nodes.insert(j++, nop); + block->insert_node(nop, j++); last_inst++; _cfg->map_node_to_block(nop, block); nop->emit(*cb, _regalloc); @@ -1394,7 +1394,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { // Insert padding between avoid_back_to_back branches. if (needs_padding && replacement->avoid_back_to_back()) { MachNode *nop = new (this) MachNopNode(); - block->_nodes.insert(j++, nop); + block->insert_node(nop, j++); _cfg->map_node_to_block(nop, block); last_inst++; nop->emit(*cb, _regalloc); @@ -1407,7 +1407,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { jmp_size[i] = new_size; jmp_rule[i] = mach->rule(); #endif - block->_nodes.map(j, replacement); + block->map_node(replacement, j); mach->subsume_by(replacement, C); n = replacement; mach = replacement; @@ -1438,7 +1438,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { count++; uint i4; for (i4 = 0; i4 < last_inst; ++i4) { - if (block->_nodes[i4] == oop_store) { + if (block->get_node(i4) == oop_store) { break; } } @@ -1548,7 +1548,7 @@ void Compile::fill_buffer(CodeBuffer* cb, uint* blk_starts) { int padding = nb->alignment_padding(current_offset); if( padding > 0 ) { MachNode *nop = new (this) MachNopNode(padding / nop_size); - block->_nodes.insert(block->_nodes.size(), nop); + block->insert_node(nop, block->number_of_nodes()); _cfg->map_node_to_block(nop, block); nop->emit(*cb, _regalloc); current_offset = cb->insts_size(); @@ -1655,8 +1655,8 @@ void Compile::FillExceptionTables(uint cnt, uint *call_returns, uint *inct_start int j; // Find the branch; ignore trailing NOPs. - for (j = block->_nodes.size() - 1; j >= 0; j--) { - n = block->_nodes[j]; + for (j = block->number_of_nodes() - 1; j >= 0; j--) { + n = block->get_node(j); if (!n->is_Mach() || n->as_Mach()->ideal_Opcode() != Op_Con) { break; } @@ -1675,8 +1675,8 @@ void Compile::FillExceptionTables(uint cnt, uint *call_returns, uint *inct_start uint call_return = call_returns[block->_pre_order]; #ifdef ASSERT assert( call_return > 0, "no call seen for this basic block" ); - while (block->_nodes[--j]->is_MachProj()) ; - assert(block->_nodes[j]->is_MachCall(), "CatchProj must follow call"); + while (block->get_node(--j)->is_MachProj()) ; + assert(block->get_node(j)->is_MachCall(), "CatchProj must follow call"); #endif // last instruction is a CatchNode, find it's CatchProjNodes int nof_succs = block->_num_succs; @@ -1782,7 +1782,7 @@ Scheduling::Scheduling(Arena *arena, Compile &compile) // Get the last node Block* block = _cfg->get_block(_cfg->number_of_blocks() - 1); - _next_node = block->_nodes[block->_nodes.size() - 1]; + _next_node = block->get_node(block->number_of_nodes() - 1); } #ifndef PRODUCT @@ -1875,7 +1875,7 @@ void Scheduling::ComputeLocalLatenciesForward(const Block *bb) { // Used to allow latency 0 to force an instruction to the beginning // of the bb uint latency = 1; - Node *use = bb->_nodes[j]; + Node *use = bb->get_node(j); uint nlen = use->len(); // Walk over all the inputs @@ -2286,7 +2286,7 @@ void Scheduling::AddNodeToBundle(Node *n, const Block *bb) { (OptoReg::is_valid(_regalloc->get_reg_first(n)) || op != Op_BoxLock)) ) { // Push any trailing projections - if( bb->_nodes[bb->_nodes.size()-1] != n ) { + if( bb->get_node(bb->number_of_nodes()-1) != n ) { for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node *foi = n->fast_out(i); if( foi->is_Proj() ) @@ -2329,21 +2329,21 @@ void Scheduling::ComputeUseCount(const Block *bb) { _unconditional_delay_slot = NULL; #ifdef ASSERT - for( uint i=0; i < bb->_nodes.size(); i++ ) - assert( _uses[bb->_nodes[i]->_idx] == 0, "_use array not clean" ); + for( uint i=0; i < bb->number_of_nodes(); i++ ) + assert( _uses[bb->get_node(i)->_idx] == 0, "_use array not clean" ); #endif // Force the _uses count to never go to zero for unscheduable pieces // of the block for( uint k = 0; k < _bb_start; k++ ) - _uses[bb->_nodes[k]->_idx] = 1; - for( uint l = _bb_end; l < bb->_nodes.size(); l++ ) - _uses[bb->_nodes[l]->_idx] = 1; + _uses[bb->get_node(k)->_idx] = 1; + for( uint l = _bb_end; l < bb->number_of_nodes(); l++ ) + _uses[bb->get_node(l)->_idx] = 1; // Iterate backwards over the instructions in the block. Don't count the // branch projections at end or the block header instructions. for( uint j = _bb_end-1; j >= _bb_start; j-- ) { - Node *n = bb->_nodes[j]; + Node *n = bb->get_node(j); if( n->is_Proj() ) continue; // Projections handled another way // Account for all uses @@ -2398,8 +2398,8 @@ void Scheduling::DoScheduling() { #ifndef PRODUCT if (_cfg->C->trace_opto_output()) { tty->print("# Schedule BB#%03d (initial)\n", i); - for (uint j = 0; j < bb->_nodes.size(); j++) { - bb->_nodes[j]->dump(); + for (uint j = 0; j < bb->number_of_nodes(); j++) { + bb->get_node(j)->dump(); } } #endif @@ -2426,10 +2426,10 @@ void Scheduling::DoScheduling() { } // Leave untouched the starting instruction, any Phis, a CreateEx node - // or Top. bb->_nodes[_bb_start] is the first schedulable instruction. - _bb_end = bb->_nodes.size()-1; + // or Top. bb->get_node(_bb_start) is the first schedulable instruction. + _bb_end = bb->number_of_nodes()-1; for( _bb_start=1; _bb_start <= _bb_end; _bb_start++ ) { - Node *n = bb->_nodes[_bb_start]; + Node *n = bb->get_node(_bb_start); // Things not matched, like Phinodes and ProjNodes don't get scheduled. // Also, MachIdealNodes do not get scheduled if( !n->is_Mach() ) continue; // Skip non-machine nodes @@ -2449,19 +2449,19 @@ void Scheduling::DoScheduling() { // in the block), because they have delay slots we can fill. Calls all // have their delay slots filled in the template expansions, so we don't // bother scheduling them. - Node *last = bb->_nodes[_bb_end]; + Node *last = bb->get_node(_bb_end); // Ignore trailing NOPs. while (_bb_end > 0 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Con) { - last = bb->_nodes[--_bb_end]; + last = bb->get_node(--_bb_end); } assert(!last->is_Mach() || last->as_Mach()->ideal_Opcode() != Op_Con, ""); if( last->is_Catch() || // Exclude unreachable path case when Halt node is in a separate block. (_bb_end > 1 && last->is_Mach() && last->as_Mach()->ideal_Opcode() == Op_Halt) ) { // There must be a prior call. Skip it. - while( !bb->_nodes[--_bb_end]->is_MachCall() ) { - assert( bb->_nodes[_bb_end]->is_MachProj(), "skipping projections after expected call" ); + while( !bb->get_node(--_bb_end)->is_MachCall() ) { + assert( bb->get_node(_bb_end)->is_MachProj(), "skipping projections after expected call" ); } } else if( last->is_MachNullCheck() ) { // Backup so the last null-checked memory instruction is @@ -2470,7 +2470,7 @@ void Scheduling::DoScheduling() { Node *mem = last->in(1); do { _bb_end--; - } while (mem != bb->_nodes[_bb_end]); + } while (mem != bb->get_node(_bb_end)); } else { // Set _bb_end to point after last schedulable inst. _bb_end++; @@ -2499,7 +2499,7 @@ void Scheduling::DoScheduling() { assert( _scheduled.size() == _bb_end - _bb_start, "wrong number of instructions" ); #ifdef ASSERT for( uint l = _bb_start; l < _bb_end; l++ ) { - Node *n = bb->_nodes[l]; + Node *n = bb->get_node(l); uint m; for( m = 0; m < _bb_end-_bb_start; m++ ) if( _scheduled[m] == n ) @@ -2510,14 +2510,14 @@ void Scheduling::DoScheduling() { // Now copy the instructions (in reverse order) back to the block for ( uint k = _bb_start; k < _bb_end; k++ ) - bb->_nodes.map(k, _scheduled[_bb_end-k-1]); + bb->map_node(_scheduled[_bb_end-k-1], k); #ifndef PRODUCT if (_cfg->C->trace_opto_output()) { tty->print("# Schedule BB#%03d (final)\n", i); uint current = 0; - for (uint j = 0; j < bb->_nodes.size(); j++) { - Node *n = bb->_nodes[j]; + for (uint j = 0; j < bb->number_of_nodes(); j++) { + Node *n = bb->get_node(j); if( valid_bundle_info(n) ) { Bundle *bundle = node_bundling(n); if (bundle->instr_count() > 0 || bundle->flags() > 0) { @@ -2579,8 +2579,8 @@ void Scheduling::verify_good_schedule( Block *b, const char *msg ) { // Walk over the block backwards. Check to make sure each DEF doesn't // kill a live value (other than the one it's supposed to). Add each // USE to the live set. - for( uint i = b->_nodes.size()-1; i >= _bb_start; i-- ) { - Node *n = b->_nodes[i]; + for( uint i = b->number_of_nodes()-1; i >= _bb_start; i-- ) { + Node *n = b->get_node(i); int n_op = n->Opcode(); if( n_op == Op_MachProj && n->ideal_reg() == MachProjNode::fat_proj ) { // Fat-proj kills a slew of registers @@ -2711,7 +2711,7 @@ void Scheduling::anti_do_use( Block *b, Node *use, OptoReg::Name use_reg ) { pinch->req() == 1 ) { // pinch not yet in block? pinch->del_req(0); // yank pointer to later-def, also set flag // Insert the pinch-point in the block just after the last use - b->_nodes.insert(b->find_node(use)+1,pinch); + b->insert_node(pinch, b->find_node(use) + 1); _bb_end++; // Increase size scheduled region in block } @@ -2763,10 +2763,10 @@ void Scheduling::ComputeRegisterAntidependencies(Block *b) { // it being in the current block. bool fat_proj_seen = false; uint last_safept = _bb_end-1; - Node* end_node = (_bb_end-1 >= _bb_start) ? b->_nodes[last_safept] : NULL; + Node* end_node = (_bb_end-1 >= _bb_start) ? b->get_node(last_safept) : NULL; Node* last_safept_node = end_node; for( uint i = _bb_end-1; i >= _bb_start; i-- ) { - Node *n = b->_nodes[i]; + Node *n = b->get_node(i); int is_def = n->outcnt(); // def if some uses prior to adding precedence edges if( n->is_MachProj() && n->ideal_reg() == MachProjNode::fat_proj ) { // Fat-proj kills a slew of registers @@ -2815,7 +2815,7 @@ void Scheduling::ComputeRegisterAntidependencies(Block *b) { // Do not allow defs of new derived values to float above GC // points unless the base is definitely available at the GC point. - Node *m = b->_nodes[i]; + Node *m = b->get_node(i); // Add precedence edge from following safepoint to use of derived pointer if( last_safept_node != end_node && @@ -2832,11 +2832,11 @@ void Scheduling::ComputeRegisterAntidependencies(Block *b) { if( n->jvms() ) { // Precedence edge from derived to safept // Check if last_safept_node was moved by pinch-point insertion in anti_do_use() - if( b->_nodes[last_safept] != last_safept_node ) { + if( b->get_node(last_safept) != last_safept_node ) { last_safept = b->find_node(last_safept_node); } for( uint j=last_safept; j > i; j-- ) { - Node *mach = b->_nodes[j]; + Node *mach = b->get_node(j); if( mach->is_Mach() && mach->as_Mach()->ideal_Opcode() == Op_AddP ) mach->add_prec( n ); } 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/phaseX.cpp b/hotspot/src/share/vm/opto/phaseX.cpp index a1d1527127e..71c8d8afcd8 100644 --- a/hotspot/src/share/vm/opto/phaseX.cpp +++ b/hotspot/src/share/vm/opto/phaseX.cpp @@ -1648,10 +1648,10 @@ void PhasePeephole::do_transform() { bool block_not_printed = true; // and each instruction within a block - uint end_index = block->_nodes.size(); + uint end_index = block->number_of_nodes(); // block->end_idx() not valid after PhaseRegAlloc for( uint instruction_index = 1; instruction_index < end_index; ++instruction_index ) { - Node *n = block->_nodes.at(instruction_index); + Node *n = block->get_node(instruction_index); if( n->is_Mach() ) { MachNode *m = n->as_Mach(); int deleted_count = 0; @@ -1673,7 +1673,7 @@ void PhasePeephole::do_transform() { } // Print instructions being deleted for( int i = (deleted_count - 1); i >= 0; --i ) { - block->_nodes.at(instruction_index-i)->as_Mach()->format(_regalloc); tty->cr(); + block->get_node(instruction_index-i)->as_Mach()->format(_regalloc); tty->cr(); } tty->print_cr("replaced with"); // Print new instruction @@ -1687,11 +1687,11 @@ void PhasePeephole::do_transform() { // the node index to live range mappings.) uint safe_instruction_index = (instruction_index - deleted_count); for( ; (instruction_index > safe_instruction_index); --instruction_index ) { - block->_nodes.remove( instruction_index ); + block->remove_node( instruction_index ); } // install new node after safe_instruction_index - block->_nodes.insert( safe_instruction_index + 1, m2 ); - end_index = block->_nodes.size() - 1; // Recompute new block size + block->insert_node(m2, safe_instruction_index + 1); + end_index = block->number_of_nodes() - 1; // Recompute new block size NOT_PRODUCT( inc_peepholes(); ) } } diff --git a/hotspot/src/share/vm/opto/postaloc.cpp b/hotspot/src/share/vm/opto/postaloc.cpp index fdb72dd42c6..76de2ed16a1 100644 --- a/hotspot/src/share/vm/opto/postaloc.cpp +++ b/hotspot/src/share/vm/opto/postaloc.cpp @@ -423,8 +423,8 @@ void PhaseChaitin::post_allocate_copy_removal() { // Count of Phis in block uint phi_dex; - for (phi_dex = 1; phi_dex < block->_nodes.size(); phi_dex++) { - Node* phi = block->_nodes[phi_dex]; + for (phi_dex = 1; phi_dex < block->number_of_nodes(); phi_dex++) { + Node* phi = block->get_node(phi_dex); if (!phi->is_Phi()) { break; } @@ -439,7 +439,7 @@ void PhaseChaitin::post_allocate_copy_removal() { Block* pb = _cfg.get_block_for_node(block->pred(j)); // Remove copies along phi edges for (uint k = 1; k < phi_dex; k++) { - elide_copy(block->_nodes[k], j, block, *blk2value[pb->_pre_order], *blk2regnd[pb->_pre_order], false); + elide_copy(block->get_node(k), j, block, *blk2value[pb->_pre_order], *blk2regnd[pb->_pre_order], false); } if (blk2value[pb->_pre_order]) { // Have a mapping on this edge? // See if this predecessor's mappings have been used by everybody @@ -510,7 +510,7 @@ void PhaseChaitin::post_allocate_copy_removal() { // For all Phi's for (j = 1; j < phi_dex; j++) { uint k; - Node *phi = block->_nodes[j]; + Node *phi = block->get_node(j); uint pidx = _lrg_map.live_range_id(phi); OptoReg::Name preg = lrgs(_lrg_map.live_range_id(phi)).reg(); @@ -522,7 +522,7 @@ void PhaseChaitin::post_allocate_copy_removal() { u = u ? NodeSentinel : x; // Capture unique input, or NodeSentinel for 2nd input } if (u != NodeSentinel) { // Junk Phi. Remove - block->_nodes.remove(j--); + block->remove_node(j--); phi_dex--; _cfg.unmap_node_from_block(phi); phi->replace_by(u); @@ -552,8 +552,8 @@ void PhaseChaitin::post_allocate_copy_removal() { } // For all remaining instructions - for (j = phi_dex; j < block->_nodes.size(); j++) { - Node* n = block->_nodes[j]; + for (j = phi_dex; j < block->number_of_nodes(); j++) { + Node* n = block->get_node(j); if(n->outcnt() == 0 && // Dead? n != C->top() && // (ignore TOP, it has no du info) diff --git a/hotspot/src/share/vm/opto/reg_split.cpp b/hotspot/src/share/vm/opto/reg_split.cpp index ac4f8e35824..2c4ad874ffe 100644 --- a/hotspot/src/share/vm/opto/reg_split.cpp +++ b/hotspot/src/share/vm/opto/reg_split.cpp @@ -112,17 +112,17 @@ Node *PhaseChaitin::get_spillcopy_wide( Node *def, Node *use, uint uidx ) { void PhaseChaitin::insert_proj( Block *b, uint i, Node *spill, uint maxlrg ) { // Skip intervening ProjNodes. Do not insert between a ProjNode and // its definer. - while( i < b->_nodes.size() && - (b->_nodes[i]->is_Proj() || - b->_nodes[i]->is_Phi() ) ) + while( i < b->number_of_nodes() && + (b->get_node(i)->is_Proj() || + b->get_node(i)->is_Phi() ) ) i++; // Do not insert between a call and his Catch - if( b->_nodes[i]->is_Catch() ) { + if( b->get_node(i)->is_Catch() ) { // Put the instruction at the top of the fall-thru block. // Find the fall-thru projection while( 1 ) { - const CatchProjNode *cp = b->_nodes[++i]->as_CatchProj(); + const CatchProjNode *cp = b->get_node(++i)->as_CatchProj(); if( cp->_con == CatchProjNode::fall_through_index ) break; } @@ -131,7 +131,7 @@ void PhaseChaitin::insert_proj( Block *b, uint i, Node *spill, uint maxlrg ) { i = 1; // Right at start of block } - b->_nodes.insert(i,spill); // Insert node in block + b->insert_node(spill, i); // Insert node in block _cfg.map_node_to_block(spill, b); // Update node->block mapping to reflect // Adjust the point where we go hi-pressure if( i <= b->_ihrp_index ) b->_ihrp_index++; @@ -160,9 +160,9 @@ uint PhaseChaitin::split_DEF( Node *def, Block *b, int loc, uint maxlrg, Node ** // (The implicit_null_check function ensures the use is also dominated // by the branch-not-taken block.) Node *be = b->end(); - if( be->is_MachNullCheck() && be->in(1) == def && def == b->_nodes[loc] ) { + if( be->is_MachNullCheck() && be->in(1) == def && def == b->get_node(loc)) { // Spill goes in the branch-not-taken block - b = b->_succs[b->_nodes[b->end_idx()+1]->Opcode() == Op_IfTrue]; + b = b->_succs[b->get_node(b->end_idx()+1)->Opcode() == Op_IfTrue]; loc = 0; // Just past the Region } assert( loc >= 0, "must insert past block head" ); @@ -450,7 +450,7 @@ bool PhaseChaitin::prompt_use( Block *b, uint lidx ) { // Scan block for 1st use. for( uint i = 1; i <= b->end_idx(); i++ ) { - Node *n = b->_nodes[i]; + Node *n = b->get_node(i); // Ignore PHI use, these can be up or down if (n->is_Phi()) { continue; @@ -647,7 +647,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // check block for appropriate phinode & update edges for( insidx = 1; insidx <= b->end_idx(); insidx++ ) { - n1 = b->_nodes[insidx]; + n1 = b->get_node(insidx); // bail if this is not a phi phi = n1->is_Phi() ? n1->as_Phi() : NULL; if( phi == NULL ) { @@ -747,7 +747,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { //----------Walk Instructions in the Block and Split---------- // For all non-phi instructions in the block for( insidx = 1; insidx <= b->end_idx(); insidx++ ) { - Node *n = b->_nodes[insidx]; + Node *n = b->get_node(insidx); // Find the defining Node's live range index uint defidx = _lrg_map.find_id(n); uint cnt = n->req(); @@ -776,7 +776,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { assert(_lrg_map.find_id(n) == _lrg_map.find_id(u), "should be the same lrg"); n->replace_by(u); // Then replace with unique input n->disconnect_inputs(NULL, C); - b->_nodes.remove(insidx); + b->remove_node(insidx); insidx--; b->_ihrp_index--; b->_fhrp_index--; @@ -789,12 +789,12 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { (b->_reg_pressure < (uint)INTPRESSURE) || b->_ihrp_index > 4000000 || b->_ihrp_index >= b->end_idx() || - !b->_nodes[b->_ihrp_index]->is_Proj(), "" ); + !b->get_node(b->_ihrp_index)->is_Proj(), "" ); assert( insidx > b->_fhrp_index || (b->_freg_pressure < (uint)FLOATPRESSURE) || b->_fhrp_index > 4000000 || b->_fhrp_index >= b->end_idx() || - !b->_nodes[b->_fhrp_index]->is_Proj(), "" ); + !b->get_node(b->_fhrp_index)->is_Proj(), "" ); // ********** Handle Crossing HRP Boundry ********** if( (insidx == b->_ihrp_index) || (insidx == b->_fhrp_index) ) { @@ -819,7 +819,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // Insert point is just past last use or def in the block int insert_point = insidx-1; while( insert_point > 0 ) { - Node *n = b->_nodes[insert_point]; + Node *n = b->get_node(insert_point); // Hit top of block? Quit going backwards if (n->is_Phi()) { break; @@ -865,7 +865,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { } } // end if LRG is UP } // end for all spilling live ranges - assert( b->_nodes[insidx] == n, "got insidx set incorrectly" ); + assert( b->get_node(insidx) == n, "got insidx set incorrectly" ); } // end if crossing HRP Boundry // If the LRG index is oob, then this is a new spillcopy, skip it. @@ -878,7 +878,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { if (copyidx && defidx == _lrg_map.live_range_id(n->in(copyidx))) { n->replace_by( n->in(copyidx) ); n->set_req( copyidx, NULL ); - b->_nodes.remove(insidx--); + b->remove_node(insidx--); b->_ihrp_index--; // Adjust the point where we go hi-pressure b->_fhrp_index--; continue; @@ -932,10 +932,10 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // Rematerializable? Then clone def at use site instead // of store/load if( def->rematerialize() ) { - int old_size = b->_nodes.size(); + int old_size = b->number_of_nodes(); def = split_Rematerialize( def, b, insidx, maxlrg, splits, slidx, lrg2reach, Reachblock, true ); if( !def ) return 0; // Bail out - insidx += b->_nodes.size()-old_size; + insidx += b->number_of_nodes()-old_size; } MachNode *mach = n->is_Mach() ? n->as_Mach() : NULL; @@ -1332,8 +1332,8 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { // so look at the node before it. int insert = pred->end_idx(); while (insert >= 1 && - pred->_nodes[insert - 1]->is_SpillCopy() && - _lrg_map.find(pred->_nodes[insert - 1]) >= lrgs_before_phi_split) { + pred->get_node(insert - 1)->is_SpillCopy() && + _lrg_map.find(pred->get_node(insert - 1)) >= lrgs_before_phi_split) { insert--; } def = split_Rematerialize(def, pred, insert, maxlrg, splits, slidx, lrg2reach, Reachblock, false); @@ -1402,7 +1402,7 @@ uint PhaseChaitin::Split(uint maxlrg, ResourceArea* split_arena) { for (bidx = 0; bidx < _cfg.number_of_blocks(); bidx++) { b = _cfg.get_block(bidx); for (insidx = 0; insidx <= b->end_idx(); insidx++) { - Node *n = b->_nodes[insidx]; + Node *n = b->get_node(insidx); uint defidx = _lrg_map.find(n); assert(defidx < _lrg_map.max_lrg_id(), "Bad live range index in Split"); assert(defidx < maxlrg,"Bad live range index in Split"); diff --git a/hotspot/src/share/vm/opto/type.cpp b/hotspot/src/share/vm/opto/type.cpp index fabcf1cad16..23e84a05d77 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); @@ -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 0626cb53f52..d4832591843 100644 --- a/hotspot/src/share/vm/opto/type.hpp +++ b/hotspot/src/share/vm/opto/type.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 @@ -169,7 +169,7 @@ protected: public: - inline void* operator new( size_t x ) { + inline void* operator new( size_t x ) throw() { Compile* compile = Compile::current(); compile->set_type_last_size(x); void *temp = compile->type_arena()->Amalloc_D(x); @@ -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/runtime/arguments.cpp b/hotspot/src/share/vm/runtime/arguments.cpp index 38f38f1c856..d8a6f90eeef 100644 --- a/hotspot/src/share/vm/runtime/arguments.cpp +++ b/hotspot/src/share/vm/runtime/arguments.cpp @@ -1605,17 +1605,6 @@ julong Arguments::limit_by_allocatable_memory(julong limit) { return result; } -void Arguments::set_heap_base_min_address() { - if (FLAG_IS_DEFAULT(HeapBaseMinAddress) && UseG1GC && HeapBaseMinAddress < 1*G) { - // By default HeapBaseMinAddress is 2G on all platforms except Solaris x86. - // G1 currently needs a lot of C-heap, so on Solaris we have to give G1 - // some extra space for the C-heap compared to other collectors. - // Use FLAG_SET_DEFAULT here rather than FLAG_SET_ERGO to make sure that - // code that checks for default values work correctly. - FLAG_SET_DEFAULT(HeapBaseMinAddress, 1*G); - } -} - void Arguments::set_heap_size() { if (!FLAG_IS_DEFAULT(DefaultMaxRAMFraction)) { // Deprecated flag @@ -2230,7 +2219,7 @@ bool Arguments::check_vm_args_consistency() { // among the distinct pages. if (ContendedPaddingWidth < 0 || ContendedPaddingWidth > 8192) { jio_fprintf(defaultStream::error_stream(), - "ContendedPaddingWidth=" INTX_FORMAT " must be the between %d and %d\n", + "ContendedPaddingWidth=" INTX_FORMAT " must be in between %d and %d\n", ContendedPaddingWidth, 0, 8192); status = false; } @@ -2239,7 +2228,7 @@ bool Arguments::check_vm_args_consistency() { // It is sufficient to check against the largest type size. if ((ContendedPaddingWidth % BytesPerLong) != 0) { jio_fprintf(defaultStream::error_stream(), - "ContendedPaddingWidth=" INTX_FORMAT " must be the multiple of %d\n", + "ContendedPaddingWidth=" INTX_FORMAT " must be a multiple of %d\n", ContendedPaddingWidth, BytesPerLong); status = false; } @@ -3537,8 +3526,6 @@ jint Arguments::parse(const JavaVMInitArgs* args) { } } - set_heap_base_min_address(); - // Set heap size based on available physical memory set_heap_size(); diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 0a6f5ee48e8..43256b75082 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -334,8 +334,6 @@ class Arguments : AllStatic { // limits the given memory size by the maximum amount of memory this process is // currently allowed to allocate or reserve. static julong limit_by_allocatable_memory(julong size); - // Setup HeapBaseMinAddress - static void set_heap_base_min_address(); // Setup heap size static void set_heap_size(); // Based on automatic selection criteria, should the diff --git a/hotspot/src/share/vm/runtime/fprofiler.cpp b/hotspot/src/share/vm/runtime/fprofiler.cpp index 111c4db5aa3..3ddf1a191dc 100644 --- a/hotspot/src/share/vm/runtime/fprofiler.cpp +++ b/hotspot/src/share/vm/runtime/fprofiler.cpp @@ -264,7 +264,7 @@ class ProfilerNode { public: - void* operator new(size_t size, ThreadProfiler* tp); + void* operator new(size_t size, ThreadProfiler* tp) throw(); void operator delete(void* p); ProfilerNode() { @@ -373,7 +373,7 @@ class ProfilerNode { } }; -void* ProfilerNode::operator new(size_t size, ThreadProfiler* tp){ +void* ProfilerNode::operator new(size_t size, ThreadProfiler* tp) throw() { void* result = (void*) tp->area_top; tp->area_top += size; @@ -925,6 +925,8 @@ void FlatProfiler::record_thread_ticks() { FlatProfiler::interval_print(); FlatProfiler::interval_reset(); } + + FREE_C_HEAP_ARRAY(JavaThread *, threadsList, mtInternal); } else { // Couldn't get the threads lock, just record that rather than blocking FlatProfiler::threads_lock_ticks += 1; diff --git a/hotspot/src/share/vm/runtime/globals.cpp b/hotspot/src/share/vm/runtime/globals.cpp index a6c47bfe1de..280e15976de 100644 --- a/hotspot/src/share/vm/runtime/globals.cpp +++ b/hotspot/src/share/vm/runtime/globals.cpp @@ -205,6 +205,7 @@ void Flag::print_as_flag(outputStream* st) { #define C1_PRODUCT_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C1 product}", DEFAULT }, #define C1_PD_PRODUCT_FLAG_STRUCT(type, name, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C1 pd product}", DEFAULT }, +#define C1_DIAGNOSTIC_FLAG_STRUCT(type, name, value, doc) { #type, XSTR(name), &name, NOT_PRODUCT_ARG(doc) "{C1 diagnostic}", DEFAULT }, #ifdef PRODUCT #define C1_DEVELOP_FLAG_STRUCT(type, name, value, doc) /* flag is constant */ #define C1_PD_DEVELOP_FLAG_STRUCT(type, name, doc) /* flag is constant */ @@ -260,7 +261,7 @@ static Flag flagTable[] = { G1_FLAGS(RUNTIME_DEVELOP_FLAG_STRUCT, RUNTIME_PD_DEVELOP_FLAG_STRUCT, RUNTIME_PRODUCT_FLAG_STRUCT, RUNTIME_PD_PRODUCT_FLAG_STRUCT, RUNTIME_DIAGNOSTIC_FLAG_STRUCT, RUNTIME_EXPERIMENTAL_FLAG_STRUCT, RUNTIME_NOTPRODUCT_FLAG_STRUCT, RUNTIME_MANAGEABLE_FLAG_STRUCT, RUNTIME_PRODUCT_RW_FLAG_STRUCT) #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 - C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) + C1_FLAGS(C1_DEVELOP_FLAG_STRUCT, C1_PD_DEVELOP_FLAG_STRUCT, C1_PRODUCT_FLAG_STRUCT, C1_PD_PRODUCT_FLAG_STRUCT, C1_DIAGNOSTIC_FLAG_STRUCT, C1_NOTPRODUCT_FLAG_STRUCT) #endif #ifdef COMPILER2 C2_FLAGS(C2_DEVELOP_FLAG_STRUCT, C2_PD_DEVELOP_FLAG_STRUCT, C2_PRODUCT_FLAG_STRUCT, C2_PD_PRODUCT_FLAG_STRUCT, C2_DIAGNOSTIC_FLAG_STRUCT, C2_EXPERIMENTAL_FLAG_STRUCT, C2_NOTPRODUCT_FLAG_STRUCT) diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index f54939096e9..7fdf668bac5 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -3514,6 +3514,8 @@ class CommandLineFlags { "Temporary flag for transition to AbstractMethodError wrapped " \ "in InvocationTargetException. See 6531596") \ \ + develop(bool, VerifyLambdaBytecodes, false, \ + "Force verification of jdk 8 lambda metafactory bytecodes.") \ \ develop(intx, FastSuperclassLimit, 8, \ "Depth of hardwired instanceof accelerator array") \ @@ -3647,6 +3649,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") \ \ @@ -3685,15 +3690,9 @@ class CommandLineFlags { develop(bool, TraceDefaultMethods, false, \ "Trace the default method processing steps") \ \ - develop(bool, ParseAllGenericSignatures, false, \ - "Parse all generic signatures while classloading") \ - \ develop(bool, VerifyGenericSignatures, false, \ "Abort VM on erroneous or inconsistent generic signatures") \ \ - product(bool, ParseGenericDefaults, false, \ - "Parse generic signatures for default method handling") \ - \ product(bool, UseVMInterruptibleIO, false, \ "(Unstable, Solaris-specific) Thread interrupt before or with " \ "EINTR for I/O operations results in OS_INTRPT. The default value"\ diff --git a/hotspot/src/share/vm/runtime/globals_extension.hpp b/hotspot/src/share/vm/runtime/globals_extension.hpp index 00d06fe276c..bc4fd4a74bc 100644 --- a/hotspot/src/share/vm/runtime/globals_extension.hpp +++ b/hotspot/src/share/vm/runtime/globals_extension.hpp @@ -57,6 +57,7 @@ #define C1_PRODUCT_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #define C1_PD_PRODUCT_FLAG_MEMBER(type, name, doc) FLAG_MEMBER(name), +#define C1_DIAGNOSTIC_FLAG_MEMBER(type, name, value, doc) FLAG_MEMBER(name), #ifdef PRODUCT #define C1_DEVELOP_FLAG_MEMBER(type, name, value, doc) /* flag is constant */ #define C1_PD_DEVELOP_FLAG_MEMBER(type, name, doc) /* flag is constant */ @@ -99,7 +100,7 @@ typedef enum { G1_FLAGS(RUNTIME_DEVELOP_FLAG_MEMBER, RUNTIME_PD_DEVELOP_FLAG_MEMBER, RUNTIME_PRODUCT_FLAG_MEMBER, RUNTIME_PD_PRODUCT_FLAG_MEMBER, RUNTIME_DIAGNOSTIC_FLAG_MEMBER, RUNTIME_EXPERIMENTAL_FLAG_MEMBER, RUNTIME_NOTPRODUCT_FLAG_MEMBER, RUNTIME_MANAGEABLE_FLAG_MEMBER, RUNTIME_PRODUCT_RW_FLAG_MEMBER) #endif // INCLUDE_ALL_GCS #ifdef COMPILER1 - C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER) + C1_FLAGS(C1_DEVELOP_FLAG_MEMBER, C1_PD_DEVELOP_FLAG_MEMBER, C1_PRODUCT_FLAG_MEMBER, C1_PD_PRODUCT_FLAG_MEMBER, C1_DIAGNOSTIC_FLAG_MEMBER, C1_NOTPRODUCT_FLAG_MEMBER) #endif #ifdef COMPILER2 C2_FLAGS(C2_DEVELOP_FLAG_MEMBER, C2_PD_DEVELOP_FLAG_MEMBER, C2_PRODUCT_FLAG_MEMBER, C2_PD_PRODUCT_FLAG_MEMBER, C2_DIAGNOSTIC_FLAG_MEMBER, C2_EXPERIMENTAL_FLAG_MEMBER, C2_NOTPRODUCT_FLAG_MEMBER) @@ -131,6 +132,7 @@ typedef enum { #define C1_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), #define C1_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE(type, name, doc) FLAG_MEMBER_WITH_TYPE(name,type), +#define C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) FLAG_MEMBER_WITH_TYPE(name,type), #ifdef PRODUCT #define C1_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, value, doc) /* flag is constant */ #define C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE(type, name, doc) /* flag is constant */ @@ -204,6 +206,7 @@ typedef enum { C1_PD_DEVELOP_FLAG_MEMBER_WITH_TYPE, C1_PRODUCT_FLAG_MEMBER_WITH_TYPE, C1_PD_PRODUCT_FLAG_MEMBER_WITH_TYPE, + C1_DIAGNOSTIC_FLAG_MEMBER_WITH_TYPE, C1_NOTPRODUCT_FLAG_MEMBER_WITH_TYPE) #endif #ifdef COMPILER2 diff --git a/hotspot/src/share/vm/runtime/handles.cpp b/hotspot/src/share/vm/runtime/handles.cpp index ebbdd9d7463..1b4e9faecf9 100644 --- a/hotspot/src/share/vm/runtime/handles.cpp +++ b/hotspot/src/share/vm/runtime/handles.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 @@ -179,11 +179,11 @@ HandleMark::~HandleMark() { _thread->set_last_handle_mark(previous_handle_mark()); } -void* HandleMark::operator new(size_t size) { +void* HandleMark::operator new(size_t size) throw() { return AllocateHeap(size, mtThread); } -void* HandleMark::operator new [] (size_t size) { +void* HandleMark::operator new [] (size_t size) throw() { return AllocateHeap(size, mtThread); } diff --git a/hotspot/src/share/vm/runtime/handles.hpp b/hotspot/src/share/vm/runtime/handles.hpp index 4a2a90c74c0..dc254227971 100644 --- a/hotspot/src/share/vm/runtime/handles.hpp +++ b/hotspot/src/share/vm/runtime/handles.hpp @@ -309,8 +309,8 @@ class HandleMark { // called in the destructor of HandleMarkCleaner void pop_and_restore(); // overloaded operators - void* operator new(size_t size); - void* operator new [](size_t size); + void* operator new(size_t size) throw(); + void* operator new [](size_t size) throw(); void operator delete(void* p); void operator delete[](void* p); }; diff --git a/hotspot/src/share/vm/runtime/interfaceSupport.hpp b/hotspot/src/share/vm/runtime/interfaceSupport.hpp index 0c48e51818e..4d2ca5137ea 100644 --- a/hotspot/src/share/vm/runtime/interfaceSupport.hpp +++ b/hotspot/src/share/vm/runtime/interfaceSupport.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 @@ -56,7 +56,7 @@ class HandleMarkCleaner: public StackObj { } private: - inline void* operator new(size_t size, void* ptr) { + inline void* operator new(size_t size, void* ptr) throw() { return ptr; } }; @@ -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/objectMonitor.hpp b/hotspot/src/share/vm/runtime/objectMonitor.hpp index f0e6ed5f8d5..10b3609c0bb 100644 --- a/hotspot/src/share/vm/runtime/objectMonitor.hpp +++ b/hotspot/src/share/vm/runtime/objectMonitor.hpp @@ -312,10 +312,10 @@ public: public: static int Knob_Verbose; static int Knob_SpinLimit; - void* operator new (size_t size) { + void* operator new (size_t size) throw() { return AllocateHeap(size, mtInternal); } - void* operator new[] (size_t size) { + void* operator new[] (size_t size) throw() { return operator new (size); } void operator delete(void* p) { diff --git a/hotspot/src/share/vm/runtime/os.cpp b/hotspot/src/share/vm/runtime/os.cpp index 5ad88e34872..0c83565195c 100644 --- a/hotspot/src/share/vm/runtime/os.cpp +++ b/hotspot/src/share/vm/runtime/os.cpp @@ -1485,44 +1485,6 @@ bool os::is_server_class_machine() { return result; } -// Read file line by line, if line is longer than bsize, -// skip rest of line. -int os::get_line_chars(int fd, char* buf, const size_t bsize){ - size_t sz, i = 0; - - // read until EOF, EOL or buf is full - while ((sz = (int) read(fd, &buf[i], 1)) == 1 && i < (bsize-2) && buf[i] != '\n') { - ++i; - } - - if (buf[i] == '\n') { - // EOL reached so ignore EOL character and return - - buf[i] = 0; - return (int) i; - } - - buf[i+1] = 0; - - if (sz != 1) { - // EOF reached. if we read chars before EOF return them and - // return EOF on next call otherwise return EOF - - return (i == 0) ? -1 : (int) i; - } - - // line is longer than size of buf, skip to EOL - char ch; - while (read(fd, &ch, 1) == 1 && ch != '\n') { - // Do nothing - } - - // return initial part of line that fits in buf. - // If we reached EOF, it will be returned on next call. - - return (int) i; -} - void os::SuspendedThreadTask::run() { assert(Threads_lock->owned_by_self() || (_thread == VMThread::vm_thread()), "must have threads lock to call this"); internal_do_task(); diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 92bce000531..e43d68981cb 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -738,10 +738,6 @@ class os: AllStatic { // Hook for os specific jvm options that we don't want to abort on seeing static bool obsolete_option(const JavaVMOption *option); - // Read file line by line. If line is longer than bsize, - // rest of line is skipped. Returns number of bytes read or -1 on EOF - static int get_line_chars(int fd, char *buf, const size_t bsize); - // Extensions #include "runtime/os_ext.hpp" diff --git a/hotspot/src/share/vm/runtime/park.cpp b/hotspot/src/share/vm/runtime/park.cpp index 6fb0224ff44..6380570ef50 100644 --- a/hotspot/src/share/vm/runtime/park.cpp +++ b/hotspot/src/share/vm/runtime/park.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 @@ -140,7 +140,7 @@ void ParkEvent::Release (ParkEvent * ev) { // well as bank access imbalance on Niagara-like platforms, // although Niagara's hash function should help. -void * ParkEvent::operator new (size_t sz) { +void * ParkEvent::operator new (size_t sz) throw() { return (void *) ((intptr_t (AllocateHeap(sz + 256, mtInternal, CALLER_PC)) + 256) & -256) ; } diff --git a/hotspot/src/share/vm/runtime/park.hpp b/hotspot/src/share/vm/runtime/park.hpp index 4b72bb60962..504cb1a8524 100644 --- a/hotspot/src/share/vm/runtime/park.hpp +++ b/hotspot/src/share/vm/runtime/park.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2010, 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 @@ -166,7 +166,7 @@ class ParkEvent : public os::PlatformEvent { // aligned on 256-byte address boundaries. This ensures that the least // significant byte of a ParkEvent address is always 0. - void * operator new (size_t sz) ; + void * operator new (size_t sz) throw(); void operator delete (void * a) ; public: diff --git a/hotspot/src/share/vm/runtime/sharedRuntime.cpp b/hotspot/src/share/vm/runtime/sharedRuntime.cpp index 874f5939146..d014eda2f80 100644 --- a/hotspot/src/share/vm/runtime/sharedRuntime.cpp +++ b/hotspot/src/share/vm/runtime/sharedRuntime.cpp @@ -1051,7 +1051,8 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, // Find receiver for non-static call if (bc != Bytecodes::_invokestatic && - bc != Bytecodes::_invokedynamic) { + bc != Bytecodes::_invokedynamic && + bc != Bytecodes::_invokehandle) { // This register map must be update since we need to find the receiver for // compiled frames. The receiver might be in a register. RegisterMap reg_map2(thread); @@ -1078,7 +1079,7 @@ Handle SharedRuntime::find_callee_info_helper(JavaThread* thread, #ifdef ASSERT // Check that the receiver klass is of the right subtype and that it is initialized for virtual calls - if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic) { + if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic && bc != Bytecodes::_invokehandle) { assert(receiver.not_null(), "should have thrown exception"); KlassHandle receiver_klass(THREAD, receiver->klass()); Klass* rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle)); @@ -1240,9 +1241,9 @@ methodHandle SharedRuntime::resolve_sub_helper(JavaThread *thread, #endif if (is_virtual) { - assert(receiver.not_null(), "sanity check"); + assert(receiver.not_null() || invoke_code == Bytecodes::_invokehandle, "sanity check"); bool static_bound = call_info.resolved_method()->can_be_statically_bound(); - KlassHandle h_klass(THREAD, receiver->klass()); + KlassHandle h_klass(THREAD, invoke_code == Bytecodes::_invokehandle ? NULL : receiver->klass()); CompiledIC::compute_monomorphic_entry(callee_method, h_klass, is_optimized, static_bound, virtual_call_info, CHECK_(methodHandle())); diff --git a/hotspot/src/share/vm/runtime/thread.cpp b/hotspot/src/share/vm/runtime/thread.cpp index 18b46c988e3..d5bc3a00006 100644 --- a/hotspot/src/share/vm/runtime/thread.cpp +++ b/hotspot/src/share/vm/runtime/thread.cpp @@ -3636,6 +3636,16 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { CompileBroker::compilation_init(); #endif + if (EnableInvokeDynamic) { + // Pre-initialize some JSR292 core classes to avoid deadlock during class loading. + // It is done after compilers are initialized, because otherwise compilations of + // signature polymorphic MH intrinsics can be missed + // (see SystemDictionary::find_method_handle_intrinsic). + initialize_class(vmSymbols::java_lang_invoke_MethodHandle(), CHECK_0); + initialize_class(vmSymbols::java_lang_invoke_MemberName(), CHECK_0); + initialize_class(vmSymbols::java_lang_invoke_MethodHandleNatives(), CHECK_0); + } + #if INCLUDE_MANAGEMENT Management::initialize(THREAD); #endif // INCLUDE_MANAGEMENT diff --git a/hotspot/src/share/vm/runtime/thread.hpp b/hotspot/src/share/vm/runtime/thread.hpp index 2c8c1875491..2afaf2a8f62 100644 --- a/hotspot/src/share/vm/runtime/thread.hpp +++ b/hotspot/src/share/vm/runtime/thread.hpp @@ -113,8 +113,9 @@ class Thread: public ThreadShadow { // Support for forcing alignment of thread objects for biased locking void* _real_malloc_address; public: - void* operator new(size_t size) { return allocate(size, true); } - void* operator new(size_t size, const std::nothrow_t& nothrow_constant) { return allocate(size, false); } + void* operator new(size_t size) throw() { return allocate(size, true); } + void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { + return allocate(size, false); } void operator delete(void* p); protected: diff --git a/hotspot/src/share/vm/services/memRecorder.hpp b/hotspot/src/share/vm/services/memRecorder.hpp index c52fad72eae..4329dad0267 100644 --- a/hotspot/src/share/vm/services/memRecorder.hpp +++ b/hotspot/src/share/vm/services/memRecorder.hpp @@ -53,13 +53,13 @@ template class FixedSizeMemPointerArray : } } - void* operator new(size_t size, const std::nothrow_t& nothrow_constant) { + void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder' // to avoid recursion return os::malloc(size, (mtNMT | otNMTRecorder)); } - void* operator new(size_t size) { + void* operator new(size_t size) throw() { assert(false, "use nothrow version"); return NULL; } diff --git a/hotspot/src/share/vm/services/memTrackWorker.cpp b/hotspot/src/share/vm/services/memTrackWorker.cpp index 3e9bcd2f6c4..e1382dd1a3a 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.cpp +++ b/hotspot/src/share/vm/services/memTrackWorker.cpp @@ -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 @@ -63,12 +63,12 @@ MemTrackWorker::~MemTrackWorker() { } } -void* MemTrackWorker::operator new(size_t size) { +void* MemTrackWorker::operator new(size_t size) throw() { assert(false, "use nothrow version"); return NULL; } -void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) { +void* MemTrackWorker::operator new(size_t size, const std::nothrow_t& nothrow_constant) throw() { return allocate(size, false, mtNMT); } diff --git a/hotspot/src/share/vm/services/memTrackWorker.hpp b/hotspot/src/share/vm/services/memTrackWorker.hpp index 5d49ae1938e..ee45244e324 100644 --- a/hotspot/src/share/vm/services/memTrackWorker.hpp +++ b/hotspot/src/share/vm/services/memTrackWorker.hpp @@ -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 @@ -90,8 +90,8 @@ class MemTrackWorker : public NamedThread { public: MemTrackWorker(MemSnapshot* snapshot); ~MemTrackWorker(); - _NOINLINE_ void* operator new(size_t size); - _NOINLINE_ void* operator new(size_t size, const std::nothrow_t& nothrow_constant); + _NOINLINE_ void* operator new(size_t size) throw(); + _NOINLINE_ void* operator new(size_t size, const std::nothrow_t& nothrow_constant) throw(); void start(); void run(); 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/array.hpp b/hotspot/src/share/vm/utilities/array.hpp index 048a5781269..fb32f5ca8fd 100644 --- a/hotspot/src/share/vm/utilities/array.hpp +++ b/hotspot/src/share/vm/utilities/array.hpp @@ -317,7 +317,7 @@ protected: Array(const Array&); void operator=(const Array&); - void* operator new(size_t size, ClassLoaderData* loader_data, int length, bool read_only, TRAPS) { + void* operator new(size_t size, ClassLoaderData* loader_data, int length, bool read_only, TRAPS) throw() { size_t word_size = Array::size(length); return (void*) Metaspace::allocate(loader_data, word_size, read_only, MetaspaceObj::array_type(sizeof(T)), CHECK_NULL); diff --git a/hotspot/test/compiler/gcbarriers/G1CrashTest.java b/hotspot/test/compiler/gcbarriers/G1CrashTest.java new file mode 100644 index 00000000000..e8c6f015132 --- /dev/null +++ b/hotspot/test/compiler/gcbarriers/G1CrashTest.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. + * + */ + +/** + * @test + * @bug 8023472 + * @summary C2 optimization breaks with G1 + * + * @run main/othervm -Xbatch -XX:+IgnoreUnrecognizedVMOptions -XX:-TieredCompilation -Dcount=100000 G1CrashTest + * + * @author pbiswal@palantir.com + */ + +public class G1CrashTest { + static Object[] set = new Object[11]; + + public static void main(String[] args) throws InterruptedException { + for (int j = 0; j < Integer.getInteger("count"); j++) { + Object key = new Object(); + insertKey(key); + if (j > set.length / 2) { + Object[] oldKeys = set; + set = new Object[2 * set.length - 1]; + for (Object o : oldKeys) { + if (o != null) + insertKey(o); + } + } + } + } + + static void insertKey(Object key) { + int hash = key.hashCode() & 0x7fffffff; + int index = hash % set.length; + Object cur = set[index]; + if (cur == null) + set[index] = key; + else + insertKeyRehash(key, index, hash, cur); + } + + static void insertKeyRehash(Object key, int index, int hash, Object cur) { + int loopIndex = index; + int firstRemoved = -1; + do { + if (cur == "dead") + firstRemoved = 1; + index--; + if (index < 0) + index += set.length; + cur = set[index]; + if (cur == null) { + if (firstRemoved != -1) + set[firstRemoved] = "dead"; + else + set[index] = key; + return; + } + } while (index != loopIndex); + if (firstRemoved != -1) + set[firstRemoved] = null; + } +} diff --git a/hotspot/test/compiler/jsr292/ConcurrentClassLoadingTest.java b/hotspot/test/compiler/jsr292/ConcurrentClassLoadingTest.java new file mode 100644 index 00000000000..35430c0274d --- /dev/null +++ b/hotspot/test/compiler/jsr292/ConcurrentClassLoadingTest.java @@ -0,0 +1,194 @@ +/* + * 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 8022595 + * @summary JSR292: deadlock during class loading of MethodHandles, MethodHandleImpl & MethodHandleNatives + * + * @run main/othervm ConcurrentClassLoadingTest + */ +import java.util.*; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; + +public class ConcurrentClassLoadingTest { + int numThreads = 0; + long seed = 0; + CyclicBarrier l; + Random rand; + + public static void main(String[] args) throws Throwable { + ConcurrentClassLoadingTest test = new ConcurrentClassLoadingTest(); + test.parseArgs(args); + test.run(); + } + + void parseArgs(String[] args) { + int i = 0; + while (i < args.length) { + String flag = args[i]; + switch(flag) { + case "-seed": + seed = Long.parseLong(args[++i]); + break; + case "-numThreads": + numThreads = Integer.parseInt(args[++i]); + break; + default: + throw new Error("Unknown flag: " + flag); + } + ++i; + } + } + + void init() { + if (numThreads == 0) { + numThreads = Runtime.getRuntime().availableProcessors(); + } + + if (seed == 0) { + seed = (new Random()).nextLong(); + } + rand = new Random(seed); + + l = new CyclicBarrier(numThreads + 1); + + System.out.printf("Threads: %d\n", numThreads); + System.out.printf("Seed: %d\n", seed); + } + + final List loaders = new ArrayList<>(); + + void prepare() { + List c = new ArrayList<>(Arrays.asList(classNames)); + + // Split classes between loading threads + int count = (classNames.length / numThreads) + 1; + for (int t = 0; t < numThreads; t++) { + List sel = new ArrayList<>(); + + System.out.printf("Thread #%d:\n", t); + for (int i = 0; i < count; i++) { + if (c.size() == 0) break; + + int k = rand.nextInt(c.size()); + String elem = c.remove(k); + sel.add(elem); + System.out.printf("\t%s\n", elem); + } + loaders.add(new Loader(sel)); + } + + // Print diagnostic info when the test hangs + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + boolean alive = false; + for (Loader l : loaders) { + if (!l.isAlive()) continue; + + if (!alive) { + System.out.println("Some threads are still alive:"); + alive = true; + } + + System.out.println(l.getName()); + for (StackTraceElement elem : l.getStackTrace()) { + System.out.println("\t"+elem.toString()); + } + } + } + }); + } + + public void run() throws Throwable { + init(); + prepare(); + + for (Loader loader : loaders) { + loader.start(); + } + + l.await(); + + for (Loader loader : loaders) { + loader.join(); + } + } + + class Loader extends Thread { + List classes; + + public Loader(List classes) { + this.classes = classes; + setDaemon(true); + } + + @Override + public void run() { + try { + l.await(); + + for (String name : classes) { + Class.forName(name).getName(); + } + } catch (ClassNotFoundException | BrokenBarrierException | InterruptedException e) { + throw new Error(e); + } + } + } + + final static String[] classNames = { + "java.lang.invoke.AbstractValidatingLambdaMetafactory", + "java.lang.invoke.BoundMethodHandle", + "java.lang.invoke.CallSite", + "java.lang.invoke.ConstantCallSite", + "java.lang.invoke.DirectMethodHandle", + "java.lang.invoke.InnerClassLambdaMetafactory", + "java.lang.invoke.InvokeDynamic", + "java.lang.invoke.InvokeGeneric", + "java.lang.invoke.InvokerBytecodeGenerator", + "java.lang.invoke.Invokers", + "java.lang.invoke.LambdaConversionException", + "java.lang.invoke.LambdaForm", + "java.lang.invoke.LambdaMetafactory", + "java.lang.invoke.MagicLambdaImpl", + "java.lang.invoke.MemberName", + "java.lang.invoke.MethodHandle", + "java.lang.invoke.MethodHandleImpl", + "java.lang.invoke.MethodHandleInfo", + "java.lang.invoke.MethodHandleNatives", + "java.lang.invoke.MethodHandleProxies", + "java.lang.invoke.MethodHandles", + "java.lang.invoke.MethodHandleStatics", + "java.lang.invoke.MethodType", + "java.lang.invoke.MethodTypeForm", + "java.lang.invoke.MutableCallSite", + "java.lang.invoke.SerializedLambda", + "java.lang.invoke.SimpleMethodHandle", + "java.lang.invoke.SwitchPoint", + "java.lang.invoke.TypeConvertingMethodAdapter", + "java.lang.invoke.VolatileCallSite", + "java.lang.invoke.WrongMethodTypeException" + }; +} diff --git a/hotspot/test/gc/TestVerifyDuringStartup.java b/hotspot/test/gc/TestVerifyDuringStartup.java index f4ac347f80e..4ac32bf118e 100644 --- a/hotspot/test/gc/TestVerifyDuringStartup.java +++ b/hotspot/test/gc/TestVerifyDuringStartup.java @@ -48,7 +48,7 @@ public class TestVerifyDuringStartup { "-XX:+VerifyDuringStartup", "-version"}); - System.out.print("Testing:\n" + JDKToolFinder.getJDKTool("java")); + System.out.print("Testing:\n" + JDKToolFinder.getCurrentJDKTool("java")); for (int i = 0; i < vmOpts.size(); i += 1) { System.out.print(" " + vmOpts.get(i)); } diff --git a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java index b1c8ad996d2..4ce2e82c771 100644 --- a/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java +++ b/hotspot/test/runtime/CDSCompressedKPtrs/CDSCompressedKPtrs.java @@ -51,9 +51,8 @@ public class CDSCompressedKPtrs { output.shouldHaveExitValue(0); } catch (RuntimeException e) { - // Report 'passed' if CDS was turned off because we could not allocate - // the klass metaspace at an address that would work with CDS. - output.shouldContain("Could not allocate metaspace at a compatible address"); + // Report 'passed' if CDS was turned off. + output.shouldContain("Unable to use shared archive"); output.shouldHaveExitValue(1); } } diff --git a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java index 0165b2cc782..7f36977ec70 100644 --- a/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java +++ b/hotspot/test/runtime/CDSCompressedKPtrs/XShareAuto.java @@ -69,7 +69,7 @@ public class XShareAuto { "-server", "-Xshare:on", "-XX:+UnlockDiagnosticVMOptions", "-XX:SharedArchiveFile=./sample.jsa", "-version"); output = new OutputAnalyzer(pb.start()); - output.shouldContain("Could not allocate metaspace at a compatible address"); + output.shouldContain("Unable to use shared archive"); output.shouldHaveExitValue(1); } } diff --git a/hotspot/test/runtime/InitialThreadOverflow/DoOverflow.java b/hotspot/test/runtime/InitialThreadOverflow/DoOverflow.java new file mode 100644 index 00000000000..958285ca915 --- /dev/null +++ b/hotspot/test/runtime/InitialThreadOverflow/DoOverflow.java @@ -0,0 +1,41 @@ +/* + * 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. + */ + +public class DoOverflow { + + static int count; + + public void overflow() { + count+=1; + overflow(); + } + + public static void printIt() { + System.out.println("Going to overflow stack"); + try { + new DoOverflow().overflow(); + } catch(java.lang.StackOverflowError e) { + System.out.println("Overflow OK " + count); + } + } +} diff --git a/hotspot/test/runtime/InitialThreadOverflow/invoke.cxx b/hotspot/test/runtime/InitialThreadOverflow/invoke.cxx new file mode 100644 index 00000000000..55213c0f3bf --- /dev/null +++ b/hotspot/test/runtime/InitialThreadOverflow/invoke.cxx @@ -0,0 +1,70 @@ +/* + * 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 +#include + +#include + +JavaVM* jvm; + +void * +floobydust (void *p) { + JNIEnv *env; + + jvm->AttachCurrentThread((void**)&env, NULL); + + jclass class_id = env->FindClass ("DoOverflow"); + assert (class_id); + + jmethodID method_id = env->GetStaticMethodID(class_id, "printIt", "()V"); + assert (method_id); + + env->CallStaticVoidMethod(class_id, method_id, NULL); + + jvm->DetachCurrentThread(); +} + +int +main (int argc, const char** argv) { + JavaVMOption options[1]; + options[0].optionString = (char*) "-Xss320k"; + + JavaVMInitArgs vm_args; + vm_args.version = JNI_VERSION_1_2; + vm_args.ignoreUnrecognized = JNI_TRUE; + vm_args.options = options; + vm_args.nOptions = 1; + + JNIEnv* env; + jint result = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); + assert(result >= 0); + + pthread_t thr; + pthread_create(&thr, NULL, floobydust, NULL); + pthread_join(thr, NULL); + + floobydust(NULL); + + return 0; +} diff --git a/hotspot/test/runtime/InitialThreadOverflow/testme.sh b/hotspot/test/runtime/InitialThreadOverflow/testme.sh new file mode 100644 index 00000000000..015a6bd43b1 --- /dev/null +++ b/hotspot/test/runtime/InitialThreadOverflow/testme.sh @@ -0,0 +1,73 @@ +#!/bin/sh + +# 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 testme.sh +# @bug 8009062 +# @summary Poor performance of JNI AttachCurrentThread after fix for 7017193 +# @compile DoOverflow.java +# @run shell testme.sh + +set -x +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 + +if [ "${VM_OS}" != "linux" ] +then + echo "Test only valid for Linux" + exit 0 +fi + +gcc_cmd=`which gcc` +if [ "x$gcc_cmd" == "x" ]; then + echo "WARNING: gcc not found. Cannot execute test." 2>&1 + exit 0; +fi + +CFLAGS="-m${VM_BITS}" + +LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH + +cp ${TESTSRC}${FS}invoke.cxx . + +# Copy the result of our @compile action: +cp ${TESTCLASSES}${FS}DoOverflow.class . + +echo "Compilation flag: ${COMP_FLAG}" +# Note pthread may not be found thus invoke creation will fail to be created. +# Check to ensure you have a /usr/lib/libpthread.so if you don't please look +# for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. + +$gcc_cmd -DLINUX ${CFLAGS} -o invoke \ + -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \ + -L${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ + -ljvm -lpthread invoke.cxx + +./invoke +exit $? diff --git a/hotspot/test/runtime/LoadClass/LoadClassNegative.java b/hotspot/test/runtime/LoadClass/LoadClassNegative.java new file mode 100644 index 00000000000..9955bca00eb --- /dev/null +++ b/hotspot/test/runtime/LoadClass/LoadClassNegative.java @@ -0,0 +1,51 @@ +/* + * 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 + * @key regression + * @bug 8020675 + * @summary make sure there is no fatal error if a class is loaded from an invalid jar file which is in the bootclasspath + * @library /testlibrary + * @build TestForName + * @build LoadClassNegative + * @run main LoadClassNegative + */ + +import java.io.File; +import com.oracle.java.testlibrary.*; + +public class LoadClassNegative { + + public static void main(String args[]) throws Exception { + String bootCP = "-Xbootclasspath/a:" + System.getProperty("test.src") + + File.separator + "dummy.jar"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + bootCP, + "TestForName"); + + OutputAnalyzer output = new OutputAnalyzer(pb.start()); + output.shouldContain("ClassNotFoundException"); + output.shouldHaveExitValue(0); + } +} diff --git a/hotspot/test/runtime/LoadClass/TestForName.java b/hotspot/test/runtime/LoadClass/TestForName.java new file mode 100644 index 00000000000..429d8691cf2 --- /dev/null +++ b/hotspot/test/runtime/LoadClass/TestForName.java @@ -0,0 +1,33 @@ +/* + * 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. + */ + +public class TestForName { + public static void main(String[] args) { + try { + Class cls = Class.forName("xxx"); + System.out.println("Class = " + cls.getName()); + } catch (ClassNotFoundException cnfe) { + cnfe.printStackTrace(); + } + } +} diff --git a/hotspot/test/runtime/LoadClass/dummy.jar b/hotspot/test/runtime/LoadClass/dummy.jar new file mode 100644 index 00000000000..e69de29bb2d diff --git a/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java b/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java index b956095697b..5c91f604a8e 100644 --- a/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java +++ b/hotspot/test/runtime/SharedArchiveFile/CdsSameObjectAlignment.java @@ -84,7 +84,7 @@ public class CdsSameObjectAlignment { // there is a chance such reservation will fail // If it does, it is NOT considered a failure of the feature, // rather a possible expected outcome, though not likely - output.shouldContain("Could not allocate metaspace at a compatible address"); + output.shouldContain("Unable to use shared archive"); output.shouldHaveExitValue(1); } } diff --git a/hotspot/test/runtime/contended/Options.java b/hotspot/test/runtime/contended/Options.java new file mode 100644 index 00000000000..589ec9b4131 --- /dev/null +++ b/hotspot/test/runtime/contended/Options.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 com.oracle.java.testlibrary.*; + +/* + * @test + * @bug 8006997 + * @summary ContendedPaddingWidth should be range-checked + * + * @library /testlibrary + * @run main Options + */ +public class Options { + + public static void main(String[] args) throws Exception { + ProcessBuilder pb; + OutputAnalyzer output; + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=-128", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be in between"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=-8", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be in between"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=-1", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be in between"); + output.shouldContain("must be a multiple of 8"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=0", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=1", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be a multiple of 8"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8184", "-version"); // 8192-8 = 8184 + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8191", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be a multiple of 8"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8192", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldHaveExitValue(0); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8193", "-version"); + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be in between"); + output.shouldContain("must be a multiple of 8"); + output.shouldHaveExitValue(1); + + pb = ProcessTools.createJavaProcessBuilder("-XX:ContendedPaddingWidth=8200", "-version"); // 8192+8 = 8200 + output = new OutputAnalyzer(pb.start()); + output.shouldContain("ContendedPaddingWidth"); + output.shouldContain("must be in between"); + output.shouldHaveExitValue(1); + + } + +} + diff --git a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java index 91ad6a8c8a9..a39abbd3626 100644 --- a/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java +++ b/hotspot/test/testlibrary/com/oracle/java/testlibrary/JDKToolFinder.java @@ -27,24 +27,43 @@ import java.io.File; 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 compile.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("compile.jdk"); + if (binPath == null) { + throw new RuntimeException("System property 'compile.jdk' not set. " + + "This property is normally set by jtreg. " + + "When running test separately, set this property using " + + "'-Dcompile.jdk=/path/to/jdk'."); + } + binPath += File.separatorChar + "bin" + File.separatorChar + tool; - return binPath; - } + return binPath; + } + /** + * Returns the full path to an executable in <current jdk>/bin based + * on System property {@code test.jdk} (set by jtreg test suite) + * + * @return Full path to an executable in jdk/bin + */ + public static String getCurrentJDKTool(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'."); + } + binPath += File.separatorChar + "bin" + File.separatorChar + tool; + + return binPath; + } } 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/jaxp/.hgtags b/jaxp/.hgtags index 4b34a22f505..e136f4f7d31 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -227,3 +227,5 @@ adf49c3ef83c160d53ece623049b2cdccaf78fc7 jdk8-b99 b1ceab582fc6d795b20aaa8a3fde2eba34af9399 jdk8-b103 a22fe9bd01e6c7e7ddc7995dfc9471711692b8d1 jdk8-b104 09a46ec11f880154886c70be03aff5ab2ddf0ab7 jdk8-b105 +d3be8e3b429df917e72c1c23e7920c651219b587 jdk8-b106 +d6a32e3831aab20a9a3bc78cdc0a60aaad725c6c jdk8-b107 diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 8becfa5e369..164a718d39c 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -227,3 +227,5 @@ b1fb4612a2caea52b5661b87509e560fa044b194 jdk8-b98 6cdc6ed987801c175a1217d0d3e53c3bd69ba52e jdk8-b103 42211ab0ab1cca51a050d184634cf1db7ef81fbf jdk8-b104 88390df7ed2cf128298a02c5e6d978f0a603cd58 jdk8-b105 +6908370afe834ff01739e8ec992d4246c74b7e6e jdk8-b106 +e3c9328f75638289a342ce15fbe532f05078946e jdk8-b107 diff --git a/jdk/.hgtags b/jdk/.hgtags index c20c5cde8f0..6eef7251ea8 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -228,3 +228,5 @@ e0f6039c0290b7381042a6fec3100a69a5a67e37 jdk8-b103 f1d8d15bfcb5ada858a942f8a31f6598f23214d1 jdk8-b104 1fe211ae3d2b8cc2dfc4f58d9a6eb96418679672 jdk8-b105 c817276bd870dfe1dcc3a3dbbc092436b6907f75 jdk8-b106 +eea685b9ccaa1980e0a7e07d6a3a84bcc7e9ab82 jdk8-b107 +006aaa5f069e7dd98fccdc696866c9f8582c087c jdk8-b108 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/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/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/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/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 dc4c250cf74..8b7612e416a 100644 --- a/jdk/make/sun/awt/Makefile +++ b/jdk/make/sun/awt/Makefile @@ -564,7 +564,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/makefiles/CompileNativeLibraries.gmk b/jdk/makefiles/CompileNativeLibraries.gmk index d507c92a594..8c59cecc4f7 100644 --- a/jdk/makefiles/CompileNativeLibraries.gmk +++ b/jdk/makefiles/CompileNativeLibraries.gmk @@ -474,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 @@ -1484,8 +1483,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),\ @@ -2963,8 +2961,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/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/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/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/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 f884f2efe03..a09aa2c86a4 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; @@ -2370,11 +2371,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) { @@ -2396,6 +2400,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); + } } /** @@ -2406,7 +2416,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; @@ -3253,8 +3263,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); } /** @@ -3275,16 +3284,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); } /** @@ -3296,8 +3303,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); } /** @@ -3308,52 +3314,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/security/cert/Certificate.java b/jdk/src/share/classes/java/security/cert/Certificate.java index 638a02e6f80..10544983d2c 100644 --- a/jdk/src/share/classes/java/security/cert/Certificate.java +++ b/jdk/src/share/classes/java/security/cert/Certificate.java @@ -66,6 +66,9 @@ public abstract class Certificate implements java.io.Serializable { // the certificate type private final String type; + /** Cache the hash code for the certiticate */ + private int hash = -1; // Default to -1 + /** * Creates a certificate of the specified type. * @@ -123,16 +126,16 @@ public abstract class Certificate implements java.io.Serializable { * @return the hashcode value. */ public int hashCode() { - int retval = 0; - try { - byte[] certData = X509CertImpl.getEncodedInternal(this); - for (int i = 1; i < certData.length; i++) { - retval += certData[i] * i; + int h = hash; + if (h == -1) { + try { + h = Arrays.hashCode(X509CertImpl.getEncodedInternal(this)); + } catch (CertificateException e) { + h = 0; } - return retval; - } catch (CertificateException e) { - return retval; + hash = h; } + return h; } /** diff --git a/jdk/src/share/classes/java/util/HashMap.java b/jdk/src/share/classes/java/util/HashMap.java index a6a7d152b5f..16880663f24 100644 --- a/jdk/src/share/classes/java/util/HashMap.java +++ b/jdk/src/share/classes/java/util/HashMap.java @@ -1132,6 +1132,8 @@ public class HashMap extends AbstractMap public V computeIfPresent(K key, BiFunction remappingFunction) { + if (remappingFunction == null) + throw new NullPointerException(); Node e; V oldValue; int hash = hash(key); if ((e = getNode(hash, key)) != null && diff --git a/jdk/src/share/classes/java/util/Map.java b/jdk/src/share/classes/java/util/Map.java index 4340e6d9c8f..bf1ba8391c8 100644 --- a/jdk/src/share/classes/java/util/Map.java +++ b/jdk/src/share/classes/java/util/Map.java @@ -934,6 +934,7 @@ public interface Map { */ default V computeIfAbsent(K key, Function mappingFunction) { + Objects.requireNonNull(mappingFunction); V v, newValue; return ((v = get(key)) == null && (newValue = mappingFunction.apply(key)) != null && @@ -992,6 +993,7 @@ public interface Map { */ default V computeIfPresent(K key, BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); V oldValue; while ((oldValue = get(key)) != null) { V newValue = remappingFunction.apply(key, oldValue); @@ -1068,6 +1070,7 @@ public interface Map { */ default V compute(K key, BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); V oldValue = get(key); for (;;) { V newValue = remappingFunction.apply(key, oldValue); @@ -1174,6 +1177,7 @@ public interface Map { */ default V merge(K key, V value, BiFunction remappingFunction) { + Objects.requireNonNull(remappingFunction); V oldValue = get(key); for (;;) { if (oldValue != null) { diff --git a/jdk/src/share/classes/java/util/Spliterator.java b/jdk/src/share/classes/java/util/Spliterator.java index 542aec76cde..08d8f1522ca 100644 --- a/jdk/src/share/classes/java/util/Spliterator.java +++ b/jdk/src/share/classes/java/util/Spliterator.java @@ -539,7 +539,7 @@ public interface Spliterator { * Spliterator is expected to have a documented policy concerning the impact * of modifications during traversal. * - *

    A top-level Spliterator should not report {@code CONCURRENT} and + *

    A top-level Spliterator should not report both {@code CONCURRENT} and * {@code SIZED}, since the finite size, if known, may change if the source * is concurrently modified during traversal. Such a Spliterator is * inconsistent and no guarantees can be made about any computation using diff --git a/jdk/src/share/classes/java/util/Spliterators.java b/jdk/src/share/classes/java/util/Spliterators.java index afa2fd379cc..3f97a833a68 100644 --- a/jdk/src/share/classes/java/util/Spliterators.java +++ b/jdk/src/share/classes/java/util/Spliterators.java @@ -409,16 +409,16 @@ public final class Spliterators { * * @param Type of elements * @param c The collection - * @param additionalCharacteristics Additional spliterator characteristics - * of this spliterator's source or elements beyond {@code SIZED} and - * {@code SUBSIZED} which are are always reported + * @param characteristics Characteristics of this spliterator's source or + * elements. The characteristics {@code SIZED} and {@code SUBSIZED} + * are additionally reported unless {@code CONCURRENT} is supplied. * @return A spliterator from an iterator * @throws NullPointerException if the given collection is {@code null} */ public static Spliterator spliterator(Collection c, - int additionalCharacteristics) { + int characteristics) { return new IteratorSpliterator<>(Objects.requireNonNull(c), - additionalCharacteristics); + characteristics); } /** @@ -439,17 +439,17 @@ public final class Spliterators { * @param iterator The iterator for the source * @param size The number of elements in the source, to be reported as * initial {@code estimateSize} - * @param additionalCharacteristics Additional spliterator characteristics - * of this spliterator's source or elements beyond {@code SIZED} and - * {@code SUBSIZED} which are are always reported + * @param characteristics Characteristics of this spliterator's source or + * elements. The characteristics {@code SIZED} and {@code SUBSIZED} + * are additionally reported unless {@code CONCURRENT} is supplied. * @return A spliterator from an iterator * @throws NullPointerException if the given iterator is {@code null} */ public static Spliterator spliterator(Iterator iterator, long size, - int additionalCharacteristics) { + int characteristics) { return new IteratorSpliterator<>(Objects.requireNonNull(iterator), size, - additionalCharacteristics); + characteristics); } /** @@ -467,7 +467,7 @@ public final class Spliterators { * * @param Type of elements * @param iterator The iterator for the source - * @param characteristics Properties of this spliterator's source + * @param characteristics Characteristics of this spliterator's source * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are * ignored and are not reported.) * @return A spliterator from an iterator @@ -496,17 +496,17 @@ public final class Spliterators { * @param iterator The iterator for the source * @param size The number of elements in the source, to be reported as * initial {@code estimateSize}. - * @param additionalCharacteristics Additional spliterator characteristics - * of this spliterator's source or elements beyond {@code SIZED} and - * {@code SUBSIZED} which are are always reported + * @param characteristics Characteristics of this spliterator's source or + * elements. The characteristics {@code SIZED} and {@code SUBSIZED} + * are additionally reported unless {@code CONCURRENT} is supplied. * @return A spliterator from an iterator * @throws NullPointerException if the given iterator is {@code null} */ public static Spliterator.OfInt spliterator(PrimitiveIterator.OfInt iterator, long size, - int additionalCharacteristics) { + int characteristics) { return new IntIteratorSpliterator(Objects.requireNonNull(iterator), - size, additionalCharacteristics); + size, characteristics); } /** @@ -524,7 +524,7 @@ public final class Spliterators { * operated on after the spliterator is returned. * * @param iterator The iterator for the source - * @param characteristics Properties of this spliterator's source + * @param characteristics Characteristics of this spliterator's source * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are * ignored and are not reported.) * @return A spliterator from an iterator @@ -553,17 +553,17 @@ public final class Spliterators { * @param iterator The iterator for the source * @param size The number of elements in the source, to be reported as * initial {@code estimateSize}. - * @param additionalCharacteristics Additional spliterator characteristics - * of this spliterator's source or elements beyond {@code SIZED} and - * {@code SUBSIZED} which are are always reported + * @param characteristics Characteristics of this spliterator's source or + * elements. The characteristics {@code SIZED} and {@code SUBSIZED} + * are additionally reported unless {@code CONCURRENT} is supplied. * @return A spliterator from an iterator * @throws NullPointerException if the given iterator is {@code null} */ public static Spliterator.OfLong spliterator(PrimitiveIterator.OfLong iterator, long size, - int additionalCharacteristics) { + int characteristics) { return new LongIteratorSpliterator(Objects.requireNonNull(iterator), - size, additionalCharacteristics); + size, characteristics); } /** @@ -581,7 +581,7 @@ public final class Spliterators { * operated on after the spliterator is returned. * * @param iterator The iterator for the source - * @param characteristics Properties of this spliterator's source + * @param characteristics Characteristics of this spliterator's source * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are * ignored and are not reported.) * @return A spliterator from an iterator @@ -610,17 +610,17 @@ public final class Spliterators { * @param iterator The iterator for the source * @param size The number of elements in the source, to be reported as * initial {@code estimateSize} - * @param additionalCharacteristics Additional spliterator characteristics - * of this spliterator's source or elements beyond {@code SIZED} and - * {@code SUBSIZED} which are are always reported + * @param characteristics Characteristics of this spliterator's source or + * elements. The characteristics {@code SIZED} and {@code SUBSIZED} + * are additionally reported unless {@code CONCURRENT} is supplied. * @return A spliterator from an iterator * @throws NullPointerException if the given iterator is {@code null} */ public static Spliterator.OfDouble spliterator(PrimitiveIterator.OfDouble iterator, long size, - int additionalCharacteristics) { + int characteristics) { return new DoubleIteratorSpliterator(Objects.requireNonNull(iterator), - size, additionalCharacteristics); + size, characteristics); } /** @@ -638,7 +638,7 @@ public final class Spliterators { * operated on after the spliterator is returned. * * @param iterator The iterator for the source - * @param characteristics Properties of this spliterator's source + * @param characteristics Characteristics of this spliterator's source * or elements ({@code SIZED} and {@code SUBSIZED}, if supplied, are * ignored and are not reported.) * @return A spliterator from an iterator @@ -1710,7 +1710,9 @@ public final class Spliterators { public IteratorSpliterator(Collection collection, int characteristics) { this.collection = collection; this.it = null; - this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED; + this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0 + ? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED + : characteristics; } /** @@ -1727,7 +1729,9 @@ public final class Spliterators { this.collection = null; this.it = iterator; this.est = size; - this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED; + this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0 + ? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED + : characteristics; } /** @@ -1857,7 +1861,9 @@ public final class Spliterators { public IntIteratorSpliterator(PrimitiveIterator.OfInt iterator, long size, int characteristics) { this.it = iterator; this.est = size; - this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED; + this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0 + ? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED + : characteristics; } /** @@ -1949,7 +1955,9 @@ public final class Spliterators { public LongIteratorSpliterator(PrimitiveIterator.OfLong iterator, long size, int characteristics) { this.it = iterator; this.est = size; - this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED; + this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0 + ? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED + : characteristics; } /** @@ -2041,7 +2049,9 @@ public final class Spliterators { public DoubleIteratorSpliterator(PrimitiveIterator.OfDouble iterator, long size, int characteristics) { this.it = iterator; this.est = size; - this.characteristics = characteristics | Spliterator.SIZED | Spliterator.SUBSIZED; + this.characteristics = (characteristics & Spliterator.CONCURRENT) == 0 + ? characteristics | Spliterator.SIZED | Spliterator.SUBSIZED + : characteristics; } /** diff --git a/jdk/src/share/classes/java/util/SplittableRandom.java b/jdk/src/share/classes/java/util/SplittableRandom.java index 5a990f4d215..c3f5c0b4234 100644 --- a/jdk/src/share/classes/java/util/SplittableRandom.java +++ b/jdk/src/share/classes/java/util/SplittableRandom.java @@ -25,8 +25,7 @@ package java.util; -import java.security.SecureRandom; -import java.net.InetAddress; +import java.net.NetworkInterface; import java.util.concurrent.atomic.AtomicLong; import java.util.function.IntConsumer; import java.util.function.LongConsumer; @@ -242,12 +241,34 @@ public final class SplittableRandom { s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); return s; } - int hh = 0; // hashed host address + long h = 0L; try { - hh = InetAddress.getLocalHost().hashCode(); + Enumeration ifcs = + NetworkInterface.getNetworkInterfaces(); + boolean retry = false; // retry once if getHardwareAddress is null + while (ifcs.hasMoreElements()) { + NetworkInterface ifc = ifcs.nextElement(); + if (!ifc.isVirtual()) { // skip fake addresses + byte[] bs = ifc.getHardwareAddress(); + if (bs != null) { + int n = bs.length; + int m = Math.min(n >>> 1, 4); + for (int i = 0; i < m; ++i) + h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i]; + if (m < 4) + h = (h << 8) ^ bs[n-1-m]; + h = mix64(h); + break; + } + else if (!retry) + retry = true; + else + break; + } + } } catch (Exception ignore) { } - return (mix64((((long)hh) << 32) ^ System.currentTimeMillis()) ^ + return (h ^ mix64(System.currentTimeMillis()) ^ mix64(System.nanoTime())); } diff --git a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java index 297f88cd5a3..2cd2b0094bf 100644 --- a/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/jdk/src/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -36,6 +36,8 @@ package java.util.concurrent; import java.io.ObjectStreamField; +import java.net.NetworkInterface; +import java.util.Enumeration; import java.util.Random; import java.util.Spliterator; import java.util.concurrent.atomic.AtomicInteger; @@ -71,7 +73,10 @@ import java.util.stream.StreamSupport; * *

    Instances of {@code ThreadLocalRandom} are not cryptographically * secure. Consider instead using {@link java.security.SecureRandom} - * in security-sensitive applications. + * in security-sensitive applications. Additionally, + * default-constructed instances do not use a cryptographically random + * seed unless the {@linkplain System#getProperty system property} + * {@code java.util.secureRandomSeed} is set to {@code true}. * * @since 1.7 * @author Doug Lea @@ -129,9 +134,49 @@ public class ThreadLocalRandom extends Random { /** * The next seed for default constructors. */ - private static final AtomicLong seeder = - new AtomicLong(mix64(System.currentTimeMillis()) ^ - mix64(System.nanoTime())); + private static final AtomicLong seeder = new AtomicLong(initialSeed()); + + private static long initialSeed() { + String pp = java.security.AccessController.doPrivileged( + new sun.security.action.GetPropertyAction( + "java.util.secureRandomSeed")); + if (pp != null && pp.equalsIgnoreCase("true")) { + byte[] seedBytes = java.security.SecureRandom.getSeed(8); + long s = (long)(seedBytes[0]) & 0xffL; + for (int i = 1; i < 8; ++i) + s = (s << 8) | ((long)(seedBytes[i]) & 0xffL); + return s; + } + long h = 0L; + try { + Enumeration ifcs = + NetworkInterface.getNetworkInterfaces(); + boolean retry = false; // retry once if getHardwareAddress is null + while (ifcs.hasMoreElements()) { + NetworkInterface ifc = ifcs.nextElement(); + if (!ifc.isVirtual()) { // skip fake addresses + byte[] bs = ifc.getHardwareAddress(); + if (bs != null) { + int n = bs.length; + int m = Math.min(n >>> 1, 4); + for (int i = 0; i < m; ++i) + h = (h << 16) ^ (bs[i] << 8) ^ bs[n-1-i]; + if (m < 4) + h = (h << 8) ^ bs[n-1-m]; + h = mix64(h); + break; + } + else if (!retry) + retry = true; + else + break; + } + } + } catch (Exception ignore) { + } + return (h ^ mix64(System.currentTimeMillis()) ^ + mix64(System.nanoTime())); + } /** * The seed increment diff --git a/jdk/src/share/classes/java/util/regex/Pattern.java b/jdk/src/share/classes/java/util/regex/Pattern.java index 1dc72c10cd3..81ea7145a78 100644 --- a/jdk/src/share/classes/java/util/regex/Pattern.java +++ b/jdk/src/share/classes/java/util/regex/Pattern.java @@ -5755,7 +5755,8 @@ NEXT: while (i <= last) { * input sequence that is terminated by another subsequence that matches * this pattern or is terminated by the end of the input sequence. The * substrings in the stream are in the order in which they occur in the - * input. + * input. Trailing empty strings will be discarded and not encountered in + * the stream. * *

    If this pattern does not match any subsequence of the input then * the resulting stream has just one element, namely the input sequence in @@ -5781,6 +5782,8 @@ NEXT: while (i <= last) { private int current; // null if the next element, if any, needs to obtained private String nextElement; + // > 0 if there are N next empty elements + private int emptyElementCount; MatcherIterator() { this.matcher = matcher(input); @@ -5790,26 +5793,46 @@ NEXT: while (i <= last) { if (!hasNext()) throw new NoSuchElementException(); - String n = nextElement; - nextElement = null; - return n; + if (emptyElementCount == 0) { + String n = nextElement; + nextElement = null; + return n; + } else { + emptyElementCount--; + return ""; + } } public boolean hasNext() { - if (nextElement != null) + if (nextElement != null || emptyElementCount > 0) return true; if (current == input.length()) return false; - if (matcher.find()) { + // Consume the next matching element + // Count sequence of matching empty elements + while (matcher.find()) { nextElement = input.subSequence(current, matcher.start()).toString(); current = matcher.end(); - } else { - nextElement = input.subSequence(current, input.length()).toString(); - current = input.length(); + if (!nextElement.isEmpty()) { + return true; + } else { + emptyElementCount++; + } + } + + // Consume last matching element + nextElement = input.subSequence(current, input.length()).toString(); + current = input.length(); + if (!nextElement.isEmpty()) { + return true; + } else { + // Ignore a terminal sequence of matching empty elements + emptyElementCount = 0; + nextElement = null; + return false; } - return true; } } return StreamSupport.stream(Spliterators.spliteratorUnknownSize( diff --git a/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java b/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java index a70fb3a3571..7a3adaa5ad8 100644 --- a/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanAttributeInfo.java @@ -286,10 +286,10 @@ public class MBeanAttributeInfo extends MBeanFeatureInfo implements Cloneable { if (!(o instanceof MBeanAttributeInfo)) return false; MBeanAttributeInfo p = (MBeanAttributeInfo) o; - return (p.getName().equals(getName()) && - p.getType().equals(getType()) && - p.getDescription().equals(getDescription()) && - p.getDescriptor().equals(getDescriptor()) && + return (Objects.equals(p.getName(), getName()) && + Objects.equals(p.getType(), getType()) && + Objects.equals(p.getDescription(), getDescription()) && + Objects.equals(p.getDescriptor(), getDescriptor()) && p.isReadable() == isReadable() && p.isWritable() == isWritable() && p.isIs() == isIs()); diff --git a/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java b/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java index ad2176367d2..d02ffce3a8d 100644 --- a/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanConstructorInfo.java @@ -191,10 +191,10 @@ public class MBeanConstructorInfo extends MBeanFeatureInfo implements Cloneable if (!(o instanceof MBeanConstructorInfo)) return false; MBeanConstructorInfo p = (MBeanConstructorInfo) o; - return (p.getName().equals(getName()) && - p.getDescription().equals(getDescription()) && + return (Objects.equals(p.getName(), getName()) && + Objects.equals(p.getDescription(), getDescription()) && Arrays.equals(p.fastGetSignature(), fastGetSignature()) && - p.getDescriptor().equals(getDescriptor())); + Objects.equals(p.getDescriptor(), getDescriptor())); } /* Unlike attributes and operations, it's quite likely we'll have diff --git a/jdk/src/share/classes/javax/management/MBeanFeatureInfo.java b/jdk/src/share/classes/javax/management/MBeanFeatureInfo.java index a2349a8c69f..ec8e8b622b8 100644 --- a/jdk/src/share/classes/javax/management/MBeanFeatureInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanFeatureInfo.java @@ -30,6 +30,7 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import java.io.StreamCorruptedException; +import java.util.Objects; /** *

    Provides general information for an MBean descriptor object. @@ -147,9 +148,9 @@ public class MBeanFeatureInfo implements Serializable, DescriptorRead { if (!(o instanceof MBeanFeatureInfo)) return false; MBeanFeatureInfo p = (MBeanFeatureInfo) o; - return (p.getName().equals(getName()) && - p.getDescription().equals(getDescription()) && - p.getDescriptor().equals(getDescriptor())); + return (Objects.equals(p.getName(), getName()) && + Objects.equals(p.getDescription(), getDescription()) && + Objects.equals(p.getDescriptor(), getDescriptor())); } public int hashCode() { diff --git a/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java b/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java index b4bbbe80292..ad1c74f83d5 100644 --- a/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanNotificationInfo.java @@ -26,6 +26,7 @@ package javax.management; import java.util.Arrays; +import java.util.Objects; /** *

    The MBeanNotificationInfo class is used to describe the @@ -191,9 +192,9 @@ public class MBeanNotificationInfo extends MBeanFeatureInfo implements Cloneable if (!(o instanceof MBeanNotificationInfo)) return false; MBeanNotificationInfo p = (MBeanNotificationInfo) o; - return (p.getName().equals(getName()) && - p.getDescription().equals(getDescription()) && - p.getDescriptor().equals(getDescriptor()) && + return (Objects.equals(p.getName(), getName()) && + Objects.equals(p.getDescription(), getDescription()) && + Objects.equals(p.getDescriptor(), getDescriptor()) && Arrays.equals(p.fastGetNotifTypes(), fastGetNotifTypes())); } diff --git a/jdk/src/share/classes/javax/management/MBeanOperationInfo.java b/jdk/src/share/classes/javax/management/MBeanOperationInfo.java index 8effa04f8d8..1be6d8f563a 100644 --- a/jdk/src/share/classes/javax/management/MBeanOperationInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanOperationInfo.java @@ -294,12 +294,12 @@ public class MBeanOperationInfo extends MBeanFeatureInfo implements Cloneable { if (!(o instanceof MBeanOperationInfo)) return false; MBeanOperationInfo p = (MBeanOperationInfo) o; - return (p.getName().equals(getName()) && - p.getReturnType().equals(getReturnType()) && - p.getDescription().equals(getDescription()) && + return (Objects.equals(p.getName(), getName()) && + Objects.equals(p.getReturnType(), getReturnType()) && + Objects.equals(p.getDescription(), getDescription()) && p.getImpact() == getImpact() && Arrays.equals(p.fastGetSignature(), fastGetSignature()) && - p.getDescriptor().equals(getDescriptor())); + Objects.equals(p.getDescriptor(), getDescriptor())); } /* We do not include everything in the hashcode. We assume that diff --git a/jdk/src/share/classes/javax/management/MBeanParameterInfo.java b/jdk/src/share/classes/javax/management/MBeanParameterInfo.java index df3d59087df..81f2eff840d 100644 --- a/jdk/src/share/classes/javax/management/MBeanParameterInfo.java +++ b/jdk/src/share/classes/javax/management/MBeanParameterInfo.java @@ -27,6 +27,7 @@ package javax.management; import java.util.Objects; + /** * Describes an argument of an operation exposed by an MBean. * Instances of this class are immutable. Subclasses may be mutable @@ -137,10 +138,10 @@ public class MBeanParameterInfo extends MBeanFeatureInfo implements Cloneable { if (!(o instanceof MBeanParameterInfo)) return false; MBeanParameterInfo p = (MBeanParameterInfo) o; - return (p.getName().equals(getName()) && - p.getType().equals(getType()) && - p.getDescription().equals(getDescription()) && - p.getDescriptor().equals(getDescriptor())); + return (Objects.equals(p.getName(), getName()) && + Objects.equals(p.getType(), getType()) && + Objects.equals(p.getDescription(), getDescription()) && + Objects.equals(p.getDescriptor(), getDescriptor())); } public int hashCode() { diff --git a/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java b/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java index 1e24504b45a..fcaede43a94 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java +++ b/jdk/src/share/classes/sun/java2d/cmm/CMSManager.java @@ -104,53 +104,53 @@ public class CMSManager { cName = tcmm.getClass().getName(); } - public long loadProfile(byte[] data) { + public Profile loadProfile(byte[] data) { System.err.print(cName + ".loadProfile"); - long profileID = tcmm.loadProfile(data); - System.err.printf("(ID=%x)\n", profileID); - return profileID; + Profile p = tcmm.loadProfile(data); + System.err.printf("(ID=%s)\n", p.toString()); + return p; } - public void freeProfile(long profileID) { - System.err.printf(cName + ".freeProfile(ID=%x)\n", profileID); - tcmm.freeProfile(profileID); + public void freeProfile(Profile p) { + System.err.printf(cName + ".freeProfile(ID=%s)\n", p.toString()); + tcmm.freeProfile(p); } - public int getProfileSize(long profileID) { - System.err.print(cName + ".getProfileSize(ID=" + profileID + ")"); - int size = tcmm.getProfileSize(profileID); + public int getProfileSize(Profile p) { + System.err.print(cName + ".getProfileSize(ID=" + p + ")"); + int size = tcmm.getProfileSize(p); System.err.println("=" + size); return size; } - public void getProfileData(long profileID, byte[] data) { - System.err.print(cName + ".getProfileData(ID=" + profileID + ") "); + public void getProfileData(Profile p, byte[] data) { + System.err.print(cName + ".getProfileData(ID=" + p + ") "); System.err.println("requested " + data.length + " byte(s)"); - tcmm.getProfileData(profileID, data); + tcmm.getProfileData(p, data); } - public int getTagSize(long profileID, int tagSignature) { + public int getTagSize(Profile p, int tagSignature) { System.err.printf(cName + ".getTagSize(ID=%x, TagSig=%s)", - profileID, signatureToString(tagSignature)); - int size = tcmm.getTagSize(profileID, tagSignature); + p, signatureToString(tagSignature)); + int size = tcmm.getTagSize(p, tagSignature); System.err.println("=" + size); return size; } - public void getTagData(long profileID, int tagSignature, + public void getTagData(Profile p, int tagSignature, byte[] data) { System.err.printf(cName + ".getTagData(ID=%x, TagSig=%s)", - profileID, signatureToString(tagSignature)); + p, signatureToString(tagSignature)); System.err.println(" requested " + data.length + " byte(s)"); - tcmm.getTagData(profileID, tagSignature, data); + tcmm.getTagData(p, tagSignature, data); } - public void setTagData(long profileID, int tagSignature, + public void setTagData(Profile p, int tagSignature, byte[] data) { - System.err.print(cName + ".setTagData(ID=" + profileID + + System.err.print(cName + ".setTagData(ID=" + p + ", TagSig=" + tagSignature + ")"); System.err.println(" sending " + data.length + " byte(s)"); - tcmm.setTagData(profileID, tagSignature, data); + tcmm.setTagData(p, tagSignature, data); } /* methods for creating ColorTransforms */ diff --git a/jdk/src/share/classes/sun/java2d/cmm/PCMM.java b/jdk/src/share/classes/sun/java2d/cmm/PCMM.java index 6b6ce93546d..03f2fab6336 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/PCMM.java +++ b/jdk/src/share/classes/sun/java2d/cmm/PCMM.java @@ -32,13 +32,13 @@ import java.awt.color.ICC_Profile; public interface PCMM { /* methods invoked from ICC_Profile */ - public long loadProfile(byte[] data); - public void freeProfile(long profileID); - public int getProfileSize(long profileID); - public void getProfileData(long profileID, byte[] data); - public void getTagData(long profileID, int tagSignature, byte[] data); - public int getTagSize(long profileID, int tagSignature); - public void setTagData(long profileID, int tagSignature, byte[] data); + public Profile loadProfile(byte[] data); + public void freeProfile(Profile p); + public int getProfileSize(Profile p); + public void getProfileData(Profile p, byte[] data); + public void getTagData(Profile p, int tagSignature, byte[] data); + public int getTagSize(Profile p, int tagSignature); + public void setTagData(Profile p, int tagSignature, byte[] data); /* methods for creating ColorTransforms */ public ColorTransform createTransform(ICC_Profile profile, int renderType, diff --git a/jdk/src/share/classes/sun/java2d/cmm/Profile.java b/jdk/src/share/classes/sun/java2d/cmm/Profile.java new file mode 100644 index 00000000000..5b766b5d079 --- /dev/null +++ b/jdk/src/share/classes/sun/java2d/cmm/Profile.java @@ -0,0 +1,43 @@ +/* + * 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 sun.java2d.cmm; + +import java.awt.color.CMMException; + +public class Profile { + private final long nativePtr; + + protected Profile(long ptr) { + nativePtr = ptr; + } + + protected final long getNativePtr() { + if (nativePtr == 0L) { + throw new CMMException("Invalid profile: ptr is null"); + } + return nativePtr; + } +} diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java index f7ecc0b67c9..d76d99638a9 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMS.java @@ -25,96 +25,139 @@ package sun.java2d.cmm.lcms; +import java.awt.color.CMMException; import java.awt.color.ICC_Profile; -import java.util.Arrays; -import java.util.HashMap; import sun.java2d.cmm.ColorTransform; import sun.java2d.cmm.PCMM; +import sun.java2d.cmm.Profile; +import sun.java2d.cmm.lcms.LCMSProfile.TagData; public class LCMS implements PCMM { /* methods invoked from ICC_Profile */ @Override - public long loadProfile(byte[] data) { - long id = loadProfileNative(data); + public Profile loadProfile(byte[] data) { + final Object disposerRef = new Object(); - if (id != 0L) { - if (profiles == null) { - profiles = new HashMap<>(); - } - profiles.put(id, new TagCache(id)); + final long ptr = loadProfileNative(data, disposerRef); + + if (ptr != 0L) { + return new LCMSProfile(ptr, disposerRef); } - return id; + return null; } - private native long loadProfileNative(byte[] data); + private native long loadProfileNative(byte[] data, Object ref); - @Override - public void freeProfile(long profileID) { - TagCache c = profiles.remove(profileID); - if (c != null) { - c.clear(); + private LCMSProfile getLcmsProfile(Profile p) { + if (p instanceof LCMSProfile) { + return (LCMSProfile)p; } - if (profiles.isEmpty()) { - profiles = null; - } - freeProfileNative(profileID); + throw new CMMException("Invalid profile: " + p); } - private native void freeProfileNative(long profileID); - - public native synchronized int getProfileSize(long profileID); - - public native synchronized void getProfileData(long profileID, byte[] data); @Override - public synchronized int getTagSize(long profileID, int tagSignature) { - TagCache cache = profiles.get(profileID); - - if (cache == null) { - cache = new TagCache(profileID); - profiles.put(profileID, cache); - } - - TagData t = cache.getTag(tagSignature); - return t == null ? 0 : t.getSize(); + public void freeProfile(Profile p) { + // we use disposer, so this method does nothing } - private static native byte[] getTagNative(long profileID, int signature); + @Override + public int getProfileSize(final Profile p) { + synchronized (p) { + return getProfileSizeNative(getLcmsProfile(p).getLcmsPtr()); + } + } + + private native int getProfileSizeNative(long ptr); @Override - public synchronized void getTagData(long profileID, int tagSignature, - byte[] data) + public void getProfileData(final Profile p, byte[] data) { + synchronized (p) { + getProfileDataNative(getLcmsProfile(p).getLcmsPtr(), data); + } + } + + private native void getProfileDataNative(long ptr, byte[] data); + + @Override + public int getTagSize(Profile p, int tagSignature) { + final LCMSProfile profile = getLcmsProfile(p); + + synchronized (profile) { + TagData t = profile.getTag(tagSignature); + return t == null ? 0 : t.getSize(); + } + } + + static native byte[] getTagNative(long profileID, int signature); + + @Override + public void getTagData(Profile p, int tagSignature, byte[] data) { - TagCache cache = profiles.get(profileID); + final LCMSProfile profile = getLcmsProfile(p); - if (cache == null) { - cache = new TagCache(profileID); - profiles.put(profileID, cache); - } - - TagData t = cache.getTag(tagSignature); - if (t != null) { - t.copyDataTo(data); + synchronized (profile) { + TagData t = profile.getTag(tagSignature); + if (t != null) { + t.copyDataTo(data); + } } } @Override - public synchronized void setTagData(long profileID, int tagSignature, byte[] data) { - TagCache cache = profiles.get(profileID); + public synchronized void setTagData(Profile p, int tagSignature, byte[] data) { + final LCMSProfile profile = getLcmsProfile(p); - if (cache != null) { - cache.clear(); + synchronized (profile) { + profile.clearTagCache(); + + // Now we are going to update the profile with new tag data + // In some cases, we may change the pointer to the native + // profile. + // + // If we fail to write tag data for any reason, the old pointer + // should be used. + setTagDataNative(profile.getLcmsPtr(), + tagSignature, data); } - setTagDataNative(profileID, tagSignature, data); } - private native synchronized void setTagDataNative(long profileID, int tagSignature, + /** + * Writes supplied data as a tag into the profile. + * Destroys old profile, if new one was successfully + * created. + * + * Returns valid pointer to new profile. + * + * Throws CMMException if operation fails, preserve old profile from + * destruction. + */ + private native void setTagDataNative(long ptr, int tagSignature, byte[] data); - public static native long getProfileID(ICC_Profile profile); + public synchronized static native LCMSProfile getProfileID(ICC_Profile profile); - public static native long createNativeTransform( + /* Helper method used from LCMSColorTransfrom */ + static long createTransform( + LCMSProfile[] profiles, int renderType, + int inFormatter, boolean isInIntPacked, + int outFormatter, boolean isOutIntPacked, + Object disposerRef) + { + long[] ptrs = new long[profiles.length]; + + for (int i = 0; i < profiles.length; i++) { + if (profiles[i] == null) throw new CMMException("Unknown profile ID"); + + ptrs[i] = profiles[i].getLcmsPtr(); + } + + return createNativeTransform(ptrs, renderType, inFormatter, + isInIntPacked, outFormatter, isOutIntPacked, disposerRef); + } + + private static native long createNativeTransform( long[] profileIDs, int renderType, int inFormatter, boolean isInIntPacked, int outFormatter, boolean isOutIntPacked, @@ -175,59 +218,4 @@ public class LCMS implements PCMM { return theLcms; } - - private static class TagData { - private int signature; - private byte[] data; - - TagData(int sig, byte[] data) { - this.signature = sig; - this.data = data; - } - - int getSize() { - return data.length; - } - - byte[] getData() { - return Arrays.copyOf(data, data.length); - } - - void copyDataTo(byte[] dst) { - System.arraycopy(data, 0, dst, 0, data.length); - } - - int getSignature() { - return signature; - } - } - - private static class TagCache { - private long profileID; - private HashMap tags; - - TagCache(long id) { - profileID = id; - - tags = new HashMap<>(); - } - - TagData getTag(int sig) { - TagData t = tags.get(sig); - if (t == null) { - byte[] tagData = getTagNative(profileID, sig); - if (tagData != null) { - t = new TagData(sig, tagData); - tags.put(sig, t); - } - } - return t; - } - - void clear() { - tags.clear(); - } - } - - private static HashMap profiles; } diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSProfile.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSProfile.java new file mode 100644 index 00000000000..12810812416 --- /dev/null +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSProfile.java @@ -0,0 +1,109 @@ +/* + * 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 sun.java2d.cmm.lcms; + +import java.awt.color.CMMException; +import java.util.Arrays; +import java.util.HashMap; +import sun.java2d.cmm.Profile; + +final class LCMSProfile extends Profile { + private final TagCache tagCache; + + private final Object disposerReferent; + + LCMSProfile(long ptr, Object ref) { + super(ptr); + + disposerReferent = ref; + + tagCache = new TagCache(this); + } + + final long getLcmsPtr() { + return this.getNativePtr(); + } + + TagData getTag(int sig) { + return tagCache.getTag(sig); + } + + void clearTagCache() { + tagCache.clear(); + } + + static class TagCache { + final LCMSProfile profile; + private HashMap tags; + + TagCache(LCMSProfile p) { + profile = p; + tags = new HashMap<>(); + } + + TagData getTag(int sig) { + TagData t = tags.get(sig); + if (t == null) { + byte[] tagData = LCMS.getTagNative(profile.getNativePtr(), sig); + if (tagData != null) { + t = new TagData(sig, tagData); + tags.put(sig, t); + } + } + return t; + } + + void clear() { + tags.clear(); + } + } + + static class TagData { + private int signature; + private byte[] data; + + TagData(int sig, byte[] data) { + this.signature = sig; + this.data = data; + } + + int getSize() { + return data.length; + } + + byte[] getData() { + return Arrays.copyOf(data, data.length); + } + + void copyDataTo(byte[] dst) { + System.arraycopy(data, 0, dst, 0, data.length); + } + + int getSignature() { + return signature; + } + } +} diff --git a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java index d5ce5525989..9d6dfa9aac3 100644 --- a/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java +++ b/jdk/src/share/classes/sun/java2d/cmm/lcms/LCMSTransform.java @@ -62,7 +62,7 @@ public class LCMSTransform implements ColorTransform { private boolean isOutIntPacked = false; ICC_Profile[] profiles; - long [] profileIDs; + LCMSProfile[] lcmsProfiles; int renderType; int transformType; @@ -84,8 +84,8 @@ public class LCMSTransform implements ColorTransform { /* Actually, it is not a complete transform but just part of it */ profiles = new ICC_Profile[1]; profiles[0] = profile; - profileIDs = new long[1]; - profileIDs[0] = LCMS.getProfileID(profile); + lcmsProfiles = new LCMSProfile[1]; + lcmsProfiles[0] = LCMS.getProfileID(profile); this.renderType = (renderType == ColorTransform.Any)? ICC_Profile.icPerceptual : renderType; this.transformType = transformType; @@ -105,14 +105,14 @@ public class LCMSTransform implements ColorTransform { size+=((LCMSTransform)transforms[i]).profiles.length; } profiles = new ICC_Profile[size]; - profileIDs = new long[size]; + lcmsProfiles = new LCMSProfile[size]; int j = 0; for (int i=0; i < transforms.length; i++) { LCMSTransform curTrans = (LCMSTransform)transforms[i]; System.arraycopy(curTrans.profiles, 0, profiles, j, curTrans.profiles.length); - System.arraycopy(curTrans.profileIDs, 0, profileIDs, j, - curTrans.profileIDs.length); + System.arraycopy(curTrans.lcmsProfiles, 0, lcmsProfiles, j, + curTrans.lcmsProfiles.length); j += curTrans.profiles.length; } renderType = ((LCMSTransform)transforms[0]).renderType; @@ -152,7 +152,7 @@ public class LCMSTransform implements ColorTransform { outFormatter = out.pixelType; isOutIntPacked = out.isIntPacked; - ID = LCMS.createNativeTransform(profileIDs, renderType, + ID = LCMS.createTransform(lcmsProfiles, renderType, inFormatter, isInIntPacked, outFormatter, isOutIntPacked, disposerReferent); diff --git a/jdk/src/share/classes/sun/launcher/LauncherHelper.java b/jdk/src/share/classes/sun/launcher/LauncherHelper.java index 5a6f40442ed..dc6a10bfac2 100644 --- a/jdk/src/share/classes/sun/launcher/LauncherHelper.java +++ b/jdk/src/share/classes/sun/launcher/LauncherHelper.java @@ -51,6 +51,7 @@ import java.nio.charset.Charset; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.Path; +import java.text.Normalizer; import java.util.ResourceBundle; import java.text.MessageFormat; import java.util.ArrayList; @@ -493,7 +494,19 @@ public enum LauncherHelper { try { mainClass = scloader.loadClass(cn); } catch (NoClassDefFoundError | ClassNotFoundException cnfe) { - abort(cnfe, "java.launcher.cls.error1", cn); + if (System.getProperty("os.name", "").contains("OS X") + && Normalizer.isNormalized(cn, Normalizer.Form.NFD)) { + try { + // On Mac OS X since all names with diacretic symbols are given as decomposed it + // is possible that main class name comes incorrectly from the command line + // and we have to re-compose it + mainClass = scloader.loadClass(Normalizer.normalize(cn, Normalizer.Form.NFC)); + } catch (NoClassDefFoundError | ClassNotFoundException cnfe1) { + abort(cnfe, "java.launcher.cls.error1", cn); + } + } else { + abort(cnfe, "java.launcher.cls.error1", cn); + } } // set to mainClass appClass = mainClass; diff --git a/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java b/jdk/src/share/classes/sun/print/DocumentPropertiesUI.java new file mode 100644 index 00000000000..9938e8b3951 --- /dev/null +++ b/jdk/src/share/classes/sun/print/DocumentPropertiesUI.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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.print; + +import java.awt.Window; +import java.awt.print.PrinterJob; +import javax.print.PrintService; +import javax.print.ServiceUIFactory; +import javax.print.attribute.PrintRequestAttributeSet; + +public abstract class DocumentPropertiesUI { + + /** + * For Win32 doc properties sheet. + */ + public static final int + DOCUMENTPROPERTIES_ROLE = ServiceUIFactory.RESERVED_UIROLE +100; + + /** + * Name of (this) abstract class for Document Properties. + */ + public static final String + DOCPROPERTIESCLASSNAME = DocumentPropertiesUI.class.getName(); + + /** + * Invokes whatever code is needed to display a native dialog + * with the specified owner. The owner should be the cross-platform + * dialog. If the user cancels the dialog the return value is null. + * A non-null return value is always a new attribute set (or is it?) + * The cross-platform dialog may need to be updated to reflect the + * updated properties. + */ + public abstract PrintRequestAttributeSet + showDocumentProperties(PrinterJob job, + Window owner, + PrintService service, + PrintRequestAttributeSet aset); + +} diff --git a/jdk/src/share/classes/sun/print/PrinterJobWrapper.java b/jdk/src/share/classes/sun/print/PrinterJobWrapper.java new file mode 100644 index 00000000000..343da0baa77 --- /dev/null +++ b/jdk/src/share/classes/sun/print/PrinterJobWrapper.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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package sun.print; + +import java.awt.print.PrinterJob; +import javax.print.attribute.PrintRequestAttribute; + +public class PrinterJobWrapper implements PrintRequestAttribute { + + private static final long serialVersionUID = -8792124426995707237L; + + private PrinterJob job; + + public PrinterJobWrapper(PrinterJob job) { + this.job = job; + } + + public PrinterJob getPrinterJob() { + return job; + } + + public final Class getCategory() { + return PrinterJobWrapper.class; + } + + public final String getName() { + return "printerjob-wrapper"; + } + + public String toString() { + return "printerjob-wrapper: " + job.toString(); + } + + public int hashCode() { + return job.hashCode(); + } +} diff --git a/jdk/src/share/classes/sun/print/RasterPrinterJob.java b/jdk/src/share/classes/sun/print/RasterPrinterJob.java index 1752016288e..37865e3246c 100644 --- a/jdk/src/share/classes/sun/print/RasterPrinterJob.java +++ b/jdk/src/share/classes/sun/print/RasterPrinterJob.java @@ -903,6 +903,9 @@ public abstract class RasterPrinterJob extends PrinterJob { int x = bounds.x+bounds.width/3; int y = bounds.y+bounds.height/3; PrintService newService; + // temporarily add an attribute pointing back to this job. + PrinterJobWrapper jobWrapper = new PrinterJobWrapper(this); + attributes.add(jobWrapper); try { newService = ServiceUI.printDialog(gc, x, y, @@ -915,6 +918,7 @@ public abstract class RasterPrinterJob extends PrinterJob { DocFlavor.SERVICE_FORMATTED.PAGEABLE, attributes); } + attributes.remove(PrinterJobWrapper.class); if (newService == null) { return false; diff --git a/jdk/src/share/classes/sun/print/ServiceDialog.java b/jdk/src/share/classes/sun/print/ServiceDialog.java index 82703406aa9..bdfd5ba1242 100644 --- a/jdk/src/share/classes/sun/print/ServiceDialog.java +++ b/jdk/src/share/classes/sun/print/ServiceDialog.java @@ -46,6 +46,7 @@ import java.awt.event.ItemEvent; import java.awt.event.ItemListener; import java.awt.event.WindowEvent; import java.awt.event.WindowAdapter; +import java.awt.print.PrinterJob; import java.io.File; import java.io.FilePermission; import java.io.IOException; @@ -119,8 +120,6 @@ public class ServiceDialog extends JDialog implements ActionListener { private AppearancePanel pnlAppearance; private boolean isAWT = false; - - static { initResource(); } @@ -801,9 +800,32 @@ public class ServiceDialog extends JDialog implements ActionListener { if (dialog != null) { dialog.show(); } else { - // REMIND: may want to notify the user why we're - // disabling the button - btnProperties.setEnabled(false); + DocumentPropertiesUI docPropertiesUI = null; + try { + docPropertiesUI = + (DocumentPropertiesUI)uiFactory.getUI + (DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE, + DocumentPropertiesUI.DOCPROPERTIESCLASSNAME); + } catch (Exception ex) { + } + if (docPropertiesUI != null) { + PrinterJobWrapper wrapper = (PrinterJobWrapper) + asCurrent.get(PrinterJobWrapper.class); + if (wrapper == null) { + return; // should not happen, defensive only. + } + PrinterJob job = wrapper.getPrinterJob(); + if (job == null) { + return; // should not happen, defensive only. + } + PrintRequestAttributeSet newAttrs = + docPropertiesUI.showDocumentProperties + (job, ServiceDialog.this, psCurrent, asCurrent); + if (newAttrs != null) { + asCurrent.addAll(newAttrs); + updatePanels(); + } + } } } } diff --git a/jdk/src/share/classes/sun/security/krb5/Config.java b/jdk/src/share/classes/sun/security/krb5/Config.java index 5771886023c..c2640adbcda 100644 --- a/jdk/src/share/classes/sun/security/krb5/Config.java +++ b/jdk/src/share/classes/sun/security/krb5/Config.java @@ -225,19 +225,19 @@ public class Config { * and has no sub-key at all (given "forwardable" is defined, otherwise, * this method has no knowledge if it's a value name or a section name), */ - @SuppressWarnings("unchecked") public String get(String... keys) { - Vector v = get0(keys); + Vector v = getString0(keys); if (v == null) return null; return v.lastElement(); } /** * Gets all values for the specified keys. - * @see #get(java.lang.String[]) + * @throws IllegalArgumentException if any of the keys is illegal + * (See {@link #get}) */ public String getAll(String... keys) { - Vector v = get0(keys); + Vector v = getString0(keys); if (v == null) return null; StringBuilder sb = new StringBuilder(); boolean first = true; @@ -252,17 +252,37 @@ public class Config { return sb.toString(); } - // Internal method. Returns the vector of strings for keys. + /** + * Returns true if keys exists, can be either final string(s) or sub-stanza + * @throws IllegalArgumentException if any of the keys is illegal + * (See {@link #get}) + */ + public boolean exists(String... keys) { + return get0(keys) != null; + } + + // Returns final string value(s) for given keys. + @SuppressWarnings("unchecked") + private Vector getString0(String... keys) { + try { + return (Vector)get0(keys); + } catch (ClassCastException cce) { + throw new IllegalArgumentException(cce); + } + } + + // Internal method. Returns the value for keys, which can be a sub-stanza + // or final string value(s). // The only method (except for toString) that reads stanzaTable directly. @SuppressWarnings("unchecked") - private Vector get0(String... keys) { + private Object get0(String... keys) { Object current = stanzaTable; try { for (String key: keys) { current = ((Hashtable)current).get(key); if (current == null) return null; } - return (Vector)current; + return current; } catch (ClassCastException cce) { throw new IllegalArgumentException(cce); } diff --git a/jdk/src/share/classes/sun/security/krb5/Realm.java b/jdk/src/share/classes/sun/security/krb5/Realm.java index bc7705c4f0e..27bedc3ecf8 100644 --- a/jdk/src/share/classes/sun/security/krb5/Realm.java +++ b/jdk/src/share/classes/sun/security/krb5/Realm.java @@ -34,10 +34,8 @@ package sun.security.krb5; import sun.security.krb5.internal.Krb5; import sun.security.util.*; import java.io.IOException; -import java.util.StringTokenizer; -import java.util.Vector; -import java.util.Stack; -import java.util.EmptyStackException; +import java.util.*; + import sun.security.krb5.internal.util.KerberosString; /** @@ -50,7 +48,6 @@ import sun.security.krb5.internal.util.KerberosString; */ public class Realm implements Cloneable { private final String realm; // not null nor empty - private static boolean DEBUG = Krb5.DEBUG; public Realm(String name) throws RealmException { realm = parseRealm(name); @@ -233,90 +230,53 @@ public class Realm implements Cloneable { } } - /* - * First leg of realms parsing. Used by getRealmsList. - */ - private static String[] doInitialParse(String cRealm, String sRealm) - throws KrbException { - if (cRealm == null || sRealm == null){ - throw new KrbException(Krb5.API_INVALID_ARG); - } - if (DEBUG) { - System.out.println(">>> Realm doInitialParse: cRealm=[" - + cRealm + "], sRealm=[" +sRealm + "]"); - } - if (cRealm.equals(sRealm)) { - String[] retList = null; - retList = new String[1]; - retList[0] = new String(cRealm); - - if (DEBUG) { - System.out.println(">>> Realm doInitialParse: " - + retList[0]); - } - return retList; - } - return null; - } - /** * Returns an array of realms that may be traversed to obtain * a TGT from the initiating realm cRealm to the target realm * sRealm. *
    - * There may be an arbitrary number of intermediate realms - * between cRealm and sRealm. The realms may be organized - * organized hierarchically, or the paths between them may be - * specified in the [capaths] stanza of the caller's - * Kerberos configuration file. The configuration file is consulted - * first. Then a hirarchical organization is assumed if no realms - * are found in the configuration file. + * This method would read [capaths] to create a path, or generate a + * hierarchical path if [capaths] does not contain a sub-stanza for cRealm + * or the sub-stanza does not contain a tag for sRealm. *
    - * The returned list, if not null, contains cRealm as the first - * entry. sRealm is not included unless it is mistakenly listed - * in the configuration file as an intermediary realm. + * The returned list would never be null, and it always contains + * cRealm as the head entry. sRealm is not included as the tail. * - * @param cRealm the initiating realm - * @param sRealm the target realm - * @returns array of realms - * @thows KrbException + * @param cRealm the initiating realm, not null + * @param sRealm the target realm, not null, not equals to cRealm + * @returns array of realms including at least cRealm as the first + * element */ - public static String[] getRealmsList(String cRealm, String sRealm) - throws KrbException { - String[] retList = doInitialParse(cRealm, sRealm); - if (retList != null && retList.length != 0) { - return retList; - } - /* - * Try [capaths]. - */ - retList = parseCapaths(cRealm, sRealm); - if (retList != null && retList.length != 0) { - return retList; - } - /* - * Now assume the realms are organized hierarchically. - */ - retList = parseHierarchy(cRealm, sRealm); - return retList; + public static String[] getRealmsList(String cRealm, String sRealm) { + try { + // Try [capaths] + return parseCapaths(cRealm, sRealm); + } catch (KrbException ke) { + // Now assume the realms are organized hierarchically. + return parseHierarchy(cRealm, sRealm); } + } /** - * Parses the [capaths] stanza of the configuration file - * for a list of realms to traverse - * to obtain credentials from the initiating realm cRealm to - * the target realm sRealm. - * @param cRealm the initiating realm - * @param sRealm the target realm - * @returns array of realms - * @ throws KrbException - */ - - /* - * parseCapaths works for a capaths organized such that - * for a given client realm C there is a tag C that - * contains subtags Ci ... Cn that completely define intermediate - * realms from C to target T. For example: + * Parses the [capaths] stanza of the configuration file for a + * list of realms to traverse to obtain credentials from the + * initiating realm cRealm to the target realm sRealm. + * + * For a given client realm C there is a tag C in [capaths] whose + * subtag S has a value which is a (possibly partial) path from C + * to S. When the path is partial, it contains only the tail of the + * full path. Values of other subtags will be used to build the full + * path. The value "." means a direct path from C to S. If realm S + * does not appear as a subtag, there is no path defined here. + * + * The implementation ignores all values which equals to C or S, or + * a "." in multiple values, or any duplicated realm names. + * + * When a path value has more than two realms, they can be specified + * with multiple key-value pairs each having a single value, but the + * order must not change. + * + * For example: * * [capaths] * TIVOLI.COM = { @@ -325,357 +285,130 @@ public class Realm implements Cloneable { * LDAPCENTRAL.NET = . * } * - * The tag TIVOLI.COM contains subtags IBM.COM, IBM_LDAPCENTRAL.COM - * and LDAPCENTRAL.NET that completely define the path from TIVOLI.COM - * to IBM.COM (TIVOLI.COM->LADAPCENTRAL.NET->IBM_LDAPCENTRAL.COM->IBM - * or TIVOLI.COM->MOONLITE.ORG->IBM.COM). + * TIVOLI.COM has a direct path to LDAPCENTRAL.NET, which has a direct + * path to IBM_LDAPCENTRAL.COM. It also has a partial path to IBM.COM + * being "IBM_LDAPCENTRAL.COM MOONLITE.ORG". Merging these info together, + * a full path from TIVOLI.COM to IBM.COM will be * - * A direct path is assumed for an intermediary whose entry is not - * "closed" by a "." In the above example, TIVOLI.COM is assumed - * to have a direct path to MOONLITE.ORG and MOONLITE.COM - * in turn to IBM.COM. + * TIVOLI.COM -> LDAPCENTRAL.NET -> IBM_LDAPCENTRAL.COM + * -> IBM_LDAPCENTRAL.COM -> MOONLITE.ORG + * + * Please note the sRealm IBM.COM does not appear in the path. + * + * @param cRealm the initiating realm + * @param sRealm the target realm, not the same as cRealm + * @returns array of realms including at least cRealm as the first + * element + * @throws KrbException if the config does not contain a sub-stanza + * for cRealm in [capaths] or the sub-stanza does not contain + * sRealm as a tag */ + private static String[] parseCapaths(String cRealm, String sRealm) + throws KrbException { - private static String[] parseCapaths(String cRealm, String sRealm) throws KrbException { - String[] retList = null; + // This line could throw a KrbException + Config cfg = Config.getInstance(); - Config cfg = null; - try { - cfg = Config.getInstance(); - } catch (Exception exc) { - if (DEBUG) { - System.out.println ("Configuration information can not be " + - "obtained " + exc.getMessage()); - } - return null; + if (!cfg.exists("capaths", cRealm, sRealm)) { + throw new KrbException("No conf"); } - String intermediaries = cfg.getAll("capaths", cRealm, sRealm); + LinkedList path = new LinkedList<>(); - if (intermediaries == null) { - if (DEBUG) { - System.out.println(">>> Realm parseCapaths: no cfg entry"); - } - return null; - } - - String tempTarget = null, tempRealm = null; - Stack iStack = new Stack<>(); - - /* - * The half-established reversed-path, starting from the final target - * (sRealm), each item can be connected to by the next one. - * Might contains wrong item, if found, a bad track is performed - */ - Vector tempList = new Vector<>(8, 8); - tempList.add(sRealm); - - int count = 0; // For debug only - tempTarget = sRealm; - - out: do { - if (DEBUG) { - count++; - System.out.println(">>> Realm parseCapaths: loop " + - count + ": target=" + tempTarget); - } - - if (intermediaries != null && - !intermediaries.equals(".") && - !intermediaries.equals(cRealm)) { - if (DEBUG) { - System.out.println(">>> Realm parseCapaths: loop " + - count + ": intermediaries=[" + - intermediaries + "]"); - } - - /* - * We have one or more space-separated intermediary realms. - * Stack them. A null is always added between intermedies of - * different targets. When this null is popped, it means none - * of the intermedies for this target is useful (because of - * infinite loop), the target is then removed from the partial - * tempList, and the next possible intermediary is tried. - */ - iStack.push(null); - String[] ints = intermediaries.split("\\s+"); - for (int i = ints.length-1; i>=0; i--) - { - tempRealm = ints[i]; - if (tempRealm.equals(PrincipalName.REALM_COMPONENT_SEPARATOR_STR)) { - break out; - } - if (!tempList.contains(tempRealm)) { - iStack.push(tempRealm); - if (DEBUG) { - System.out.println(">>> Realm parseCapaths: loop " + - count + - ": pushed realm on to stack: " + - tempRealm); - } - } else if (DEBUG) { - System.out.println(">>> Realm parseCapaths: loop " + - count + - ": ignoring realm: [" + - tempRealm + "]"); - } - } - } else { - if (DEBUG) { - System.out.println(">>> Realm parseCapaths: loop " + - count + - ": no intermediaries"); - } + String head = sRealm; + while (true) { + String value = cfg.getAll("capaths", cRealm, head); + if (value == null) { break; } - - /* - * Get next intermediary realm from the stack - */ - - try { - while ((tempTarget = iStack.pop()) == null) { - tempList.removeElementAt(tempList.size()-1); - if (DEBUG) { - System.out.println(">>> Realm parseCapaths: backtrack, remove tail"); - } + String[] more = value.split("\\s+"); + boolean changed = false; + for (int i=more.length-1; i>=0; i--) { + if (path.contains(more[i]) + || more[i].equals(".") + || more[i].equals(cRealm) + || more[i].equals(sRealm) + || more[i].equals(head)) { + // Ignore invalid values + continue; } - } catch (EmptyStackException exc) { - tempTarget = null; + changed = true; + path.addFirst(more[i]); } - - if (tempTarget == null) { - /* - * No more intermediaries. We're done. - */ - break; - } - - tempList.add(tempTarget); - - if (DEBUG) { - System.out.println(">>> Realm parseCapaths: loop " + count + - ": added intermediary to list: " + - tempTarget); - } - - intermediaries = cfg.getAll("capaths", cRealm, tempTarget); - - } while (true); - - if (tempList.isEmpty()) { - return null; + if (!changed) break; + head = path.getFirst(); } - - // From (SREALM, T1, T2) to (CREALM, T2, T1) - retList = new String[tempList.size()]; - retList[0] = cRealm; - for (int i=1; i>> Realm parseCapaths [" + i + - "]=" + retList[i]); - } - } - - return retList; - } + path.addFirst(cRealm); + return path.toArray(new String[path.size()]); + } /** * Build a list of realm that can be traversed * to obtain credentials from the initiating realm cRealm * for a service in the target realm sRealm. * @param cRealm the initiating realm - * @param sRealm the target realm - * @returns array of realms - * @throws KrbException + * @param sRealm the target realm, not the same as cRealm + * @returns array of realms including cRealm as the first element */ - private static String[] parseHierarchy(String cRealm, String sRealm) - throws KrbException - { - String[] retList = null; + private static String[] parseHierarchy(String cRealm, String sRealm) { - // Parse the components and determine common part, if any. + String[] cComponents = cRealm.split("\\."); + String[] sComponents = sRealm.split("\\."); - String[] cComponents = null; - String[] sComponents = null; + int cPos = cComponents.length; + int sPos = sComponents.length; - StringTokenizer strTok = - new StringTokenizer(cRealm, - PrincipalName.REALM_COMPONENT_SEPARATOR_STR); - - // Parse cRealm - - int cCount = strTok.countTokens(); - cComponents = new String[cCount]; - - for (cCount = 0; strTok.hasMoreTokens(); cCount++) { - cComponents[cCount] = strTok.nextToken(); + boolean hasCommon = false; + for (sPos--, cPos--; sPos >=0 && cPos >= 0 && + sComponents[sPos].equals(cComponents[cPos]); + sPos--, cPos--) { + hasCommon = true; } - if (DEBUG) { - System.out.println(">>> Realm parseHierarchy: cRealm has " + - cCount + " components:"); - int j = 0; - while (j < cCount) { - System.out.println(">>> Realm parseHierarchy: " + - "cComponents["+j+"]=" + cComponents[j++]); - } + // For those with common components: + // length pos + // SITES1.SALES.EXAMPLE.COM 4 1 + // EVERYWHERE.EXAMPLE.COM 3 0 + + // For those without common components: + // length pos + // DEVEL.EXAMPLE.COM 3 2 + // PROD.EXAMPLE.ORG 3 2 + + LinkedList path = new LinkedList<>(); + + // Un-common ones for client side + for (int i=0; i<=cPos; i++) { + path.addLast(subStringFrom(cComponents, i)); } - // Parse sRealm - - strTok = new StringTokenizer(sRealm, - PrincipalName.REALM_COMPONENT_SEPARATOR_STR); - - int sCount = strTok.countTokens(); - sComponents = new String[sCount]; - - for (sCount = 0; strTok.hasMoreTokens(); sCount++) { - sComponents[sCount] = strTok.nextToken(); + // Common one + if (hasCommon) { + path.addLast(subStringFrom(cComponents, cPos+1)); } - if (DEBUG) { - System.out.println(">>> Realm parseHierarchy: sRealm has " + - sCount + " components:"); - int j = 0; - while (j < sCount) { - System.out.println(">>> Realm parseHierarchy: sComponents["+j+ - "]=" + sComponents[j++]); - } + // Un-common ones for server side + for (int i=sPos; i>=0; i--) { + path.addLast(subStringFrom(sComponents, i)); } - // Determine common components, if any. + // Remove sRealm from path. Note that it might be added at last loop + // or as a common component, if sRealm is a parent of cRealm + path.removeLast(); - int commonComponents = 0; - - //while (sCount > 0 && cCount > 0 && - // sComponents[--sCount].equals(cComponents[--cCount])) - - for (sCount--, cCount--; sCount >=0 && cCount >= 0 && - sComponents[sCount].equals(cComponents[cCount]); - sCount--, cCount--) { - commonComponents++; - } - - int cCommonStart = -1; - int sCommonStart = -1; - - int links = 0; - - if (commonComponents > 0) { - sCommonStart = sCount+1; - cCommonStart = cCount+1; - - // components from common to ancestors - links += sCommonStart; - links += cCommonStart; - } else { - links++; - } - - if (DEBUG) { - if (commonComponents > 0) { - System.out.println(">>> Realm parseHierarchy: " + - commonComponents + " common component" + - (commonComponents > 1 ? "s" : " ")); - - System.out.println(">>> Realm parseHierarchy: common part " - + - "in cRealm (starts at index " + - cCommonStart + ")"); - System.out.println(">>> Realm parseHierarchy: common part in sRealm (starts at index " + - sCommonStart + ")"); - - - String commonPart = substring(cRealm, cCommonStart); - System.out.println(">>> Realm parseHierarchy: common part in cRealm=" + - commonPart); - - commonPart = substring(sRealm, sCommonStart); - System.out.println(">>> Realm parseHierarchy: common part in sRealm=" + - commonPart); - - } else - System.out.println(">>> Realm parseHierarchy: no common part"); - } - - if (DEBUG) { - System.out.println(">>> Realm parseHierarchy: total links=" + links); - } - - retList = new String[links]; - - retList[0] = new String(cRealm); - - if (DEBUG) { - System.out.println(">>> Realm parseHierarchy A: retList[0]=" + - retList[0]); - } - - // For an initiator realm A.B.C.D.COM, - // build a list krbtgt/B.C.D.COM@A.B.C.D.COM up to the common part, - // ie the issuer realm is the immediate descendant - // of the target realm. - - String cTemp = null, sTemp = null; - int i; - for (i = 1, cCount = 0; i < links && cCount < cCommonStart; cCount++) { - sTemp = substring(cRealm, cCount+1); - //cTemp = substring(cRealm, cCount); - retList[i++] = new String(sTemp); - - if (DEBUG) { - System.out.println(">>> Realm parseHierarchy B: retList[" + - (i-1) +"]="+retList[i-1]); - } - } - - - for (sCount = sCommonStart; i < links && sCount - 1 > 0; sCount--) { - sTemp = substring(sRealm, sCount-1); - //cTemp = substring(sRealm, sCount); - retList[i++] = new String(sTemp); - if (DEBUG) { - System.out.println(">>> Realm parseHierarchy D: retList[" + - (i-1) +"]="+retList[i-1]); - } - } - - return retList; + return path.toArray(new String[path.size()]); } - private static String substring(String realm, int componentIndex) - { - int i = 0 , j = 0, len = realm.length(); - - while(i < len && j != componentIndex) { - if (realm.charAt(i++) != PrincipalName.REALM_COMPONENT_SEPARATOR) - continue; - j++; + /** + * Creates a realm name using components from the given postion. + * For example, subStringFrom({"A", "B", "C"}, 1) is "B.C". + */ + private static String subStringFrom(String[] components, int from) { + StringBuilder sb = new StringBuilder(); + for (int i=from; i>> Credentials acquireServiceCreds: no realms list"); - } - return null; - } - int i = 0, k = 0; Credentials cTgt = null, newTgt = null, theTgt = null; PrincipalName tempService = null; @@ -206,16 +198,14 @@ public class CredentialsUtil { if (newTgt == null) { if (DEBUG) { System.out.println(">>> Credentials acquireServiceCreds: " - + "no tgt; searching backwards"); + + "no tgt; searching thru capath"); } /* - * No tgt found. Try to get one for a - * realm as close to the target as possible. - * That means traversing the realms list backwards. + * No tgt found. Let's go thru the realms list one by one. */ - for (newTgt = null, k = realms.length - 1; - newTgt == null && k > i; k--) { + for (newTgt = null, k = i+1; + newTgt == null && k < realms.length; k++) { tempService = PrincipalName.tgsService(realms[k], realms[i]); if (DEBUG) { System.out.println( diff --git a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java index 73495df5bcc..e14229b3c9d 100644 --- a/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java +++ b/jdk/src/share/classes/sun/security/util/UntrustedCertificates.java @@ -24,13 +24,15 @@ */ package sun.security.util; -import java.io.IOException; -import java.io.ByteArrayInputStream; +import java.io.*; +import java.security.AccessController; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.PrivilegedAction; import java.security.cert.X509Certificate; -import java.security.cert.CertificateFactory; import java.security.cert.CertificateException; -import java.util.Set; -import java.util.HashSet; +import java.util.*; +import sun.security.x509.X509CertImpl; /** * A utility class to check if a certificate is untrusted. This is an internal @@ -42,8 +44,50 @@ import java.util.HashSet; */ public final class UntrustedCertificates { - private final static Set untrustedCerts = new HashSet<>(); + private static final Debug debug = Debug.getInstance("certpath"); + private static final String ALGORITHM_KEY = "Algorithm"; + private static final Properties props = new Properties(); + private static final String algorithm; + + static { + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + File f = new File(System.getProperty("java.home"), + "lib/security/blacklisted.certs"); + try (FileInputStream fin = new FileInputStream(f)) { + props.load(fin); + // It's said that the fingerprint could contain colons + for (Map.Entry e: props.entrySet()) { + e.setValue(stripColons(e.getValue())); + } + } catch (IOException fnfe) { + if (debug != null) { + debug.println("Error parsing blacklisted.certs"); + } + } + return null; + } + }); + algorithm = props.getProperty(ALGORITHM_KEY); + } + + private static String stripColons(Object input) { + String s = (String)input; + char[] letters = s.toCharArray(); + int pos = 0; + for (int i = 0; i < letters.length; i++) { + if (letters[i] != ':') { + if (i != pos) { + letters[pos] = letters[i]; + } + pos++; + } + } + if (pos == letters.length) return s; + else return new String(letters, 0, pos); + } /** * Checks if a certificate is untrusted. * @@ -51,844 +95,21 @@ public final class UntrustedCertificates { * @return true if the certificate is untrusted. */ public static boolean isUntrusted(X509Certificate cert) { - return untrustedCerts.contains(cert); - } - - private static void add(String alias, String pemCert) { - // generate certificate from PEM certificate - try (ByteArrayInputStream is = - new ByteArrayInputStream(pemCert.getBytes())) { - CertificateFactory cf = CertificateFactory.getInstance("X.509"); - X509Certificate cert = (X509Certificate)cf.generateCertificate(is); - - if (!untrustedCerts.add(cert)) { - throw new RuntimeException("Duplicate untrusted certificate: " + - cert.getSubjectX500Principal()); - } - } catch (CertificateException | IOException e) { - throw new RuntimeException( - "Incorrect untrusted certificate: " + alias, e); + if (algorithm == null) { + return false; } + String key; + if (cert instanceof X509CertImpl) { + key = ((X509CertImpl)cert).getFingerprint(algorithm); + } else { + try { + key = new X509CertImpl(cert.getEncoded()).getFingerprint(algorithm); + } catch (CertificateException cee) { + return false; + } + } + return props.containsKey(key); } - static { - // ----------------------------------------------------------------- - // Compromised CAs of Digicert Malaysia - // - // Reported by Digicert in its announcement on November 05, 2011. - // - - // Digicert Malaysia intermediate, cross-signed by CyberTrust - // - // Subject: CN=Digisign Server ID (Enrich), - // OU=457608-K, - // O=Digicert Sdn. Bhd., - // C=MY - // Issuer: CN=GTE CyberTrust Global Root, - // OU=GTE CyberTrust Solutions, Inc., - // O=GTE Corporation, - // C=US - // Serial: 120001705 (07:27:14:a9) - add("digicert-server-cross-to-cybertrust-4C0E636A", - "-----BEGIN CERTIFICATE-----\n" + - "MIIDyzCCAzSgAwIBAgIEBycUqTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV\n" + - "UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU\n" + - "cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds\n" + - "b2JhbCBSb290MB4XDTA3MDcxNzE1MTc0OFoXDTEyMDcxNzE1MTY1NFowYzELMAkG\n" + - "A1UEBhMCTVkxGzAZBgNVBAoTEkRpZ2ljZXJ0IFNkbi4gQmhkLjERMA8GA1UECxMI\n" + - "NDU3NjA4LUsxJDAiBgNVBAMTG0RpZ2lzaWduIFNlcnZlciBJRCAoRW5yaWNoKTCB\n" + - "nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArahkS02Hx4RZufuQRqCmicDx/tXa\n" + - "VII3DZkrRSYK6Fawf8qo9I5HhAGCKeOzarWR8/uVhbxyqGToCkCcxfRxrnt7agfq\n" + - "kBRPjYmvlKuyBtQCanuYH1m5Os1U+iDfsioK6bjdaZDAKdNO0JftZszFGUkGf/pe\n" + - "LHx7hRsyQt97lSUCAwEAAaOCAXgwggF0MBIGA1UdEwEB/wQIMAYBAf8CAQAwXAYD\n" + - "VR0gBFUwUzBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcCARYtaHR0cDovL2N5YmVy\n" + - "dHJ1c3Qub21uaXJvb3QuY29tL3JlcG9zaXRvcnkuY2ZtMAcGBWCDSgEBMA4GA1Ud\n" + - "DwEB/wQEAwIB5jCBiQYDVR0jBIGBMH+heaR3MHUxCzAJBgNVBAYTAlVTMRgwFgYD\n" + - "VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv\n" + - "bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv\n" + - "b3SCAgGlMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly93d3cucHVibGljLXRydXN0\n" + - "LmNvbS9jZ2ktYmluL0NSTC8yMDE4L2NkcC5jcmwwHQYDVR0OBBYEFMYWk04WF+wW\n" + - "royUdvOGbcV0boR3MA0GCSqGSIb3DQEBBQUAA4GBAHYAe6Z4K2Ydjl42xqSOBfIj\n" + - "knyTZ9P0wAp9iy3Z6tVvGvPhSilaIoRNUC9LDPL/hcJ7VdREgr5trGeOvLQfkpxR\n" + - "gBoU9m6rYYgLrRx/90tQUdZlG6ZHcRVesHHzNRTyN71jyNXwk1o0X9g96F33xR7A\n" + - "5c8fhiSpPAdmzcHSNmNZ\n" + - "-----END CERTIFICATE-----"); - - // Digicert Malaysia intermediate, cross-signed by Entrust - // - // Subject: CN=Digisign Server ID - (Enrich), - // OU=457608-K, - // O=Digicert Sdn. Bhd., - // C=MY - // Issuer: CN=Entrust.net Certification Authority (2048) - // OU=(c) 1999 Entrust.net Limited, - // OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), - // O=Entrust.net - // Serial: 1184644297 (4c:0e:63:6a) - add("digicert-server-cross-to-entrust-ca-4C0E636A", - "-----BEGIN CERTIFICATE-----\n" + - "MIIEzjCCA7agAwIBAgIETA5jajANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML\n" + - "RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp\n" + - "bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5\n" + - "IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp\n" + - "ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw0xMDA3MTYxNzIzMzdaFw0xNTA3\n" + - "MTYxNzUzMzdaMGUxCzAJBgNVBAYTAk1ZMRswGQYDVQQKExJEaWdpY2VydCBTZG4u\n" + - "IEJoZC4xETAPBgNVBAsTCDQ1NzYwOC1LMSYwJAYDVQQDEx1EaWdpc2lnbiBTZXJ2\n" + - "ZXIgSUQgLSAoRW5yaWNoKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\n" + - "AMWJ5PQNBkCSWccaszXRDkwqM/n4r8qef+65p21g9FTob9Wb8xtjMQRoctE0Foy0\n" + - "FyyX3nPF2JAVoBor9cuzSIZE8B2ITM5BQhrv9Qze/kDaOSD3BlU6ap1GwdJvpbLI\n" + - "Vz4po5zg6YV3ZuiYpyR+vsBZIOVEb7ZX2L7OwmV3WMZhQdF0BMh/SULFcqlyFu6M\n" + - "3RJdtErU0a9Qt9iqdXZorT5dqjBtYairEFs+E78z4K9EnTgiW+9ML6ZxJhUmyiiM\n" + - "2fqOjqmiFDXimySItPR/hZ2DTwehthSQNsQ0HI0mYW0Tb3i+6I8nx0uElqOGaAwj\n" + - "vgvsjJQAqQSKE5D334VsDLECAwEAAaOCATQwggEwMA4GA1UdDwEB/wQEAwIBBjAS\n" + - "BgNVHRMBAf8ECDAGAQH/AgEAMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggrBgEFBQcD\n" + - "AgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8v\n" + - "b2NzcC5lbnRydXN0Lm5ldDBEBgNVHSAEPTA7MDkGBWCDSgEBMDAwLgYIKwYBBQUH\n" + - "AgEWImh0dHA6Ly93d3cuZGlnaWNlcnQuY29tLm15L2Nwcy5odG0wMgYDVR0fBCsw\n" + - "KTAnoCWgI4YhaHR0cDovL2NybC5lbnRydXN0Lm5ldC8yMDQ4Y2EuY3JsMBEGA1Ud\n" + - "DgQKBAhMTswlKAMpgTAfBgNVHSMEGDAWgBRV5IHREYC+2Im5CKMx+aEkCRa5cDAN\n" + - "BgkqhkiG9w0BAQUFAAOCAQEAl0zvSjpJrHL8MCBrtClbp8WVBJD5MtXChWreA6E3\n" + - "+YkAsFqsVX7bQzX/yQH4Ub7MJsrIaqTEVD4mHucMo82XZ5TdpkLrXM2POXlrM3kh\n" + - "Bnn6gkQVmczBtznTRmJ8snDrb84gqj4Zt+l0gpy0pUtNYQA35IfS8hQ6ZHy4qXth\n" + - "4JMi59WfPkfmNnagU9gAAzoPtTP+lsrT0oI6Lt3XSOHkp2nMHOmZSufKcEXXCwcO\n" + - "mnUb0C+Sb/akB8O9HEumhLZ9qJqp0qcp8QtXaR6XVybsK0Os1EWDBQDp4/BGQAf6\n" + - "6rFRc5Mcpd1TETfIKqcVJx20qsx/qjEw/LhFn0gJ7RDixQ==\n" + - "-----END CERTIFICATE-----"); - - - // ----------------------------------------------------------------- - // - // No longer used certificates - // - - // Subject: CN=Java Media APIs, - // OU=Java Signed Extensions, - // OU=Corporate Object Signing, - // O=Sun Microsystems Inc - // Issuer: CN=Object Signing CA, - // OU=Class 2 OnSite Subscriber CA, - // OU=VeriSign Trust Network, - // O=Sun Microsystems Inc - // Serial: 6a:8b:99:91:37:59:4f:89:53:e2:97:18:9f:19:1e:4e - add("java-media-pretrusted-9F191E4E", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFdzCCBF+gAwIBAgIQaouZkTdZT4lT4pcYnxkeTjANBgkqhkiG9w0BAQUFADCB\n" + - "gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT\n" + - "aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj\n" + - "cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA5MDUxMjAw\n" + - "MDAwMFoXDTEyMDUxMTIzNTk1OVowfTEdMBsGA1UEChQUU3VuIE1pY3Jvc3lzdGVt\n" + - "cyBJbmMxITAfBgNVBAsUGENvcnBvcmF0ZSBPYmplY3QgU2lnbmluZzEfMB0GA1UE\n" + - "CxQWSmF2YSBTaWduZWQgRXh0ZW5zaW9uczEYMBYGA1UEAxQPSmF2YSBNZWRpYSBB\n" + - "UElzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl5blzoKTVE8y4Hpz\n" + - "q6E15RZz1bF5HnYEyYqgHkZXnAKedmYCoMzm1XK8s+gQWShLEvGEAvs5yqarx9gE\n" + - "nnC21N28aEZgIJMa2/arKxCUkS4pxdGPYGexL9UzSRkUpoBShCZKEGdmX7gfJE2K\n" + - "/sd9MFvGV5/yZtWXrADzvm0Kd/9mg1KRv1gfrZIq0TJbupoXPYYqb73AkI9eT2ZD\n" + - "q9MdwD4E5+oojsDFXt8GU/D00fUhtXpYwuplU7D667WHYdJhIah0ST6JywyqcLXG\n" + - "XSuFTXOgITT2idSHluZVmx3dqJ72u9kPkO4JdJTMDfaK8zgNLaRkiU8Qcj+qhLYH\n" + - "ytaqcwIDAQABo4IB6jCCAeYwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwfwYD\n" + - "VR0fBHgwdjB0oHKgcIZuaHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vU3Vu\n" + - "TWljcm9zeXN0ZW1zSW5jQ29ycG9yYXRlT2JqZWN0U2lnbmluZ0phdmFTaWduZWRF\n" + - "eHRlbnNpb25zQ2xhc3NCL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAUs0crgn5T\n" + - "tHPKuLsZt76BTQeVx+0wHQYDVR0OBBYEFKS32mVx0gNWTeS4ProHEaeSpvvIMDsG\n" + - "CCsGAQUFBwEBBC8wLTArBggrBgEFBQcwAYYfaHR0cDovL29uc2l0ZS1vY3NwLnZl\n" + - "cmlzaWduLmNvbTCBtQYDVR0gBIGtMIGqMDkGC2CGSAGG+EUBBxcCMCowKAYIKwYB\n" + - "BQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwbQYLYIZIAYb3AIN9\n" + - "nD8wXjAnBggrBgEFBQcCARYbaHR0cHM6Ly93d3cuc3VuLmNvbS9wa2kvY3BzMDMG\n" + - "CCsGAQUFBwICMCcaJVZhbGlkYXRlZCBGb3IgU3VuIEJ1c2luZXNzIE9wZXJhdGlv\n" + - "bnMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQEFBQADggEBAAe6BO4W\n" + - "3TSNWfezyelJs6kE3HfulT6Bdyz4UUoh9ykXcV8nRwT+kh25I5MdyG2GfkJoADPR\n" + - "VhC5DYo13UFpIsTNVjq+hGYe2hML93bN7ad9SxCCyjHUo3yMz2qgBbHZI3VA9ZHA\n" + - "aWM4Tx0saMwbcnVvlbuGh+PXvStfypJqYT6lzcdFfjNVX4FI/QQNGhBswMY51tC8\n" + - "GTBCL2qhJon0gSCU4zaawDOf7+XxJWirLamYL1Aal1/h2z2sFrvA/1ftxtU3kZ6I\n" + - "7De8DyoHeZg7pYGdrj7g+lPhCga/WvEhN152I+aP08YbFcJHYmK05ngl/Ye4c6Bd\n" + - "cdrdfbw6QzEUIYY=\n" + - "-----END CERTIFICATE-----"); - - // Subject: CN=JavaFX 1.0 Runtime, - // OU=Java Signed Extensions, - // OU=Corporate Object Signing, - // O=Sun Microsystems Inc - // Issuer: CN=Object Signing CA, - // OU=Class 2 OnSite Subscriber CA, - // OU=VeriSign Trust Network, - // O=Sun Microsystems Inc - // Serial: 55:c0:e6:44:59:59:79:9e:d9:26:f1:b0:4a:1e:f0:27 - add("java-fx10-pretrusted-4A1EF027", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFezCCBGOgAwIBAgIQVcDmRFlZeZ7ZJvGwSh7wJzANBgkqhkiG9w0BAQUFADCB\n" + - "gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT\n" + - "aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj\n" + - "cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA4MTAwOTAw\n" + - "MDAwMFoXDTExMTAwOTIzNTk1OVowgYAxHTAbBgNVBAoUFFN1biBNaWNyb3N5c3Rl\n" + - "bXMgSW5jMSEwHwYDVQQLFBhDb3Jwb3JhdGUgT2JqZWN0IFNpZ25pbmcxHzAdBgNV\n" + - "BAsUFkphdmEgU2lnbmVkIEV4dGVuc2lvbnMxGzAZBgNVBAMUEkphdmFGWCAxLjAg\n" + - "UnVudGltZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM+WDc6+bu+4\n" + - "tmAcS/lBtUc02WOt9QZpVsXg9cG2pu/8bUtmDELa8iiYBVFpIs8DU58HLrGQtCUY\n" + - "SIAGOVPsOJoN29UKCDWfY9j5JeVhfhMGqk9DwrWhzgsjy4cpZ1pIp+k/fJ8zT8Ul\n" + - "aYLpow1vg3UNddsmwz02tN7cOrMw9WYIG4CRYnY1OrtJSfe2pYzheC4zyvR+aiVl\n" + - "nang2OtqikSQsNFOFHsLOJFxngy9LrO8evDSu25VTKI6zlWU6/bMeqtztJPN0VOn\n" + - "NyUrJZvkxZ207Jg0T693BGSxNC1n+ihztXogql8950M/pEuUbDjylv5FFvlp6DSB\n" + - "dDT2MkutmyMCAwEAAaOCAeowggHmMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeA\n" + - "MH8GA1UdHwR4MHYwdKByoHCGbmh0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29t\n" + - "L1N1bk1pY3Jvc3lzdGVtc0luY0NvcnBvcmF0ZU9iamVjdFNpZ25pbmdKYXZhU2ln\n" + - "bmVkRXh0ZW5zaW9uc0NsYXNzQi9MYXRlc3RDUkwuY3JsMB8GA1UdIwQYMBaAFLNH\n" + - "K4J+U7Rzyri7Gbe+gU0HlcftMB0GA1UdDgQWBBTjgufVi3XJ3gx1ewsA6Rr7BR4Z\n" + - "zjA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAGGH2h0dHA6Ly9vbnNpdGUtb2Nz\n" + - "cC52ZXJpc2lnbi5jb20wgbUGA1UdIASBrTCBqjA5BgtghkgBhvhFAQcXAjAqMCgG\n" + - "CCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMG0GC2CGSAGG\n" + - "9wCDfZw/MF4wJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3LnN1bi5jb20vcGtpL2Nw\n" + - "czAzBggrBgEFBQcCAjAnGiVWYWxpZGF0ZWQgRm9yIFN1biBCdXNpbmVzcyBPcGVy\n" + - "YXRpb25zMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4IBAQAB\n" + - "YVJTTVe7rzyTO4jc3zajErOT/COkdQTfNo0eIX1QbNynFieJvwY/jRzUZwjktIFR\n" + - "2p4JtbpHGAtKtjOAOTieQ8xdDOoC1djzpE7/AbMvuvlTavtUKT+F7tPdhfXgWXJV\n" + - "6Wbt8jryKyk3zZGiEhauIwZUkfjRkEtffEmZWLUd8c8rURJjfC/XHH2oyurscoxc\n" + - "CjX29c9ynxSiS/VvQp1an0HvErGh69N48wj7cj8mtZ1yHzd2XCzSSR1OfTPfk0Pt\n" + - "yg51p7yJaFiH21PTZegEL6zyVNOYBTKwwIi2OzpwYalD3uvK6e3OKDrfFCOxu17u\n" + - "4PveESbrdyrmvLe7IVez\n" + - "-----END CERTIFICATE-----"); - - // Subject: CN=JavaFX Runtime, - // OU=Java Signed Extensions, - // OU=Corporate Object Signing, - // O=Sun Microsystems Inc - // Issuer: CN=Object Signing CA, - // OU=Class 2 OnSite Subscriber CA, - // OU=VeriSign Trust Network, - // O=Sun Microsystems Inc - // Serial: 47:f4:55:f1:da:4a:5e:f9:e3:f7:a8:03:62:17:c0:ff - add("javafx-runtime-pretrusted-6217C0FF", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFdjCCBF6gAwIBAgIQR/RV8dpKXvnj96gDYhfA/zANBgkqhkiG9w0BAQUFADCB\n" + - "gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT\n" + - "aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj\n" + - "cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA5MDEyOTAw\n" + - "MDAwMFoXDTEyMDEyOTIzNTk1OVowfDEdMBsGA1UEChQUU3VuIE1pY3Jvc3lzdGVt\n" + - "cyBJbmMxITAfBgNVBAsUGENvcnBvcmF0ZSBPYmplY3QgU2lnbmluZzEfMB0GA1UE\n" + - "CxQWSmF2YSBTaWduZWQgRXh0ZW5zaW9uczEXMBUGA1UEAxQOSmF2YUZYIFJ1bnRp\n" + - "bWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIzd0fAk8mI9ONc6RJ\n" + - "aGieioK2FLdXEwj8zL3vdGDVmBwyR1zwYkaOIFFgF9IW/8qc4iAYA5sGUY+0g8q3\n" + - "5DuYAxfTzBB5KdaYvbuq6GGnoHIWmTirXY+1friFp8lyXSvtuEaGB1VHaBoZchEg\n" + - "k+UgeVDA43dHwcT1Ov3DePczJRUes8T/QHzLX+BxUDG43vjyncCEO/AjqLZxXEz2\n" + - "xrNbKLcH3lGMJK7hdbfssUfF5BjC38Hn71HauYlA43b2no+2y0Sjulwzez2YPbDC\n" + - "0GLR3TnKtA8dqOrnl5t3DniDbfOBNtBE3VOydJO0XW57Ng1HRXD023nm9ECPY2xp\n" + - "0N/pAgMBAAGjggHqMIIB5jAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDB/BgNV\n" + - "HR8EeDB2MHSgcqBwhm5odHRwOi8vb25zaXRlY3JsLnZlcmlzaWduLmNvbS9TdW5N\n" + - "aWNyb3N5c3RlbXNJbmNDb3Jwb3JhdGVPYmplY3RTaWduaW5nSmF2YVNpZ25lZEV4\n" + - "dGVuc2lvbnNDbGFzc0IvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBSzRyuCflO0\n" + - "c8q4uxm3voFNB5XH7TAdBgNVHQ4EFgQUvOdd0cKPj+Yik/iOBwTdphh5A+gwOwYI\n" + - "KwYBBQUHAQEELzAtMCsGCCsGAQUFBzABhh9odHRwOi8vb25zaXRlLW9jc3AudmVy\n" + - "aXNpZ24uY29tMIG1BgNVHSAEga0wgaowOQYLYIZIAYb4RQEHFwIwKjAoBggrBgEF\n" + - "BQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTBtBgtghkgBhvcAg32c\n" + - "PzBeMCcGCCsGAQUFBwIBFhtodHRwczovL3d3dy5zdW4uY29tL3BraS9jcHMwMwYI\n" + - "KwYBBQUHAgIwJxolVmFsaWRhdGVkIEZvciBTdW4gQnVzaW5lc3MgT3BlcmF0aW9u\n" + - "czATBgNVHSUEDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQUFAAOCAQEAbGcf2NjL\n" + - "AI93HG6ny2BbepaZA1a8xa/R6uUc7xV+Qw6MgLwFD4Q4i6LWUztQDvg9l68MM2/i\n" + - "Y9LEi1KM4lcNbK5+D+t9x98wXBiuojXhVdp5ZmC03EyEBbriopdBsmXVLDSu/Y3+\n" + - "zowOO5xwpMK3dbgsSDs2Vt0UosD3FTcRaD3GNfOhXMp+o1grHNiXF9YgkmdQbPPZ\n" + - "DQ2KBhFPCRJXBGvyKOqno/DTg0sQ3crGH/C4/4t7mnQXWldZotmJUZ0ONc9oD+Q1\n" + - "JAaguUKqIwn9yZ093ie+JWHbYNid9IIIPXYgtRxmf9a376WBhqhu56uJftBJ7x9g\n" + - "eQ7Lot6CSWCiFw==\n" + - "-----END CERTIFICATE-----"); - - // - // Compromised Solaris INTERNAL DEVELOPMENT USE ONLY certificate - // - - // Subject: CN=Solaris INTERNAL DEVELOPMENT USE ONLY, - // OU=Solaris Cryptographic Framework, - // OU=Corporate Object Signing, - // O=Sun Microsystems Inc - // Issuer: CN=Object Signing CA, - // OU=Class 2 OnSite Subscriber CA, - // OU=VeriSign Trust Network, - // O=Sun Microsystems Inc - // Serial: 77:29:77:52:6a:19:7b:9a:a6:a2:c7:99:a0:e1:cd:8c - add("solaris-internal-dev-A0E1CD8C", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFHjCCBAagAwIBAgIQdyl3UmoZe5qmoseZoOHNjDANBgkqhkiG9w0BAQUFADCB\n" + - "gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT\n" + - "aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj\n" + - "cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA3MDEwNDAw\n" + - "MDAwMFoXDTEwMDEwMzIzNTk1OVowgZwxHTAbBgNVBAoUFFN1biBNaWNyb3N5c3Rl\n" + - "bXMgSW5jMSEwHwYDVQQLFBhDb3Jwb3JhdGUgT2JqZWN0IFNpZ25pbmcxKDAmBgNV\n" + - "BAsUH1NvbGFyaXMgQ3J5cHRvZ3JhcGhpYyBGcmFtZXdvcmsxLjAsBgNVBAMUJVNv\n" + - "bGFyaXMgSU5URVJOQUwgREVWRUxPUE1FTlQgVVNFIE9OTFkwgZ8wDQYJKoZIhvcN\n" + - "AQEBBQADgY0AMIGJAoGBALbNU4hf3mD5ArDI9pjgioAyvV3bjMPRQdCZniIeGJBp\n" + - "odFlSEH+Mh64W1DsY8coeZ7FvvGJkx9IpTMJW9k8w1oJK9UNqHyAQfaYjQyXi3xQ\n" + - "LJp62EvYdGfDlwOZejEcR/MbzZG+GOPMMvQj5+xyFDvLXNGfQNTnxw2qnBgCJXjj\n" + - "AgMBAAGjggH1MIIB8TAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDCBiQYDVR0f\n" + - "BIGBMH8wfaB7oHmGd2h0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL1N1bk1p\n" + - "Y3Jvc3lzdGVtc0luY0NvcnBvcmF0ZU9iamVjdFNpZ25pbmdTb2xhcmlzQ3J5cHRv\n" + - "Z3JhcGhpY0ZyYW1ld29ya0NsYXNzQi9MYXRlc3RDUkwuY3JsMB8GA1UdIwQYMBaA\n" + - "FLNHK4J+U7Rzyri7Gbe+gU0HlcftMB0GA1UdDgQWBBRpfiGYkehTnsIzuN2H6AFb\n" + - "VCZG8jA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAGGH2h0dHA6Ly9vbnNpdGUt\n" + - "b2NzcC52ZXJpc2lnbi5jb20wgbUGA1UdIASBrTCBqjA5BgtghkgBhvhFAQcXAjAq\n" + - "MCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMG0GC2CG\n" + - "SAGG9wCDfZw/MF4wJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3LnN1bi5jb20vcGtp\n" + - "L2NwczAzBggrBgEFBQcCAjAnFiVWYWxpZGF0ZWQgRm9yIFN1biBCdXNpbmVzcyBP\n" + - "cGVyYXRpb25zMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4IB\n" + - "AQCG5soy3LFHTFbA8/5SzDRhQoJkHUnOP0t3b6nvX6vZYRp649fje7TQOPRm1pFd\n" + - "CZ17J+tggdZwgzTqY4aYpJ00jZaK6pV37q/vgFC/ia6jDs8Q+ly9cEcadBZ5loYg\n" + - "cmxp9p57W2MNWx8VA8oFdNtKfF0jUNXbLNtvwGHmgR6YcwLrGN1b6/9Lt9bO3ODl\n" + - "FO+ZDwkfQz5ClUVrTx2dGBvKRYFqSG5S8JAfsgYhPvcacUQkA7ExyKvfRXLWVrce\n" + - "ZiPpcElbx+819H2sAPvVvparVeAruZGMAtejHZp9NFoowKen5drJp9VxePS4eM49\n" + - "3DepB6lKRrNRw66LNQol4ZBz\n" + - "-----END CERTIFICATE-----"); - - - // ----------------------------------------------------------------- - // Compromised CAs of DigiNotar - // - // Reported by Fox-IT in its interim report on September 5, 2011, - // "DigiNotar Certificate Authority breach 'Operation Black Tulip'". - // - - // - // Compromised DigiNotar Cyber CA - // - - // DigiNotar intermediate, cross-signed by CyberTrust - // - // Subject: EMAILADDRESS=info@diginotar.nl, CN=DigiNotar Cyber CA, - // O=DigiNotar, C=NL - // Issuer: CN=GTE CyberTrust Global Root, - // OU=GTE CyberTrust Solutions, Inc., - // O=GTE Corporation, - // C=US - // Serial: 120000525 (07:27:10:0D) - add("info-at-diginotar-cyber-ca-cross-to-gte-cybertrust-0727100D", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFWjCCBMOgAwIBAgIEBycQDTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV\n" + - "UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU\n" + - "cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds\n" + - "b2JhbCBSb290MB4XDTA2MTAwNDEwNTQxMVoXDTExMTAwNDEwNTMxMVowYDELMAkG\n" + - "A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy\n" + - "IEN5YmVyIENBMSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIw\n" + - "DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANLOFQotqF6EZ639vu9Gx8i5z3P8\n" + - "9DS5+SxD52ATPXrjss87Z2yQrcC5P4RS8DVC3HTcKDu9UrSnrHJFF8bwieu0qiXy\n" + - "XUte0dmHutZ9fPXOMp8QM8WxSrtekTHC0OlBwpFkfglBO9uLCDdqqspS3rU5HsCI\n" + - "A6U/i5kTYUO1m4Kz7iBvz6FEouova0CfjytXraFTwoUiaZ2gP1HfC0GRDaXhqKpc\n" + - "SQhdvd5wQbEPyWNr0380dAIvNFp4dRxoeoFnivPaQPBgY/SSINcDpj2jHmfEhBtB\n" + - "pcmM5r3qSLYFFgizNxJa92E89zhvLpfgb1Y4VNMota0Ubi5LZLUnZbd1JQm2Bz2V\n" + - "VgIKgmCyc0XgMyZRdJq51FAc9k1bW1JSE1qmf6cO4ehBVGeYjIfVydNsy9NUkgYJ\n" + - "NEH3gW8/nsl8dVWw58Gzd+jDxAA1lUBwEEoF3iW7n1mlZLxHYL9g43aLE1Xd4XR6\n" + - "uc8kpmp/3mQiRFhogmoQ+T3lPhu5vfwi9GAEibtVbShV+t6OjRshFNc3izR7Tfay\n" + - "shDPM7F9HGKZSMsrbHaWVb8ZDR0fu2WqG46ZtcYokOWCLXhQIJr9eS8kf/CJKWn0\n" + - "fc1zvrPtTsHR7VJej/e4142HrbLZG1ES/1az4a80fVykeIgQnp0DxqWqoiRR90kU\n" + - "xbHuWUOV36toKDA/AgMBAAGjggGGMIIBgjASBgNVHRMBAf8ECDAGAQH/AgEBMFMG\n" + - "A1UdIARMMEowSAYJKwYBBAGxPgEAMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93d3cu\n" + - "cHVibGljLXRydXN0LmNvbS9DUFMvT21uaVJvb3QuaHRtbDAOBgNVHQ8BAf8EBAMC\n" + - "AQYwgaAGA1UdIwSBmDCBlYAUpgwdn2H/Bxe1vzhG20Mw1Y6wUgaheaR3MHUxCzAJ\n" + - "BgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdU\n" + - "RSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVy\n" + - "VHJ1c3QgR2xvYmFsIFJvb3SCAgGlMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly93\n" + - "d3cucHVibGljLXRydXN0LmNvbS9jZ2ktYmluL0NSTC8yMDE4L2NkcC5jcmwwHQYD\n" + - "VR0OBBYEFKv5aN/PSjfXe0WMX3LeQETDZbvCMA0GCSqGSIb3DQEBBQUAA4GBAI9o\n" + - "a6VbB7pEZg4cqFwwezPkCiYE/O+eGjjWLqEf0JlHwnVkJP2eOyh2uSYoYZEMbSz4\n" + - "BJ98UAHV42mv7xXSRZskCSpmBU8lgcpdvqrBWSeuM46C9990sFWzjvjnN8huqlZE\n" + - "9r1TgSOWPbT6MopTZkQloiXGpjwljPDgKAYityZB\n" + - "-----END CERTIFICATE-----"); - - // DigiNotar intermediate, cross-signed by CyberTrust - // - // Subject: CN=DigiNotar Cyber CA, O=DigiNotar, C=NL - // Issuer: CN=GTE CyberTrust Global Root, - // OU=GTE CyberTrust Solutions, Inc., - // O=GTE Corporation, - // C=US - // Serial: 120000505 (07:27:0F:F9) - add("diginotar-cyber-ca-cross-to-gte-cybertrust-07270FF9", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFODCCBKGgAwIBAgIEBycP+TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV\n" + - "UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU\n" + - "cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds\n" + - "b2JhbCBSb290MB4XDTA2MDkyMDA5NDUzMloXDTEzMDkyMDA5NDQwNlowPjELMAkG\n" + - "A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy\n" + - "IEN5YmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0s4VCi2o\n" + - "XoRnrf2+70bHyLnPc/z0NLn5LEPnYBM9euOyzztnbJCtwLk/hFLwNULcdNwoO71S\n" + - "tKesckUXxvCJ67SqJfJdS17R2Ye61n189c4ynxAzxbFKu16RMcLQ6UHCkWR+CUE7\n" + - "24sIN2qqylLetTkewIgDpT+LmRNhQ7WbgrPuIG/PoUSi6i9rQJ+PK1etoVPChSJp\n" + - "naA/Ud8LQZENpeGoqlxJCF293nBBsQ/JY2vTfzR0Ai80Wnh1HGh6gWeK89pA8GBj\n" + - "9JIg1wOmPaMeZ8SEG0GlyYzmvepItgUWCLM3Elr3YTz3OG8ul+BvVjhU0yi1rRRu\n" + - "LktktSdlt3UlCbYHPZVWAgqCYLJzReAzJlF0mrnUUBz2TVtbUlITWqZ/pw7h6EFU\n" + - "Z5iMh9XJ02zL01SSBgk0QfeBbz+eyXx1VbDnwbN36MPEADWVQHAQSgXeJbufWaVk\n" + - "vEdgv2DjdosTVd3hdHq5zySman/eZCJEWGiCahD5PeU+G7m9/CL0YASJu1VtKFX6\n" + - "3o6NGyEU1zeLNHtN9rKyEM8zsX0cYplIyytsdpZVvxkNHR+7Zaobjpm1xiiQ5YIt\n" + - "eFAgmv15LyR/8IkpafR9zXO+s+1OwdHtUl6P97jXjYetstkbURL/VrPhrzR9XKR4\n" + - "iBCenQPGpaqiJFH3SRTFse5ZQ5Xfq2goMD8CAwEAAaOCAYYwggGCMBIGA1UdEwEB\n" + - "/wQIMAYBAf8CAQEwUwYDVR0gBEwwSjBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcC\n" + - "ARYtaHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL0NQUy9PbW5pUm9vdC5odG1s\n" + - "MA4GA1UdDwEB/wQEAwIBBjCBoAYDVR0jBIGYMIGVgBSmDB2fYf8HF7W/OEbbQzDV\n" + - "jrBSBqF5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlv\n" + - "bjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRpb25zLCBJbmMuMSMwIQYD\n" + - "VQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIICAaUwRQYDVR0fBD4wPDA6\n" + - "oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL2NnaS1iaW4vQ1JMLzIw\n" + - "MTgvY2RwLmNybDAdBgNVHQ4EFgQUq/lo389KN9d7RYxfct5ARMNlu8IwDQYJKoZI\n" + - "hvcNAQEFBQADgYEACcpiD427SuDUejUrBi3RKGG2rAH7g0m8rtQvLYauGYOl1h0T\n" + - "4he+/jJ06XoUOMqUXvcpAWlxG5Ea/aO7qh3Ke+IW/aGjDvMMX7LhIDGUK16Sdu36\n" + - "6bUjpr8KOwOpb1JgVM1f6bcvfKIn/UGDdbYN+3gm87FF6TKVKho1IZXFonU=\n" + - "-----END CERTIFICATE-----"); - - // DigiNotar intermediate, cross-signed by CyberTrust - // - // Subject: CN=DigiNotar Cyber CA, O=DigiNotar, C=NL - // Issuer: CN=GTE CyberTrust Global Root, - // OU=GTE CyberTrust Solutions, Inc., - // O=GTE Corporation, - // C=US - // Serial: 120000515 (07:27:10:03) - add("diginotar-cyber-ca-cross-to-gte-cybertrust-07271003", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFODCCBKGgAwIBAgIEBycQAzANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV\n" + - "UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU\n" + - "cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds\n" + - "b2JhbCBSb290MB4XDTA2MDkyNzEwNTMzMloXDTExMDkyNzEwNTIzMFowPjELMAkG\n" + - "A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy\n" + - "IEN5YmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0s4VCi2o\n" + - "XoRnrf2+70bHyLnPc/z0NLn5LEPnYBM9euOyzztnbJCtwLk/hFLwNULcdNwoO71S\n" + - "tKesckUXxvCJ67SqJfJdS17R2Ye61n189c4ynxAzxbFKu16RMcLQ6UHCkWR+CUE7\n" + - "24sIN2qqylLetTkewIgDpT+LmRNhQ7WbgrPuIG/PoUSi6i9rQJ+PK1etoVPChSJp\n" + - "naA/Ud8LQZENpeGoqlxJCF293nBBsQ/JY2vTfzR0Ai80Wnh1HGh6gWeK89pA8GBj\n" + - "9JIg1wOmPaMeZ8SEG0GlyYzmvepItgUWCLM3Elr3YTz3OG8ul+BvVjhU0yi1rRRu\n" + - "LktktSdlt3UlCbYHPZVWAgqCYLJzReAzJlF0mrnUUBz2TVtbUlITWqZ/pw7h6EFU\n" + - "Z5iMh9XJ02zL01SSBgk0QfeBbz+eyXx1VbDnwbN36MPEADWVQHAQSgXeJbufWaVk\n" + - "vEdgv2DjdosTVd3hdHq5zySman/eZCJEWGiCahD5PeU+G7m9/CL0YASJu1VtKFX6\n" + - "3o6NGyEU1zeLNHtN9rKyEM8zsX0cYplIyytsdpZVvxkNHR+7Zaobjpm1xiiQ5YIt\n" + - "eFAgmv15LyR/8IkpafR9zXO+s+1OwdHtUl6P97jXjYetstkbURL/VrPhrzR9XKR4\n" + - "iBCenQPGpaqiJFH3SRTFse5ZQ5Xfq2goMD8CAwEAAaOCAYYwggGCMBIGA1UdEwEB\n" + - "/wQIMAYBAf8CAQEwUwYDVR0gBEwwSjBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcC\n" + - "ARYtaHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL0NQUy9PbW5pUm9vdC5odG1s\n" + - "MA4GA1UdDwEB/wQEAwIBBjCBoAYDVR0jBIGYMIGVgBSmDB2fYf8HF7W/OEbbQzDV\n" + - "jrBSBqF5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlv\n" + - "bjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRpb25zLCBJbmMuMSMwIQYD\n" + - "VQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIICAaUwRQYDVR0fBD4wPDA6\n" + - "oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL2NnaS1iaW4vQ1JMLzIw\n" + - "MTgvY2RwLmNybDAdBgNVHQ4EFgQUq/lo389KN9d7RYxfct5ARMNlu8IwDQYJKoZI\n" + - "hvcNAQEFBQADgYEAWcyGZhizJlRP1jjNupZey+yZG6oMDW4Z11boriMHbYPCndBE\n" + - "bVh07zmPbZsihOw9w/vm5KbVX5CgxUv4Rhzh/20Faixf3P3bpWg0qgzHVVusNVR/\n" + - "P50aKkpdK3hp+QLl56e+lWOddSAINIpmcuyDI1hyuzB+GJEASm9tNU/6rs8=\n" + - "-----END CERTIFICATE-----"); - - // - // Compromised DigiNotar Root CA - // - - // DigiNotar intermediate, cross-signed by Entrust - // - // Subject: EMAILADDRESS=info@diginotar.nl, - // CN=DigiNotar Root CA, - // O=DigiNotar, C=NL - // Issuer: CN=Entrust.net Secure Server Certification Authority - // OU=(c) 1999 Entrust.net Limited, - // OU=www.entrust.net/CPS incorp. by ref. (limits liab.), - // O=Entrust.net, - // C=US, - // Serial: 1184644297 (46:9C:3C:C9) - add("info-at-diginotar-root-ca-cross-to-entrust-secure-server-469C3CC9", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFSDCCBLGgAwIBAgIERpw8yTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC\n" + - "VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u\n" + - "ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc\n" + - "KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u\n" + - "ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA0\n" + - "MjYwNTAwMDBaFw0xMzA4MTQyMDEyMzZaMF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQK\n" + - "EwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZI\n" + - "hvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIP\n" + - "ADCCAgoCggIBAKywWMEAvdghCAsrmv5uVjAFnxt3kBBBXMMNhxF3joHxynzpjGrt\n" + - "OHQ1u9rf+bvACTe0lnOBfTMamDn3k2+Vfz25sXWHulFI6ItwPpUExdi2wxbZiLCx\n" + - "hx1w2oa0DxSLes8Q0XQ2ohJ7d4ZKeeZ73wIRaKVOhq40WJskE3hWIiUeAYtLUXH7\n" + - "gsxZlmmIWmhTxbkNAjfLS7xmSpB+KgsFB+0WX1WQddhGyRuD4gi+8SPMmR3WKg+D\n" + - "IBVYJ4Iu+uIiwkmxuQGBap1tnUB3aHZOISpthECFTnaZfILz87cCWdQmARuO361T\n" + - "BtGuGN3isjrL14g4jqxbKbkZ05j5GAPPSIKGZgsbaQ/J6ziIeiYaBUyS1yTUlvKs\n" + - "Ui2jR9VS9j/+zoQGcKaqPqLytlY0GFei5IFt58rwatPHkWsCg0F8Fe9rmmRe49A8\n" + - "5bHre12G+8vmd0nNo2Xc97mcuOQLX5PPzDAaMhzOHGOVpfnq4XSLnukrqTB7oBgf\n" + - "DhgL5Vup09FsHgdnj5FLqYq80maqkwGIspH6MVzVpsFSCAnNCmOi0yKm6KHZOQaX\n" + - "9W6NApCMFHs/gM0bnLrEWHIjr7ZWn8Z6QjMpBz+CyeYfBQ3NTCg2i9PIPhzGiO9e\n" + - "7olk6R3r2ol+MqZp0d3MiJ/R0MlmIdwGZ8WUepptYkx9zOBkgLKeR46jAgMBAAGj\n" + - "ggEmMIIBIjASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMB\n" + - "BggrBgEFBQcDAgYIKwYBBQUHAwQwEQYDVR0gBAowCDAGBgRVHSAAMDMGCCsGAQUF\n" + - "BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD\n" + - "VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNy\n" + - "bDAdBgNVHQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wCwYDVR0PBAQDAgEGMB8G\n" + - "A1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob\n" + - "BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAI979rBep8tu3TeLunapgsZ0jtXp\n" + - "GDFjKWSk87dj1jCyYi+q/GyDyZ6ZQZNRP0sF+6twscq05lClWNy3TROMp7QeuoLO\n" + - "G7Utw3OJaswUtp4YglANMRTHEe3g9ltifUXRH5tSuy7u6yi4LD4WTm5ULP6r/g6l\n" + - "0CnjXYb0+b1Fmz6U\n" + - "-----END CERTIFICATE-----"); - - // DigiNotar intermediate, cross-signed by Entrust - // - // Subject: EMAILADDRESS=info@diginotar.nl, - // CN=DigiNotar Root CA, - // O=DigiNotar, C=NL - // Issuer: CN=Entrust.net Secure Server Certification Authority - // OU=(c) 1999 Entrust.net Limited, - // OU=www.entrust.net/CPS incorp. by ref. (limits liab.), - // O=Entrust.net, - // C=US, - // Serial: 1184640175 (46:9C:2C:AF) - add("info-at-diginotar-root-ca-cross-to-entrust-secure-server-469C2CAF", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFSDCCBLGgAwIBAgIERpwsrzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC\n" + - "VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u\n" + - "ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc\n" + - "KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u\n" + - "ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA3\n" + - "MjYxNTU3MzlaFw0xMzA4MjYxNjI3MzlaMF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQK\n" + - "EwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZI\n" + - "hvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIP\n" + - "ADCCAgoCggIBAKywWMEAvdghCAsrmv5uVjAFnxt3kBBBXMMNhxF3joHxynzpjGrt\n" + - "OHQ1u9rf+bvACTe0lnOBfTMamDn3k2+Vfz25sXWHulFI6ItwPpUExdi2wxbZiLCx\n" + - "hx1w2oa0DxSLes8Q0XQ2ohJ7d4ZKeeZ73wIRaKVOhq40WJskE3hWIiUeAYtLUXH7\n" + - "gsxZlmmIWmhTxbkNAjfLS7xmSpB+KgsFB+0WX1WQddhGyRuD4gi+8SPMmR3WKg+D\n" + - "IBVYJ4Iu+uIiwkmxuQGBap1tnUB3aHZOISpthECFTnaZfILz87cCWdQmARuO361T\n" + - "BtGuGN3isjrL14g4jqxbKbkZ05j5GAPPSIKGZgsbaQ/J6ziIeiYaBUyS1yTUlvKs\n" + - "Ui2jR9VS9j/+zoQGcKaqPqLytlY0GFei5IFt58rwatPHkWsCg0F8Fe9rmmRe49A8\n" + - "5bHre12G+8vmd0nNo2Xc97mcuOQLX5PPzDAaMhzOHGOVpfnq4XSLnukrqTB7oBgf\n" + - "DhgL5Vup09FsHgdnj5FLqYq80maqkwGIspH6MVzVpsFSCAnNCmOi0yKm6KHZOQaX\n" + - "9W6NApCMFHs/gM0bnLrEWHIjr7ZWn8Z6QjMpBz+CyeYfBQ3NTCg2i9PIPhzGiO9e\n" + - "7olk6R3r2ol+MqZp0d3MiJ/R0MlmIdwGZ8WUepptYkx9zOBkgLKeR46jAgMBAAGj\n" + - "ggEmMIIBIjASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMB\n" + - "BggrBgEFBQcDAgYIKwYBBQUHAwQwEQYDVR0gBAowCDAGBgRVHSAAMDMGCCsGAQUF\n" + - "BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD\n" + - "VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNy\n" + - "bDAdBgNVHQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wCwYDVR0PBAQDAgEGMB8G\n" + - "A1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob\n" + - "BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAEa6RcDNcEIGUlkDJUY/pWTds4zh\n" + - "xbVkp3wSmpwPFhx5fxTyF4HD2L60jl3aqjTB7gPpsL2Pk5QZlNsi3t4UkCV70UOd\n" + - "ueJRN3o/LOtk4+bjXY2lC0qTHbN80VMLqPjmaf9ghSA9hwhskdtMgRsgfd90q5QP\n" + - "ZFdYf+hthc3m6IcJ\n" + - "-----END CERTIFICATE-----"); - - // - // Compromised DigiNotar PKIoverheid CA Organisatie - G2 - // - - // DigiNotar intermediate, cross-signed by the Dutch government - // - // Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2, - // O=DigiNotar B.V., - // C=NL - // Issuer: CN=Staat der Nederlanden Organisatie CA - G2, - // O=Staat der Nederlanden, - // C=NL - // Serial: 20001983 (01:31:34:bf) - add("diginotar-pkioverheid-organisatie-cross-to-nederlanden-013134BF", - "-----BEGIN CERTIFICATE-----\n" + - "MIIGnDCCBISgAwIBAgIEATE0vzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJO\n" + - "TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTIwMAYDVQQDDClTdGFh\n" + - "dCBkZXIgTmVkZXJsYW5kZW4gT3JnYW5pc2F0aWUgQ0EgLSBHMjAeFw0xMDA1MTIw\n" + - "ODUxMzhaFw0yMDAzMjMwOTUwMDRaMFoxCzAJBgNVBAYTAk5MMRcwFQYDVQQKDA5E\n" + - "aWdpTm90YXIgQi5WLjEyMDAGA1UEAwwpRGlnaU5vdGFyIFBLSW92ZXJoZWlkIENB\n" + - "IE9yZ2FuaXNhdGllIC0gRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC\n" + - "AQCxExkPJ+Zs1FWGS9DsiYpFkXisR71HK+T8RetPtCZzWzfTw3/2497Xo/gtaMUI\n" + - "PkuU1uSHJTZrhLUYdPMoWHMvm2rPvAQe9t7dr/xLqvXbZmIlASWC3vKXWhBu3V2p\n" + - "IrEEqSNzOvhxrR3PhETrR9Gvbch8KKvH8jd6dF9fxQIUiqNa4xtsAeNdjtlo1vQJ\n" + - "GzLckbUs9SDrjANtJkm4k8SFXdjSm69WaswFM8ygQp40VUSca6DUEtArVM23iQ3l\n" + - "9uvo+4UBM096a/GdcjOWDveyhKWlJ8Qn8VFzKXe6Z27+TNy04qGhgS85SY1DOBPO\n" + - "0KVcwoc6AGdlQiPxNlkKHaNRyLyjlCox3+M88p0aPASw77EKMBNzttfzo0wBdRSF\n" + - "eMDXijlYhVD6LubFvs+LP6+PNtQlCS3SD6xyk/K/i9RQs/kVUJuZ9RTZ+4uRozIm\n" + - "JqD43ztggYaDeVsr6xM9KTrBbd29no6H1kquNJcF7hSm9tw4fkrpJFQHPZdoN0Zr\n" + - "DceoIa8TVOQJavFNRgrJXfubT73e+7dUy7g4nKc5+2otwHuNq6WnV+xKkoozxeEg\n" + - "XHPYkJIrgNUPhhhpfDlPhIa890xb89W0yqDC8DciynlSH1PmqvOQsDvd8ij9rOvF\n" + - "BiSgydQvD1j9tZ7sD8+yWdCiBHo4aq5y+73wJWKUCacFCwIDAQABo4IBYTCCAV0w\n" + - "SAYDVR0gBEEwPzA9BgRVHSAAMDUwMwYIKwYBBQUHAgEWJ2h0dHA6Ly93d3cuZGln\n" + - "aW5vdGFyLm5sL2Nwcy9wa2lvdmVyaGVpZDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud\n" + - "DwEB/wQEAwIBBjCBhQYDVR0jBH4wfIAUORCLSZJc22ESIM1JnRqO2pxnQLmhXqRc\n" + - "MFoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4x\n" + - "KzApBgNVBAMMIlN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENBIC0gRzKCBACY\n" + - "lvQwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5wa2lvdmVyaGVpZC5ubC9E\n" + - "b21PcmdhbmlzYXRpZUxhdGVzdENSTC1HMi5jcmwwHQYDVR0OBBYEFLxdlDvZq3sD\n" + - "JXNhwtst7vyrj2WhMA0GCSqGSIb3DQEBCwUAA4ICAQCP/C1Mt9kt1R+978v0t2gX\n" + - "dZ1O1ffdnPEqJu2forYcA9VTs+wIzzTi48P0tRYvyMO+19NzqwA2+RpKftZj6V5G\n" + - "uqW2jhW3oyrYQx3vXcgfgYWzi/f/PPTZ9EYIP5y8HaDZqEzNJVJOCrEg9x/pQ9lU\n" + - "RoETmsBedGwqmDLq/He7DaWiMZgifnx859qkrey3LhoZcfhIUNpDjyyE3cFAJ+O1\n" + - "8BVOltT4XOOGKUYr1zsH6zh/yIZXl9PvKjPEF1DVZGlrK2tFXl0vF8paTs/D1zk8\n" + - "9TufRrmb5w5Jl53W1eMbD+qPAU6aE5RZCgIHSEsaYKt/T+0L2FUNaG9VnGllFULs\n" + - "wNzdbKzDFs4LHVabpMTE0i7gD+JEJytQaaTcYuiKISlCbMwAOpZ2m+9AwKRed4Qy\n" + - "bCYqOWauXeO5ubIsaB8empADOfCqs6TMSYsYNOk3yXspx4R8b0QVL+xhWQTJRcui\n" + - "1lKifH8pktZKxYtCqNT+6tjHhyMY5J16fXNAUpigrm7jBT8FD+Clxm1N7YM3iJzH\n" + - "89xCmmq21yFJNnfy7xhPxXDZnunetyuL9Lx+KN8NQMmFXK6dxTH/0FwOtah+8Okv\n" + - "uq+IruW10Vilr5xxpykBkINpN4IFuvwJwQhujHg7wzMCgD9EhQgd31VWCK0shS1d\n" + - "sQPhrqp0xaTzTro3mHuCuQ==\n" + - "-----END CERTIFICATE-----"); - - // - // Compromised DigiNotar PKIoverheid CA Overheid en Bedrijven - // - - // DigiNotar intermediate, cross-signed by the Dutch government - // - // Subject: CN=DigiNotar PKIoverheid CA Overheid en Bedrijven, - // O=DigiNotar B.V., - // C=NL - // Issuer: CN=Staat der Nederlanden Overheid CA - // O=Staat der Nederlanden, - // C=NL - // Serial: 20015536 (01:31:69:b0) - add("diginotar-pkioverheid-overheid-enb-cross-to-nederlanden-013169B0", - "-----BEGIN CERTIFICATE-----\n" + - "MIIEiDCCA3CgAwIBAgIEATFpsDANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO\n" + - "TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh\n" + - "dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDcwNzA1MDg0MjA3WhcN\n" + - "MTUwNzI3MDgzOTQ2WjBfMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy\n" + - "IEIuVi4xNzA1BgNVBAMTLkRpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp\n" + - "ZCBlbiBCZWRyaWp2ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc\n" + - "vdKnTmoKuzuiheF/AK2+tDBomAfNoHrElM9x+Yo35FPrV3bMi+Zs/u6HVcg+uwQ5\n" + - "AKeAeKxbT370vbhUuHE7BzFJOZNUfCA7eSuPu2GQfbGs5h+QLp1FAalkLU3DL7nn\n" + - "UNVOKlyrdnY3Rtd57EKZ96LspIlw3Dgrh6aqJOadkiQbvvb91C8ZF3rmMgeUVAVT\n" + - "Q+lsvK9Hy7zL/b07RBKB8WtLu+20z6slTxjSzAL8o0+1QjPLWc0J3NNQ/aB2jKx+\n" + - "ZopC9q0ckvO2+xRG603XLzDgbe5bNr5EdLcgBVeFTegAGaL2DOauocBC36esgl3H\n" + - "aLcY5olLmmv6znn58yynAgMBAAGjggFQMIIBTDBIBgNVHSAEQTA/MD0GBFUdIAAw\n" + - "NTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5kaWdpbm90YXIubmwvY3BzL3BraW92\n" + - "ZXJoZWlkMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIGABgNVHSME\n" + - "eTB3gBQLhtYPd6NosftkCcOIblwEHFfpPaFZpFcwVTELMAkGA1UEBhMCTkwxHjAc\n" + - "BgNVBAoTFVN0YWF0IGRlciBOZWRlcmxhbmRlbjEmMCQGA1UEAxMdU3RhYXQgZGVy\n" + - "IE5lZGVybGFuZGVuIFJvb3QgQ0GCBACYmnkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0\n" + - "cDovL2NybC5wa2lvdmVyaGVpZC5ubC9Eb21PdkxhdGVzdENSTC5jcmwwHQYDVR0O\n" + - "BBYEFEwIyY128ZjHPt881y91DbF2eZfMMA0GCSqGSIb3DQEBBQUAA4IBAQAMlIca\n" + - "v03jheLu19hjeQ5Q38aEW9K72fUxCho1l3TfFPoqDz7toOMI9tVOW6+mriXiRWsi\n" + - "D7dUKH6S3o0UbNEc5W50BJy37zRERd/Jgx0ZH8Apad+J1T/CsFNt5U4X5HNhIxMm\n" + - "cUP9TFnLw98iqiEr2b+VERqKpOKrp11Lbyn1UtHk0hWxi/7wA8+nfemZhzizDXMU\n" + - "5HIs4c71rQZIZPrTKbmi2Lv01QulQERDjqC/zlqlUkxk0xcxYczopIro5Ij76eUv\n" + - "BjMzm5RmZrGrUDqhCYF0U1onuabSJc/Tw6f/ltAv6uAejVLpGBwgCkegllYOQJBR\n" + - "RKwa/fHuhR/3Qlpl\n" + - "-----END CERTIFICATE-----"); - - // - // Compromised DigiNotar PKIoverheid CA Overheid - // - - // DigiNotar intermediate, cross-signed by the Dutch government - // - // Subject: CN=DigiNotar PKIoverheid CA Overheid - // O=DigiNotar B.V., - // C=NL - // Issuer: CN=Staat der Nederlanden Overheid CA - // O=Staat der Nederlanden, - // C=NL - // Serial: 20006006 (01:31:44:76) - add("diginotar-pkioverheid-overheid-cross-to-nederlanden-01314476", - "-----BEGIN CERTIFICATE-----\n" + - "MIIEezCCA2OgAwIBAgIEATFEdjANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO\n" + - "TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh\n" + - "dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDQwNjI0MDgxOTMyWhcN\n" + - "MTAwNjIzMDgxNzM2WjBSMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy\n" + - "IEIuVi4xKjAoBgNVBAMTIURpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp\n" + - "ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANSlrubta5tlOjVCi/gb\n" + - "yLCvRqfBjxG8H594VcKHu0WAYc99SPZF9cycj5mw2GyfQvy/WIrGrL4iyNq1gSqR\n" + - "0QA/mTXKZIaPqzpDhdm+VvrKkmjrbZfaQxgMSs3ChtBsjcP9Lc0X1zXZ4Q8nBe3k\n" + - "BTp+zehINfmbjoEgXLxsMR5RQ6GxzKjuC04PQpbJQgTIakglKaqYcDDZbEscWgPV\n" + - "Hgj/2aoHlj6leW/ThHZ+O41jUguEmBLZA3mu3HrCfrHntb5dPt0ihzSx7GtD/SaX\n" + - "5HBLxnP189YuqMk5iRA95CtiSdKauvon/xRKRLNgG6XAz0ctSoY7xLDdiBVU5kJd\n" + - "FScCAwEAAaOCAVAwggFMMEgGA1UdIARBMD8wPQYEVR0gADA1MDMGCCsGAQUFBwIB\n" + - "FidodHRwOi8vd3d3LmRpZ2lub3Rhci5ubC9jcHMvcGtpb3ZlcmhlaWQwDwYDVR0T\n" + - "AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgYAGA1UdIwR5MHeAFAuG1g93o2ix\n" + - "+2QJw4huXAQcV+k9oVmkVzBVMQswCQYDVQQGEwJOTDEeMBwGA1UEChMVU3RhYXQg\n" + - "ZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g\n" + - "Um9vdCBDQYIEAJiaeTA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnBraW92\n" + - "ZXJoZWlkLm5sL0RvbU92TGF0ZXN0Q1JMLmNybDAdBgNVHQ4EFgQUvRaYQh2+kdE9\n" + - "wpcl4CjXWOC1f+IwDQYJKoZIhvcNAQEFBQADggEBAGhQsCWLiaN2EOhPAW+JQP6o\n" + - "XBOrLv5w6joahzBFVn1BiefzmlMKjibqKYxURRvMAsMkh82/MfL8V0w6ugxl81lu\n" + - "i42dcxl9cKSVXKMw4bbBzJ2VQI5HTIABwefeNuy/eX6idVwYdt3ajAH7fUA8Q9Cq\n" + - "vr6H8B+8mwoEqTVTEVlCSsC/EXsokYEUr06PPzRudKjDmijgj7zFaIioZNc8hk7g\n" + - "ufEgrs/tmcNGylrwRHgCXjCRBt2NHlZ08l7A1AGU8HcHlSbG9Un/2q9kVHUkps0D\n" + - "gtUaEK+x6jpAu/R8Ojezu/+ZEcwwjI/KOhG+84+ejFmtyEkrUdsAdEdLf/2dKsw=\n" + - "-----END CERTIFICATE-----"); - - // - // Compromised DigiNotar Services 1024 CA - // - - // DigiNotar intermediate, cross-signed by the Entrust - // - // Subject: EMAILADDRESS=info@diginotar.nl, - // CN=DigiNotar Services 1024 CA - // O=DigiNotar, C=NL - // Issuer: CN=Entrust.net Secure Server Certification Authority, - // OU=(c) 1999 Entrust.net Limited, - // OU=www.entrust.net/CPS incorp. by ref. (limits liab.), - // O=Entrust.net, - // C=US - // Serial: 1184640176 (46:9c:2c:b0) - add("diginotar-services-1024-ca-cross-to-entrust-469C2CB0", - "-----BEGIN CERTIFICATE-----\n" + - "MIIDzTCCAzagAwIBAgIERpwssDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC\n" + - "VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u\n" + - "ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc\n" + - "KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u\n" + - "ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA3\n" + - "MjYxNTU5MDBaFw0xMzA4MjYxNjI5MDBaMGgxCzAJBgNVBAYTAk5MMRIwEAYDVQQK\n" + - "EwlEaWdpTm90YXIxIzAhBgNVBAMTGkRpZ2lOb3RhciBTZXJ2aWNlcyAxMDI0IENB\n" + - "MSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCBnzANBgkqhkiG9w0B\n" + - "AQEFAAOBjQAwgYkCgYEA2ptNXTz50eKLxsYIIMXZHkjsZlhneWIrQWP0iY1o2q+4\n" + - "lDaLGSSkoJPSmQ+yrS01Tc0vauH5mxkrvAQafi09UmTN8T5nD4ku6PJPrqYIoYX+\n" + - "oakJ5sarPkP8r3oDkdqmOaZh7phPGKjTs69mgumfvN1y+QYEvRLZGCTnq5NTi1kC\n" + - "AwEAAaOCASYwggEiMBIGA1UdEwEB/wQIMAYBAf8CAQAwJwYDVR0lBCAwHgYIKwYB\n" + - "BQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDBDARBgNVHSAECjAIMAYGBFUdIAAwMwYI\n" + - "KwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5l\n" + - "dDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmVudHJ1c3QubmV0L3NlcnZl\n" + - "cjEuY3JsMB0GA1UdDgQWBBT+3JRJDG/vXH/G8RKZTxZJrfuCZTALBgNVHQ8EBAMC\n" + - "AQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0BowGQYJKoZIhvZ9B0EA\n" + - "BAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEFBQADgYEAY3RqN6k/lpxmyFisCcnv\n" + - "9WWUf6MCxDgxvV0jh+zUVrLJsm7kBQb87PX6iHBZ1O7m3bV6oKNgLwIMq94SXa/w\n" + - "NUuqikeRGvWFLELHHe+VQ7NeuJWTpdrFKKqtci0xrZlrbP+MISevrZqRK8fdWMNu\n" + - "B8WfedLHjFW/TMcnXlEWKz4=\n" + - "-----END CERTIFICATE-----"); - - // - // Revoked DigiCert code signing certificates used to sign malware - // - - // Subject: CN=Buster Paper Comercial Ltda, - // O=Buster Paper Comercial Ltda, - // L=S?o Jos? Dos Campos, - // ST=S?o Paulo, - // C=BR - // Issuer: CN=DigiCert Assured ID Code Signing CA-1, - // OU=www.digicert.com, - // O=DigiCert Inc, - // C=US - // Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12 - add("buster-paper-comercial-ltda-72A67312", - "-----BEGIN CERTIFICATE-----\n" + - "MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv\n" + - "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + - "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + - "ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow\n" + - "gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT\n" + - "w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l\n" + - "cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh\n" + - "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL\n" + - "HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn\n" + - "2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4\n" + - "tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi\n" + - "mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf\n" + - "Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx\n" + - "BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw\n" + - "HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT\n" + - "BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js\n" + - "My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6\n" + - "Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud\n" + - "IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov\n" + - "L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG\n" + - "AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD\n" + - "AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh\n" + - "AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy\n" + - "AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn\n" + - "ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs\n" + - "AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp\n" + - "AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl\n" + - "AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho\n" + - "dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl\n" + - "cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et\n" + - "MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI\n" + - "hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft\n" + - "jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e\n" + - "gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44\n" + - "/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc\n" + - "BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj\n" + - "XMuKLxbh7g==\n" + - "-----END CERTIFICATE-----"); - - // Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, - // O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, - // L=S?o Paulo, - // ST=S?o Paulo, - // C=BR - // Issuer: CN=DigiCert Assured ID Code Signing CA-1, - // OU=www.digicert.com, - // O=DigiCert Inc, - // C=US - // Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f - add("buster-assistencia-tecnica-electronica-ltda-3FD74D2F", - "-----BEGIN CERTIFICATE-----\n" + - "MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv\n" + - "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n" + - "d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv\n" + - "ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow\n" + - "gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT\n" + - "w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF\n" + - "TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB\n" + - "IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA\n" + - "A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR\n" + - "4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V\n" + - "JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW\n" + - "kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb\n" + - "0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj\n" + - "NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV\n" + - "HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30\n" + - "o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD\n" + - "MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1\n" + - "cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t\n" + - "L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB\n" + - "hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z\n" + - "c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A\n" + - "eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA\n" + - "ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA\n" + - "IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA\n" + - "YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA\n" + - "cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA\n" + - "aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA\n" + - "ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC\n" + - "BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0\n" + - "LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp\n" + - "Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA\n" + - "MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ\n" + - "A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE\n" + - "Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA\n" + - "XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9\n" + - "UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL\n" + - "zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc\n" + - "-----END CERTIFICATE-----"); - - // - // Revoked code signing certificate w/ a stolen key issued by GoDaddy - // used to sign malware - // - - // Subject: CN=CLEARESULT CONSULTING INC., OU=Corporate IT, - // O=CLEARESULT CONSULTING INC., L=Austin, ST=TX, C=US - // Issuer: SERIALNUMBER=07969287, - // CN=Go Daddy Secure Certification Authority, - // OU=http://certificates.godaddy.com/repository, - // O="GoDaddy.com, Inc.", - // L=Scottsdale, - // ST=Arizona, - // C=US - // Serial: 2b:73:43:2a:a8:4f:44 - add("clearesult-consulting-inc-2AA84F44", - "-----BEGIN CERTIFICATE-----\n" + - "MIIFYjCCBEqgAwIBAgIHK3NDKqhPRDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE\n" + - "BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY\n" + - "BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm\n" + - "aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5\n" + - "IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky\n" + - "ODcwHhcNMTIwMjE1MjEwOTA2WhcNMTQwMjE1MjEwOTA2WjCBjDELMAkGA1UEBgwC\n" + - "VVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0aW4xIzAhBgNVBAoMGkNMRUFS\n" + - "RVNVTFQgQ09OU1VMVElORyBJTkMuMRUwEwYDVQQLDAxDb3Jwb3JhdGUgSVQxIzAh\n" + - "BgNVBAMMGkNMRUFSRVNVTFQgQ09OU1VMVElORyBJTkMuMIIBIjANBgkqhkiG9w0B\n" + - "AQEFAAOCAQ8AMIIBCgKCAQEAtIOjCKeAicull+7ZIzt0/4ya3IeXUFlfypqKMLkU\n" + - "IbKjn0P5uMj6VE3rlbZr44RCegxvdnR6umBh1c0ZXoN3o+yc0JKcKcLiApmJJ277\n" + - "p7IbLwYDhBXRQNoIJm187IOMRPIxsKN4hL91txn9jGBmW+9zKlJlNhR5R7vjwU2E\n" + - "jrH/6oqsc9EM2yYpfjlNv6+3jSwAYZCkSWr+27PQOV+YHKmIxtJjX0upFz5FdIrV\n" + - "9CCX+L2Kji1THOkSgG4QTbYxmEcHqGViWz8hXLeNXjcbEsPuIiAu3hknxRHfUTE/\n" + - "U0Lh0Ug1e3LrJu+WnxM2SmUY4krsZ22c0yWUW9hzWITIjQIDAQABo4IBhzCCAYMw\n" + - "DwYDVR0TAQH/BAUwAwEBADATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8E\n" + - "BAMCB4AwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5LmNvbS9n\n" + - "ZHM1LTE2LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcCMDkwNwYIKwYBBQUH\n" + - "AgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8w\n" + - "gYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRk\n" + - "eS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHku\n" + - "Y29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSMEGDAWgBT9\n" + - "rGEyk2xF1uLuhV+auud2mWjM5zAdBgNVHQ4EFgQUDtdeKqeN2QkcbEp1HovFieNB\n" + - "XiowDQYJKoZIhvcNAQEFBQADggEBAD74Agw5tvi2aBl4/f/s7/VE/BClzDsKMb9K\n" + - "v9qpeC45ZA/jelxV11HKbQnVF194gDb7D2H9OsAsRUy8HVKbXEcc/8dKvwOqb+BC\n" + - "2i/EmfjLgmCfezNFtLq8xcPxF3zIRc44vPrK0z4YZsaHdH+yTEJ51p5EMdTqaLaP\n" + - "4n5m8LX3RfqlQB9dYFe6dUoYZjKm9d/pIRww3VqfOzjl42Edi1w6dWmBVMx1NZuR\n" + - "DBabJH1vJ9Gd+KwxMCmBZ6pQPl28JDimhJhI2LNqU349uADQVV0HJosddN/ARyyI\n" + - "LSIQO7BnNVKVG9Iujf33bvPNeg0qNz5qw+rKKq97Pqeum+L5oKU=\n" + - "-----END CERTIFICATE-----"); - } + private UntrustedCertificates() {} } diff --git a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java index bd59b62811a..b96674e2e1d 100644 --- a/jdk/src/share/classes/sun/security/x509/X509CertImpl.java +++ b/jdk/src/share/classes/sun/security/x509/X509CertImpl.java @@ -37,6 +37,7 @@ import java.security.*; import java.security.cert.*; import java.security.cert.Certificate; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import javax.security.auth.x500.X500Principal; @@ -1913,4 +1914,45 @@ public class X509CertImpl extends X509Certificate implements DerEncoder { } return false; } + + private ConcurrentHashMap fingerprints = + new ConcurrentHashMap<>(2); + + public String getFingerprint(String algorithm) { + return fingerprints.computeIfAbsent(algorithm, + x -> getCertificateFingerPrint(x)); + } + + /** + * Gets the requested finger print of the certificate. The result + * only contains 0-9 and A-F. No small case, no colon. + */ + private String getCertificateFingerPrint(String mdAlg) { + String fingerPrint = ""; + try { + byte[] encCertInfo = getEncoded(); + MessageDigest md = MessageDigest.getInstance(mdAlg); + byte[] digest = md.digest(encCertInfo); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < digest.length; i++) { + byte2hex(digest[i], buf); + } + fingerPrint = buf.toString(); + } catch (NoSuchAlgorithmException | CertificateEncodingException e) { + // ignored + } + return fingerPrint; + } + + /** + * Converts a byte to hex digit and writes to the supplied buffer + */ + private static void byte2hex(byte b, StringBuffer buf) { + char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + int high = ((b & 0xf0) >> 4); + int low = (b & 0x0f); + buf.append(hexChars[high]); + buf.append(hexChars[low]); + } } diff --git a/jdk/src/share/classes/sun/tools/jstat/resources/jstat_options b/jdk/src/share/classes/sun/tools/jstat/resources/jstat_options index bead54260fd..a629a3c6206 100644 --- a/jdk/src/share/classes/sun/tools/jstat/resources/jstat_options +++ b/jdk/src/share/classes/sun/tools/jstat/resources/jstat_options @@ -207,6 +207,22 @@ option gc { scale K format "0.0" } + column { + header "^CCSC^" /* Compressed Class Space Capacity - Current */ + data sun.gc.compressedclassspace.capacity + align center + width 6 + scale K + format "0.0" + } + column { + header "^CCSU^" /* Compressed Class Space Used */ + data sun.gc.compressedclassspace.used + align center + width 6 + scale K + format "0.0" + } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations @@ -353,6 +369,30 @@ option gccapacity { width 8 format "0.0" } + column { + header "^CCSMN^" /* Compressed Class Space Capacity - Minimum */ + data sun.gc.compressedclassspace.minCapacity + scale K + align right + width 8 + format "0.0" + } + column { + header "^CCSMX^" /* Compressed Class Space Capacity - Maximum */ + data sun.gc.compressedclassspace.maxCapacity + scale K + align right + width 8 + format "0.0" + } + column { + header "^CCSC^" /* Compressed Class Space Capacity - Current */ + data sun.gc.compressedclassspace.capacity + scale K + align right + width 8 + format "0.0" + } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations @@ -411,6 +451,14 @@ option gccause { scale raw format "0.00" } + column { + header "^CCS^" /* Compressed Class Space - Percent Used */ + data (1-((sun.gc.compressedclassspace.capacity - sun.gc.compressedclassspace.used)/sun.gc.compressedclassspace.capacity)) * 100 + align right + width 6 + scale raw + format "0.00" + } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations @@ -661,6 +709,22 @@ option gcold { scale K format "0.0" } + column { + header "^CCSC^" /* Compressed Class Space Capacity - Current */ + data sun.gc.compressedclassspace.capacity + width 8 + align right + scale K + format "0.0" + } + column { + header "^CCSU^" /* Compressed Class Space Used */ + data sun.gc.compressedclassspace.used + width 8 + align right + scale K + format "0.0" + } column { header "^OC^" /* Old Space Capacity - Current */ data sun.gc.generation.1.space.0.capacity @@ -801,6 +865,30 @@ option gcmetacapacity { width 10 format "0.0" } + column { + header "^CCSMN^" /* Compressed Class Space Capacity - Minimum */ + data sun.gc.compressedclassspace.minCapacity + scale K + align right + width 10 + format "0.0" + } + column { + header "^CCSMX^" /* Compressed Class Space Capacity - Maximum */ + data sun.gc.compressedclassspace.maxCapacity + scale K + align right + width 10 + format "0.0" + } + column { + header "^CCSC^" /* Compressed Class Space Capacity - Current */ + data sun.gc.compressedclassspace.capacity + scale K + align right + width 10 + format "0.0" + } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations @@ -875,6 +963,14 @@ option gcutil { scale raw format "0.00" } + column { + header "^CCS^" /* Compressed Class Space Space - Percent Used */ + data (1-((sun.gc.compressedclassspace.capacity - sun.gc.compressedclassspace.used)/sun.gc.compressedclassspace.capacity)) * 100 + align right + width 6 + scale raw + format "0.00" + } column { header "^YGC^" /* Young Generation Collections */ data sun.gc.collector.0.invocations diff --git a/jdk/src/share/lib/security/BlacklistedCertsConverter.java b/jdk/src/share/lib/security/BlacklistedCertsConverter.java new file mode 100644 index 00000000000..65a88f00a2e --- /dev/null +++ b/jdk/src/share/lib/security/BlacklistedCertsConverter.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. + */ + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Collection; + +/** + * This is the tool to convert blacklisted.certs.pem to blacklisted.certs. + * Every time a new blacklisted certs is added, please append the PEM format + * to the end of blacklisted.certs.pem (with proper comments) and then use + * this tool to generate an updated blacklisted.certs. Make sure to include + * changes to both in a changeset. + */ +public class BlacklistedCertsConverter { + public static void main(String[] args) throws Exception { + if (args.length == 0) { + System.out.println("Usage: java BlacklistedCertsConverter SHA-256" + + " < blacklisted.certs.pem > blacklisted.certs"); + System.exit(1); + } + String mdAlg = args[0]; + CertificateFactory cf = CertificateFactory.getInstance("X.509"); + Collection certs + = cf.generateCertificates(System.in); + System.out.println("Algorithm=" + mdAlg); + for (Certificate cert: certs) { + System.out.println( + getCertificateFingerPrint(mdAlg, (X509Certificate)cert)); + } + } + + /** + * Converts a byte to hex digit and writes to the supplied buffer + */ + private static void byte2hex(byte b, StringBuffer buf) { + char[] hexChars = { '0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'A', 'B', 'C', 'D', 'E', 'F' }; + int high = ((b & 0xf0) >> 4); + int low = (b & 0x0f); + buf.append(hexChars[high]); + buf.append(hexChars[low]); + } + + /** + * Gets the requested finger print of the certificate. + */ + private static String getCertificateFingerPrint(String mdAlg, + X509Certificate cert) { + String fingerPrint = ""; + try { + byte[] encCertInfo = cert.getEncoded(); + MessageDigest md = MessageDigest.getInstance(mdAlg); + byte[] digest = md.digest(encCertInfo); + StringBuffer buf = new StringBuffer(); + for (int i = 0; i < digest.length; i++) { + byte2hex(digest[i], buf); + } + fingerPrint = buf.toString(); + } catch (NoSuchAlgorithmException | CertificateEncodingException e) { + // ignored + } + return fingerPrint; + } +} diff --git a/jdk/src/share/lib/security/blacklisted.certs b/jdk/src/share/lib/security/blacklisted.certs new file mode 100644 index 00000000000..cb1e4d59e38 --- /dev/null +++ b/jdk/src/share/lib/security/blacklisted.certs @@ -0,0 +1,19 @@ +Algorithm=SHA-256 +76A45A496031E4DD2D7ED23E8F6FF97DBDEA980BAAC8B0BA94D7EDB551348645 +4CBBF8256BC9888A8007B2F386940A2E394378B0D903CBB3863C5A6394B889CE +D24566BF315F4E597D6E381C87119FB4198F5E9E2607F5F4AB362EF7E2E7672F +14E6D2764A4B06701C6CBC376A253775F79C782FBCB6C0EE6F99DE4BA1024ADD +D3A936E1A7775A45217C8296A1F22AC5631DCDEC45594099E78EEEBBEDCBA967 +5E83124D68D24E8E177E306DF643D5EA99C5A94D6FC34B072F7544A1CABB7C7B +9ED8F9B0E8E42A1656B8E1DD18F42BA42DC06FE52686173BA2FC70E756F207DC +FDEDB5BDFCB67411513A61AEE5CB5B5D7C52AF06028EFC996CC1B05B1D6CEA2B +A686FEE577C88AB664D0787ECDFFF035F4806F3DE418DC9E4D516324FFF02083 +4FEE0163686ECBD65DB968E7494F55D84B25486D438E9DE558D629D28CD4D176 +8A1BD21661C60015065212CC98B1ABB50DFD14C872A208E66BAE890F25C448AF +B8686723E415534BC0DBD16326F9486F85B0B0799BF6639334E61DAAE67F36CD +3946901F46B0071E90D78279E82FABABCA177231A704BE72C5B0E8918566EA66 +31C8FD37DB9B56E708B03D1F01848B068C6DA66F36FB5D82C008C6040FA3E133 +450F1B421BB05C8609854884559C323319619E8B06B001EA2DCBB74A23AA3BE2 +FC02FD48DB92D4DCE6F11679D38354CF750CFC7F584A520EB90BDE80E241F2BD +DF21016B00FC54F9FE3BC8B039911BB216E9162FAD2FD14D990AB96E951B49BE +F5B6F88F75D391A4B1EB336F9E201239FB6B1377DB8CFA7B84736216E5AFFFD7 diff --git a/jdk/src/share/lib/security/blacklisted.certs.pem b/jdk/src/share/lib/security/blacklisted.certs.pem new file mode 100644 index 00000000000..f44a6985352 --- /dev/null +++ b/jdk/src/share/lib/security/blacklisted.certs.pem @@ -0,0 +1,721 @@ +// Subject: CN=Digisign Server ID (Enrich), +// OU=457608-K, +// O=Digicert Sdn. Bhd., +// C=MY +// Issuer: CN=GTE CyberTrust Global Root, +// OU=GTE CyberTrust Solutions, Inc., +// O=GTE Corporation, +// C=US +// Serial: 120001705 (07:27:14:a9) +-----BEGIN CERTIFICATE----- +MIIDyzCCAzSgAwIBAgIEBycUqTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MB4XDTA3MDcxNzE1MTc0OFoXDTEyMDcxNzE1MTY1NFowYzELMAkG +A1UEBhMCTVkxGzAZBgNVBAoTEkRpZ2ljZXJ0IFNkbi4gQmhkLjERMA8GA1UECxMI +NDU3NjA4LUsxJDAiBgNVBAMTG0RpZ2lzaWduIFNlcnZlciBJRCAoRW5yaWNoKTCB +nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArahkS02Hx4RZufuQRqCmicDx/tXa +VII3DZkrRSYK6Fawf8qo9I5HhAGCKeOzarWR8/uVhbxyqGToCkCcxfRxrnt7agfq +kBRPjYmvlKuyBtQCanuYH1m5Os1U+iDfsioK6bjdaZDAKdNO0JftZszFGUkGf/pe +LHx7hRsyQt97lSUCAwEAAaOCAXgwggF0MBIGA1UdEwEB/wQIMAYBAf8CAQAwXAYD +VR0gBFUwUzBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcCARYtaHR0cDovL2N5YmVy +dHJ1c3Qub21uaXJvb3QuY29tL3JlcG9zaXRvcnkuY2ZtMAcGBWCDSgEBMA4GA1Ud +DwEB/wQEAwIB5jCBiQYDVR0jBIGBMH+heaR3MHUxCzAJBgNVBAYTAlVTMRgwFgYD +VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv +bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv +b3SCAgGlMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly93d3cucHVibGljLXRydXN0 +LmNvbS9jZ2ktYmluL0NSTC8yMDE4L2NkcC5jcmwwHQYDVR0OBBYEFMYWk04WF+wW +royUdvOGbcV0boR3MA0GCSqGSIb3DQEBBQUAA4GBAHYAe6Z4K2Ydjl42xqSOBfIj +knyTZ9P0wAp9iy3Z6tVvGvPhSilaIoRNUC9LDPL/hcJ7VdREgr5trGeOvLQfkpxR +gBoU9m6rYYgLrRx/90tQUdZlG6ZHcRVesHHzNRTyN71jyNXwk1o0X9g96F33xR7A +5c8fhiSpPAdmzcHSNmNZ +-----END CERTIFICATE----- + +// Subject: CN=Digisign Server ID - (Enrich), +// OU=457608-K, +// O=Digicert Sdn. Bhd., +// C=MY +// Issuer: CN=Entrust.net Certification Authority (2048) +// OU=(c) 1999 Entrust.net Limited, +// OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), +// O=Entrust.net +// Serial: 1184644297 (4c:0e:63:6a) +-----BEGIN CERTIFICATE----- +MIIEzjCCA7agAwIBAgIETA5jajANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML +RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp +bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5 +IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw0xMDA3MTYxNzIzMzdaFw0xNTA3 +MTYxNzUzMzdaMGUxCzAJBgNVBAYTAk1ZMRswGQYDVQQKExJEaWdpY2VydCBTZG4u +IEJoZC4xETAPBgNVBAsTCDQ1NzYwOC1LMSYwJAYDVQQDEx1EaWdpc2lnbiBTZXJ2 +ZXIgSUQgLSAoRW5yaWNoKTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB +AMWJ5PQNBkCSWccaszXRDkwqM/n4r8qef+65p21g9FTob9Wb8xtjMQRoctE0Foy0 +FyyX3nPF2JAVoBor9cuzSIZE8B2ITM5BQhrv9Qze/kDaOSD3BlU6ap1GwdJvpbLI +Vz4po5zg6YV3ZuiYpyR+vsBZIOVEb7ZX2L7OwmV3WMZhQdF0BMh/SULFcqlyFu6M +3RJdtErU0a9Qt9iqdXZorT5dqjBtYairEFs+E78z4K9EnTgiW+9ML6ZxJhUmyiiM +2fqOjqmiFDXimySItPR/hZ2DTwehthSQNsQ0HI0mYW0Tb3i+6I8nx0uElqOGaAwj +vgvsjJQAqQSKE5D334VsDLECAwEAAaOCATQwggEwMA4GA1UdDwEB/wQEAwIBBjAS +BgNVHRMBAf8ECDAGAQH/AgEAMCcGA1UdJQQgMB4GCCsGAQUFBwMBBggrBgEFBQcD +AgYIKwYBBQUHAwQwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8v +b2NzcC5lbnRydXN0Lm5ldDBEBgNVHSAEPTA7MDkGBWCDSgEBMDAwLgYIKwYBBQUH +AgEWImh0dHA6Ly93d3cuZGlnaWNlcnQuY29tLm15L2Nwcy5odG0wMgYDVR0fBCsw +KTAnoCWgI4YhaHR0cDovL2NybC5lbnRydXN0Lm5ldC8yMDQ4Y2EuY3JsMBEGA1Ud +DgQKBAhMTswlKAMpgTAfBgNVHSMEGDAWgBRV5IHREYC+2Im5CKMx+aEkCRa5cDAN +BgkqhkiG9w0BAQUFAAOCAQEAl0zvSjpJrHL8MCBrtClbp8WVBJD5MtXChWreA6E3 ++YkAsFqsVX7bQzX/yQH4Ub7MJsrIaqTEVD4mHucMo82XZ5TdpkLrXM2POXlrM3kh +Bnn6gkQVmczBtznTRmJ8snDrb84gqj4Zt+l0gpy0pUtNYQA35IfS8hQ6ZHy4qXth +4JMi59WfPkfmNnagU9gAAzoPtTP+lsrT0oI6Lt3XSOHkp2nMHOmZSufKcEXXCwcO +mnUb0C+Sb/akB8O9HEumhLZ9qJqp0qcp8QtXaR6XVybsK0Os1EWDBQDp4/BGQAf6 +6rFRc5Mcpd1TETfIKqcVJx20qsx/qjEw/LhFn0gJ7RDixQ== +-----END CERTIFICATE----- + +// Subject: CN=Java Media APIs, +// OU=Java Signed Extensions, +// OU=Corporate Object Signing, +// O=Sun Microsystems Inc +// Issuer: CN=Object Signing CA, +// OU=Class 2 OnSite Subscriber CA, +// OU=VeriSign Trust Network, +// O=Sun Microsystems Inc +// Serial: 6a:8b:99:91:37:59:4f:89:53:e2:97:18:9f:19:1e:4e +-----BEGIN CERTIFICATE----- +MIIFdzCCBF+gAwIBAgIQaouZkTdZT4lT4pcYnxkeTjANBgkqhkiG9w0BAQUFADCB +gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj +cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA5MDUxMjAw +MDAwMFoXDTEyMDUxMTIzNTk1OVowfTEdMBsGA1UEChQUU3VuIE1pY3Jvc3lzdGVt +cyBJbmMxITAfBgNVBAsUGENvcnBvcmF0ZSBPYmplY3QgU2lnbmluZzEfMB0GA1UE +CxQWSmF2YSBTaWduZWQgRXh0ZW5zaW9uczEYMBYGA1UEAxQPSmF2YSBNZWRpYSBB +UElzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAl5blzoKTVE8y4Hpz +q6E15RZz1bF5HnYEyYqgHkZXnAKedmYCoMzm1XK8s+gQWShLEvGEAvs5yqarx9gE +nnC21N28aEZgIJMa2/arKxCUkS4pxdGPYGexL9UzSRkUpoBShCZKEGdmX7gfJE2K +/sd9MFvGV5/yZtWXrADzvm0Kd/9mg1KRv1gfrZIq0TJbupoXPYYqb73AkI9eT2ZD +q9MdwD4E5+oojsDFXt8GU/D00fUhtXpYwuplU7D667WHYdJhIah0ST6JywyqcLXG +XSuFTXOgITT2idSHluZVmx3dqJ72u9kPkO4JdJTMDfaK8zgNLaRkiU8Qcj+qhLYH +ytaqcwIDAQABo4IB6jCCAeYwCQYDVR0TBAIwADAOBgNVHQ8BAf8EBAMCB4AwfwYD +VR0fBHgwdjB0oHKgcIZuaHR0cDovL29uc2l0ZWNybC52ZXJpc2lnbi5jb20vU3Vu +TWljcm9zeXN0ZW1zSW5jQ29ycG9yYXRlT2JqZWN0U2lnbmluZ0phdmFTaWduZWRF +eHRlbnNpb25zQ2xhc3NCL0xhdGVzdENSTC5jcmwwHwYDVR0jBBgwFoAUs0crgn5T +tHPKuLsZt76BTQeVx+0wHQYDVR0OBBYEFKS32mVx0gNWTeS4ProHEaeSpvvIMDsG +CCsGAQUFBwEBBC8wLTArBggrBgEFBQcwAYYfaHR0cDovL29uc2l0ZS1vY3NwLnZl +cmlzaWduLmNvbTCBtQYDVR0gBIGtMIGqMDkGC2CGSAGG+EUBBxcCMCowKAYIKwYB +BQUHAgEWHGh0dHBzOi8vd3d3LnZlcmlzaWduLmNvbS9ycGEwbQYLYIZIAYb3AIN9 +nD8wXjAnBggrBgEFBQcCARYbaHR0cHM6Ly93d3cuc3VuLmNvbS9wa2kvY3BzMDMG +CCsGAQUFBwICMCcaJVZhbGlkYXRlZCBGb3IgU3VuIEJ1c2luZXNzIE9wZXJhdGlv +bnMwEwYDVR0lBAwwCgYIKwYBBQUHAwMwDQYJKoZIhvcNAQEFBQADggEBAAe6BO4W +3TSNWfezyelJs6kE3HfulT6Bdyz4UUoh9ykXcV8nRwT+kh25I5MdyG2GfkJoADPR +VhC5DYo13UFpIsTNVjq+hGYe2hML93bN7ad9SxCCyjHUo3yMz2qgBbHZI3VA9ZHA +aWM4Tx0saMwbcnVvlbuGh+PXvStfypJqYT6lzcdFfjNVX4FI/QQNGhBswMY51tC8 +GTBCL2qhJon0gSCU4zaawDOf7+XxJWirLamYL1Aal1/h2z2sFrvA/1ftxtU3kZ6I +7De8DyoHeZg7pYGdrj7g+lPhCga/WvEhN152I+aP08YbFcJHYmK05ngl/Ye4c6Bd +cdrdfbw6QzEUIYY= +-----END CERTIFICATE----- + +// Subject: CN=JavaFX 1.0 Runtime, +// OU=Java Signed Extensions, +// OU=Corporate Object Signing, +// O=Sun Microsystems Inc +// Issuer: CN=Object Signing CA, +// OU=Class 2 OnSite Subscriber CA, +// OU=VeriSign Trust Network, +// O=Sun Microsystems Inc +// Serial: 55:c0:e6:44:59:59:79:9e:d9:26:f1:b0:4a:1e:f0:27 +-----BEGIN CERTIFICATE----- +MIIFezCCBGOgAwIBAgIQVcDmRFlZeZ7ZJvGwSh7wJzANBgkqhkiG9w0BAQUFADCB +gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj +cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA4MTAwOTAw +MDAwMFoXDTExMTAwOTIzNTk1OVowgYAxHTAbBgNVBAoUFFN1biBNaWNyb3N5c3Rl +bXMgSW5jMSEwHwYDVQQLFBhDb3Jwb3JhdGUgT2JqZWN0IFNpZ25pbmcxHzAdBgNV +BAsUFkphdmEgU2lnbmVkIEV4dGVuc2lvbnMxGzAZBgNVBAMUEkphdmFGWCAxLjAg +UnVudGltZTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM+WDc6+bu+4 +tmAcS/lBtUc02WOt9QZpVsXg9cG2pu/8bUtmDELa8iiYBVFpIs8DU58HLrGQtCUY +SIAGOVPsOJoN29UKCDWfY9j5JeVhfhMGqk9DwrWhzgsjy4cpZ1pIp+k/fJ8zT8Ul +aYLpow1vg3UNddsmwz02tN7cOrMw9WYIG4CRYnY1OrtJSfe2pYzheC4zyvR+aiVl +nang2OtqikSQsNFOFHsLOJFxngy9LrO8evDSu25VTKI6zlWU6/bMeqtztJPN0VOn +NyUrJZvkxZ207Jg0T693BGSxNC1n+ihztXogql8950M/pEuUbDjylv5FFvlp6DSB +dDT2MkutmyMCAwEAAaOCAeowggHmMAkGA1UdEwQCMAAwDgYDVR0PAQH/BAQDAgeA +MH8GA1UdHwR4MHYwdKByoHCGbmh0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29t +L1N1bk1pY3Jvc3lzdGVtc0luY0NvcnBvcmF0ZU9iamVjdFNpZ25pbmdKYXZhU2ln +bmVkRXh0ZW5zaW9uc0NsYXNzQi9MYXRlc3RDUkwuY3JsMB8GA1UdIwQYMBaAFLNH +K4J+U7Rzyri7Gbe+gU0HlcftMB0GA1UdDgQWBBTjgufVi3XJ3gx1ewsA6Rr7BR4Z +zjA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAGGH2h0dHA6Ly9vbnNpdGUtb2Nz +cC52ZXJpc2lnbi5jb20wgbUGA1UdIASBrTCBqjA5BgtghkgBhvhFAQcXAjAqMCgG +CCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMG0GC2CGSAGG +9wCDfZw/MF4wJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3LnN1bi5jb20vcGtpL2Nw +czAzBggrBgEFBQcCAjAnGiVWYWxpZGF0ZWQgRm9yIFN1biBCdXNpbmVzcyBPcGVy +YXRpb25zMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4IBAQAB +YVJTTVe7rzyTO4jc3zajErOT/COkdQTfNo0eIX1QbNynFieJvwY/jRzUZwjktIFR +2p4JtbpHGAtKtjOAOTieQ8xdDOoC1djzpE7/AbMvuvlTavtUKT+F7tPdhfXgWXJV +6Wbt8jryKyk3zZGiEhauIwZUkfjRkEtffEmZWLUd8c8rURJjfC/XHH2oyurscoxc +CjX29c9ynxSiS/VvQp1an0HvErGh69N48wj7cj8mtZ1yHzd2XCzSSR1OfTPfk0Pt +yg51p7yJaFiH21PTZegEL6zyVNOYBTKwwIi2OzpwYalD3uvK6e3OKDrfFCOxu17u +4PveESbrdyrmvLe7IVez +-----END CERTIFICATE----- + +// Subject: CN=JavaFX Runtime, +// OU=Java Signed Extensions, +// OU=Corporate Object Signing, +// O=Sun Microsystems Inc +// Issuer: CN=Object Signing CA, +// OU=Class 2 OnSite Subscriber CA, +// OU=VeriSign Trust Network, +// O=Sun Microsystems Inc +// Serial: 47:f4:55:f1:da:4a:5e:f9:e3:f7:a8:03:62:17:c0:ff +-----BEGIN CERTIFICATE----- +MIIFdjCCBF6gAwIBAgIQR/RV8dpKXvnj96gDYhfA/zANBgkqhkiG9w0BAQUFADCB +gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj +cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA5MDEyOTAw +MDAwMFoXDTEyMDEyOTIzNTk1OVowfDEdMBsGA1UEChQUU3VuIE1pY3Jvc3lzdGVt +cyBJbmMxITAfBgNVBAsUGENvcnBvcmF0ZSBPYmplY3QgU2lnbmluZzEfMB0GA1UE +CxQWSmF2YSBTaWduZWQgRXh0ZW5zaW9uczEXMBUGA1UEAxQOSmF2YUZYIFJ1bnRp +bWUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCIzd0fAk8mI9ONc6RJ +aGieioK2FLdXEwj8zL3vdGDVmBwyR1zwYkaOIFFgF9IW/8qc4iAYA5sGUY+0g8q3 +5DuYAxfTzBB5KdaYvbuq6GGnoHIWmTirXY+1friFp8lyXSvtuEaGB1VHaBoZchEg +k+UgeVDA43dHwcT1Ov3DePczJRUes8T/QHzLX+BxUDG43vjyncCEO/AjqLZxXEz2 +xrNbKLcH3lGMJK7hdbfssUfF5BjC38Hn71HauYlA43b2no+2y0Sjulwzez2YPbDC +0GLR3TnKtA8dqOrnl5t3DniDbfOBNtBE3VOydJO0XW57Ng1HRXD023nm9ECPY2xp +0N/pAgMBAAGjggHqMIIB5jAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDB/BgNV +HR8EeDB2MHSgcqBwhm5odHRwOi8vb25zaXRlY3JsLnZlcmlzaWduLmNvbS9TdW5N +aWNyb3N5c3RlbXNJbmNDb3Jwb3JhdGVPYmplY3RTaWduaW5nSmF2YVNpZ25lZEV4 +dGVuc2lvbnNDbGFzc0IvTGF0ZXN0Q1JMLmNybDAfBgNVHSMEGDAWgBSzRyuCflO0 +c8q4uxm3voFNB5XH7TAdBgNVHQ4EFgQUvOdd0cKPj+Yik/iOBwTdphh5A+gwOwYI +KwYBBQUHAQEELzAtMCsGCCsGAQUFBzABhh9odHRwOi8vb25zaXRlLW9jc3AudmVy +aXNpZ24uY29tMIG1BgNVHSAEga0wgaowOQYLYIZIAYb4RQEHFwIwKjAoBggrBgEF +BQcCARYcaHR0cHM6Ly93d3cudmVyaXNpZ24uY29tL3JwYTBtBgtghkgBhvcAg32c +PzBeMCcGCCsGAQUFBwIBFhtodHRwczovL3d3dy5zdW4uY29tL3BraS9jcHMwMwYI +KwYBBQUHAgIwJxolVmFsaWRhdGVkIEZvciBTdW4gQnVzaW5lc3MgT3BlcmF0aW9u +czATBgNVHSUEDDAKBggrBgEFBQcDAzANBgkqhkiG9w0BAQUFAAOCAQEAbGcf2NjL +AI93HG6ny2BbepaZA1a8xa/R6uUc7xV+Qw6MgLwFD4Q4i6LWUztQDvg9l68MM2/i +Y9LEi1KM4lcNbK5+D+t9x98wXBiuojXhVdp5ZmC03EyEBbriopdBsmXVLDSu/Y3+ +zowOO5xwpMK3dbgsSDs2Vt0UosD3FTcRaD3GNfOhXMp+o1grHNiXF9YgkmdQbPPZ +DQ2KBhFPCRJXBGvyKOqno/DTg0sQ3crGH/C4/4t7mnQXWldZotmJUZ0ONc9oD+Q1 +JAaguUKqIwn9yZ093ie+JWHbYNid9IIIPXYgtRxmf9a376WBhqhu56uJftBJ7x9g +eQ7Lot6CSWCiFw== +-----END CERTIFICATE----- + +// Subject: CN=Solaris INTERNAL DEVELOPMENT USE ONLY, +// OU=Solaris Cryptographic Framework, +// OU=Corporate Object Signing, +// O=Sun Microsystems Inc +// Issuer: CN=Object Signing CA, +// OU=Class 2 OnSite Subscriber CA, +// OU=VeriSign Trust Network, +// O=Sun Microsystems Inc +// Serial: 77:29:77:52:6a:19:7b:9a:a6:a2:c7:99:a0:e1:cd:8c +-----BEGIN CERTIFICATE----- +MIIFHjCCBAagAwIBAgIQdyl3UmoZe5qmoseZoOHNjDANBgkqhkiG9w0BAQUFADCB +gzEdMBsGA1UEChMUU3VuIE1pY3Jvc3lzdGVtcyBJbmMxHzAdBgNVBAsTFlZlcmlT +aWduIFRydXN0IE5ldHdvcmsxJTAjBgNVBAsTHENsYXNzIDIgT25TaXRlIFN1YnNj +cmliZXIgQ0ExGjAYBgNVBAMTEU9iamVjdCBTaWduaW5nIENBMB4XDTA3MDEwNDAw +MDAwMFoXDTEwMDEwMzIzNTk1OVowgZwxHTAbBgNVBAoUFFN1biBNaWNyb3N5c3Rl +bXMgSW5jMSEwHwYDVQQLFBhDb3Jwb3JhdGUgT2JqZWN0IFNpZ25pbmcxKDAmBgNV +BAsUH1NvbGFyaXMgQ3J5cHRvZ3JhcGhpYyBGcmFtZXdvcmsxLjAsBgNVBAMUJVNv +bGFyaXMgSU5URVJOQUwgREVWRUxPUE1FTlQgVVNFIE9OTFkwgZ8wDQYJKoZIhvcN +AQEBBQADgY0AMIGJAoGBALbNU4hf3mD5ArDI9pjgioAyvV3bjMPRQdCZniIeGJBp +odFlSEH+Mh64W1DsY8coeZ7FvvGJkx9IpTMJW9k8w1oJK9UNqHyAQfaYjQyXi3xQ +LJp62EvYdGfDlwOZejEcR/MbzZG+GOPMMvQj5+xyFDvLXNGfQNTnxw2qnBgCJXjj +AgMBAAGjggH1MIIB8TAJBgNVHRMEAjAAMA4GA1UdDwEB/wQEAwIHgDCBiQYDVR0f +BIGBMH8wfaB7oHmGd2h0dHA6Ly9vbnNpdGVjcmwudmVyaXNpZ24uY29tL1N1bk1p +Y3Jvc3lzdGVtc0luY0NvcnBvcmF0ZU9iamVjdFNpZ25pbmdTb2xhcmlzQ3J5cHRv +Z3JhcGhpY0ZyYW1ld29ya0NsYXNzQi9MYXRlc3RDUkwuY3JsMB8GA1UdIwQYMBaA +FLNHK4J+U7Rzyri7Gbe+gU0HlcftMB0GA1UdDgQWBBRpfiGYkehTnsIzuN2H6AFb +VCZG8jA7BggrBgEFBQcBAQQvMC0wKwYIKwYBBQUHMAGGH2h0dHA6Ly9vbnNpdGUt +b2NzcC52ZXJpc2lnbi5jb20wgbUGA1UdIASBrTCBqjA5BgtghkgBhvhFAQcXAjAq +MCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy52ZXJpc2lnbi5jb20vcnBhMG0GC2CG +SAGG9wCDfZw/MF4wJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3LnN1bi5jb20vcGtp +L2NwczAzBggrBgEFBQcCAjAnFiVWYWxpZGF0ZWQgRm9yIFN1biBCdXNpbmVzcyBP +cGVyYXRpb25zMBMGA1UdJQQMMAoGCCsGAQUFBwMDMA0GCSqGSIb3DQEBBQUAA4IB +AQCG5soy3LFHTFbA8/5SzDRhQoJkHUnOP0t3b6nvX6vZYRp649fje7TQOPRm1pFd +CZ17J+tggdZwgzTqY4aYpJ00jZaK6pV37q/vgFC/ia6jDs8Q+ly9cEcadBZ5loYg +cmxp9p57W2MNWx8VA8oFdNtKfF0jUNXbLNtvwGHmgR6YcwLrGN1b6/9Lt9bO3ODl +FO+ZDwkfQz5ClUVrTx2dGBvKRYFqSG5S8JAfsgYhPvcacUQkA7ExyKvfRXLWVrce +ZiPpcElbx+819H2sAPvVvparVeAruZGMAtejHZp9NFoowKen5drJp9VxePS4eM49 +3DepB6lKRrNRw66LNQol4ZBz +-----END CERTIFICATE----- + +// Subject: EMAILADDRESS=info@diginotar.nl, CN=DigiNotar Cyber CA, +// O=DigiNotar, C=NL +// Issuer: CN=GTE CyberTrust Global Root, +// OU=GTE CyberTrust Solutions, Inc., +// O=GTE Corporation, +// C=US +// Serial: 120000525 (07:27:10:0D) +-----BEGIN CERTIFICATE----- +MIIFWjCCBMOgAwIBAgIEBycQDTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MB4XDTA2MTAwNDEwNTQxMVoXDTExMTAwNDEwNTMxMVowYDELMAkG +A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy +IEN5YmVyIENBMSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIw +DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANLOFQotqF6EZ639vu9Gx8i5z3P8 +9DS5+SxD52ATPXrjss87Z2yQrcC5P4RS8DVC3HTcKDu9UrSnrHJFF8bwieu0qiXy +XUte0dmHutZ9fPXOMp8QM8WxSrtekTHC0OlBwpFkfglBO9uLCDdqqspS3rU5HsCI +A6U/i5kTYUO1m4Kz7iBvz6FEouova0CfjytXraFTwoUiaZ2gP1HfC0GRDaXhqKpc +SQhdvd5wQbEPyWNr0380dAIvNFp4dRxoeoFnivPaQPBgY/SSINcDpj2jHmfEhBtB +pcmM5r3qSLYFFgizNxJa92E89zhvLpfgb1Y4VNMota0Ubi5LZLUnZbd1JQm2Bz2V +VgIKgmCyc0XgMyZRdJq51FAc9k1bW1JSE1qmf6cO4ehBVGeYjIfVydNsy9NUkgYJ +NEH3gW8/nsl8dVWw58Gzd+jDxAA1lUBwEEoF3iW7n1mlZLxHYL9g43aLE1Xd4XR6 +uc8kpmp/3mQiRFhogmoQ+T3lPhu5vfwi9GAEibtVbShV+t6OjRshFNc3izR7Tfay +shDPM7F9HGKZSMsrbHaWVb8ZDR0fu2WqG46ZtcYokOWCLXhQIJr9eS8kf/CJKWn0 +fc1zvrPtTsHR7VJej/e4142HrbLZG1ES/1az4a80fVykeIgQnp0DxqWqoiRR90kU +xbHuWUOV36toKDA/AgMBAAGjggGGMIIBgjASBgNVHRMBAf8ECDAGAQH/AgEBMFMG +A1UdIARMMEowSAYJKwYBBAGxPgEAMDswOQYIKwYBBQUHAgEWLWh0dHA6Ly93d3cu +cHVibGljLXRydXN0LmNvbS9DUFMvT21uaVJvb3QuaHRtbDAOBgNVHQ8BAf8EBAMC +AQYwgaAGA1UdIwSBmDCBlYAUpgwdn2H/Bxe1vzhG20Mw1Y6wUgaheaR3MHUxCzAJ +BgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdU +RSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVy +VHJ1c3QgR2xvYmFsIFJvb3SCAgGlMEUGA1UdHwQ+MDwwOqA4oDaGNGh0dHA6Ly93 +d3cucHVibGljLXRydXN0LmNvbS9jZ2ktYmluL0NSTC8yMDE4L2NkcC5jcmwwHQYD +VR0OBBYEFKv5aN/PSjfXe0WMX3LeQETDZbvCMA0GCSqGSIb3DQEBBQUAA4GBAI9o +a6VbB7pEZg4cqFwwezPkCiYE/O+eGjjWLqEf0JlHwnVkJP2eOyh2uSYoYZEMbSz4 +BJ98UAHV42mv7xXSRZskCSpmBU8lgcpdvqrBWSeuM46C9990sFWzjvjnN8huqlZE +9r1TgSOWPbT6MopTZkQloiXGpjwljPDgKAYityZB +-----END CERTIFICATE----- + +// Subject: CN=DigiNotar Cyber CA, O=DigiNotar, C=NL +// Issuer: CN=GTE CyberTrust Global Root, +// OU=GTE CyberTrust Solutions, Inc., +// O=GTE Corporation, +// C=US +// Serial: 120000505 (07:27:0F:F9) +-----BEGIN CERTIFICATE----- +MIIFODCCBKGgAwIBAgIEBycP+TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MB4XDTA2MDkyMDA5NDUzMloXDTEzMDkyMDA5NDQwNlowPjELMAkG +A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy +IEN5YmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0s4VCi2o +XoRnrf2+70bHyLnPc/z0NLn5LEPnYBM9euOyzztnbJCtwLk/hFLwNULcdNwoO71S +tKesckUXxvCJ67SqJfJdS17R2Ye61n189c4ynxAzxbFKu16RMcLQ6UHCkWR+CUE7 +24sIN2qqylLetTkewIgDpT+LmRNhQ7WbgrPuIG/PoUSi6i9rQJ+PK1etoVPChSJp +naA/Ud8LQZENpeGoqlxJCF293nBBsQ/JY2vTfzR0Ai80Wnh1HGh6gWeK89pA8GBj +9JIg1wOmPaMeZ8SEG0GlyYzmvepItgUWCLM3Elr3YTz3OG8ul+BvVjhU0yi1rRRu +LktktSdlt3UlCbYHPZVWAgqCYLJzReAzJlF0mrnUUBz2TVtbUlITWqZ/pw7h6EFU +Z5iMh9XJ02zL01SSBgk0QfeBbz+eyXx1VbDnwbN36MPEADWVQHAQSgXeJbufWaVk +vEdgv2DjdosTVd3hdHq5zySman/eZCJEWGiCahD5PeU+G7m9/CL0YASJu1VtKFX6 +3o6NGyEU1zeLNHtN9rKyEM8zsX0cYplIyytsdpZVvxkNHR+7Zaobjpm1xiiQ5YIt +eFAgmv15LyR/8IkpafR9zXO+s+1OwdHtUl6P97jXjYetstkbURL/VrPhrzR9XKR4 +iBCenQPGpaqiJFH3SRTFse5ZQ5Xfq2goMD8CAwEAAaOCAYYwggGCMBIGA1UdEwEB +/wQIMAYBAf8CAQEwUwYDVR0gBEwwSjBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcC +ARYtaHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL0NQUy9PbW5pUm9vdC5odG1s +MA4GA1UdDwEB/wQEAwIBBjCBoAYDVR0jBIGYMIGVgBSmDB2fYf8HF7W/OEbbQzDV +jrBSBqF5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlv +bjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRpb25zLCBJbmMuMSMwIQYD +VQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIICAaUwRQYDVR0fBD4wPDA6 +oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL2NnaS1iaW4vQ1JMLzIw +MTgvY2RwLmNybDAdBgNVHQ4EFgQUq/lo389KN9d7RYxfct5ARMNlu8IwDQYJKoZI +hvcNAQEFBQADgYEACcpiD427SuDUejUrBi3RKGG2rAH7g0m8rtQvLYauGYOl1h0T +4he+/jJ06XoUOMqUXvcpAWlxG5Ea/aO7qh3Ke+IW/aGjDvMMX7LhIDGUK16Sdu36 +6bUjpr8KOwOpb1JgVM1f6bcvfKIn/UGDdbYN+3gm87FF6TKVKho1IZXFonU= +-----END CERTIFICATE----- + +// Subject: CN=DigiNotar Cyber CA, O=DigiNotar, C=NL +// Issuer: CN=GTE CyberTrust Global Root, +// OU=GTE CyberTrust Solutions, Inc., +// O=GTE Corporation, +// C=US +// Serial: 120000515 (07:27:10:03) +-----BEGIN CERTIFICATE----- +MIIFODCCBKGgAwIBAgIEBycQAzANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJV +UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU +cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds +b2JhbCBSb290MB4XDTA2MDkyNzEwNTMzMloXDTExMDkyNzEwNTIzMFowPjELMAkG +A1UEBhMCTkwxEjAQBgNVBAoTCURpZ2lOb3RhcjEbMBkGA1UEAxMSRGlnaU5vdGFy +IEN5YmVyIENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0s4VCi2o +XoRnrf2+70bHyLnPc/z0NLn5LEPnYBM9euOyzztnbJCtwLk/hFLwNULcdNwoO71S +tKesckUXxvCJ67SqJfJdS17R2Ye61n189c4ynxAzxbFKu16RMcLQ6UHCkWR+CUE7 +24sIN2qqylLetTkewIgDpT+LmRNhQ7WbgrPuIG/PoUSi6i9rQJ+PK1etoVPChSJp +naA/Ud8LQZENpeGoqlxJCF293nBBsQ/JY2vTfzR0Ai80Wnh1HGh6gWeK89pA8GBj +9JIg1wOmPaMeZ8SEG0GlyYzmvepItgUWCLM3Elr3YTz3OG8ul+BvVjhU0yi1rRRu +LktktSdlt3UlCbYHPZVWAgqCYLJzReAzJlF0mrnUUBz2TVtbUlITWqZ/pw7h6EFU +Z5iMh9XJ02zL01SSBgk0QfeBbz+eyXx1VbDnwbN36MPEADWVQHAQSgXeJbufWaVk +vEdgv2DjdosTVd3hdHq5zySman/eZCJEWGiCahD5PeU+G7m9/CL0YASJu1VtKFX6 +3o6NGyEU1zeLNHtN9rKyEM8zsX0cYplIyytsdpZVvxkNHR+7Zaobjpm1xiiQ5YIt +eFAgmv15LyR/8IkpafR9zXO+s+1OwdHtUl6P97jXjYetstkbURL/VrPhrzR9XKR4 +iBCenQPGpaqiJFH3SRTFse5ZQ5Xfq2goMD8CAwEAAaOCAYYwggGCMBIGA1UdEwEB +/wQIMAYBAf8CAQEwUwYDVR0gBEwwSjBIBgkrBgEEAbE+AQAwOzA5BggrBgEFBQcC +ARYtaHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL0NQUy9PbW5pUm9vdC5odG1s +MA4GA1UdDwEB/wQEAwIBBjCBoAYDVR0jBIGYMIGVgBSmDB2fYf8HF7W/OEbbQzDV +jrBSBqF5pHcwdTELMAkGA1UEBhMCVVMxGDAWBgNVBAoTD0dURSBDb3Jwb3JhdGlv +bjEnMCUGA1UECxMeR1RFIEN5YmVyVHJ1c3QgU29sdXRpb25zLCBJbmMuMSMwIQYD +VQQDExpHVEUgQ3liZXJUcnVzdCBHbG9iYWwgUm9vdIICAaUwRQYDVR0fBD4wPDA6 +oDigNoY0aHR0cDovL3d3dy5wdWJsaWMtdHJ1c3QuY29tL2NnaS1iaW4vQ1JMLzIw +MTgvY2RwLmNybDAdBgNVHQ4EFgQUq/lo389KN9d7RYxfct5ARMNlu8IwDQYJKoZI +hvcNAQEFBQADgYEAWcyGZhizJlRP1jjNupZey+yZG6oMDW4Z11boriMHbYPCndBE +bVh07zmPbZsihOw9w/vm5KbVX5CgxUv4Rhzh/20Faixf3P3bpWg0qgzHVVusNVR/ +P50aKkpdK3hp+QLl56e+lWOddSAINIpmcuyDI1hyuzB+GJEASm9tNU/6rs8= +-----END CERTIFICATE----- + +// Subject: EMAILADDRESS=info@diginotar.nl, +// CN=DigiNotar Root CA, +// O=DigiNotar, C=NL +// Issuer: CN=Entrust.net Secure Server Certification Authority +// OU=(c) 1999 Entrust.net Limited, +// OU=www.entrust.net/CPS incorp. by ref. (limits liab.), +// O=Entrust.net, +// C=US, +// Serial: 1184644297 (46:9C:3C:C9) +-----BEGIN CERTIFICATE----- +MIIFSDCCBLGgAwIBAgIERpw8yTANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA0 +MjYwNTAwMDBaFw0xMzA4MTQyMDEyMzZaMF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQK +EwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZI +hvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKywWMEAvdghCAsrmv5uVjAFnxt3kBBBXMMNhxF3joHxynzpjGrt +OHQ1u9rf+bvACTe0lnOBfTMamDn3k2+Vfz25sXWHulFI6ItwPpUExdi2wxbZiLCx +hx1w2oa0DxSLes8Q0XQ2ohJ7d4ZKeeZ73wIRaKVOhq40WJskE3hWIiUeAYtLUXH7 +gsxZlmmIWmhTxbkNAjfLS7xmSpB+KgsFB+0WX1WQddhGyRuD4gi+8SPMmR3WKg+D +IBVYJ4Iu+uIiwkmxuQGBap1tnUB3aHZOISpthECFTnaZfILz87cCWdQmARuO361T +BtGuGN3isjrL14g4jqxbKbkZ05j5GAPPSIKGZgsbaQ/J6ziIeiYaBUyS1yTUlvKs +Ui2jR9VS9j/+zoQGcKaqPqLytlY0GFei5IFt58rwatPHkWsCg0F8Fe9rmmRe49A8 +5bHre12G+8vmd0nNo2Xc97mcuOQLX5PPzDAaMhzOHGOVpfnq4XSLnukrqTB7oBgf +DhgL5Vup09FsHgdnj5FLqYq80maqkwGIspH6MVzVpsFSCAnNCmOi0yKm6KHZOQaX +9W6NApCMFHs/gM0bnLrEWHIjr7ZWn8Z6QjMpBz+CyeYfBQ3NTCg2i9PIPhzGiO9e +7olk6R3r2ol+MqZp0d3MiJ/R0MlmIdwGZ8WUepptYkx9zOBkgLKeR46jAgMBAAGj +ggEmMIIBIjASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMB +BggrBgEFBQcDAgYIKwYBBQUHAwQwEQYDVR0gBAowCDAGBgRVHSAAMDMGCCsGAQUF +BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD +VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNy +bDAdBgNVHQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wCwYDVR0PBAQDAgEGMB8G +A1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob +BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAI979rBep8tu3TeLunapgsZ0jtXp +GDFjKWSk87dj1jCyYi+q/GyDyZ6ZQZNRP0sF+6twscq05lClWNy3TROMp7QeuoLO +G7Utw3OJaswUtp4YglANMRTHEe3g9ltifUXRH5tSuy7u6yi4LD4WTm5ULP6r/g6l +0CnjXYb0+b1Fmz6U +-----END CERTIFICATE----- + +// Subject: EMAILADDRESS=info@diginotar.nl, +// CN=DigiNotar Root CA, +// O=DigiNotar, C=NL +// Issuer: CN=Entrust.net Secure Server Certification Authority +// OU=(c) 1999 Entrust.net Limited, +// OU=www.entrust.net/CPS incorp. by ref. (limits liab.), +// O=Entrust.net, +// C=US, +// Serial: 1184640175 (46:9C:2C:AF) +-----BEGIN CERTIFICATE----- +MIIFSDCCBLGgAwIBAgIERpwsrzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA3 +MjYxNTU3MzlaFw0xMzA4MjYxNjI3MzlaMF8xCzAJBgNVBAYTAk5MMRIwEAYDVQQK +EwlEaWdpTm90YXIxGjAYBgNVBAMTEURpZ2lOb3RhciBSb290IENBMSAwHgYJKoZI +hvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCCAiIwDQYJKoZIhvcNAQEBBQADggIP +ADCCAgoCggIBAKywWMEAvdghCAsrmv5uVjAFnxt3kBBBXMMNhxF3joHxynzpjGrt +OHQ1u9rf+bvACTe0lnOBfTMamDn3k2+Vfz25sXWHulFI6ItwPpUExdi2wxbZiLCx +hx1w2oa0DxSLes8Q0XQ2ohJ7d4ZKeeZ73wIRaKVOhq40WJskE3hWIiUeAYtLUXH7 +gsxZlmmIWmhTxbkNAjfLS7xmSpB+KgsFB+0WX1WQddhGyRuD4gi+8SPMmR3WKg+D +IBVYJ4Iu+uIiwkmxuQGBap1tnUB3aHZOISpthECFTnaZfILz87cCWdQmARuO361T +BtGuGN3isjrL14g4jqxbKbkZ05j5GAPPSIKGZgsbaQ/J6ziIeiYaBUyS1yTUlvKs +Ui2jR9VS9j/+zoQGcKaqPqLytlY0GFei5IFt58rwatPHkWsCg0F8Fe9rmmRe49A8 +5bHre12G+8vmd0nNo2Xc97mcuOQLX5PPzDAaMhzOHGOVpfnq4XSLnukrqTB7oBgf +DhgL5Vup09FsHgdnj5FLqYq80maqkwGIspH6MVzVpsFSCAnNCmOi0yKm6KHZOQaX +9W6NApCMFHs/gM0bnLrEWHIjr7ZWn8Z6QjMpBz+CyeYfBQ3NTCg2i9PIPhzGiO9e +7olk6R3r2ol+MqZp0d3MiJ/R0MlmIdwGZ8WUepptYkx9zOBkgLKeR46jAgMBAAGj +ggEmMIIBIjASBgNVHRMBAf8ECDAGAQH/AgEBMCcGA1UdJQQgMB4GCCsGAQUFBwMB +BggrBgEFBQcDAgYIKwYBBQUHAwQwEQYDVR0gBAowCDAGBgRVHSAAMDMGCCsGAQUF +BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD +VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9zZXJ2ZXIxLmNy +bDAdBgNVHQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wCwYDVR0PBAQDAgEGMB8G +A1UdIwQYMBaAFPAXYhNVPbP/CgBr+1CEl/PtYtAaMBkGCSqGSIb2fQdBAAQMMAob +BFY3LjEDAgCBMA0GCSqGSIb3DQEBBQUAA4GBAEa6RcDNcEIGUlkDJUY/pWTds4zh +xbVkp3wSmpwPFhx5fxTyF4HD2L60jl3aqjTB7gPpsL2Pk5QZlNsi3t4UkCV70UOd +ueJRN3o/LOtk4+bjXY2lC0qTHbN80VMLqPjmaf9ghSA9hwhskdtMgRsgfd90q5QP +ZFdYf+hthc3m6IcJ +-----END CERTIFICATE----- + +// Subject: CN=DigiNotar PKIoverheid CA Organisatie - G2, +// O=DigiNotar B.V., +// C=NL +// Issuer: CN=Staat der Nederlanden Organisatie CA - G2, +// O=Staat der Nederlanden, +// C=NL +// Serial: 20001983 (01:31:34:bf) +-----BEGIN CERTIFICATE----- +MIIGnDCCBISgAwIBAgIEATE0vzANBgkqhkiG9w0BAQsFADBhMQswCQYDVQQGEwJO +TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMTIwMAYDVQQDDClTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gT3JnYW5pc2F0aWUgQ0EgLSBHMjAeFw0xMDA1MTIw +ODUxMzhaFw0yMDAzMjMwOTUwMDRaMFoxCzAJBgNVBAYTAk5MMRcwFQYDVQQKDA5E +aWdpTm90YXIgQi5WLjEyMDAGA1UEAwwpRGlnaU5vdGFyIFBLSW92ZXJoZWlkIENB +IE9yZ2FuaXNhdGllIC0gRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC +AQCxExkPJ+Zs1FWGS9DsiYpFkXisR71HK+T8RetPtCZzWzfTw3/2497Xo/gtaMUI +PkuU1uSHJTZrhLUYdPMoWHMvm2rPvAQe9t7dr/xLqvXbZmIlASWC3vKXWhBu3V2p +IrEEqSNzOvhxrR3PhETrR9Gvbch8KKvH8jd6dF9fxQIUiqNa4xtsAeNdjtlo1vQJ +GzLckbUs9SDrjANtJkm4k8SFXdjSm69WaswFM8ygQp40VUSca6DUEtArVM23iQ3l +9uvo+4UBM096a/GdcjOWDveyhKWlJ8Qn8VFzKXe6Z27+TNy04qGhgS85SY1DOBPO +0KVcwoc6AGdlQiPxNlkKHaNRyLyjlCox3+M88p0aPASw77EKMBNzttfzo0wBdRSF +eMDXijlYhVD6LubFvs+LP6+PNtQlCS3SD6xyk/K/i9RQs/kVUJuZ9RTZ+4uRozIm +JqD43ztggYaDeVsr6xM9KTrBbd29no6H1kquNJcF7hSm9tw4fkrpJFQHPZdoN0Zr +DceoIa8TVOQJavFNRgrJXfubT73e+7dUy7g4nKc5+2otwHuNq6WnV+xKkoozxeEg +XHPYkJIrgNUPhhhpfDlPhIa890xb89W0yqDC8DciynlSH1PmqvOQsDvd8ij9rOvF +BiSgydQvD1j9tZ7sD8+yWdCiBHo4aq5y+73wJWKUCacFCwIDAQABo4IBYTCCAV0w +SAYDVR0gBEEwPzA9BgRVHSAAMDUwMwYIKwYBBQUHAgEWJ2h0dHA6Ly93d3cuZGln +aW5vdGFyLm5sL2Nwcy9wa2lvdmVyaGVpZDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud +DwEB/wQEAwIBBjCBhQYDVR0jBH4wfIAUORCLSZJc22ESIM1JnRqO2pxnQLmhXqRc +MFoxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIgTmVkZXJsYW5kZW4x +KzApBgNVBAMMIlN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENBIC0gRzKCBACY +lvQwSQYDVR0fBEIwQDA+oDygOoY4aHR0cDovL2NybC5wa2lvdmVyaGVpZC5ubC9E +b21PcmdhbmlzYXRpZUxhdGVzdENSTC1HMi5jcmwwHQYDVR0OBBYEFLxdlDvZq3sD +JXNhwtst7vyrj2WhMA0GCSqGSIb3DQEBCwUAA4ICAQCP/C1Mt9kt1R+978v0t2gX +dZ1O1ffdnPEqJu2forYcA9VTs+wIzzTi48P0tRYvyMO+19NzqwA2+RpKftZj6V5G +uqW2jhW3oyrYQx3vXcgfgYWzi/f/PPTZ9EYIP5y8HaDZqEzNJVJOCrEg9x/pQ9lU +RoETmsBedGwqmDLq/He7DaWiMZgifnx859qkrey3LhoZcfhIUNpDjyyE3cFAJ+O1 +8BVOltT4XOOGKUYr1zsH6zh/yIZXl9PvKjPEF1DVZGlrK2tFXl0vF8paTs/D1zk8 +9TufRrmb5w5Jl53W1eMbD+qPAU6aE5RZCgIHSEsaYKt/T+0L2FUNaG9VnGllFULs +wNzdbKzDFs4LHVabpMTE0i7gD+JEJytQaaTcYuiKISlCbMwAOpZ2m+9AwKRed4Qy +bCYqOWauXeO5ubIsaB8empADOfCqs6TMSYsYNOk3yXspx4R8b0QVL+xhWQTJRcui +1lKifH8pktZKxYtCqNT+6tjHhyMY5J16fXNAUpigrm7jBT8FD+Clxm1N7YM3iJzH +89xCmmq21yFJNnfy7xhPxXDZnunetyuL9Lx+KN8NQMmFXK6dxTH/0FwOtah+8Okv +uq+IruW10Vilr5xxpykBkINpN4IFuvwJwQhujHg7wzMCgD9EhQgd31VWCK0shS1d +sQPhrqp0xaTzTro3mHuCuQ== +-----END CERTIFICATE----- + +// Subject: CN=DigiNotar PKIoverheid CA Overheid en Bedrijven, +// O=DigiNotar B.V., +// C=NL +// Issuer: CN=Staat der Nederlanden Overheid CA +// O=Staat der Nederlanden, +// C=NL +// Serial: 20015536 (01:31:69:b0) +-----BEGIN CERTIFICATE----- +MIIEiDCCA3CgAwIBAgIEATFpsDANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDcwNzA1MDg0MjA3WhcN +MTUwNzI3MDgzOTQ2WjBfMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy +IEIuVi4xNzA1BgNVBAMTLkRpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp +ZCBlbiBCZWRyaWp2ZW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDc +vdKnTmoKuzuiheF/AK2+tDBomAfNoHrElM9x+Yo35FPrV3bMi+Zs/u6HVcg+uwQ5 +AKeAeKxbT370vbhUuHE7BzFJOZNUfCA7eSuPu2GQfbGs5h+QLp1FAalkLU3DL7nn +UNVOKlyrdnY3Rtd57EKZ96LspIlw3Dgrh6aqJOadkiQbvvb91C8ZF3rmMgeUVAVT +Q+lsvK9Hy7zL/b07RBKB8WtLu+20z6slTxjSzAL8o0+1QjPLWc0J3NNQ/aB2jKx+ +ZopC9q0ckvO2+xRG603XLzDgbe5bNr5EdLcgBVeFTegAGaL2DOauocBC36esgl3H +aLcY5olLmmv6znn58yynAgMBAAGjggFQMIIBTDBIBgNVHSAEQTA/MD0GBFUdIAAw +NTAzBggrBgEFBQcCARYnaHR0cDovL3d3dy5kaWdpbm90YXIubmwvY3BzL3BraW92 +ZXJoZWlkMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMIGABgNVHSME +eTB3gBQLhtYPd6NosftkCcOIblwEHFfpPaFZpFcwVTELMAkGA1UEBhMCTkwxHjAc +BgNVBAoTFVN0YWF0IGRlciBOZWRlcmxhbmRlbjEmMCQGA1UEAxMdU3RhYXQgZGVy +IE5lZGVybGFuZGVuIFJvb3QgQ0GCBACYmnkwPQYDVR0fBDYwNDAyoDCgLoYsaHR0 +cDovL2NybC5wa2lvdmVyaGVpZC5ubC9Eb21PdkxhdGVzdENSTC5jcmwwHQYDVR0O +BBYEFEwIyY128ZjHPt881y91DbF2eZfMMA0GCSqGSIb3DQEBBQUAA4IBAQAMlIca +v03jheLu19hjeQ5Q38aEW9K72fUxCho1l3TfFPoqDz7toOMI9tVOW6+mriXiRWsi +D7dUKH6S3o0UbNEc5W50BJy37zRERd/Jgx0ZH8Apad+J1T/CsFNt5U4X5HNhIxMm +cUP9TFnLw98iqiEr2b+VERqKpOKrp11Lbyn1UtHk0hWxi/7wA8+nfemZhzizDXMU +5HIs4c71rQZIZPrTKbmi2Lv01QulQERDjqC/zlqlUkxk0xcxYczopIro5Ij76eUv +BjMzm5RmZrGrUDqhCYF0U1onuabSJc/Tw6f/ltAv6uAejVLpGBwgCkegllYOQJBR +RKwa/fHuhR/3Qlpl +-----END CERTIFICATE----- + +// Subject: CN=DigiNotar PKIoverheid CA Overheid +// O=DigiNotar B.V., +// C=NL +// Issuer: CN=Staat der Nederlanden Overheid CA +// O=Staat der Nederlanden, +// C=NL +// Serial: 20006006 (01:31:44:76) +-----BEGIN CERTIFICATE----- +MIIEezCCA2OgAwIBAgIEATFEdjANBgkqhkiG9w0BAQUFADBZMQswCQYDVQQGEwJO +TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSowKAYDVQQDEyFTdGFh +dCBkZXIgTmVkZXJsYW5kZW4gT3ZlcmhlaWQgQ0EwHhcNMDQwNjI0MDgxOTMyWhcN +MTAwNjIzMDgxNzM2WjBSMQswCQYDVQQGEwJOTDEXMBUGA1UEChMORGlnaU5vdGFy +IEIuVi4xKjAoBgNVBAMTIURpZ2lOb3RhciBQS0lvdmVyaGVpZCBDQSBPdmVyaGVp +ZDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANSlrubta5tlOjVCi/gb +yLCvRqfBjxG8H594VcKHu0WAYc99SPZF9cycj5mw2GyfQvy/WIrGrL4iyNq1gSqR +0QA/mTXKZIaPqzpDhdm+VvrKkmjrbZfaQxgMSs3ChtBsjcP9Lc0X1zXZ4Q8nBe3k +BTp+zehINfmbjoEgXLxsMR5RQ6GxzKjuC04PQpbJQgTIakglKaqYcDDZbEscWgPV +Hgj/2aoHlj6leW/ThHZ+O41jUguEmBLZA3mu3HrCfrHntb5dPt0ihzSx7GtD/SaX +5HBLxnP189YuqMk5iRA95CtiSdKauvon/xRKRLNgG6XAz0ctSoY7xLDdiBVU5kJd +FScCAwEAAaOCAVAwggFMMEgGA1UdIARBMD8wPQYEVR0gADA1MDMGCCsGAQUFBwIB +FidodHRwOi8vd3d3LmRpZ2lub3Rhci5ubC9jcHMvcGtpb3ZlcmhlaWQwDwYDVR0T +AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgYAGA1UdIwR5MHeAFAuG1g93o2ix ++2QJw4huXAQcV+k9oVmkVzBVMQswCQYDVQQGEwJOTDEeMBwGA1UEChMVU3RhYXQg +ZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g +Um9vdCBDQYIEAJiaeTA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnBraW92 +ZXJoZWlkLm5sL0RvbU92TGF0ZXN0Q1JMLmNybDAdBgNVHQ4EFgQUvRaYQh2+kdE9 +wpcl4CjXWOC1f+IwDQYJKoZIhvcNAQEFBQADggEBAGhQsCWLiaN2EOhPAW+JQP6o +XBOrLv5w6joahzBFVn1BiefzmlMKjibqKYxURRvMAsMkh82/MfL8V0w6ugxl81lu +i42dcxl9cKSVXKMw4bbBzJ2VQI5HTIABwefeNuy/eX6idVwYdt3ajAH7fUA8Q9Cq +vr6H8B+8mwoEqTVTEVlCSsC/EXsokYEUr06PPzRudKjDmijgj7zFaIioZNc8hk7g +ufEgrs/tmcNGylrwRHgCXjCRBt2NHlZ08l7A1AGU8HcHlSbG9Un/2q9kVHUkps0D +gtUaEK+x6jpAu/R8Ojezu/+ZEcwwjI/KOhG+84+ejFmtyEkrUdsAdEdLf/2dKsw= +-----END CERTIFICATE----- + +// Subject: EMAILADDRESS=info@diginotar.nl, +// CN=DigiNotar Services 1024 CA +// O=DigiNotar, C=NL +// Issuer: CN=Entrust.net Secure Server Certification Authority, +// OU=(c) 1999 Entrust.net Limited, +// OU=www.entrust.net/CPS incorp. by ref. (limits liab.), +// O=Entrust.net, +// C=US +// Serial: 1184640176 (46:9c:2c:b0) +-----BEGIN CERTIFICATE----- +MIIDzTCCAzagAwIBAgIERpwssDANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC +VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u +ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc +KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u +ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNzA3 +MjYxNTU5MDBaFw0xMzA4MjYxNjI5MDBaMGgxCzAJBgNVBAYTAk5MMRIwEAYDVQQK +EwlEaWdpTm90YXIxIzAhBgNVBAMTGkRpZ2lOb3RhciBTZXJ2aWNlcyAxMDI0IENB +MSAwHgYJKoZIhvcNAQkBFhFpbmZvQGRpZ2lub3Rhci5ubDCBnzANBgkqhkiG9w0B +AQEFAAOBjQAwgYkCgYEA2ptNXTz50eKLxsYIIMXZHkjsZlhneWIrQWP0iY1o2q+4 +lDaLGSSkoJPSmQ+yrS01Tc0vauH5mxkrvAQafi09UmTN8T5nD4ku6PJPrqYIoYX+ +oakJ5sarPkP8r3oDkdqmOaZh7phPGKjTs69mgumfvN1y+QYEvRLZGCTnq5NTi1kC +AwEAAaOCASYwggEiMBIGA1UdEwEB/wQIMAYBAf8CAQAwJwYDVR0lBCAwHgYIKwYB +BQUHAwEGCCsGAQUFBwMCBggrBgEFBQcDBDARBgNVHSAECjAIMAYGBFUdIAAwMwYI +KwYBBQUHAQEEJzAlMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5lbnRydXN0Lm5l +dDAzBgNVHR8ELDAqMCigJqAkhiJodHRwOi8vY3JsLmVudHJ1c3QubmV0L3NlcnZl +cjEuY3JsMB0GA1UdDgQWBBT+3JRJDG/vXH/G8RKZTxZJrfuCZTALBgNVHQ8EBAMC +AQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0BowGQYJKoZIhvZ9B0EA +BAwwChsEVjcuMQMCAIEwDQYJKoZIhvcNAQEFBQADgYEAY3RqN6k/lpxmyFisCcnv +9WWUf6MCxDgxvV0jh+zUVrLJsm7kBQb87PX6iHBZ1O7m3bV6oKNgLwIMq94SXa/w +NUuqikeRGvWFLELHHe+VQ7NeuJWTpdrFKKqtci0xrZlrbP+MISevrZqRK8fdWMNu +B8WfedLHjFW/TMcnXlEWKz4= +-----END CERTIFICATE----- + +// Subject: CN=Buster Paper Comercial Ltda, +// O=Buster Paper Comercial Ltda, +// L=S?o Jos? Dos Campos, +// ST=S?o Paulo, +// C=BR +// Issuer: CN=DigiCert Assured ID Code Signing CA-1, +// OU=www.digicert.com, +// O=DigiCert Inc, +// C=US +// Serial: 07:b4:4c:db:ff:fb:78:de:05:f4:26:16:72:a6:73:12 +-----BEGIN CERTIFICATE----- +MIIGwzCCBaugAwIBAgIQB7RM2//7eN4F9CYWcqZzEjANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv +ZGUgU2lnbmluZyBDQS0xMB4XDTEzMDExNzAwMDAwMFoXDTE0MDEyMjEyMDAwMFow +gY4xCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMR4wHAYDVQQHDBVT +w6NvIEpvc8OpIERvcyBDYW1wb3MxJDAiBgNVBAoTG0J1c3RlciBQYXBlciBDb21l +cmNpYWwgTHRkYTEkMCIGA1UEAxMbQnVzdGVyIFBhcGVyIENvbWVyY2lhbCBMdGRh +MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAzO0l6jWIpEfO2oUpVHpL +HETj5lzivNb0S9jKHgGJax917czh81PnGTxwxFXd6gLJuy/XFHvmiSi8g8jzlymn +2Ji5zQ3CPaz7nomJokSUDlMVJ2qYWtctw4jrdjuI4qtn+koXXUFkWjkf8h8251I4 +tUs7S49HE2Go5owCYP3byajj7fsFAYR/Xb7TdVtndkZsUB/YgOjHovyACjouaNCi +mDiRyQ6zLLjZGiyeD65Yiseuhp5b8/BL5h1p7w76QYMYMVQNAdtDKut2R8MBpuWf +Ny7Eoi0x/gm1p9X5Rcl5aN7K0G4UtTAJKbkuUfXddsyFoM0Nx8uo8SgNQ8Y/X5Jx +BwIDAQABo4IDOTCCAzUwHwYDVR0jBBgwFoAUe2jOKarAF75JeuHlP9an90WPNTIw +HQYDVR0OBBYEFFLZ3n5nt/Eer7n1bvtOqMb1qKO5MA4GA1UdDwEB/wQEAwIHgDAT +BgNVHSUEDDAKBggrBgEFBQcDAzBzBgNVHR8EbDBqMDOgMaAvhi1odHRwOi8vY3Js +My5kaWdpY2VydC5jb20vYXNzdXJlZC1jcy0yMDExYS5jcmwwM6AxoC+GLWh0dHA6 +Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9hc3N1cmVkLWNzLTIwMTFhLmNybDCCAcQGA1Ud +IASCAbswggG3MIIBswYJYIZIAYb9bAMBMIIBpDA6BggrBgEFBQcCARYuaHR0cDov +L3d3dy5kaWdpY2VydC5jb20vc3NsLWNwcy1yZXBvc2l0b3J5Lmh0bTCCAWQGCCsG +AQUFBwICMIIBVh6CAVIAQQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABD +AGUAcgB0AGkAZgBpAGMAYQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABh +AGMAYwBlAHAAdABhAG4AYwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQBy +AHQAIABDAFAALwBDAFAAUwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBn +ACAAUABhAHIAdAB5ACAAQQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABs +AGkAbQBpAHQAIABsAGkAYQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABp +AG4AYwBvAHIAcABvAHIAYQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBl +AGYAZQByAGUAbgBjAGUALjCBggYIKwYBBQUHAQEEdjB0MCQGCCsGAQUFBzABhhho +dHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTAYIKwYBBQUHMAKGQGh0dHA6Ly9jYWNl +cnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENvZGVTaWduaW5nQ0Et +MS5jcnQwDAYDVR0TAQH/BAIwADANBgkqhkiG9w0BAQUFAAOCAQEAPTTQvpOIikXI +hTLnNbajaFRR5GhQpTzUNgBfF9VYSlNw/wMjpGsrh5RxaJCip52jbehmTgjMRhft +jRYyml44PAVsCcR9uEoDpCZYpI1fHI1R+F8jd1C9rqprbSwwOG4xlg4SmvTHYs6e +gBItQ/1p9XY+Sf4Wv1qOuOFL1qvV/5VyR2zdlOQCmKCeMgxt6a/tHLBDiAA67D44 +/vfdoNJl0CU2It0PO60jdCPFNWIRcxL+OSDqAoePeUC7xQ+JsTEIxuUE8+d6w6fc +BV2mYb1flh22t46GLjh4gyo7xw3aL6L0L0jzlTT6IcEw6NIbaPbIKj/npQnHobYj +XMuKLxbh7g== +-----END CERTIFICATE----- + +// Subject: CN=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, +// O=BUSTER ASSISTENCIA TECNICA ELETRONICA LTDA - ME, +// L=S?o Paulo, +// ST=S?o Paulo, +// C=BR +// Issuer: CN=DigiCert Assured ID Code Signing CA-1, +// OU=www.digicert.com, +// O=DigiCert Inc, +// C=US +// Serial: 0a:38:9b:95:ee:73:6d:d1:3b:c0:ed:74:3f:d7:4d:2f +-----BEGIN CERTIFICATE----- +MIIG4DCCBcigAwIBAgIQCjible5zbdE7wO10P9dNLzANBgkqhkiG9w0BAQUFADBv +MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3 +d3cuZGlnaWNlcnQuY29tMS4wLAYDVQQDEyVEaWdpQ2VydCBBc3N1cmVkIElEIENv +ZGUgU2lnbmluZyBDQS0xMB4XDTEyMTEwOTAwMDAwMFoXDTEzMTExNDEyMDAwMFow +gasxCzAJBgNVBAYTAkJSMRMwEQYDVQQIDApTw6NvIFBhdWxvMRMwEQYDVQQHDApT +w6NvIFBhdWxvMTgwNgYDVQQKEy9CVVNURVIgQVNTSVNURU5DSUEgVEVDTklDQSBF +TEVUUk9OSUNBIExUREEgLSBNRTE4MDYGA1UEAxMvQlVTVEVSIEFTU0lTVEVOQ0lB +IFRFQ05JQ0EgRUxFVFJPTklDQSBMVERBIC0gTUUwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDAqNeEs5/B2CTXGjTOkUIdu6jV6qulOZwdw4sefHWYj1UR +4z6zPk9kjpUgbnb402RFq88QtfInwddZ/wXn9OxMtDd/3TnC7HrhNS7ga79ZFL2V +JnmzKHum2Yvh0q82QEJ9tHBR2X9VdKpUIH08Zs3k6cWWM1H0YX0cxA/HohhesQJW +kwJ3urOIJiH/HeByDk8a1NS8safcCxk5vxvW4WvCg43iT09LeHY5Aa8abKw8lqVb +0tD5ZSIjdmdj3TT1U37iAHLLRM2DXbxfdbhouUX1c5U1ZHAMA67HwjKiseOiDaHj +NUGbC37C+cgbc9VVM/cURD8WvS0Kj6fQv7F2QtJDAgMBAAGjggM5MIIDNTAfBgNV +HSMEGDAWgBR7aM4pqsAXvkl64eU/1qf3RY81MjAdBgNVHQ4EFgQU88EXKAyDsh30 +o9+Gu9a4xUy+FSMwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMD +MHMGA1UdHwRsMGowM6AxoC+GLWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9hc3N1 +cmVkLWNzLTIwMTFhLmNybDAzoDGgL4YtaHR0cDovL2NybDQuZGlnaWNlcnQuY29t +L2Fzc3VyZWQtY3MtMjAxMWEuY3JsMIIBxAYDVR0gBIIBuzCCAbcwggGzBglghkgB +hv1sAwEwggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9z +c2wtY3BzLXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4A +eQAgAHUAcwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQA +ZQAgAGMAbwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUA +IABvAGYAIAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAA +YQBuAGQAIAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcA +cgBlAGUAbQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIA +aQBsAGkAdAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQA +ZQBkACAAaABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMIGC +BggrBgEFBQcBAQR2MHQwJAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0 +LmNvbTBMBggrBgEFBQcwAoZAaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0Rp +Z2lDZXJ0QXNzdXJlZElEQ29kZVNpZ25pbmdDQS0xLmNydDAMBgNVHRMBAf8EAjAA +MA0GCSqGSIb3DQEBBQUAA4IBAQAei1QmiXepje8OIfo/WonD4MIXgpPr2dfRaquQ +A8q63OpTRSveyqdQDCSPpDRF/nvO1Y30yksZvIH1tNBsW5LBdxAKN3lFdBlqBwtE +Q3jHc0KVVYRJ0FBaGE/PJHmRajscdAhYIcMPhTga0u0tDK+wOHEq3993dfl6yHjA +XHU2iW5pnk75ZoE39zALD5eKXT8ZXrET5c3XUFJKWA+XuGmdmyzqo0Au49PanBv9 +UlZnabYfqoMArqMS0tGSX4cGgi9/2E+pHG9BX4sFW+ZDumroOA2pxyMWEKjxePEL +zCOfhbsRWdMLYepauaNZOIMZXmFwcrIl0TGMkTAtATz+XmZc +-----END CERTIFICATE----- + +// Subject: CN=CLEARESULT CONSULTING INC., OU=Corporate IT, +// O=CLEARESULT CONSULTING INC., L=Austin, ST=TX, C=US +// Issuer: SERIALNUMBER=07969287, +// CN=Go Daddy Secure Certification Authority, +// OU=http://certificates.godaddy.com/repository, +// O="GoDaddy.com, Inc.", +// L=Scottsdale, +// ST=Arizona, +// C=US +// Serial: 2b:73:43:2a:a8:4f:44 +-----BEGIN CERTIFICATE----- +MIIFYjCCBEqgAwIBAgIHK3NDKqhPRDANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE +BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY +BgNVBAoTEUdvRGFkZHkuY29tLCBJbmMuMTMwMQYDVQQLEypodHRwOi8vY2VydGlm +aWNhdGVzLmdvZGFkZHkuY29tL3JlcG9zaXRvcnkxMDAuBgNVBAMTJ0dvIERhZGR5 +IFNlY3VyZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTERMA8GA1UEBRMIMDc5Njky +ODcwHhcNMTIwMjE1MjEwOTA2WhcNMTQwMjE1MjEwOTA2WjCBjDELMAkGA1UEBgwC +VVMxCzAJBgNVBAgMAlRYMQ8wDQYDVQQHDAZBdXN0aW4xIzAhBgNVBAoMGkNMRUFS +RVNVTFQgQ09OU1VMVElORyBJTkMuMRUwEwYDVQQLDAxDb3Jwb3JhdGUgSVQxIzAh +BgNVBAMMGkNMRUFSRVNVTFQgQ09OU1VMVElORyBJTkMuMIIBIjANBgkqhkiG9w0B +AQEFAAOCAQ8AMIIBCgKCAQEAtIOjCKeAicull+7ZIzt0/4ya3IeXUFlfypqKMLkU +IbKjn0P5uMj6VE3rlbZr44RCegxvdnR6umBh1c0ZXoN3o+yc0JKcKcLiApmJJ277 +p7IbLwYDhBXRQNoIJm187IOMRPIxsKN4hL91txn9jGBmW+9zKlJlNhR5R7vjwU2E +jrH/6oqsc9EM2yYpfjlNv6+3jSwAYZCkSWr+27PQOV+YHKmIxtJjX0upFz5FdIrV +9CCX+L2Kji1THOkSgG4QTbYxmEcHqGViWz8hXLeNXjcbEsPuIiAu3hknxRHfUTE/ +U0Lh0Ug1e3LrJu+WnxM2SmUY4krsZ22c0yWUW9hzWITIjQIDAQABo4IBhzCCAYMw +DwYDVR0TAQH/BAUwAwEBADATBgNVHSUEDDAKBggrBgEFBQcDAzAOBgNVHQ8BAf8E +BAMCB4AwMwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5nb2RhZGR5LmNvbS9n +ZHM1LTE2LmNybDBTBgNVHSAETDBKMEgGC2CGSAGG/W0BBxcCMDkwNwYIKwYBBQUH +AgEWK2h0dHA6Ly9jZXJ0aWZpY2F0ZXMuZ29kYWRkeS5jb20vcmVwb3NpdG9yeS8w +gYAGCCsGAQUFBwEBBHQwcjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZ29kYWRk +eS5jb20vMEoGCCsGAQUFBzAChj5odHRwOi8vY2VydGlmaWNhdGVzLmdvZGFkZHku +Y29tL3JlcG9zaXRvcnkvZ2RfaW50ZXJtZWRpYXRlLmNydDAfBgNVHSMEGDAWgBT9 +rGEyk2xF1uLuhV+auud2mWjM5zAdBgNVHQ4EFgQUDtdeKqeN2QkcbEp1HovFieNB +XiowDQYJKoZIhvcNAQEFBQADggEBAD74Agw5tvi2aBl4/f/s7/VE/BClzDsKMb9K +v9qpeC45ZA/jelxV11HKbQnVF194gDb7D2H9OsAsRUy8HVKbXEcc/8dKvwOqb+BC +2i/EmfjLgmCfezNFtLq8xcPxF3zIRc44vPrK0z4YZsaHdH+yTEJ51p5EMdTqaLaP +4n5m8LX3RfqlQB9dYFe6dUoYZjKm9d/pIRww3VqfOzjl42Edi1w6dWmBVMx1NZuR +DBabJH1vJ9Gd+KwxMCmBZ6pQPl28JDimhJhI2LNqU349uADQVV0HJosddN/ARyyI +LSIQO7BnNVKVG9Iujf33bvPNeg0qNz5qw+rKKq97Pqeum+L5oKU= +-----END CERTIFICATE----- diff --git a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c index e0716b1835b..fce061d0fb8 100644 --- a/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c +++ b/jdk/src/share/native/sun/awt/image/jpeg/imageioJPEG.c @@ -930,9 +930,10 @@ imageio_fill_input_buffer(j_decompress_ptr cinfo) * Now fill a complete buffer, or as much of one as the stream * will give us if we are near the end. */ + RELEASE_ARRAYS(env, data, src->next_input_byte); + GET_IO_REF(input); - RELEASE_ARRAYS(env, data, src->next_input_byte); ret = (*env)->CallIntMethod(env, input, JPEGImageReader_readInputDataID, @@ -1017,9 +1018,11 @@ imageio_fill_suspended_buffer(j_decompress_ptr cinfo) memcpy(sb->buf, src->next_input_byte, offset); } - GET_IO_REF(input); RELEASE_ARRAYS(env, data, src->next_input_byte); + + GET_IO_REF(input); + buflen = sb->bufferLength - offset; if (buflen <= 0) { if (!GET_ARRAYS(env, data, &(src->next_input_byte))) { @@ -1121,9 +1124,10 @@ imageio_skip_input_data(j_decompress_ptr cinfo, long num_bytes) return; } + RELEASE_ARRAYS(env, data, src->next_input_byte); + GET_IO_REF(input); - RELEASE_ARRAYS(env, data, src->next_input_byte); ret = (*env)->CallLongMethod(env, input, JPEGImageReader_skipInputBytesID, @@ -2306,10 +2310,10 @@ imageio_empty_output_buffer (j_compress_ptr cinfo) JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2); jobject output = NULL; - GET_IO_REF(output); - RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte)); + GET_IO_REF(output); + (*env)->CallVoidMethod(env, output, JPEGImageWriter_writeOutputDataID, @@ -2348,10 +2352,10 @@ imageio_term_destination (j_compress_ptr cinfo) if (datacount != 0) { jobject output = NULL; - GET_IO_REF(output); - RELEASE_ARRAYS(env, data, (const JOCTET *)(dest->next_output_byte)); + GET_IO_REF(output); + (*env)->CallVoidMethod(env, output, JPEGImageWriter_writeOutputDataID, diff --git a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp index b32f2601b4d..8036a64c4be 100644 --- a/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp +++ b/jdk/src/share/native/sun/font/layout/SunLayoutEngine.cpp @@ -179,6 +179,10 @@ JNIEXPORT void JNICALL Java_sun_font_SunLayoutEngine_nativeLayout FontInstanceAdapter fia(env, font2d, strike, mat, 72, 72, (le_int32) upem, (TTLayoutTableCache *) layoutTables); LEErrorCode success = LE_NO_ERROR; LayoutEngine *engine = LayoutEngine::layoutEngineFactory(&fia, script, lang, typo_flags & TYPO_MASK, success); + if (engine == NULL) { + env->SetIntField(gvdata, gvdCountFID, -1); // flag failure + return; + } if (min < 0) min = 0; if (max < min) max = min; /* defensive coding */ // have to copy, yuck, since code does upcalls now. this will be soooo slow diff --git a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c index 1340c82a822..b2c4fce4229 100644 --- a/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c +++ b/jdk/src/share/native/sun/java2d/cmm/lcms/LCMS.c @@ -94,8 +94,12 @@ cmsInt32Number TransportValue32(cmsInt32Number Value) # endif #endif -typedef union storeID_s { /* store SProfile stuff in a Java Long */ +typedef struct lcmsProfile_s { cmsHPROFILE pf; +} lcmsProfile_t, *lcmsProfile_p; + +typedef union storeID_s { /* store SProfile stuff in a Java Long */ + lcmsProfile_p lcmsPf; cmsHTRANSFORM xf; jobject jobj; jlong j; @@ -106,7 +110,6 @@ typedef union { jint j; } TagSignature_t, *TagSignature_p; -static jfieldID Trans_profileIDs_fID; static jfieldID Trans_renderType_fID; static jfieldID Trans_ID_fID; static jfieldID IL_isIntPacked_fID; @@ -118,7 +121,6 @@ static jfieldID IL_nextRowOffset_fID; static jfieldID IL_width_fID; static jfieldID IL_height_fID; static jfieldID IL_imageAtOnce_fID; -static jfieldID PF_ID_fID; JavaVM *javaVM; @@ -145,6 +147,18 @@ JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { return JNI_VERSION_1_6; } +void LCMS_freeProfile(JNIEnv *env, jlong ptr) { + storeID_t sProfile; + sProfile.j = ptr; + + if (sProfile.lcmsPf != NULL) { + if (sProfile.lcmsPf->pf != NULL) { + cmsCloseProfile(sProfile.lcmsPf->pf); + } + free(sProfile.lcmsPf); + } +} + void LCMS_freeTransform(JNIEnv *env, jlong ID) { storeID_t sTrans; @@ -170,7 +184,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform jlong* ids; size = (*env)->GetArrayLength (env, profileIDs); - ids = (*env)->GetPrimitiveArrayCritical(env, profileIDs, 0); + ids = (*env)->GetLongArrayElements(env, profileIDs, 0); #ifdef _LITTLE_ENDIAN /* Reversing data packed into int for LE archs */ @@ -186,6 +200,8 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform iccArray = (cmsHPROFILE*) malloc( size*2*sizeof(cmsHPROFILE)); if (iccArray == NULL) { + (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0); + J2dRlsTraceLn(J2D_TRACE_ERROR, "getXForm: iccArray == NULL"); return 0L; } @@ -197,7 +213,7 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform cmsColorSpaceSignature cs; sTrans.j = ids[i]; - icc = sTrans.pf; + icc = sTrans.lcmsPf->pf; iccArray[j++] = icc; /* Middle non-abstract profiles should be doubled before passing to @@ -215,13 +231,15 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform sTrans.xf = cmsCreateMultiprofileTransform(iccArray, j, inFormatter, outFormatter, renderType, 0); - (*env)->ReleasePrimitiveArrayCritical(env, profileIDs, ids, 0); + (*env)->ReleaseLongArrayElements(env, profileIDs, ids, 0); if (sTrans.xf == NULL) { J2dRlsTraceLn(J2D_TRACE_ERROR, "LCMS_createNativeTransform: " "sTrans.xf == NULL"); - JNU_ThrowByName(env, "java/awt/color/CMMException", - "Cannot get color transform"); + if ((*env)->ExceptionOccurred(env) == NULL) { + JNU_ThrowByName(env, "java/awt/color/CMMException", + "Cannot get color transform"); + } } else { Disposer_AddRecord(env, disposerRef, LCMS_freeTransform, sTrans.j); } @@ -236,20 +254,23 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_createNativeTransform /* * Class: sun_java2d_cmm_lcms_LCMS * Method: loadProfile - * Signature: ([B)J + * Signature: ([B,Lsun/java2d/cmm/lcms/LCMSProfile;)V */ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative - (JNIEnv *env, jobject obj, jbyteArray data) + (JNIEnv *env, jobject obj, jbyteArray data, jobject disposerRef) { jbyte* dataArray; jint dataSize; storeID_t sProf; + cmsHPROFILE pf; if (JNU_IsNull(env, data)) { JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); return 0L; } + sProf.j = 0L; + dataArray = (*env)->GetByteArrayElements (env, data, 0); dataSize = (*env)->GetArrayLength (env, data); @@ -258,22 +279,37 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative return 0L; } - sProf.pf = cmsOpenProfileFromMem((const void *)dataArray, + pf = cmsOpenProfileFromMem((const void *)dataArray, (cmsUInt32Number) dataSize); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); - if (sProf.pf == NULL) { + if (pf == NULL) { JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); } else { /* Sanity check: try to save the profile in order * to force basic validation. */ cmsUInt32Number pfSize = 0; - if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) || + if (!cmsSaveProfileToMem(pf, NULL, &pfSize) || pfSize < sizeof(cmsICCHeader)) { JNU_ThrowIllegalArgumentException(env, "Invalid profile data"); + + cmsCloseProfile(pf); + pf = NULL; + } + } + + if (pf != NULL) { + // create profile holder + sProf.lcmsPf = (lcmsProfile_p)malloc(sizeof(lcmsProfile_t)); + if (sProf.lcmsPf != NULL) { + // register the disposer record + sProf.lcmsPf->pf = pf; + Disposer_AddRecord(env, disposerRef, LCMS_freeProfile, sProf.j); + } else { + cmsCloseProfile(pf); } } @@ -282,37 +318,17 @@ JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_loadProfileNative /* * Class: sun_java2d_cmm_lcms_LCMS - * Method: freeProfile - * Signature: (J)V - */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_freeProfileNative - (JNIEnv *env, jobject obj, jlong id) -{ - storeID_t sProf; - - sProf.j = id; - if (cmsCloseProfile(sProf.pf) == 0) { - J2dRlsTraceLn1(J2D_TRACE_ERROR, "LCMS_freeProfile: cmsCloseProfile(%d)" - "== 0", id); - JNU_ThrowByName(env, "java/awt/color/CMMException", - "Cannot close profile"); - } - -} - -/* - * Class: sun_java2d_cmm_lcms_LCMS - * Method: getProfileSize + * Method: getProfileSizeNative * Signature: (J)I */ -JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize +JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSizeNative (JNIEnv *env, jobject obj, jlong id) { storeID_t sProf; cmsUInt32Number pfSize = 0; sProf.j = id; - if (cmsSaveProfileToMem(sProf.pf, NULL, &pfSize) && ((jint)pfSize > 0)) { + if (cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize) && ((jint)pfSize > 0)) { return (jint)pfSize; } else { JNU_ThrowByName(env, "java/awt/color/CMMException", @@ -323,10 +339,10 @@ JNIEXPORT jint JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileSize /* * Class: sun_java2d_cmm_lcms_LCMS - * Method: getProfileData + * Method: getProfileDataNative * Signature: (J[B)V */ -JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData +JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileDataNative (JNIEnv *env, jobject obj, jlong id, jbyteArray data) { storeID_t sProf; @@ -338,7 +354,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData sProf.j = id; // determine actual profile size - if (!cmsSaveProfileToMem(sProf.pf, NULL, &pfSize)) { + if (!cmsSaveProfileToMem(sProf.lcmsPf->pf, NULL, &pfSize)) { JNU_ThrowByName(env, "java/awt/color/CMMException", "Can not access specified profile."); return; @@ -354,7 +370,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData dataArray = (*env)->GetByteArrayElements (env, data, 0); - status = cmsSaveProfileToMem(sProf.pf, dataArray, &pfSize); + status = cmsSaveProfileToMem(sProf.lcmsPf->pf, dataArray, &pfSize); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); @@ -368,7 +384,7 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileData /* Get profile header info */ static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize); -static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size); +static cmsHPROFILE _writeCookedTag(cmsHPROFILE pfTarget, cmsTagSignature sig, jbyte *pData, jint size); /* @@ -412,7 +428,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative return NULL; } - status = _getHeaderInfo(sProf.pf, dataArray, bufSize); + status = _getHeaderInfo(sProf.lcmsPf->pf, dataArray, bufSize); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); @@ -425,8 +441,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative return data; } - if (cmsIsTag(sProf.pf, sig.cms)) { - tagSize = cmsReadRawTag(sProf.pf, sig.cms, NULL, 0); + if (cmsIsTag(sProf.lcmsPf->pf, sig.cms)) { + tagSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, NULL, 0); } else { JNU_ThrowByName(env, "java/awt/color/CMMException", "ICC profile tag not found"); @@ -449,7 +465,7 @@ JNIEXPORT jbyteArray JNICALL Java_sun_java2d_cmm_lcms_LCMS_getTagNative return NULL; } - bufSize = cmsReadRawTag(sProf.pf, sig.cms, dataArray, tagSize); + bufSize = cmsReadRawTag(sProf.lcmsPf->pf, sig.cms, dataArray, tagSize); (*env)->ReleaseByteArrayElements (env, data, dataArray, 0); @@ -470,8 +486,10 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative (JNIEnv *env, jobject obj, jlong id, jint tagSig, jbyteArray data) { storeID_t sProf; + cmsHPROFILE pfReplace = NULL; + TagSignature_t sig; - cmsBool status; + cmsBool status = FALSE; jbyte* dataArray; int tagSize; @@ -493,15 +511,24 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_setTagDataNative } if (tagSig == SigHead) { - status = _setHeaderInfo(sProf.pf, dataArray, tagSize); + status = _setHeaderInfo(sProf.lcmsPf->pf, dataArray, tagSize); } else { - status = _writeCookedTag(sProf.pf, sig.cms, dataArray, tagSize); + /* + * New strategy for generic tags: create a place holder, + * dump all existing tags there, dump externally supplied + * tag, and return the new profile to the java. + */ + pfReplace = _writeCookedTag(sProf.lcmsPf->pf, sig.cms, dataArray, tagSize); + status = (pfReplace != NULL); } (*env)->ReleaseByteArrayElements(env, data, dataArray, 0); if (!status) { JNU_ThrowIllegalArgumentException(env, "Can not write tag data."); + } else if (pfReplace != NULL) { + cmsCloseProfile(sProf.lcmsPf->pf); + sProf.lcmsPf->pf = pfReplace; } } @@ -624,12 +651,27 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_colorConvert /* * Class: sun_java2d_cmm_lcms_LCMS * Method: getProfileID - * Signature: (Ljava/awt/color/ICC_Profile;)J + * Signature: (Ljava/awt/color/ICC_Profile;)Lsun/java2d/cmm/lcms/LCMSProfile */ -JNIEXPORT jlong JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID +JNIEXPORT jobject JNICALL Java_sun_java2d_cmm_lcms_LCMS_getProfileID (JNIEnv *env, jclass cls, jobject pf) { - return (*env)->GetLongField (env, pf, PF_ID_fID); + jfieldID fid = (*env)->GetFieldID (env, + (*env)->GetObjectClass(env, pf), + "cmmProfile", "Lsun/java2d/cmm/Profile;"); + + jclass clsLcmsProfile = (*env)->FindClass(env, + "sun/java2d/cmm/lcms/LCMSProfile"); + + jobject cmmProfile = (*env)->GetObjectField (env, pf, fid); + + if (JNU_IsNull(env, cmmProfile)) { + return NULL; + } + if ((*env)->IsInstanceOf(env, cmmProfile, clsLcmsProfile)) { + return cmmProfile; + } + return NULL; } /* @@ -644,7 +686,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS * corresponding classes to avoid problems with invalidating ids by class * unloading */ - Trans_profileIDs_fID = (*env)->GetFieldID (env, Trans, "profileIDs", "[J"); Trans_renderType_fID = (*env)->GetFieldID (env, Trans, "renderType", "I"); Trans_ID_fID = (*env)->GetFieldID (env, Trans, "ID", "J"); @@ -658,8 +699,6 @@ JNIEXPORT void JNICALL Java_sun_java2d_cmm_lcms_LCMS_initLCMS IL_offset_fID = (*env)->GetFieldID (env, IL, "offset", "I"); IL_imageAtOnce_fID = (*env)->GetFieldID (env, IL, "imageAtOnce", "Z"); IL_nextRowOffset_fID = (*env)->GetFieldID (env, IL, "nextRowOffset", "I"); - - PF_ID_fID = (*env)->GetFieldID (env, Pf, "ID", "J"); } static cmsBool _getHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize) @@ -714,76 +753,114 @@ static cmsBool _setHeaderInfo(cmsHPROFILE pf, jbyte* pBuffer, jint bufferSize) return TRUE; } -static cmsBool _writeCookedTag(cmsHPROFILE pfTarget, - cmsTagSignature sig, +/* Returns new profile handler, if it was created successfully, + NULL otherwise. + */ +static cmsHPROFILE _writeCookedTag(const cmsHPROFILE pfTarget, + const cmsTagSignature sig, jbyte *pData, jint size) { - cmsBool status; cmsUInt32Number pfSize = 0; - cmsUInt8Number* pfBuffer = NULL; + const cmsInt32Number tagCount = cmsGetTagCount(pfTarget); + cmsInt32Number i; + cmsHPROFILE pfSanity = NULL; + + cmsICCHeader hdr = { 0 }; cmsHPROFILE p = cmsCreateProfilePlaceholder(NULL); - if (NULL != p) { - cmsICCHeader hdr = { 0 }; - /* Populate the placeholder's header according to target profile */ - hdr.flags = cmsGetHeaderFlags(pfTarget); - hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget); - hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget); - hdr.model = cmsGetHeaderModel(pfTarget); - hdr.pcs = cmsGetPCS(pfTarget); - hdr.colorSpace = cmsGetColorSpace(pfTarget); - hdr.deviceClass = cmsGetDeviceClass(pfTarget); - hdr.version = cmsGetEncodedICCversion(pfTarget); - cmsGetHeaderAttributes(pfTarget, &hdr.attributes); - cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID); + if (NULL == p) { + return NULL; + } - cmsSetHeaderFlags(p, hdr.flags); - cmsSetHeaderManufacturer(p, hdr.manufacturer); - cmsSetHeaderModel(p, hdr.model); - cmsSetHeaderAttributes(p, hdr.attributes); - cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID)); - cmsSetHeaderRenderingIntent(p, hdr.renderingIntent); - cmsSetPCS(p, hdr.pcs); - cmsSetColorSpace(p, hdr.colorSpace); - cmsSetDeviceClass(p, hdr.deviceClass); - cmsSetEncodedICCversion(p, hdr.version); + // Populate the placeholder's header according to target profile + hdr.flags = cmsGetHeaderFlags(pfTarget); + hdr.renderingIntent = cmsGetHeaderRenderingIntent(pfTarget); + hdr.manufacturer = cmsGetHeaderManufacturer(pfTarget); + hdr.model = cmsGetHeaderModel(pfTarget); + hdr.pcs = cmsGetPCS(pfTarget); + hdr.colorSpace = cmsGetColorSpace(pfTarget); + hdr.deviceClass = cmsGetDeviceClass(pfTarget); + hdr.version = cmsGetEncodedICCversion(pfTarget); + cmsGetHeaderAttributes(pfTarget, &hdr.attributes); + cmsGetHeaderProfileID(pfTarget, (cmsUInt8Number*)&hdr.profileID); + cmsSetHeaderFlags(p, hdr.flags); + cmsSetHeaderManufacturer(p, hdr.manufacturer); + cmsSetHeaderModel(p, hdr.model); + cmsSetHeaderAttributes(p, hdr.attributes); + cmsSetHeaderProfileID(p, (cmsUInt8Number*)&(hdr.profileID)); + cmsSetHeaderRenderingIntent(p, hdr.renderingIntent); + cmsSetPCS(p, hdr.pcs); + cmsSetColorSpace(p, hdr.colorSpace); + cmsSetDeviceClass(p, hdr.deviceClass); + cmsSetEncodedICCversion(p, hdr.version); - if (cmsWriteRawTag(p, sig, pData, size)) { - if (cmsSaveProfileToMem(p, NULL, &pfSize)) { - pfBuffer = malloc(pfSize); - if (pfBuffer != NULL) { - /* load raw profile data into the buffer */ - if (!cmsSaveProfileToMem(p, pfBuffer, &pfSize)) { - free(pfBuffer); - pfBuffer = NULL; - } + // now write the user supplied tag + if (size <= 0 || !cmsWriteRawTag(p, sig, pData, size)) { + cmsCloseProfile(p); + return NULL; + } + + // copy tags from the original profile + for (i = 0; i < tagCount; i++) { + cmsBool isTagReady = FALSE; + const cmsTagSignature s = cmsGetTagSignature(pfTarget, i); + const cmsInt32Number tagSize = cmsReadRawTag(pfTarget, s, NULL, 0); + + if (s == sig) { + // skip the user supplied tag + continue; + } + + // read raw tag from the original profile + if (tagSize > 0) { + cmsUInt8Number* buf = (cmsUInt8Number*)malloc(tagSize); + if (buf != NULL) { + if (tagSize == cmsReadRawTag(pfTarget, s, buf, tagSize)) { + // now we are ready to write the tag + isTagReady = cmsWriteRawTag(p, s, buf, tagSize); } + free(buf); } } - cmsCloseProfile(p); - } - if (pfBuffer == NULL) { - return FALSE; - } - - /* re-open the placeholder profile */ - p = cmsOpenProfileFromMem(pfBuffer, pfSize); - free(pfBuffer); - status = FALSE; - - if (p != NULL) { - /* Note that pCookedTag points to internal structures of the placeholder, - * so this data is valid only while the placeholder is open. - */ - void *pCookedTag = cmsReadTag(p, sig); - if (pCookedTag != NULL) { - status = cmsWriteTag(pfTarget, sig, pCookedTag); + if (!isTagReady) { + cmsCloseProfile(p); + return NULL; } - pCookedTag = NULL; - cmsCloseProfile(p); } - return status; + + // now we have all tags moved to the new profile. + // do some sanity checks: write it to a memory buffer and read again. + if (cmsSaveProfileToMem(p, NULL, &pfSize)) { + void* buf = malloc(pfSize); + if (buf != NULL) { + // load raw profile data into the buffer + if (cmsSaveProfileToMem(p, buf, &pfSize)) { + pfSanity = cmsOpenProfileFromMem(buf, pfSize); + } + free(buf); + } + } + + if (pfSanity == NULL) { + // for some reason, we failed to save and read the updated profile + // It likely indicates that the profile is not correct, so we report + // a failure here. + cmsCloseProfile(p); + p = NULL; + } else { + // do final check whether we can read and handle the the target tag. + const void* pTag = cmsReadTag(pfSanity, sig); + if (pTag == NULL) { + // the tag can not be cooked + cmsCloseProfile(p); + p = NULL; + } + cmsCloseProfile(pfSanity); + pfSanity = NULL; + } + + return p; } diff --git a/jdk/src/share/npt/utf.c b/jdk/src/share/npt/utf.c index 9c88ca0583d..55ddd210d57 100644 --- a/jdk/src/share/npt/utf.c +++ b/jdk/src/share/npt/utf.c @@ -105,18 +105,24 @@ utf16ToUtf8m(struct UtfInst *ui, unsigned short *utf16, int len, jbyte *output, code = utf16[i]; if ( code >= 0x0001 && code <= 0x007F ) { + if ( outputLen + 1 >= outputMaxLen ) { + return -1; + } output[outputLen++] = code; } else if ( code == 0 || ( code >= 0x0080 && code <= 0x07FF ) ) { + if ( outputLen + 2 >= outputMaxLen ) { + return -1; + } output[outputLen++] = ((code>>6) & 0x1F) | 0xC0; output[outputLen++] = (code & 0x3F) | 0x80; } else if ( code >= 0x0800 && code <= 0xFFFF ) { + if ( outputLen + 3 >= outputMaxLen ) { + return -1; + } output[outputLen++] = ((code>>12) & 0x0F) | 0xE0; output[outputLen++] = ((code>>6) & 0x3F) | 0x80; output[outputLen++] = (code & 0x3F) | 0x80; } - if ( outputLen > outputMaxLen ) { - return -1; - } } output[outputLen] = 0; return outputLen; @@ -412,12 +418,15 @@ bytesToPrintable(struct UtfInst *ui, char *bytes, int len, char *output, int out unsigned byte; byte = bytes[i]; - if ( outputLen >= outputMaxLen ) { - return -1; - } if ( byte <= 0x7f && isprint(byte) && !iscntrl(byte) ) { + if ( outputLen + 1 >= outputMaxLen ) { + return -1; + } output[outputLen++] = (char)byte; } else { + if ( outputLen + 4 >= outputMaxLen ) { + return -1; + } (void)sprintf(output+outputLen,"\\x%02x",byte); outputLen += 4; } diff --git a/jdk/src/solaris/classes/sun/font/XRTextRenderer.java b/jdk/src/solaris/classes/sun/font/XRTextRenderer.java index c2aa27b43e0..308de3ab300 100644 --- a/jdk/src/solaris/classes/sun/font/XRTextRenderer.java +++ b/jdk/src/solaris/classes/sun/font/XRTextRenderer.java @@ -142,7 +142,7 @@ public class XRTextRenderer extends GlyphListPipe { } int maskFormat = containsLCDGlyphs ? XRUtils.PictStandardARGB32 : XRUtils.PictStandardA8; - maskBuffer.compositeText(x11sd.picture, 0, maskFormat, eltList); + maskBuffer.compositeText(x11sd, (int) gl.getX(), (int) gl.getY(), 0, maskFormat, eltList); eltList.clear(); } finally { diff --git a/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java b/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java index a6ffd0defcd..205ff13c6fc 100644 --- a/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java +++ b/jdk/src/solaris/classes/sun/java2d/xr/XRBackendNative.java @@ -267,8 +267,9 @@ public class XRBackendNative implements XRBackend { private static native void XRenderCompositeTextNative(int op, int src, int dst, - long maskFormat, int[] eltArray, - int[] glyphIDs, int eltCnt, int glyphCnt); + int srcX, int srcY, long maskFormat, + int[] eltArray, int[] glyphIDs, int eltCnt, + int glyphCnt); public int XRenderCreateGlyphSet(int formatID) { return XRenderCreateGlyphSetNative(getFormatPtr(formatID)); @@ -278,11 +279,11 @@ public class XRBackendNative implements XRBackend { public void XRenderCompositeText(byte op, int src, int dst, int maskFormatID, - int src2, int src3, int dst2, int dst3, + int sx, int sy, int dx, int dy, int glyphset, GrowableEltArray elts) { GrowableIntArray glyphs = elts.getGlyphs(); - XRenderCompositeTextNative(op, src, dst, 0, elts.getArray(), + XRenderCompositeTextNative(op, src, dst, sx, sy, 0, elts.getArray(), glyphs.getArray(), elts.getSize(), glyphs.getSize()); } diff --git a/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java index 1264d539611..39b8642bb9d 100644 --- a/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java +++ b/jdk/src/solaris/classes/sun/java2d/xr/XRCompositeManager.java @@ -285,7 +285,12 @@ public class XRCompositeManager { if (xorEnabled) { con.GCRectangles(dst.getXid(), dst.getGC(), rects); } else { - con.renderRectangles(dst.getPicture(), compRule, solidColor, rects); + if (rects.getSize() == 1) { + con.renderRectangle(dst.getPicture(), compRule, solidColor, + rects.getX(0), rects.getY(0), rects.getWidth(0), rects.getHeight(0)); + } else { + con.renderRectangles(dst.getPicture(), compRule, solidColor, rects); + } } } @@ -295,10 +300,10 @@ public class XRCompositeManager { sy, 0, 0, dx, dy, w, h); } - public void compositeText(int dst, int glyphSet, int maskFormat, - GrowableEltArray elts) { - con.XRenderCompositeText(compRule, src.picture, dst, maskFormat, 0, 0, - 0, 0, glyphSet, elts); + public void compositeText(XRSurfaceData dst, int sx, int sy, + int glyphSet, int maskFormat, GrowableEltArray elts) { + con.XRenderCompositeText(compRule, src.picture, dst.picture, + maskFormat, sx, sy, 0, 0, glyphSet, elts); } public XRColor getMaskColor() { diff --git a/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java b/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java index aaa48af2e16..20f84fa8ba3 100644 --- a/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java +++ b/jdk/src/solaris/classes/sun/java2d/xr/XRPMBlitLoops.java @@ -225,6 +225,9 @@ class XRPMScaledBlit extends ScaledBlit { * @author Clemens Eisserer */ class XRPMTransformedBlit extends TransformBlit { + final Rectangle compositeBounds = new Rectangle(); + final double[] srcCoords = new double[8]; + final double[] dstCoords = new double[8]; public XRPMTransformedBlit(SurfaceType srcType, SurfaceType dstType) { super(srcType, CompositeType.AnyAlpha, dstType); @@ -235,61 +238,68 @@ class XRPMTransformedBlit extends TransformBlit { * method is functionally equal to: Shape shp = * xform.createTransformedShape(rect); Rectangle bounds = shp.getBounds(); * but performs significantly better. + * Returns true if the destination shape is parallel to x/y axis */ - public Rectangle getCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) { - double[] compBounds = new double[8]; - compBounds[0] = dstx; - compBounds[1] = dsty; - compBounds[2] = dstx + width; - compBounds[3] = dsty; - compBounds[4] = dstx + width; - compBounds[5] = dsty + height; - compBounds[6] = dstx; - compBounds[7] = dsty + height; + protected boolean adjustCompositeBounds(AffineTransform tr, int dstx, int dsty, int width, int height) { + srcCoords[0] = dstx; + srcCoords[1] = dsty; + srcCoords[2] = dstx + width; + srcCoords[3] = dsty; + srcCoords[4] = dstx + width; + srcCoords[5] = dsty + height; + srcCoords[6] = dstx; + srcCoords[7] = dsty + height; - tr.transform(compBounds, 0, compBounds, 0, 4); + tr.transform(srcCoords, 0, dstCoords, 0, 4); - double minX = Math.min(compBounds[0], Math.min(compBounds[2], Math.min(compBounds[4], compBounds[6]))); - double minY = Math.min(compBounds[1], Math.min(compBounds[3], Math.min(compBounds[5], compBounds[7]))); - double maxX = Math.max(compBounds[0], Math.max(compBounds[2], Math.max(compBounds[4], compBounds[6]))); - double maxY = Math.max(compBounds[1], Math.max(compBounds[3], Math.max(compBounds[5], compBounds[7]))); + double minX = Math.min(dstCoords[0], Math.min(dstCoords[2], Math.min(dstCoords[4], dstCoords[6]))); + double minY = Math.min(dstCoords[1], Math.min(dstCoords[3], Math.min(dstCoords[5], dstCoords[7]))); + double maxX = Math.max(dstCoords[0], Math.max(dstCoords[2], Math.max(dstCoords[4], dstCoords[6]))); + double maxY = Math.max(dstCoords[1], Math.max(dstCoords[3], Math.max(dstCoords[5], dstCoords[7]))); - minX = Math.floor(minX); - minY = Math.floor(minY); - maxX = Math.ceil(maxX); - maxY = Math.ceil(maxY); + minX = Math.round(minX); + minY = Math.round(minY); + maxX = Math.round(maxX); + maxY = Math.round(maxY); - return new Rectangle((int) minX, (int) minY, (int) (maxX - minX), (int) (maxY - minY)); + compositeBounds.x = (int) minX; + compositeBounds.y = (int) minY; + compositeBounds.width = (int) (maxX - minX); + compositeBounds.height = (int) (maxY - minY); + + boolean is0or180 = (dstCoords[1] == dstCoords[3]) && (dstCoords[2] == dstCoords[4]); + boolean is90or270 = (dstCoords[0] == dstCoords[2]) && (dstCoords[3] == dstCoords[5]); + + return is0or180 || is90or270; } - public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, int hint, int srcx, int srcy, - int dstx, int dsty, int width, int height) { + public void Transform(SurfaceData src, SurfaceData dst, Composite comp, Region clip, AffineTransform xform, + int hint, int srcx, int srcy, int dstx, int dsty, int width, int height) { try { SunToolkit.awtLock(); - int filter = XRUtils.ATransOpToXRQuality(hint); - XRSurfaceData x11sdDst = (XRSurfaceData) dst; - x11sdDst.validateAsDestination(null, clip); XRSurfaceData x11sdSrc = (XRSurfaceData) src; + + int filter = XRUtils.ATransOpToXRQuality(hint); + boolean isAxisAligned = adjustCompositeBounds(xform, dstx, dsty, width, height); + + x11sdDst.validateAsDestination(null, clip); x11sdDst.maskBuffer.validateCompositeState(comp, null, null, null); - Rectangle bounds = getCompositeBounds(xform, dstx, dsty, width, height); - - AffineTransform trx = AffineTransform.getTranslateInstance((-bounds.x), (-bounds.y)); + AffineTransform trx = AffineTransform.getTranslateInstance(-compositeBounds.x, -compositeBounds.y); trx.concatenate(xform); AffineTransform maskTX = (AffineTransform) trx.clone(); - trx.translate(-srcx, -srcy); try { trx.invert(); } catch (NoninvertibleTransformException ex) { trx.setToIdentity(); - System.err.println("Reseted to identity!"); } - boolean omitMask = isMaskOmittable(trx, comp, filter); + boolean omitMask = (filter == XRUtils.FAST) + || (isAxisAligned && ((AlphaComposite) comp).getAlpha() == 1.0f); if (!omitMask) { XRMaskImage mask = x11sdSrc.maskBuffer.getMaskImage(); @@ -297,33 +307,17 @@ class XRPMTransformedBlit extends TransformBlit { x11sdSrc.validateAsSource(trx, XRUtils.RepeatPad, filter); int maskPicture = mask.prepareBlitMask(x11sdDst, maskTX, width, height); x11sdDst.maskBuffer.con.renderComposite(XRCompositeManager.getInstance(x11sdSrc).getCompRule(), x11sdSrc.picture, maskPicture, x11sdDst.picture, - 0, 0, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height); + 0, 0, 0, 0, compositeBounds.x, compositeBounds.y, compositeBounds.width, compositeBounds.height); } else { int repeat = filter == XRUtils.FAST ? XRUtils.RepeatNone : XRUtils.RepeatPad; x11sdSrc.validateAsSource(trx, repeat, filter); - x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, bounds.x, bounds.y, bounds.width, bounds.height); + x11sdDst.maskBuffer.compositeBlit(x11sdSrc, x11sdDst, 0, 0, compositeBounds.x, compositeBounds.y, compositeBounds.width, compositeBounds.height); } } finally { SunToolkit.awtUnlock(); } } - - /* TODO: Is mask ever omitable??? ... should be for 90 degree rotation and no shear, but we always need to use RepeatPad */ - protected static boolean isMaskOmittable(AffineTransform trx, Composite comp, int filter) { - return (filter == XRUtils.FAST || trx.getTranslateX() == (int) trx.getTranslateX() /* - * If - * translate - * is - * integer - * only - */ - && trx.getTranslateY() == (int) trx.getTranslateY() && (trx.getShearX() == 0 && trx.getShearY() == 0 // Only - // 90 degree - // rotation - || trx.getShearX() == -trx.getShearY())) && ((AlphaComposite) comp).getAlpha() == 1.0f; // No - // ExtraAlpha!=1 - } } class XrSwToPMBlit extends Blit { diff --git a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java index df30e2924f2..6eeee2a7532 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java +++ b/jdk/src/solaris/classes/sun/nio/ch/DevPollArrayWrapper.java @@ -26,9 +26,11 @@ package sun.nio.ch; import java.io.IOException; +import java.security.AccessController; import java.util.BitSet; import java.util.Map; import java.util.HashMap; +import sun.security.action.GetIntegerAction; /** @@ -78,10 +80,11 @@ class DevPollArrayWrapper { static final int NUM_POLLFDS = Math.min(OPEN_MAX-1, 8192); // Initial size of arrays for fd registration changes - private final int INITIAL_PENDING_UPDATE_SIZE = 64; + private static final int INITIAL_PENDING_UPDATE_SIZE = 64; // maximum size of updatesLow - private final int MAX_UPDATE_ARRAY_SIZE = Math.min(OPEN_MAX, 64*1024); + private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged( + new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024))); // The pollfd array for results from devpoll driver private final AllocatedNativeObject pollArray; diff --git a/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java b/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java index a73d3c2dff1..f64feb24c75 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java +++ b/jdk/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java @@ -26,9 +26,11 @@ package sun.nio.ch; import java.io.IOException; +import java.security.AccessController; import java.util.BitSet; import java.util.HashMap; import java.util.Map; +import sun.security.action.GetIntegerAction; /** * Manipulates a native array of epoll_event structs on Linux: @@ -78,8 +80,8 @@ class EPollArrayWrapper { private static final int INITIAL_PENDING_UPDATE_SIZE = 64; // maximum size of updatesLow - private static final int MAX_UPDATE_ARRAY_SIZE = Math.min(OPEN_MAX, 64*1024); - + private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged( + new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024))); // The fd of the epoll driver private final int epfd; @@ -163,6 +165,16 @@ class EPollArrayWrapper { return pollArray.getInt(offset); } + /** + * Returns {@code true} if updates for the given key (file + * descriptor) are killed. + */ + private boolean isEventsHighKilled(Integer key) { + assert key >= MAX_UPDATE_ARRAY_SIZE; + Byte value = eventsHigh.get(key); + return (value != null && value == KILLED); + } + /** * Sets the pending update events for the given file descriptor. This * method has no effect if the update events is already set to KILLED, @@ -175,7 +187,7 @@ class EPollArrayWrapper { } } else { Integer key = Integer.valueOf(fd); - if ((eventsHigh.get(key) != KILLED) || force) { + if (!isEventsHighKilled(key) || force) { eventsHigh.put(key, Byte.valueOf(events)); } } diff --git a/jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java b/jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java index bec37360642..d9383eb7ed0 100644 --- a/jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java +++ b/jdk/src/solaris/classes/sun/nio/ch/EventPortWrapper.java @@ -25,9 +25,14 @@ package sun.nio.ch; -import sun.misc.Unsafe; import java.io.IOException; -import java.util.*; +import java.security.AccessController; +import java.util.BitSet; +import java.util.HashMap; +import java.util.Map; + +import sun.misc.Unsafe; +import sun.security.action.GetIntegerAction; import static sun.nio.ch.SolarisEventPort.*; /** @@ -49,7 +54,8 @@ class EventPortWrapper { private final int INITIAL_PENDING_UPDATE_SIZE = 256; // maximum size of updateArray - private final int MAX_UPDATE_ARRAY_SIZE = Math.min(OPEN_MAX, 64*1024); + private static final int MAX_UPDATE_ARRAY_SIZE = AccessController.doPrivileged( + new GetIntegerAction("sun.nio.ch.maxUpdateArraySize", Math.min(OPEN_MAX, 64*1024))); // special update status to indicate that it should be ignored private static final byte IGNORE = -1; diff --git a/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c b/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c index 75d1cd2f4d2..cbcf0c357e3 100644 --- a/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c +++ b/jdk/src/solaris/native/sun/java2d/x11/XRBackendNative.c @@ -911,8 +911,9 @@ Java_sun_java2d_xr_XRBackendNative_XRenderCreateGlyphSetNative JNIEXPORT void JNICALL Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative - (JNIEnv *env, jclass cls, jint op, jint src, jint dst, jlong maskFmt, - jintArray eltArray, jintArray glyphIDArray, jint eltCnt, jint glyphCnt) { + (JNIEnv *env, jclass cls, jint op, jint src, jint dst, + jint sx, jint sy, jlong maskFmt, jintArray eltArray, + jintArray glyphIDArray, jint eltCnt, jint glyphCnt) { jint i; jint *ids; jint *elts; @@ -991,7 +992,7 @@ Java_sun_java2d_xr_XRBackendNative_XRenderCompositeTextNative XRenderCompositeText32(awt_display, op, (Picture) src, (Picture) dst, (XRenderPictFormat *) jlong_to_ptr(maskFmt), - 0, 0, 0, 0, xelts, eltCnt); + sx, sy, 0, 0, xelts, eltCnt); (*env)->ReleasePrimitiveArrayCritical(env, glyphIDArray, ids, JNI_ABORT); (*env)->ReleasePrimitiveArrayCritical(env, eltArray, elts, JNI_ABORT); diff --git a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java index 897e8f1baf1..519a0be422e 100644 --- a/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java +++ b/jdk/src/windows/classes/sun/awt/windows/WPrinterJob.java @@ -179,6 +179,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { private static final int SET_RES_LOW = 0x00000080; private static final int SET_COLOR = 0x00000200; private static final int SET_ORIENTATION = 0x00004000; + private static final int SET_COLLATED = 0x00008000; /** * Values must match those defined in wingdi.h & commdlg.h @@ -189,10 +190,33 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { private static final int PD_NOSELECTION = 0x00000004; private static final int PD_COLLATE = 0x00000010; private static final int PD_PRINTTOFILE = 0x00000020; - private static final int DM_ORIENTATION = 0x00000001; - private static final int DM_PRINTQUALITY = 0x00000400; - private static final int DM_COLOR = 0x00000800; - private static final int DM_DUPLEX = 0x00001000; + private static final int DM_ORIENTATION = 0x00000001; + private static final int DM_PAPERSIZE = 0x00000002; + private static final int DM_COPIES = 0x00000100; + private static final int DM_DEFAULTSOURCE = 0x00000200; + private static final int DM_PRINTQUALITY = 0x00000400; + private static final int DM_COLOR = 0x00000800; + private static final int DM_DUPLEX = 0x00001000; + private static final int DM_YRESOLUTION = 0x00002000; + private static final int DM_COLLATE = 0x00008000; + + private static final short DMCOLLATE_FALSE = 0; + private static final short DMCOLLATE_TRUE = 1; + + private static final short DMORIENT_PORTRAIT = 1; + private static final short DMORIENT_LANDSCAPE = 2; + + private static final short DMCOLOR_MONOCHROME = 1; + private static final short DMCOLOR_COLOR = 2; + + private static final short DMRES_DRAFT = -1; + private static final short DMRES_LOW = -2; + private static final short DMRES_MEDIUM = -3; + private static final short DMRES_HIGH = -4; + + private static final short DMDUP_SIMPLEX = 1; + private static final short DMDUP_VERTICAL = 2; + private static final short DMDUP_HORIZONTAL = 3; /** * Pageable MAX pages @@ -592,13 +616,23 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } driverDoesMultipleCopies = false; driverDoesCollation = false; - setNativePrintService(service.getName()); + setNativePrintServiceIfNeeded(service.getName()); } /* associates this job with the specified native service */ private native void setNativePrintService(String name) throws PrinterException; + private String lastNativeService = null; + private void setNativePrintServiceIfNeeded(String name) + throws PrinterException { + + if (name != null && !(name.equals(lastNativeService))) { + setNativePrintService(name); + lastNativeService = name; + } + } + public PrintService getPrintService() { if (myService == null) { String printerName = getNativePrintService(); @@ -616,7 +650,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { myService = PrintServiceLookup.lookupDefaultPrintService(); if (myService != null) { try { - setNativePrintService(myService.getName()); + setNativePrintServiceIfNeeded(myService.getName()); } catch (Exception e) { myService = null; } @@ -1754,8 +1788,13 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { mAttMediaSizeName = ((Win32PrintService)myService).findPaperID(msn); } - private void setWin32MediaAttrib(int dmIndex, int width, int length) { - MediaSizeName msn = + private void addPaperSize(PrintRequestAttributeSet aset, + int dmIndex, int width, int length) { + + if (aset == null) { + return; + } + MediaSizeName msn = ((Win32PrintService)myService).findWin32Media(dmIndex); if (msn == null) { msn = ((Win32PrintService)myService). @@ -1763,10 +1802,12 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } if (msn != null) { - if (attributes != null) { - attributes.add(msn); - } + aset.add(msn); } + } + + private void setWin32MediaAttrib(int dmIndex, int width, int length) { + addPaperSize(attributes, dmIndex, width, length); mAttMediaSizeName = dmIndex; } @@ -1788,7 +1829,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { // no equivalent predefined value mAttMediaTray = 7; // DMBIN_AUTO } else if (attr == MediaTray.TOP) { - mAttMediaTray =1; // DMBIN_UPPER + mAttMediaTray = 1; // DMBIN_UPPER } else { if (attr instanceof Win32MediaTray) { mAttMediaTray = ((Win32MediaTray)attr).winID; @@ -1914,6 +1955,254 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } } + private static final class DevModeValues { + int dmFields; + short copies; + short collate; + short color; + short duplex; + short orient; + short paper; + short bin; + short xres_quality; + short yres; + } + + private void getDevModeValues(PrintRequestAttributeSet aset, + DevModeValues info) { + + Copies c = (Copies)aset.get(Copies.class); + if (c != null) { + info.dmFields |= DM_COPIES; + info.copies = (short)c.getValue(); + } + + SheetCollate sc = (SheetCollate)aset.get(SheetCollate.class); + if (sc != null) { + info.dmFields |= DM_COLLATE; + info.collate = (sc == SheetCollate.COLLATED) ? + DMCOLLATE_TRUE : DMCOLLATE_FALSE; + } + + Chromaticity ch = (Chromaticity)aset.get(Chromaticity.class); + if (ch != null) { + info.dmFields |= DM_COLOR; + if (ch == Chromaticity.COLOR) { + info.color = DMCOLOR_COLOR; + } else { + info.color = DMCOLOR_MONOCHROME; + } + } + + Sides s = (Sides)aset.get(Sides.class); + if (s != null) { + info.dmFields |= DM_DUPLEX; + if (s == Sides.TWO_SIDED_LONG_EDGE) { + info.duplex = DMDUP_VERTICAL; + } else if (s == Sides.TWO_SIDED_SHORT_EDGE) { + info.duplex = DMDUP_HORIZONTAL; + } else { // Sides.ONE_SIDED + info.duplex = DMDUP_SIMPLEX; + } + } + + OrientationRequested or = + (OrientationRequested)aset.get(OrientationRequested.class); + if (or != null) { + info.dmFields |= DM_ORIENTATION; + info.orient = (or == OrientationRequested.LANDSCAPE) + ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT; + } + + Media m = (Media)aset.get(Media.class); + if (m instanceof MediaSizeName) { + info.dmFields |= DM_PAPERSIZE; + MediaSizeName msn = (MediaSizeName)m; + info.paper = + (short)((Win32PrintService)myService).findPaperID(msn); + } + + MediaTray mt = null; + if (m instanceof MediaTray) { + mt = (MediaTray)m; + } + if (mt == null) { + SunAlternateMedia sam = + (SunAlternateMedia)aset.get(SunAlternateMedia.class); + if (sam != null && (sam.getMedia() instanceof MediaTray)) { + mt = (MediaTray)sam.getMedia(); + } + } + + if (mt != null) { + info.dmFields |= DM_DEFAULTSOURCE; + info.bin = (short)(((Win32PrintService)myService).findTrayID(mt)); + } + + PrintQuality q = (PrintQuality)aset.get(PrintQuality.class); + if (q != null) { + info.dmFields |= DM_PRINTQUALITY; + if (q == PrintQuality.DRAFT) { + info.xres_quality = DMRES_DRAFT; + } else if (q == PrintQuality.HIGH) { + info.xres_quality = DMRES_HIGH; + } else { + info.xres_quality = DMRES_MEDIUM; + } + } + + PrinterResolution r = + (PrinterResolution)aset.get(PrinterResolution.class); + if (r != null) { + info.dmFields |= DM_PRINTQUALITY | DM_YRESOLUTION; + info.xres_quality = + (short)r.getCrossFeedResolution(PrinterResolution.DPI); + info.yres = (short)r.getFeedResolution(PrinterResolution.DPI); + } + } + + /* This method is called from native to update the values in the + * attribute set which originates from the cross-platform dialog, + * but updated by the native DocumentPropertiesUI which updates the + * devmode. This syncs the devmode back in to the attributes so that + * we can update the cross-platform dialog. + * The attribute set here is a temporary one installed whilst this + * happens, + */ + private final void setJobAttributes(PrintRequestAttributeSet attributes, + int fields, int values, + short copies, + short dmPaperSize, + short dmPaperWidth, + short dmPaperLength, + short dmDefaultSource, + short xRes, + short yRes) { + + if (attributes == null) { + return; + } + + if ((fields & DM_COPIES) != 0) { + attributes.add(new Copies(copies)); + } + + if ((fields & DM_COLLATE) != 0) { + if ((values & SET_COLLATED) != 0) { + attributes.add(SheetCollate.COLLATED); + } else { + attributes.add(SheetCollate.UNCOLLATED); + } + } + + if ((fields & DM_ORIENTATION) != 0) { + if ((values & SET_ORIENTATION) != 0) { + attributes.add(OrientationRequested.LANDSCAPE); + } else { + attributes.add(OrientationRequested.PORTRAIT); + } + } + + if ((fields & DM_COLOR) != 0) { + if ((values & SET_COLOR) != 0) { + attributes.add(Chromaticity.COLOR); + } else { + attributes.add(Chromaticity.MONOCHROME); + } + } + + if ((fields & DM_PRINTQUALITY) != 0) { + /* value < 0 indicates quality setting. + * value > 0 indicates X resolution. In that case + * hopefully we will also find y-resolution specified. + * If its not, assume its the same as x-res. + * Maybe Java code should try to reconcile this against + * the printers claimed set of supported resolutions. + */ + if (xRes < 0) { + PrintQuality quality; + if ((values & SET_RES_LOW) != 0) { + quality = PrintQuality.DRAFT; + } else if ((fields & SET_RES_HIGH) != 0) { + quality = PrintQuality.HIGH; + } else { + quality = PrintQuality.NORMAL; + } + attributes.add(quality); + } else if (xRes > 0 && yRes > 0) { + attributes.add( + new PrinterResolution(xRes, yRes, PrinterResolution.DPI)); + } + } + + if ((fields & DM_DUPLEX) != 0) { + Sides sides; + if ((values & SET_DUP_VERTICAL) != 0) { + sides = Sides.TWO_SIDED_LONG_EDGE; + } else if ((values & SET_DUP_HORIZONTAL) != 0) { + sides = Sides.TWO_SIDED_SHORT_EDGE; + } else { + sides = Sides.ONE_SIDED; + } + attributes.add(sides); + } + + if ((fields & DM_PAPERSIZE) != 0) { + addPaperSize(attributes, dmPaperSize, dmPaperWidth, dmPaperLength); + } + + if ((fields & DM_DEFAULTSOURCE) != 0) { + MediaTray tray = + ((Win32PrintService)myService).findMediaTray(dmDefaultSource); + attributes.add(new SunAlternateMedia(tray)); + } + } + + private native boolean showDocProperties(long hWnd, + PrintRequestAttributeSet aset, + int dmFields, + short copies, + short collate, + short color, + short duplex, + short orient, + short paper, + short bin, + short xres_quality, + short yres); + + @SuppressWarnings("deprecation") + public PrintRequestAttributeSet + showDocumentProperties(Window owner, + PrintService service, + PrintRequestAttributeSet aset) + { + try { + setNativePrintServiceIfNeeded(service.getName()); + } catch (PrinterException e) { + } + long hWnd = ((WWindowPeer)(owner.getPeer())).getHWnd(); + DevModeValues info = new DevModeValues(); + getDevModeValues(aset, info); + boolean ok = + showDocProperties(hWnd, aset, + info.dmFields, + info.copies, + info.collate, + info.color, + info.duplex, + info.orient, + info.paper, + info.bin, + info.xres_quality, + info.yres); + + if (ok) { + return aset; + } else { + return null; + } + } /* Printer Resolution. See also getXRes() and getYRes() */ private final void setResolutionDPI(int xres, int yres) { @@ -1956,7 +2245,7 @@ public class WPrinterJob extends RasterPrinterJob implements DisposerTarget { } //** END Functions called by native code for querying/updating attributes - } + } class PrintToFileErrorDialog extends Dialog implements ActionListener{ public PrintToFileErrorDialog(Frame parent, String title, String message, diff --git a/jdk/src/windows/classes/sun/print/Win32MediaTray.java b/jdk/src/windows/classes/sun/print/Win32MediaTray.java index ecafcef5668..2f2cafce035 100644 --- a/jdk/src/windows/classes/sun/print/Win32MediaTray.java +++ b/jdk/src/windows/classes/sun/print/Win32MediaTray.java @@ -70,6 +70,10 @@ public class Win32MediaTray extends MediaTray { winEnumTable.add(this); } + public int getDMBinID() { + return winID; + } + private static final String[] myStringTable ={ "Manual-Envelope", "Automatic-Feeder", diff --git a/jdk/src/windows/classes/sun/print/Win32PrintService.java b/jdk/src/windows/classes/sun/print/Win32PrintService.java index c42de1ae7df..73e89269285 100644 --- a/jdk/src/windows/classes/sun/print/Win32PrintService.java +++ b/jdk/src/windows/classes/sun/print/Win32PrintService.java @@ -25,6 +25,8 @@ package sun.print; +import java.awt.Window; +import java.awt.print.PrinterJob; import java.io.File; import java.net.URI; import java.net.URISyntaxException; @@ -39,6 +41,7 @@ import javax.print.attribute.AttributeSet; import javax.print.attribute.AttributeSetUtilities; import javax.print.attribute.EnumSyntax; import javax.print.attribute.HashAttributeSet; +import javax.print.attribute.PrintRequestAttributeSet; import javax.print.attribute.PrintServiceAttribute; import javax.print.attribute.PrintServiceAttributeSet; import javax.print.attribute.HashPrintServiceAttributeSet; @@ -69,6 +72,7 @@ import javax.print.attribute.standard.PrintQuality; import javax.print.attribute.standard.PrinterResolution; import javax.print.attribute.standard.SheetCollate; import javax.print.event.PrintServiceAttributeListener; +import sun.awt.windows.WPrinterJob; public class Win32PrintService implements PrintService, AttributeUpdater, SunPrinterJobService { @@ -282,6 +286,22 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return 0; } + public int findTrayID(MediaTray tray) { + + getMediaTrays(); // make sure they are initialised. + + if (tray instanceof Win32MediaTray) { + Win32MediaTray winTray = (Win32MediaTray)tray; + return winTray.getDMBinID(); + } + for (int id=0; id= 1 && dmBin <= dmPaperBinToPrintService.length) { return dmPaperBinToPrintService[dmBin-1]; @@ -673,7 +693,6 @@ public class Win32PrintService implements PrintService, AttributeUpdater, return arr2; } - private PrinterIsAcceptingJobs getPrinterIsAcceptingJobs() { if (getJobStatus(printer, 2) != 1) { return PrinterIsAcceptingJobs.NOT_ACCEPTING_JOBS; @@ -1596,8 +1615,76 @@ public class Win32PrintService implements PrintService, AttributeUpdater, } } - public ServiceUIFactory getServiceUIFactory() { - return null; + private Win32DocumentPropertiesUI docPropertiesUI = null; + + private static class Win32DocumentPropertiesUI + extends DocumentPropertiesUI { + + Win32PrintService service; + + private Win32DocumentPropertiesUI(Win32PrintService s) { + service = s; + } + + public PrintRequestAttributeSet + showDocumentProperties(PrinterJob job, + Window owner, + PrintService service, + PrintRequestAttributeSet aset) { + + if (!(job instanceof WPrinterJob)) { + return null; + } + WPrinterJob wJob = (WPrinterJob)job; + return wJob.showDocumentProperties(owner, service, aset); + } + } + + private synchronized DocumentPropertiesUI getDocumentPropertiesUI() { + return new Win32DocumentPropertiesUI(this); + } + + private static class Win32ServiceUIFactory extends ServiceUIFactory { + + Win32PrintService service; + + Win32ServiceUIFactory(Win32PrintService s) { + service = s; + } + + public Object getUI(int role, String ui) { + if (role <= ServiceUIFactory.MAIN_UIROLE) { + return null; + } + if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE && + DocumentPropertiesUI.DOCPROPERTIESCLASSNAME.equals(ui)) + { + return service.getDocumentPropertiesUI(); + } + throw new IllegalArgumentException("Unsupported role"); + } + + public String[] getUIClassNamesForRole(int role) { + + if (role <= ServiceUIFactory.MAIN_UIROLE) { + return null; + } + if (role == DocumentPropertiesUI.DOCUMENTPROPERTIES_ROLE) { + String[] names = new String[0]; + names[0] = DocumentPropertiesUI.DOCPROPERTIESCLASSNAME; + return names; + } + throw new IllegalArgumentException("Unsupported role"); + } + } + + private Win32ServiceUIFactory uiFactory = null; + + public synchronized ServiceUIFactory getServiceUIFactory() { + if (uiFactory == null) { + uiFactory = new Win32ServiceUIFactory(this); + } + return uiFactory; } public String toString() { diff --git a/jdk/src/windows/native/java/lang/ProcessImpl_md.c b/jdk/src/windows/native/java/lang/ProcessImpl_md.c index 1806fb8193c..da7d00b081a 100644 --- a/jdk/src/windows/native/java/lang/ProcessImpl_md.c +++ b/jdk/src/windows/native/java/lang/ProcessImpl_md.c @@ -308,7 +308,11 @@ static jlong processCreate( if (success) { PROCESS_INFORMATION pi; - DWORD processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT; + DWORD processFlag = CREATE_UNICODE_ENVIRONMENT; + + /* Suppress popping-up of a console window for non-console applications */ + if (GetConsoleWindow() == NULL) + processFlag |= CREATE_NO_WINDOW; si.dwFlags = STARTF_USESTDHANDLES; if (!CreateProcessW( diff --git a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp index 71a08d3df33..07dd90fcf2c 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.cpp @@ -81,6 +81,7 @@ jmethodID AwtPrintControl::setToPageID; jmethodID AwtPrintControl::setNativeAttID; jmethodID AwtPrintControl::setRangeCopiesID; jmethodID AwtPrintControl::setResID; +jmethodID AwtPrintControl::setJobAttributesID; BOOL AwtPrintControl::IsSupportedLevel(HANDLE hPrinter, DWORD dwLevel) { @@ -297,6 +298,10 @@ void AwtPrintControl::initIDs(JNIEnv *env, jclass cls) AwtPrintControl::setPrinterID = env->GetMethodID(cls, "setPrinterNameAttrib", "(Ljava/lang/String;)V"); + AwtPrintControl::setJobAttributesID = + env->GetMethodID(cls, "setJobAttributes", + "(Ljavax/print/attribute/PrintRequestAttributeSet;IISSSSSSS)V"); + DASSERT(AwtPrintControl::driverDoesMultipleCopiesID != NULL); DASSERT(AwtPrintControl::getPrintDCID != NULL); DASSERT(AwtPrintControl::setPrintDCID != NULL); @@ -327,6 +332,7 @@ void AwtPrintControl::initIDs(JNIEnv *env, jclass cls) DASSERT(AwtPrintControl::getSidesID != NULL); DASSERT(AwtPrintControl::getSelectID != NULL); DASSERT(AwtPrintControl::getPrintToFileEnabledID != NULL); + DASSERT(AwtPrintControl::setJobAttributesID != NULL); CATCH_BAD_ALLOC; diff --git a/jdk/src/windows/native/sun/windows/awt_PrintControl.h b/jdk/src/windows/native/sun/windows/awt_PrintControl.h index 2e3fbaf2e60..e8b7415f305 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintControl.h +++ b/jdk/src/windows/native/sun/windows/awt_PrintControl.h @@ -47,7 +47,6 @@ public: static jmethodID setDevmodeID; static jmethodID getDevnamesID; static jmethodID setDevnamesID; - static jmethodID getWin32MediaID; static jmethodID setWin32MediaID; static jmethodID getWin32MediaTrayID; @@ -73,6 +72,7 @@ public: static jmethodID setNativeAttID; static jmethodID setRangeCopiesID; static jmethodID setResID; + static jmethodID setJobAttributesID; static void initIDs(JNIEnv *env, jclass cls); static BOOL FindPrinter(jstring printerName, LPBYTE pPrinterEnum, diff --git a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp index a2deb14b58c..c19e4306114 100644 --- a/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp +++ b/jdk/src/windows/native/sun/windows/awt_PrintJob.cpp @@ -329,6 +329,156 @@ static int CALLBACK fontEnumProcA(ENUMLOGFONTEXA *logfont, static int embolden(int currentWeight); static BOOL getPrintableArea(HDC pdc, HANDLE hDevMode, RectDouble *margin); + + +/************************************************************************ + * DocumentProperties native support + */ + +/* Values must match those defined in WPrinterJob.java */ +static const DWORD SET_COLOR = 0x00000200; +static const DWORD SET_ORIENTATION = 0x00004000; +static const DWORD SET_COLLATED = 0x00008000; +static const DWORD SET_DUP_VERTICAL = 0x00000010; +static const DWORD SET_DUP_HORIZONTAL = 0x00000020; +static const DWORD SET_RES_HIGH = 0x00000040; +static const DWORD SET_RES_LOW = 0x00000080; + +/* + * Copy DEVMODE state back into JobAttributes. + */ + +static void UpdateJobAttributes(JNIEnv *env, + jobject wJob, + jobject attrSet, + DEVMODE *devmode) { + + DWORD dmValues = 0; + int xRes = 0, yRes = 0; + + if (devmode->dmFields & DM_COLOR) { + if (devmode->dmColor == DMCOLOR_COLOR) { + dmValues |= SET_COLOR; + } + } + + if (devmode->dmFields & DM_ORIENTATION) { + if (devmode->dmOrientation == DMORIENT_LANDSCAPE) { + dmValues |= SET_ORIENTATION; + } + } + + if (devmode->dmFields & DM_COLLATE && + devmode->dmCollate == DMCOLLATE_TRUE) { + dmValues |= SET_COLLATED; + } + + if (devmode->dmFields & DM_PRINTQUALITY) { + /* value < 0 indicates quality setting. + * value > 0 indicates X resolution. In that case + * hopefully we will also find y-resolution specified. + * If its not, assume its the same as x-res. + * Maybe Java code should try to reconcile this against + * the printers claimed set of supported resolutions. + */ + if (devmode->dmPrintQuality < 0) { + if (devmode->dmPrintQuality == DMRES_HIGH) { + dmValues |= SET_RES_HIGH; + } else if ((devmode->dmPrintQuality == DMRES_LOW) || + (devmode->dmPrintQuality == DMRES_DRAFT)) { + dmValues |= SET_RES_LOW; + } + /* else if (devmode->dmPrintQuality == DMRES_MEDIUM) + * will set to NORMAL. + */ + } else { + xRes = devmode->dmPrintQuality; + yRes = (devmode->dmFields & DM_YRESOLUTION) ? + devmode->dmYResolution : devmode->dmPrintQuality; + } + } + + if (devmode->dmFields & DM_DUPLEX) { + if (devmode->dmDuplex == DMDUP_HORIZONTAL) { + dmValues |= SET_DUP_HORIZONTAL; + } else if (devmode->dmDuplex == DMDUP_VERTICAL) { + dmValues |= SET_DUP_VERTICAL; + } + } + + env->CallVoidMethod(wJob, AwtPrintControl::setJobAttributesID, attrSet, + devmode->dmFields, dmValues, devmode->dmCopies, + devmode->dmPaperSize, devmode->dmPaperWidth, + devmode->dmPaperLength, devmode->dmDefaultSource, + xRes, yRes); + +} + +JNIEXPORT jboolean JNICALL +Java_sun_awt_windows_WPrinterJob_showDocProperties(JNIEnv *env, + jobject wJob, + jlong hWndParent, + jobject attrSet, + jint dmFields, + jshort copies, + jshort collate, + jshort color, + jshort duplex, + jshort orient, + jshort paper, + jshort bin, + jshort xres_quality, + jshort yres) +{ + TRY; + + HGLOBAL hDevMode = AwtPrintControl::getPrintHDMode(env, wJob); + HGLOBAL hDevNames = AwtPrintControl::getPrintHDName(env, wJob); + DEVMODE *devmode = NULL; + DEVNAMES *devnames = NULL; + LONG rval = IDCANCEL; + jboolean ret = JNI_FALSE; + + if (hDevMode != NULL && hDevNames != NULL) { + devmode = (DEVMODE *)::GlobalLock(hDevMode); + devnames = (DEVNAMES *)::GlobalLock(hDevNames); + + LPTSTR lpdevnames = (LPTSTR)devnames; + // No need to call _tcsdup as we won't unlock until we are done. + LPTSTR printerName = lpdevnames+devnames->wDeviceOffset; + LPTSTR portName = lpdevnames+devnames->wOutputOffset; + + HANDLE hPrinter; + if (::OpenPrinter(printerName, &hPrinter, NULL) == TRUE) { + devmode->dmFields |= dmFields; + devmode->dmCopies = copies; + devmode->dmCollate = collate; + devmode->dmColor = color; + devmode->dmDuplex = duplex; + devmode->dmOrientation = orient; + devmode->dmPrintQuality = xres_quality; + devmode->dmYResolution = yres; + devmode->dmPaperSize = paper; + devmode->dmDefaultSource = bin; + + rval = ::DocumentProperties((HWND)hWndParent, + hPrinter, printerName, devmode, devmode, + DM_IN_BUFFER | DM_OUT_BUFFER | DM_IN_PROMPT); + if (rval == IDOK) { + UpdateJobAttributes(env, wJob, attrSet, devmode); + ret = JNI_TRUE; + } + VERIFY(::ClosePrinter(hPrinter)); + } + ::GlobalUnlock(hDevNames); + ::GlobalUnlock(hDevMode); + } + + return ret; + + CATCH_BAD_ALLOC_RET(0); +} + /************************************************************************ * WPageDialog native methods */ @@ -732,7 +882,6 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self, memset(&pd, 0, sizeof(PRINTDLG)); pd.lStructSize = sizeof(PRINTDLG); pd.Flags = PD_RETURNDEFAULT | PD_RETURNDC; - if (::PrintDlg(&pd)) { printDC = pd.hDC; hDevMode = pd.hDevMode; @@ -792,8 +941,19 @@ Java_sun_awt_windows_WPrinterJob_validatePaper(JNIEnv *env, jobject self, jint imgPixelWid = GetDeviceCaps(printDC, HORZRES); jint imgPixelHgt = GetDeviceCaps(printDC, VERTRES); + // The DC may be obtained when we first selected the printer as a + // result of a call to setNativePrintService. + // If the Devmode was obtained later on from the DocumentProperties dialog + // the DC won't have been updated and its settings may be for PORTRAIT. + // This may happen in other cases too, but was observed for the above. + // To get a DC compatible with this devmode we should really call + // CreateDC() again to get a DC for the devmode we are using. + // The changes for that are a lot more risk, so to minimise that + // risk, assume its not LANDSCAPE unless width > height, even if the + // devmode says its LANDSCAPE. // if the values were obtained from a rotated device, swap. - if (getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) { + if ((getOrientationFromDevMode2(hDevMode) == DMORIENT_LANDSCAPE) && + (imgPixelWid > imgPixelHgt)) { jint tmp; tmp = xPixelRes; xPixelRes = yPixelRes; @@ -941,6 +1101,9 @@ Java_sun_awt_windows_WPrinterJob_initPrinter(JNIEnv *env, jobject self) { setBooleanField(env, self, DRIVER_COLLATE_STR, JNI_FALSE); } + if (dmFields & DM_COPIES) { + setBooleanField(env, self, DRIVER_COPIES_STR, JNI_TRUE); + } } CATCH_BAD_ALLOC; diff --git a/jdk/test/ProblemList.txt b/jdk/test/ProblemList.txt index 1ac61aa2c3f..90ac26d0f69 100644 --- a/jdk/test/ProblemList.txt +++ b/jdk/test/ProblemList.txt @@ -166,6 +166,13 @@ demo/jvmti/hprof/MonitorTest.java generic-all # 8021186 jdk/lambda/vm/DefaultMethodsTest.java generic-all +# 8024423 - JVMTI: GetLoadedClasses doesn't enumerate anonymous classes +demo/jvmti/hprof/HeapAllTest.java generic-all +demo/jvmti/hprof/HeapBinaryFormatTest.java generic-all +demo/jvmti/hprof/HeapDumpTest.java generic-all +demo/jvmti/hprof/OptionsTest.java generic-all +demo/jvmti/hprof/StackMapTableTest.java generic-all + ############################################################################ # jdk_net diff --git a/jdk/test/com/sun/jdi/ExceptionEvents.java b/jdk/test/com/sun/jdi/ExceptionEvents.java index 88633b6fcde..42a532e4c44 100644 --- a/jdk/test/com/sun/jdi/ExceptionEvents.java +++ b/jdk/test/com/sun/jdi/ExceptionEvents.java @@ -417,8 +417,12 @@ public class ExceptionEvents extends TestScaffold { request = eventRequestManager().createExceptionRequest(exceptionClass, caught, uncaught); request.addClassExclusionFilter("java.*"); + request.addClassExclusionFilter("javax.*"); request.addClassExclusionFilter("sun.*"); request.addClassExclusionFilter("com.sun.*"); + request.addClassExclusionFilter("com.oracle.*"); + request.addClassExclusionFilter("oracle.*"); + request.addClassExclusionFilter("jdk.internal.*"); request.setSuspendPolicy(suspendPolicy); request.enable(); diff --git a/jdk/test/com/sun/jdi/FilterNoMatch.java b/jdk/test/com/sun/jdi/FilterNoMatch.java index 1feb8992f3a..3a8ecd2abdb 100644 --- a/jdk/test/com/sun/jdi/FilterNoMatch.java +++ b/jdk/test/com/sun/jdi/FilterNoMatch.java @@ -121,9 +121,13 @@ public class FilterNoMatch extends JDIScaffold { // We have to filter out all these so that they don't cause the // listener to be called. - request1.addClassExclusionFilter( "java.*"); - request1.addClassExclusionFilter( "com.*"); - request1.addClassExclusionFilter( "sun.*"); + request1.addClassExclusionFilter("java.*"); + request1.addClassExclusionFilter("javax.*"); + request1.addClassExclusionFilter("sun.*"); + request1.addClassExclusionFilter("com.sun.*"); + request1.addClassExclusionFilter("com.oracle.*"); + request1.addClassExclusionFilter("oracle.*"); + request1.addClassExclusionFilter("jdk.internal.*"); // We want our listener to be called if a pattern does not match. // So, here we want patterns that do not match HelloWorld. diff --git a/jdk/test/com/sun/jdi/JDIScaffold.java b/jdk/test/com/sun/jdi/JDIScaffold.java index e0a95dfbe09..0c60c0767dd 100644 --- a/jdk/test/com/sun/jdi/JDIScaffold.java +++ b/jdk/test/com/sun/jdi/JDIScaffold.java @@ -450,8 +450,12 @@ abstract public class JDIScaffold { requestManager.createStepRequest(thread, gran, depth); sr.addClassExclusionFilter("java.*"); + sr.addClassExclusionFilter("javax.*"); sr.addClassExclusionFilter("sun.*"); sr.addClassExclusionFilter("com.sun.*"); + sr.addClassExclusionFilter("com.oracle.*"); + sr.addClassExclusionFilter("oracle.*"); + sr.addClassExclusionFilter("jdk.internal.*"); sr.addCountFilter(1); sr.enable(); StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr); diff --git a/jdk/test/com/sun/jdi/MethodEntryExitEvents.java b/jdk/test/com/sun/jdi/MethodEntryExitEvents.java index a1c67cbfdd4..a14a63e3491 100644 --- a/jdk/test/com/sun/jdi/MethodEntryExitEvents.java +++ b/jdk/test/com/sun/jdi/MethodEntryExitEvents.java @@ -115,7 +115,7 @@ public class MethodEntryExitEvents extends TestScaffold { */ private String[] excludes = {"java.*", "javax.*", "sun.*", "com.sun.*", "com.oracle.*", - "oracle.*"}; + "oracle.*", "jdk.internal.*"}; MethodEntryExitEvents (String args[]) { super(args); diff --git a/jdk/test/com/sun/jdi/PopAndStepTest.java b/jdk/test/com/sun/jdi/PopAndStepTest.java index c5487fe787d..76dc0f5038c 100644 --- a/jdk/test/com/sun/jdi/PopAndStepTest.java +++ b/jdk/test/com/sun/jdi/PopAndStepTest.java @@ -130,8 +130,12 @@ public class PopAndStepTest extends TestScaffold { StepRequest srInto = erm.createStepRequest(mainThread, StepRequest.STEP_LINE, StepRequest.STEP_INTO); srInto.addClassExclusionFilter("java.*"); + srInto.addClassExclusionFilter("javax.*"); srInto.addClassExclusionFilter("sun.*"); srInto.addClassExclusionFilter("com.sun.*"); + srInto.addClassExclusionFilter("com.oracle.*"); + srInto.addClassExclusionFilter("oracle.*"); + srInto.addClassExclusionFilter("jdk.internal.*"); srInto.addCountFilter(1); srInto.enable(); // This fails mainThread.popFrames(frameFor("A")); diff --git a/jdk/test/com/sun/jdi/RepStep.java b/jdk/test/com/sun/jdi/RepStep.java index 665dfb79845..80ce449b304 100644 --- a/jdk/test/com/sun/jdi/RepStep.java +++ b/jdk/test/com/sun/jdi/RepStep.java @@ -75,8 +75,12 @@ public class RepStep { DEPTH); sr.addClassExclusionFilter("java.*"); + sr.addClassExclusionFilter("javax.*"); sr.addClassExclusionFilter("sun.*"); sr.addClassExclusionFilter("com.sun.*"); + sr.addClassExclusionFilter("com.oracle.*"); + sr.addClassExclusionFilter("oracle.*"); + sr.addClassExclusionFilter("jdk.internal.*"); sr.enable(); } diff --git a/jdk/test/com/sun/jdi/TestScaffold.java b/jdk/test/com/sun/jdi/TestScaffold.java index 61f8e053eaf..5dc5640f91f 100644 --- a/jdk/test/com/sun/jdi/TestScaffold.java +++ b/jdk/test/com/sun/jdi/TestScaffold.java @@ -746,8 +746,12 @@ abstract public class TestScaffold extends TargetAdapter { requestManager.createStepRequest(thread, gran, depth); sr.addClassExclusionFilter("java.*"); + sr.addClassExclusionFilter("javax.*"); sr.addClassExclusionFilter("sun.*"); sr.addClassExclusionFilter("com.sun.*"); + sr.addClassExclusionFilter("com.oracle.*"); + sr.addClassExclusionFilter("oracle.*"); + sr.addClassExclusionFilter("jdk.internal.*"); sr.addCountFilter(1); sr.enable(); StepEvent retEvent = (StepEvent)waitForRequestedEvent(sr); @@ -829,7 +833,8 @@ abstract public class TestScaffold extends TargetAdapter { Method method = findMethod(rt, methodName, methodSignature); if (method == null) { - throw new IllegalArgumentException("Bad method name/signature"); + throw new IllegalArgumentException("Bad method name/signature: " + + clsName + "." + methodName + ":" + methodSignature); } return resumeTo(method.location()); 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/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/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/util/Map/Defaults.java b/jdk/test/java/util/Map/Defaults.java index 82470019048..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 @@ -288,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"); @@ -328,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"); @@ -414,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) { @@ -456,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, diff --git a/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java b/jdk/test/java/util/Spliterator/SpliteratorCharacteristics.java index 3c74ce29dc1..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 8012913 + * @bug 8020156 8020009 8022326 8012913 8024405 * @run testng SpliteratorCharacteristics */ @@ -36,21 +36,150 @@ 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 { + 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); @@ -199,10 +328,19 @@ public class SpliteratorCharacteristics { } void assertCharacteristics(Collection c, int expectedCharacteristics) { - assertTrue(c.spliterator().hasCharacteristics(expectedCharacteristics), + assertCharacteristics(c.spliterator(), expectedCharacteristics); + } + + void assertCharacteristics(Spliterator s, int expectedCharacteristics) { + assertTrue(s.hasCharacteristics(expectedCharacteristics), "Spliterator characteristics"); } + void assertHasNotCharacteristics(Spliterator s, int expectedCharacteristics) { + assertFalse(s.hasCharacteristics(expectedCharacteristics), + "Spliterator characteristics"); + } + void assertNullComparator(Collection c) { assertNull(c.spliterator().getComparator(), "Comparator of Spliterator of Collection"); 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/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/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/javax/imageio/plugins/jpeg/JpegWriterLeakTest.java b/jdk/test/javax/imageio/plugins/jpeg/JpegWriterLeakTest.java index ffb2b63b0b0..bb5fc06e99b 100644 --- a/jdk/test/javax/imageio/plugins/jpeg/JpegWriterLeakTest.java +++ b/jdk/test/javax/imageio/plugins/jpeg/JpegWriterLeakTest.java @@ -23,7 +23,7 @@ /** * @test - * @bug 8020983 + * @bug 8020983 8024697 * @summary Test verifies that jpeg writer instances are collected * even if destroy() or reset() methods is not invoked. * diff --git a/jdk/test/javax/management/MBeanInfo/MBeanInfoEqualsNPETest.java b/jdk/test/javax/management/MBeanInfo/MBeanInfoEqualsNPETest.java new file mode 100644 index 00000000000..440878c37f3 --- /dev/null +++ b/jdk/test/javax/management/MBeanInfo/MBeanInfoEqualsNPETest.java @@ -0,0 +1,216 @@ +/* + * 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.MBeanFeatureInfo; +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 8023954 + * @summary Test that MBean*Info.equals do not throw NPE + * @author Shanliang JIANG + * @run clean MBeanInfoEqualsNPETest + * @run build MBeanInfoEqualsNPETest + * @run main MBeanInfoEqualsNPETest + */ +public class MBeanInfoEqualsNPETest { + private static int failed = 0; + + public static void main(String[] args) throws Exception { + System.out.println("---MBeanInfoEqualsNPETest-main ..."); + + // ---- + System.out.println("\n---Testing on MBeanAttributeInfo..."); + MBeanAttributeInfo mbeanAttributeInfo0 = new MBeanAttributeInfo( + "name", SimpleType.INTEGER.getClassName(), "description", true, true, false); + MBeanAttributeInfo mbeanAttributeInfo = new MBeanAttributeInfo( + null, SimpleType.INTEGER.getClassName(), "description", true, true, false); + test(mbeanAttributeInfo0, mbeanAttributeInfo, "class name"); + + mbeanAttributeInfo = new MBeanAttributeInfo( + "name", null, "description", true, true, false); + test(mbeanAttributeInfo0, mbeanAttributeInfo, "type"); + + mbeanAttributeInfo = new MBeanAttributeInfo( + "name", SimpleType.INTEGER.getClassName(), null, true, true, false); + test(mbeanAttributeInfo0, mbeanAttributeInfo, "description"); + + // ---- + System.out.println("\n---Testing on MBeanConstructorInfo..."); + MBeanConstructorInfo mbeanConstructorInfo0 = new MBeanConstructorInfo( + "", "", new MBeanParameterInfo[]{}, new DescriptorSupport()); + MBeanConstructorInfo mbeanConstructorInfo = new MBeanConstructorInfo( + null, "", new MBeanParameterInfo[]{}, new DescriptorSupport()); + test(mbeanConstructorInfo0, mbeanConstructorInfo, "name"); + + mbeanConstructorInfo = new MBeanConstructorInfo( + "", null, new MBeanParameterInfo[]{}, new DescriptorSupport()); + test(mbeanConstructorInfo0, mbeanConstructorInfo, "description"); + + mbeanConstructorInfo = new MBeanConstructorInfo( + "", "", null, new DescriptorSupport()); + test(mbeanConstructorInfo0, mbeanConstructorInfo, "MBeanParameterInfo"); + + mbeanConstructorInfo = new MBeanConstructorInfo( + "", "", new MBeanParameterInfo[]{}, null); + test(mbeanConstructorInfo0, mbeanConstructorInfo, "descriptor"); + + // ---- + System.out.println("\n---Testing on MBeanOperationInfo..."); + MBeanOperationInfo mbeanOperationInfo0 = new MBeanOperationInfo( + "name", "description", new MBeanParameterInfo[]{}, "type", + MBeanOperationInfo.UNKNOWN, new DescriptorSupport()); + + MBeanOperationInfo mbeanOperationInfo = new MBeanOperationInfo( + null, "description", new MBeanParameterInfo[]{}, "type", + MBeanOperationInfo.UNKNOWN, new DescriptorSupport()); + test(mbeanOperationInfo0, mbeanOperationInfo, "name"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", null, new MBeanParameterInfo[]{}, "type", + MBeanOperationInfo.UNKNOWN, new DescriptorSupport()); + test(mbeanOperationInfo0, mbeanOperationInfo, "description"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", null, "type", 1, new DescriptorSupport()); + test(mbeanOperationInfo0, mbeanOperationInfo, "MBeanParameterInfo"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", new MBeanParameterInfo[]{}, null, + MBeanOperationInfo.UNKNOWN, new DescriptorSupport()); + test(mbeanOperationInfo0, mbeanOperationInfo, "type"); + + mbeanOperationInfo = new MBeanOperationInfo( + "name", "description", new MBeanParameterInfo[]{}, null, + MBeanOperationInfo.UNKNOWN, null); + test(mbeanOperationInfo0, mbeanOperationInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on MBeanParameterInfo..."); + MBeanParameterInfo mbeanParameterInfo0 = new MBeanParameterInfo( + "name", "type", "description", new DescriptorSupport()); + MBeanParameterInfo mbeanParameterInfo = new MBeanParameterInfo( + null, "type", "description", new DescriptorSupport()); + test(mbeanParameterInfo0, mbeanParameterInfo, "name"); + + mbeanParameterInfo = new MBeanParameterInfo( + "name", null, "description", new DescriptorSupport()); + test(mbeanParameterInfo0, mbeanParameterInfo, "type"); + + mbeanParameterInfo = new MBeanParameterInfo( + "name", "type", null, new DescriptorSupport()); + test(mbeanParameterInfo0, mbeanParameterInfo, "description"); + + mbeanParameterInfo = new MBeanParameterInfo( + "name", "type", "description", null); + test(mbeanParameterInfo0, mbeanParameterInfo, "Descriptor"); + + // ---- + System.out.println("\n---Testing on MBeanFeatureInfo ..."); + MBeanFeatureInfo mbeanFeatureInfo0 = new MBeanFeatureInfo( + "name", "description", new DescriptorSupport()); + MBeanFeatureInfo mbeanFeatureInfo = new MBeanFeatureInfo( + null, "description", new DescriptorSupport()); + test(mbeanFeatureInfo0, mbeanFeatureInfo, "name"); + + mbeanFeatureInfo = new MBeanFeatureInfo( + "name", null, new DescriptorSupport()); + test(mbeanParameterInfo0, mbeanParameterInfo, "description"); + + mbeanFeatureInfo = new MBeanFeatureInfo( + "name", "description", null); + test(mbeanParameterInfo0, 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 minfo0 = new MBeanInfo("toto", description, attrInfos, constrInfos, operaInfos, notifInfos); + MBeanInfo minfo = new MBeanInfo(null, description, attrInfos, constrInfos, operaInfos, notifInfos); + test(minfo0, minfo, "class name"); + + minfo = new MBeanInfo(className, null, attrInfos, constrInfos, operaInfos, notifInfos); + test(minfo0, minfo, "description"); + + minfo = new MBeanInfo(className, description, null, constrInfos, operaInfos, notifInfos); + test(minfo0, minfo, "attrInfos"); + + minfo = new MBeanInfo(className, description, attrInfos, null, operaInfos, notifInfos); + test(minfo0, minfo, "constrInfos"); + + minfo = new MBeanInfo(className, description, attrInfos, constrInfos, null, notifInfos); + test(minfo0, minfo, "operaInfos"); + + minfo = new MBeanInfo(className, description, attrInfos, constrInfos, operaInfos, null); + test(minfo0, minfo, "notifInfos"); + + 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 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/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 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/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/langtools/.hgtags b/langtools/.hgtags index 221777df498..f3ac2a1e9ab 100644 --- a/langtools/.hgtags +++ b/langtools/.hgtags @@ -227,3 +227,5 @@ ce5a90df517bdceb2739d7dd3e6764b070def802 jdk8-b98 76cfe7c61f2575ea5400845b8e80dab6f4b1d7d0 jdk8-b103 dd4a00c220c6e14d9b2ce93a2bd436a1d04f0d03 jdk8-b104 375834b5cf086dd7ce9e49f602d81bb51d3e0fa9 jdk8-b105 +fcd768844b9926c5f994292ec6350c20cc7c0f76 jdk8-b106 +3f274927ec1863544b8214262ab02b7de2970da6 jdk8-b107 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/netbeans/langtools/build.xml b/langtools/make/netbeans/langtools/build.xml index dd2caf9e3bc..cbb007057cc 100644 --- a/langtools/make/netbeans/langtools/build.xml +++ b/langtools/make/netbeans/langtools/build.xml @@ -1,6 +1,6 @@ @@ -136,9 +145,9 @@ - + - + @@ -207,6 +216,7 @@ @@ -216,6 +226,7 @@ @@ -226,10 +237,12 @@ + + - + diff --git a/langtools/make/tools/anttasks/SelectToolTask.java b/langtools/make/tools/anttasks/SelectToolTask.java index fb2cf49e312..5897398d173 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,31 @@ 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 boostrap) { + this.toolName = toolName; + } + + @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 +122,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 +144,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 +158,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 +171,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 +197,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 +239,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 +320,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/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/AnnotationTypeWriterImpl.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/AnnotationTypeWriterImpl.java index 869bc75f89c..c1c4c9d40e6 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 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..da36fedcff0 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 @@ -406,10 +406,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 +499,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 +517,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/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/HtmlWriter.java b/langtools/src/share/classes/com/sun/tools/doclets/formats/html/markup/HtmlWriter.java index 5369733893b..36becd2e7ef 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. * 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/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/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/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/code/DeferredLintHandler.java b/langtools/src/share/classes/com/sun/tools/javac/code/DeferredLintHandler.java index 022681bd8f6..9392046bb2d 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 = ListBuffer.lb()); + } + 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..3a4084ed2a8 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 @@ -266,6 +265,11 @@ public class Flags { */ 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/Symbol.java b/langtools/src/share/classes/com/sun/tools/javac/code/Symbol.java index 64c117cb2bc..65459ec3daf 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; } @@ -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/Types.java b/langtools/src/share/classes/com/sun/tools/javac/code/Types.java index 06744bf6d06..0d060b60bb7 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 @@ -3055,7 +3055,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() && 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..cb2337f936c 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 @@ -748,19 +748,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 +760,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 +1003,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 +1033,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 +1047,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 +1095,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(); { @@ -2319,30 +2308,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 +2372,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 +2392,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 +2407,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); @@ -2604,10 +2584,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 +2603,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 +2638,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()) { @@ -3731,7 +3712,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 +3801,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); } } @@ -4206,6 +4198,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 && 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..5f6d1886bd8 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 @@ -1050,6 +1041,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 +1062,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 +1074,7 @@ public class Check { } else { mask = implicit = InterfaceMethodFlags; } - } - else { + } else { mask = MethodFlags; } // Imply STRICTFP if owner has STRICTFP set. @@ -2368,7 +2362,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 +2403,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); + } + } } } @@ -2496,6 +2496,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 +3331,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..4db110579f7 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 = ListBuffer.lb(); + 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/Flow.java b/langtools/src/share/classes/com/sun/tools/javac/comp/Flow.java index e488d45b0c0..252124370e5 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) { @@ -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) { @@ -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(); 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(); 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..4c9568eb32c 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); @@ -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,8 +1825,8 @@ 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(); } }); } @@ -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..b2a501d27d6 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 @@ -1745,6 +1745,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) { 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..cb054fe80f2 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); @@ -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..634e875d5aa 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 @@ -84,6 +84,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { 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); @@ -109,6 +110,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { source = Source.instance(context); target = Target.instance(context); deferredLintHandler = DeferredLintHandler.instance(context); + lint = Lint.instance(context); allowTypeAnnos = source.allowTypeAnnotations(); } @@ -506,9 +508,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 +520,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 +568,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 +576,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 +600,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 +633,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 +660,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } } } finally { - chk.setDeferredLintHandler(prevLintHandler); + deferredLintHandler.setPos(prevLintPos); } if ((tree.mods.flags & VARARGS) != 0) { @@ -680,15 +682,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 +721,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 +736,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 +832,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 +850,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 +863,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 +985,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 +1007,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 +1070,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 +1078,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 +1148,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer { } catch (CompletionFailure ex) { chk.completionError(tree.pos(), ex); } finally { + deferredLintHandler.setPos(prevLintPos); log.useSource(prev); } @@ -1186,9 +1209,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 +1222,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 +1235,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 +1245,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 +1296,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 +1572,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 +1581,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..e3c427413ec 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 @@ -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; } @@ -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; }}); @@ -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..d747a2b5156 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; } 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..d3d9d302f1e 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 @@ -72,7 +72,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 +234,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 +275,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 @@ -727,12 +738,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 +810,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 '/': @@ -2310,7 +2330,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 +2400,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 +2621,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..6698c7fde27 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. * @@ -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..d0ed7ec559c 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) { @@ -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..ba369172f43 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 @@ -80,7 +80,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 +310,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 +385,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); 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/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/TreeMaker.java b/langtools/src/share/classes/com/sun/tools/javac/tree/TreeMaker.java index b94dd5f8a4f..4e6ef7ba6ff 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 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..aa9899ed210 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; @@ -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) { @@ -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..dee69807e2c 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 @@ -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 = ListBuffer.lb(); + 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) { 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/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/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/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:
    " + - "
    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/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/testProfiles/TestProfiles.java b/langtools/test/com/sun/javadoc/testProfiles/TestProfiles.java index 7d878d7ecd3..8dda141791c 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 * @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 = { @@ -143,12 +189,12 @@ public class TestProfiles extends JavadocTester { private static final String[][] PACKAGES_NEGATED_TEST = { {PACKAGE_BUG_ID + FS + "profile-overview-frame.html", "All Packages" + + "target=\"packageListFrame\">All Packages" }, {PACKAGE_BUG_ID + FS + "compact2-frame.html", "" - + "All PackagesAll Profiles" + + "All PackagesAll Profiles" }, {PACKAGE_BUG_ID + FS + "pkg2" + FS + "compact2-package-frame.html", "" @@ -163,7 +209,7 @@ public class TestProfiles extends JavadocTester { }, {PACKAGE_BUG_ID + FS + "overview-frame.html", "All Profiles" + + "target=\"packageListFrame\">All Profiles" }, {PACKAGE_BUG_ID + FS + "pkg2" + FS + "Class1Pkg2.html", "
    compact1, compact2, compact3
    " 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/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/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/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..0dd25871f3a --- /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_langth == 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/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/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/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..7794ded19dd --- /dev/null +++ b/langtools/test/tools/javac/flow/LVTHarness.java @@ -0,0 +1,280 @@ +/* + * 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; + +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 { + fm.setLocation(SOURCE_PATH, + Arrays.asList(new File(System.getProperty("test.src"), "tests"))); + for (JavaFileObject jfo : fm.list(SOURCE_PATH, "", + Collections.singleton(JavaFileObject.Kind.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.toString()); + ct.setProcessors(Collections.singleton(new AliveRangeFinder())); + if (!ct.call()) { + throw new AssertionError("Error during compilation"); + } + + checkClassFile(new File(jfo.getName().replace(".java", ".class"))); + + //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..205ff9eefdc --- /dev/null +++ b/langtools/test/tools/javac/lambda/8023558/T8023558a.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. + */ + +/* + * @test + * @bug 8023558 + * @summary Javac creates invalid bootstrap methods for complex lambda/methodref case + */ +public class T8023558a { + interface SAM { + T get(); + } + + public static void main(String[] args) { + SAM sam = new SAM() { public SAM get() { return null; } }; + 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/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/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/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/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/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/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
    Bug id:" diff --git a/nashorn/.hgtags b/nashorn/.hgtags index 14ef8a6ccb7..05fbb43822b 100644 --- a/nashorn/.hgtags +++ b/nashorn/.hgtags @@ -215,3 +215,5 @@ e966ff0a3ffef8a687eaf5a14167bb595b623d02 jdk8-b102 414203de4374e1964a9918c38a95fb245010a9f1 jdk8-b103 afc100513451d22f0b8135999d6eb52f36df3d36 jdk8-b104 f484bfb624dd06683cb33b524700a5dd4927a82b jdk8-b105 +bf70cbd2c8369fd97ffdfcbe1a80dbc2797408ee jdk8-b106 +f35e1255024b66f7cf82517798f45f6e194e5567 jdk8-b107 diff --git a/nashorn/make/build.xml b/nashorn/make/build.xml index 9a31be88592..73644a6b523 100644 --- a/nashorn/make/build.xml +++ b/nashorn/make/build.xml @@ -230,6 +230,10 @@ + + + + @@ -238,6 +242,7 @@ + @@ -264,6 +269,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"; }; 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..45eddd117aa 100644 --- a/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java +++ b/nashorn/src/jdk/nashorn/api/scripting/NashornScriptEngine.java @@ -315,7 +315,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 +326,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 +394,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; } @@ -470,7 +470,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 +481,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 +494,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) { @@ -617,4 +617,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..813d3fc9083 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"; @@ -886,10 +910,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 +998,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 +1600,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 +1697,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..809b2ec21e2 100644 --- a/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java +++ b/nashorn/src/jdk/nashorn/internal/codegen/CodeGenerator.java @@ -1361,6 +1361,7 @@ 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 +1370,9 @@ final class CodeGenerator extends NodeOperatorVisitor * * @return true if can have callsite type */ diff --git a/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java b/nashorn/src/jdk/nashorn/internal/ir/debug/JSONWriter.java index be4d49b444a..dabc7e36bf1 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,41 @@ 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"); + if (functionNode.isAnonymous()) { + 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 +754,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 +808,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 +828,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 +851,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 +873,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 +912,7 @@ public final class JSONWriter extends NodeVisitor { whileNode.getTest().accept(this); comma(); - property("block"); + property("body"); whileNode.getBody().accept(this); } @@ -894,23 +951,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..b7a902b745e 100644 --- a/nashorn/src/jdk/nashorn/internal/objects/Global.java +++ b/nashorn/src/jdk/nashorn/internal/objects/Global.java @@ -412,6 +412,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 +447,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 +489,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) { @@ -1765,7 +1783,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/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/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/parser/Parser.java b/nashorn/src/jdk/nashorn/internal/parser/Parser.java index ab008900f50..d051917149e 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; @@ -115,6 +114,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 +512,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 +2067,7 @@ loop: case FLOATING: return getLiteral(); default: - return getIdentifierName(); + return getIdentifierName().setIsPropertyName(); } } @@ -2449,7 +2456,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 +2475,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 +2493,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/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/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..5115e2ce0c7 100644 --- a/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties +++ b/nashorn/src/jdk/nashorn/internal/runtime/resources/Messages.properties @@ -110,6 +110,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/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..067c506ab95 --- /dev/null +++ b/nashorn/test/script/basic/parser/objectLitExpr.js.EXPECTED @@ -0,0 +1,189 @@ +{ + "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": { + "type": "Identifier", + "name": "get x" + }, + "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": { + "type": "Identifier", + "name": "get y" + }, + "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/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/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);