- 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/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/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/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/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/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/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/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/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/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/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 extends ICC_Profile> 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/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