This commit is contained in:
J. Duke 2017-07-05 20:06:54 +02:00
commit 75a2a53eb5
253 changed files with 7404 additions and 2306 deletions

View File

@ -280,3 +280,4 @@ e4ba01b726e263953ae129be37c94de6ed145b1d jdk9-b33
c173ba994245380fb11ef077d1e59823386840eb jdk9-b35
201d4e235d597a25a2d3ee1404394789ba386119 jdk9-b36
723a67b0c442391447b1d8aad8b249d06d1032e8 jdk9-b37
d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38

View File

@ -684,8 +684,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
AC_SUBST(CONF_NAME, $CONF_NAME)
AC_SUBST(OUTPUT_ROOT, $OUTPUT_ROOT)
# Most of the probed defines are put into config.h
AC_CONFIG_HEADERS([$OUTPUT_ROOT/config.h:$AUTOCONF_DIR/config.h.in])
# The spec.gmk file contains all variables for the make system.
AC_CONFIG_FILES([$OUTPUT_ROOT/spec.gmk:$AUTOCONF_DIR/spec.gmk.in])
# The hotspot-spec.gmk file contains legacy variables for the hotspot make system.
@ -694,8 +692,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_OUTPUT_DIR],
AC_CONFIG_FILES([$OUTPUT_ROOT/bootcycle-spec.gmk:$AUTOCONF_DIR/bootcycle-spec.gmk.in])
# The compare.sh is used to compare the build output to other builds.
AC_CONFIG_FILES([$OUTPUT_ROOT/compare.sh:$AUTOCONF_DIR/compare.sh.in])
# Spec.sh is currently used by compare-objects.sh
AC_CONFIG_FILES([$OUTPUT_ROOT/spec.sh:$AUTOCONF_DIR/spec.sh.in])
# The generated Makefile knows where the spec.gmk is and where the source is.
# You can run make from the OUTPUT_ROOT, or from the top-level Makefile
# which will look for generated configurations

File diff suppressed because it is too large Load Diff

View File

@ -131,7 +131,7 @@ yum_help() {
pulse)
PKGHANDLER_COMMAND="sudo yum install pulseaudio-libs-devel" ;;
x11)
PKGHANDLER_COMMAND="sudo yum install libXtst-devel libXt-devel libXrender-devel" ;;
PKGHANDLER_COMMAND="sudo yum install libXtst-devel libXt-devel libXrender-devel libXi-devel" ;;
ccache)
PKGHANDLER_COMMAND="sudo yum install ccache" ;;
esac

View File

@ -91,85 +91,93 @@ AC_DEFUN_ONCE([LIB_SETUP_X11],
# Check for X Windows
#
# Check if the user has specified sysroot, but not --x-includes or --x-libraries.
# Make a simple check for the libraries at the sysroot, and setup --x-includes and
# --x-libraries for the sysroot, if that seems to be correct.
if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
if test "x$SYSROOT" != "x"; then
if test "x$x_includes" = xNONE; then
if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
x_includes="$SYSROOT/usr/X11R6/include"
elif test -f "$SYSROOT/usr/include/X11/Xlib.h"; then
x_includes="$SYSROOT/usr/include"
if test "x$X11_NOT_NEEDED" = xyes; then
if test "x${with_x}" != x; then
AC_MSG_WARN([X11 is not used, so --with-x is ignored])
fi
X_CFLAGS=
X_LIBS=
else
# Check if the user has specified sysroot, but not --x-includes or --x-libraries.
# Make a simple check for the libraries at the sysroot, and setup --x-includes and
# --x-libraries for the sysroot, if that seems to be correct.
if test "x$OPENJDK_TARGET_OS" = "xlinux"; then
if test "x$SYSROOT" != "x"; then
if test "x$x_includes" = xNONE; then
if test -f "$SYSROOT/usr/X11R6/include/X11/Xlib.h"; then
x_includes="$SYSROOT/usr/X11R6/include"
elif test -f "$SYSROOT/usr/include/X11/Xlib.h"; then
x_includes="$SYSROOT/usr/include"
fi
fi
fi
if test "x$x_libraries" = xNONE; then
if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
x_libraries="$SYSROOT/usr/X11R6/lib"
elif test "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
x_libraries="$SYSROOT/usr/lib64"
elif test -f "$SYSROOT/usr/lib/libX11.so"; then
x_libraries="$SYSROOT/usr/lib"
if test "x$x_libraries" = xNONE; then
if test -f "$SYSROOT/usr/X11R6/lib/libX11.so"; then
x_libraries="$SYSROOT/usr/X11R6/lib"
elif test "$SYSROOT/usr/lib64/libX11.so" && test "x$OPENJDK_TARGET_CPU_BITS" = x64; then
x_libraries="$SYSROOT/usr/lib64"
elif test -f "$SYSROOT/usr/lib/libX11.so"; then
x_libraries="$SYSROOT/usr/lib"
fi
fi
fi
fi
fi
# Now let autoconf do it's magic
AC_PATH_X
AC_PATH_XTRA
# Now let autoconf do it's magic
AC_PATH_X
AC_PATH_XTRA
# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling
# this doesn't make sense so we remove it.
if test "x$COMPILE_TYPE" = xcross; then
X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[[^ ]]*//g'`
fi
# AC_PATH_XTRA creates X_LIBS and sometimes adds -R flags. When cross compiling
# this doesn't make sense so we remove it.
if test "x$COMPILE_TYPE" = xcross; then
X_LIBS=`$ECHO $X_LIBS | $SED 's/-R \{0,1\}[[^ ]]*//g'`
fi
if test "x$no_x" = xyes && test "x$X11_NOT_NEEDED" != xyes; then
HELP_MSG_MISSING_DEPENDENCY([x11])
AC_MSG_ERROR([Could not find X11 libraries. $HELP_MSG])
fi
if test "x$no_x" = xyes; then
HELP_MSG_MISSING_DEPENDENCY([x11])
AC_MSG_ERROR([Could not find X11 libraries. $HELP_MSG])
fi
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
OPENWIN_HOME="/usr/openwin"
X_CFLAGS="-I$SYSROOT$OPENWIN_HOME/include -I$SYSROOT$OPENWIN_HOME/include/X11/extensions"
X_LIBS="-L$SYSROOT$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
-L$SYSROOT$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR \
-R$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
-R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR"
fi
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
OPENWIN_HOME="/usr/openwin"
X_CFLAGS="-I$SYSROOT$OPENWIN_HOME/include -I$SYSROOT$OPENWIN_HOME/include/X11/extensions"
X_LIBS="-L$SYSROOT$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
-L$SYSROOT$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR \
-R$OPENWIN_HOME/sfw/lib$OPENJDK_TARGET_CPU_ISADIR \
-R$OPENWIN_HOME/lib$OPENJDK_TARGET_CPU_ISADIR"
fi
AC_LANG_PUSH(C)
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $SYSROOT_CFLAGS $X_CFLAGS"
AC_LANG_PUSH(C)
OLD_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS $SYSROOT_CFLAGS $X_CFLAGS"
# Need to include Xlib.h and Xutil.h to avoid "present but cannot be compiled" warnings on Solaris 10
AC_CHECK_HEADERS([X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h],
[X11_A_OK=yes],
[X11_A_OK=no; break],
[
# include <X11/Xlib.h>
# include <X11/Xutil.h>
]
)
# Need to include Xlib.h and Xutil.h to avoid "present but cannot be compiled" warnings on Solaris 10
AC_CHECK_HEADERS([X11/extensions/shape.h X11/extensions/Xrender.h X11/extensions/XTest.h X11/Intrinsic.h],
[X11_HEADERS_OK=yes],
[X11_HEADERS_OK=no; break],
[
# include <X11/Xlib.h>
# include <X11/Xutil.h>
]
)
# If XLinearGradient isn't available in Xrender.h, signal that it needs to be
# defined in libawt_xawt.
AC_MSG_CHECKING([if XlinearGradient is defined in Xrender.h])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <X11/extensions/Xrender.h>]],
[[XLinearGradient x;]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
X_CFLAGS="$X_CFLAGS -DSOLARIS10_NO_XRENDER_STRUCTS"])
if test "x$X11_HEADERS_OK" = xno; then
HELP_MSG_MISSING_DEPENDENCY([x11])
AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h XTest.h Intrinsic.h). $HELP_MSG])
fi
CFLAGS="$OLD_CFLAGS"
AC_LANG_POP(C)
# If XLinearGradient isn't available in Xrender.h, signal that it needs to be
# defined in libawt_xawt.
AC_MSG_CHECKING([if XlinearGradient is defined in Xrender.h])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <X11/extensions/Xrender.h>]],
[[XLinearGradient x;]])],
[AC_MSG_RESULT([yes])],
[AC_MSG_RESULT([no])
X_CFLAGS="$X_CFLAGS -DSOLARIS10_NO_XRENDER_STRUCTS"])
if test "x$X11_A_OK" = xno && test "x$X11_NOT_NEEDED" != xyes; then
HELP_MSG_MISSING_DEPENDENCY([x11])
AC_MSG_ERROR([Could not find all X11 headers (shape.h Xrender.h XTest.h Intrinsic.h). $HELP_MSG])
fi
CFLAGS="$OLD_CFLAGS"
AC_LANG_POP(C)
fi # X11_NOT_NEEDED
AC_SUBST(X_CFLAGS)
AC_SUBST(X_LIBS)
@ -264,7 +272,7 @@ AC_DEFUN([LIB_BUILD_FREETYPE],
fi
# Now check if configure found a version of 'msbuild.exe'
if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then
AC_MSG_WARN([Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src])
AC_MSG_WARN([Can not find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src])
BUILD_FREETYPE=no
fi
@ -335,27 +343,50 @@ AC_DEFUN([LIB_CHECK_POTENTIAL_FREETYPE],
POTENTIAL_FREETYPE_LIB_PATH="$2"
METHOD="$3"
# First check if the files exists.
if test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
# We found an arbitrary include file. That's a good sign.
AC_MSG_NOTICE([Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD])
FOUND_FREETYPE=yes
# Let's start with an optimistic view of the world :-)
FOUND_FREETYPE=yes
FREETYPE_LIB_NAME="${LIBRARY_PREFIX}freetype${SHARED_LIBRARY_SUFFIX}"
if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location.])
# First look for the canonical freetype main include file ft2build.h.
if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
# Oh no! Let's try in the freetype2 directory. This is needed at least at Mac OS X Yosemite.
POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH/freetype2"
if ! test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then
# Fail.
FOUND_FREETYPE=no
fi
fi
if test "x$FOUND_FREETYPE" = xyes; then
# Include file found, let's continue the sanity check.
AC_MSG_NOTICE([Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD])
# Reset to default value
FREETYPE_BASE_NAME=freetype
FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then
if test "x$OPENJDK_TARGET_OS" = xmacosx \
&& test -s "$POTENTIAL_FREETYPE_LIB_PATH/${LIBRARY_PREFIX}freetype.6${SHARED_LIBRARY_SUFFIX}"; then
# On Mac OS X Yosemite, the symlink from libfreetype.dylib to libfreetype.6.dylib disappeared. Check
# for the .6 version explicitly.
FREETYPE_BASE_NAME=freetype.6
FREETYPE_LIB_NAME="${LIBRARY_PREFIX}${FREETYPE_BASE_NAME}${SHARED_LIBRARY_SUFFIX}"
AC_MSG_NOTICE([Compensating for missing symlink by using version 6 explicitly])
else
AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location.])
FOUND_FREETYPE=no
fi
else
if test "x$OPENJDK_TARGET_OS" = xwindows; then
# On Windows, we will need both .lib and .dll file.
if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/freetype.lib"; then
AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location.])
if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib"; then
AC_MSG_NOTICE([Could not find $POTENTIAL_FREETYPE_LIB_PATH/${FREETYPE_BASE_NAME}.lib. Ignoring location.])
FOUND_FREETYPE=no
fi
elif test "x$OPENJDK_TARGET_OS" = xsolaris \
&& test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then
# Found lib in isa dir, use that instead.
POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR"
AC_MSG_NOTICE([Rewriting to use $POTENTIAL_FREETYPE_LIB_PATH instead])
fi
fi
fi
@ -392,6 +423,8 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
AC_ARG_ENABLE(freetype-bundling, [AS_HELP_STRING([--disable-freetype-bundling],
[disable bundling of the freetype library with the build result @<:@enabled on Windows or when using --with-freetype, disabled otherwise@:>@])])
# Need to specify explicitly since it needs to be overridden on some versions of macosx
FREETYPE_BASE_NAME=freetype
FREETYPE_CFLAGS=
FREETYPE_LIBS=
FREETYPE_BUNDLE_LIB_PATH=
@ -575,9 +608,9 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
if test "x$FREETYPE_LIBS" = x; then
BASIC_FIXUP_PATH(FREETYPE_LIB_PATH)
if test "x$OPENJDK_TARGET_OS" = xwindows; then
FREETYPE_LIBS="$FREETYPE_LIB_PATH/freetype.lib"
FREETYPE_LIBS="$FREETYPE_LIB_PATH/$FREETYPE_BASE_NAME.lib"
else
FREETYPE_LIBS="-L$FREETYPE_LIB_PATH -lfreetype"
FREETYPE_LIBS="-L$FREETYPE_LIB_PATH -l$FREETYPE_BASE_NAME"
fi
fi

View File

@ -1,36 +0,0 @@
#
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
CAT="@CAT@"
CD=cd
CP="@CP@"
DIFF="@DIFF@"
ECHO="@ECHO@"
FIND="@FIND@"
GREP="@GREP@"
RM="@RM@"
SED="@SED@"
POST_STRIP_CMD="@POST_STRIP_CMD@"

View File

@ -1,77 +0,0 @@
#!/bin/bash
#
# 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.
#
# The boot_cycle.sh script performs two complete image builds (no javadoc though....)
# where the second build uses the first build as the boot jdk.
#
# This is useful to verify that the build is self hoisting and assists
# in flushing out bugs. You can follow up with compare_objects.sh to check
# that the two boot_cycle_?/images/j2sdk are identical. They should be.
#
# Usage:
# Specify the configure arguments to boot_cycle.sh, for example:
#
# sh common/bin/boot_cycle.sh --enable-debug --with-jvm-variants=server
#
# The same arguments will be used for both builds, except of course --with-boot-jdk
# that will be adjusted to boot_cycle_1 for the second build.
SCRIPT_DIR=`pwd`/`dirname $0`
ROOT_DIR=`(cd $SCRIPT_DIR/../.. ; pwd)`
BUILD_DIR=$ROOT_DIR/build
mkdir -p $BUILD_DIR
AUTOCONF_DIR=`(cd $SCRIPT_DIR/../autoconf ; pwd)`
BOOT_CYCLE_1_DIR=$BUILD_DIR/boot_cycle_1
BOOT_CYCLE_2_DIR=$BUILD_DIR/boot_cycle_2
# Create the boot cycle dirs in the build directory.
mkdir -p $BOOT_CYCLE_1_DIR
mkdir -p $BOOT_CYCLE_2_DIR
cd $BOOT_CYCLE_1_DIR
# Configure!
sh $AUTOCONF_DIR/configure "$@"
# Now build!
make images
if ! test -x $BOOT_CYCLE_1_DIR/images/j2sdk-image/bin/java ; then
echo Failed to build the executable $BOOT_CYCLE_1_DIR/images/j2sdk-image/bin/java
exit 1
fi
cd $BOOT_CYCLE_2_DIR
# Pickup the configure arguments, but drop any --with-boot-jdk=....
# and add the correct --with-boot-jdk=...boot_cycle_1... at the end.
ARGUMENTS="`cat $BOOT_CYCLE_1_DIR/configure-arguments|sed 's/--with-boot-jdk=[^ ]*//'` --with-boot-jdk=$BOOT_CYCLE_1_DIR/images/j2sdk-image"
# Configure using these adjusted arguments.
sh $AUTOCONF_DIR/configure $ARGUMENTS
# Now build!
make images
if ! test -x $BOOT_CYCLE_2_DIR/images/j2sdk-image/bin/java ; then
echo Failed to build the final executable $BOOT_CYCLE_2_DIR/images/j2sdk-image/bin/java
exit 1
fi

View File

@ -1,235 +0,0 @@
#!/bin/bash
#
# 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.
#
# MANUAL
#
# ./common/bin/compare-objects.sh old_jdk_build_dir new_jdk_build_dir
#
# Compares object files
#
if [ "x$1" = "x-h" ] || [ "x$1" = "x--help" ] || [ "x$1" == "x" ]; then
echo "bash ./common/bin/compare-objects.sh old_jdk_build_dir new_jdk_build_dir <pattern>"
echo ""
echo "Compare object files"
echo ""
exit 10
fi
#######
#
# List of files (grep patterns) that are ignored
#
# 1) hotspot object files
IGNORE="-e hotspot"
# 2) various build artifacts: sizer.32.o sizer.64.o dummyodbc.o
# these are produced during build and then e.g run to produce other data
# i.e not directly put into build => safe to ignore
IGNORE="${IGNORE} -e sizer.32.o -e sizer.64.o"
IGNORE="${IGNORE} -e dummyodbc.o"
IGNORE="${IGNORE} -e genSolarisConstants.o"
IGNORE="${IGNORE} -e genUnixConstants.o"
OLD="$1"
NEW="$2"
shift; shift
PATTERN="$*"
if [ -f $NEW/spec.sh ]; then
. $NEW/spec.sh
elif [ -f $NEW/../../spec.sh ]; then
. $NEW/../../spec.sh
elif [ -f $OLD/spec.sh ]; then
. $OLD/spec.sh
elif [ -f $OLD/../../spec.sh ]; then
. $OLD/../../spec.sh
else
echo "Unable to find spec.sh"
echo "Giving up"
exit 1
fi
export COMPARE_ROOT=/tmp/cimages.$USER/objects
mkdir -p $COMPARE_ROOT
(${CD} $OLD && ${FIND} . -name '*.o') > $COMPARE_ROOT/list.old
(${CD} $NEW && ${FIND} . -name '*.o') > $COMPARE_ROOT/list.new
# On macosx JobjC is build in both i386 and x86_64 variant (universial binary)
# but new build only builds the x86_64
# Remove the 386 variants from comparison...to avoid "false" positives
${GREP} -v 'JObjC.dst/Objects-normal/i386' $COMPARE_ROOT/list.old > $COMPARE_ROOT/list.old.new
${CP} $COMPARE_ROOT/list.old $COMPARE_ROOT/list.old.full
${CP} $COMPARE_ROOT/list.old.new $COMPARE_ROOT/list.old
findnew() {
arg_1=$1
arg_2=$2
# special case 1 unpack-cmd => unpackexe
arg_1=`${ECHO} $arg_1 | ${SED} 's!unpack-cmd!unpackexe!g'`
arg_2=`${ECHO} $arg_2 | ${SED} 's!unpack-cmd!unpackexe!g'`
# special case 2 /JObjC.dst/ => /libjobjc/
arg_1=`${ECHO} $arg_1 | ${SED} 's!/JObjC.dst/!/libjobjc/!g'`
arg_2=`${ECHO} $arg_2 | ${SED} 's!/JObjC.dst/!/libjobjc/!g'`
full=`${ECHO} $arg_1 | ${SED} 's!\.!\\\.!g'`
medium=`${ECHO} $arg_1 | ${SED} 's!.*/\([^/]*/[^/]*\)!\1!'`
short=`${ECHO} $arg_2 | ${SED} 's!\.!\\\.!g'`
if [ "`${GREP} -c "/$full" $COMPARE_ROOT/list.new`" -eq 1 ]
then
${ECHO} $NEW/$arg_1
return
fi
if [ "`${GREP} -c "$medium" $COMPARE_ROOT/list.new`" -eq 1 ]
then
${GREP} "$medium" $COMPARE_ROOT/list.new
return
fi
if [ "`${GREP} -c "/$short" $COMPARE_ROOT/list.new`" -eq 1 ]
then
${GREP} "/$short" $COMPARE_ROOT/list.new
return
fi
# old style has "dir" before obj{64}
dir=`${ECHO} $arg_1 | ${SED} 's!.*/\([^/]*\)/obj[64]*.*!\1!g'`
if [ -n "$dir" -a "$dir" != "$arg_1" ]
then
if [ "`${GREP} $dir $COMPARE_ROOT/list.new | ${GREP} -c "/$short"`" -eq 1 ]
then
${GREP} $dir $COMPARE_ROOT/list.new | ${GREP} "/$short"
return
fi
# Try with lib$dir/
if [ "`${GREP} "lib$dir/" $COMPARE_ROOT/list.new | ${GREP} -c "/$short"`" -eq 1 ]
then
${GREP} "lib$dir/" $COMPARE_ROOT/list.new | ${GREP} "/$short"
return
fi
# Try with $dir_objs
if [ "`${GREP} "${dir}_objs" $COMPARE_ROOT/list.new | ${GREP} -c "/$short"`" -eq 1 ]
then
${GREP} "${dir}_objs" $COMPARE_ROOT/list.new | ${GREP} "/$short"
return
fi
fi
# check for some specifics...
for i in demo hotspot jobjc
do
if [ "`${ECHO} $full | ${GREP} -c $i`" -gt 0 ]
then
if [ "`${GREP} $i $COMPARE_ROOT/list.new | ${GREP} -c "/$short"`" -eq 1 ]
then
${GREP} $i $COMPARE_ROOT/list.new | ${GREP} "/$short"
return
fi
fi
done
# check for specific demo
demo=`${ECHO} $arg_1 | ${SED} 's!.*/demo/jvmti/\([^/]*\)/.*!\1!g'`
if [ -n "$demo" -a "$dir" != "$demo" ]
then
if [ "`${GREP} $demo $COMPARE_ROOT/list.new | ${GREP} -c "/$short"`" -eq 1 ]
then
${GREP} $demo $COMPARE_ROOT/list.new | ${GREP} "/$short"
return
fi
fi
return
}
compare() {
old=$1
new=$2
${DIFF} $old $new > /dev/null
res=$?
if [ $res -eq 0 ]
then
${ECHO} 0
return
fi
# check if stripped objects gives equality
${CP} $old $COMPARE_ROOT/`basename $old`.old
${CP} $new $COMPARE_ROOT/`basename $old`.new
${POST_STRIP_CMD} $COMPARE_ROOT/`basename $old`.old $COMPARE_ROOT/`basename $old`.new > /dev/null 2>&1
${DIFF} $COMPARE_ROOT/`basename $old`.old $COMPARE_ROOT/`basename $old`.new > /dev/null
res=$?
${RM} $COMPARE_ROOT/`basename $old`.old $COMPARE_ROOT/`basename $old`.new
if [ $res -eq 0 ]
then
${ECHO} S
return
fi
name=`basename $1 | ${SED} 's!\.o!!'`
cntold=`strings $old | ${GREP} -c $name`
cntnew=`strings $new | ${GREP} -c $name`
if [ $cntold -gt 0 -a $cntnew -gt 0 ]
then
${ECHO} F
return
fi
${ECHO} 1
}
for F in `${CAT} $COMPARE_ROOT/list.old`
do
if [ "${IGNORE}" ] && [ "`${ECHO} $F | ${GREP} ${IGNORE}`" ]
then
#
# skip ignored files
#
continue;
fi
if [ "$PATTERN" ] && [ `${ECHO} $F | ${GREP} -c $PATTERN` -eq 0 ]
then
continue;
fi
f=`basename $F`
o=$OLD/$F
n=`findnew $F $f`
if [ "$n" ]
then
n="$NEW/$n"
${ECHO} `compare $o $n` : $f : $o : $n
else
${ECHO} "- : $f : $o "
fi
done

View File

@ -280,3 +280,4 @@ cfdac5887952c2dd73c73a1d8d9aa880d0539bbf jdk9-b33
9bc2dbd3dfb8c9fa88e00056b8b93a81ee6d306e jdk9-b35
ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36
7e9add74ad50841fb39dae75db56374aefa1de4c jdk9-b37
8acf056126e819cf536eef02aee0f61f207a6b52 jdk9-b38

View File

@ -440,3 +440,4 @@ af46576a8d7cb4003028b8ee8bf408cfe227315b jdk9-b32
438cb613151c4bd290bb732697517cba1cafcb04 jdk9-b35
464ab653fbb17eb518d8ef60f8df301de7ef00d0 jdk9-b36
b1c2dd843f247a1db19e1e85eb62ca405f72dc26 jdk9-b37
c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38

View File

@ -280,3 +280,4 @@ b940ca3d2c7e8a279ca850706b89c2ad3a841e82 jdk9-b32
b9370464572fc663a38956047aa612d6e7854c3d jdk9-b35
61b4c9acaa58e482db6601ec5dc4fc3d2d8dbb55 jdk9-b36
48e4ec70cc1c8651e4a0324d91f193c4edd83af9 jdk9-b37
6c6b34477e93e6fb350035f73ed7c02266b78380 jdk9-b38

View File

@ -383,6 +383,8 @@ public class XMLDocumentFragmentScannerImpl
protected boolean foundBuiltInRefs = false;
/** Built-in reference character event */
protected boolean builtInRefCharacterHandled = false;
//skip element algorithm
static final short MAX_DEPTH_LIMIT = 5 ;
@ -1949,7 +1951,10 @@ public class XMLDocumentFragmentScannerImpl
fDocumentHandler.startGeneralEntity(entity, null, null, null);
}
fTempString.setValues(fSingleChar, 0, 1);
//fDocumentHandler.characters(fTempString, null);
if(!fIsCoalesce){
fDocumentHandler.characters(fTempString, null);
builtInRefCharacterHandled = true;
}
if (fNotifyBuiltInRefs) {
fDocumentHandler.endGeneralEntity(entity, null);
@ -3068,7 +3073,12 @@ public class XMLDocumentFragmentScannerImpl
//return CHARACTERS
if(fScannerState == SCANNER_STATE_BUILT_IN_REFS && !fIsCoalesce){
setScannerState(SCANNER_STATE_CONTENT);
return XMLEvent.CHARACTERS;
if (builtInRefCharacterHandled) {
builtInRefCharacterHandled = false;
return XMLEvent.ENTITY_REFERENCE;
} else {
return XMLEvent.CHARACTERS;
}
}
//if there was a text declaration, call next() it will be taken care.

View File

@ -283,3 +283,4 @@ e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30
afe0c89e2edbdfb1a7ceff3d9b3ff46c4186202f jdk9-b35
84803c3be7f79d29c7dc40749d7743675f64107a jdk9-b36
90de6ecbff46386a3f9d6f7ca876e7aa6381f50a jdk9-b37
dd4ba422dba858b1c3c4b38f49a3e514be4e2790 jdk9-b38

View File

@ -280,3 +280,4 @@ f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27
e549291a0227031310fa91c574891f892d27f959 jdk9-b35
cdcf2e599e42935c2d1d19a24bb19e808aeb43b5 jdk9-b36
27c3345d6dce39a22c262f30bb1f0e0b00c3709e jdk9-b37
d2d745313c81d1fc01f426983b9f784ab1f750e8 jdk9-b38

View File

@ -29,12 +29,10 @@ import java.io.IOException;
import java.io.File;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.AccessController;
import java.security.AccessControlContext;
import java.security.CodeSource;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
@ -54,7 +52,6 @@ import java.util.concurrent.ConcurrentHashMap;
import sun.misc.CompoundEnumeration;
import sun.misc.Resource;
import sun.misc.URLClassPath;
import sun.misc.VM;
import sun.reflect.CallerSensitive;
import sun.reflect.Reflection;
import sun.reflect.misc.ReflectUtil;
@ -268,8 +265,8 @@ public abstract class ClassLoader {
// The packages defined in this class loader. Each package name is mapped
// to its corresponding Package object.
// @GuardedBy("itself")
private final HashMap<String, Package> packages = new HashMap<>();
private final ConcurrentHashMap<String, Package> packages
= new ConcurrentHashMap<>();
private static Void checkCreateClassLoader() {
SecurityManager security = System.getSecurityManager();
@ -1575,17 +1572,17 @@ public abstract class ClassLoader {
String implVendor, URL sealBase)
throws IllegalArgumentException
{
synchronized (packages) {
Package pkg = getPackage(name);
if (pkg != null) {
throw new IllegalArgumentException(name);
}
pkg = new Package(name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor,
sealBase, this);
packages.put(name, pkg);
return pkg;
Package pkg = getPackage(name);
if (pkg != null) {
throw new IllegalArgumentException(name);
}
pkg = new Package(name, specTitle, specVersion, specVendor,
implTitle, implVersion, implVendor,
sealBase, this);
if (packages.putIfAbsent(name, pkg) != null) {
throw new IllegalArgumentException(name);
}
return pkg;
}
/**
@ -1601,26 +1598,13 @@ public abstract class ClassLoader {
* @since 1.2
*/
protected Package getPackage(String name) {
Package pkg;
synchronized (packages) {
pkg = packages.get(name);
}
Package pkg = packages.get(name);
if (pkg == null) {
if (parent != null) {
pkg = parent.getPackage(name);
} else {
pkg = Package.getSystemPackage(name);
}
if (pkg != null) {
synchronized (packages) {
Package pkg2 = packages.get(name);
if (pkg2 == null) {
packages.put(name, pkg);
} else {
pkg = pkg2;
}
}
}
}
return pkg;
}
@ -1635,22 +1619,18 @@ public abstract class ClassLoader {
* @since 1.2
*/
protected Package[] getPackages() {
Map<String, Package> map;
synchronized (packages) {
map = new HashMap<>(packages);
}
Package[] pkgs;
if (parent != null) {
pkgs = parent.getPackages();
} else {
pkgs = Package.getSystemPackages();
}
Map<String, Package> map = packages;
if (pkgs != null) {
map = new HashMap<>(packages);
for (Package pkg : pkgs) {
String pkgName = pkg.getName();
if (map.get(pkgName) == null) {
map.put(pkgName, pkg);
}
map.putIfAbsent(pkg.getName(), pkg);
}
}
return map.values().toArray(new Package[map.size()]);

View File

@ -26,27 +26,21 @@
package java.lang;
import java.lang.reflect.AnnotatedElement;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.StringTokenizer;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.MalformedURLException;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.concurrent.ConcurrentHashMap;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarException;
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import sun.net.www.ParseUtil;
import sun.reflect.CallerSensitive;
@ -538,17 +532,15 @@ public class Package implements java.lang.reflect.AnnotatedElement {
* Returns the loaded system package for the specified name.
*/
static Package getSystemPackage(String name) {
synchronized (pkgs) {
Package pkg = pkgs.get(name);
if (pkg == null) {
name = name.replace('.', '/').concat("/");
String fn = getSystemPackage0(name);
if (fn != null) {
pkg = defineSystemPackage(name, fn);
}
Package pkg = pkgs.get(name);
if (pkg == null) {
name = name.replace('.', '/').concat("/");
String fn = getSystemPackage0(name);
if (fn != null) {
pkg = defineSystemPackage(name, fn);
}
return pkg;
}
return pkg;
}
/*
@ -557,74 +549,98 @@ public class Package implements java.lang.reflect.AnnotatedElement {
static Package[] getSystemPackages() {
// First, update the system package map with new package names
String[] names = getSystemPackages0();
synchronized (pkgs) {
for (String name : names) {
for (String name : names) {
if (!pkgs.containsKey(name)) {
defineSystemPackage(name, getSystemPackage0(name));
}
return pkgs.values().toArray(new Package[pkgs.size()]);
}
return pkgs.values().toArray(new Package[pkgs.size()]);
}
private static Package defineSystemPackage(final String iname,
final String fn)
{
return AccessController.doPrivileged(new PrivilegedAction<Package>() {
public Package run() {
String name = iname;
// Get the cached code source url for the file name
URL url = urls.get(fn);
if (url == null) {
// URL not found, so create one
File file = new File(fn);
try {
url = ParseUtil.fileToEncodedURL(file);
} catch (MalformedURLException e) {
}
if (url != null) {
urls.put(fn, url);
// If loading a JAR file, then also cache the manifest
if (file.isFile()) {
mans.put(fn, loadManifest(fn));
}
}
}
// Convert to "."-separated package name
name = name.substring(0, name.length() - 1).replace('/', '.');
Package pkg;
Manifest man = mans.get(fn);
if (man != null) {
pkg = new Package(name, man, url, null);
} else {
pkg = new Package(name, null, null, null,
null, null, null, null, null);
}
pkgs.put(name, pkg);
return pkg;
}
});
// Convert to "."-separated package name
String name = iname.substring(0, iname.length() - 1).replace('/', '.');
// Creates a cached manifest for the file name, allowing
// only-once, lazy reads of manifest from jar files
CachedManifest cachedManifest = createCachedManifest(fn);
pkgs.putIfAbsent(name, new Package(name, cachedManifest.getManifest(),
cachedManifest.getURL(), null));
// Ensure we only expose one Package object
return pkgs.get(name);
}
/*
* Returns the Manifest for the specified JAR file name.
*/
private static Manifest loadManifest(String fn) {
try (FileInputStream fis = new FileInputStream(fn);
JarInputStream jis = new JarInputStream(fis, false))
{
return jis.getManifest();
} catch (IOException e) {
return null;
private static CachedManifest createCachedManifest(String fn) {
if (!manifests.containsKey(fn)) {
manifests.putIfAbsent(fn, new CachedManifest(fn));
}
return manifests.get(fn);
}
// The map of loaded system packages
private static Map<String, Package> pkgs = new HashMap<>(31);
private static final ConcurrentHashMap<String, Package> pkgs
= new ConcurrentHashMap<>();
// Maps each directory or zip file name to its corresponding url
private static Map<String, URL> urls = new HashMap<>(10);
// Maps each directory or zip file name to its corresponding manifest, if
// it exists
private static final ConcurrentHashMap<String, CachedManifest> manifests
= new ConcurrentHashMap<>();
// Maps each code source url for a jar file to its manifest
private static Map<String, Manifest> mans = new HashMap<>(10);
private static class CachedManifest {
private static final Manifest EMPTY_MANIFEST = new Manifest();
private final String fileName;
private final URL url;
private volatile Manifest manifest;
CachedManifest(final String fileName) {
this.fileName = fileName;
this.url = AccessController.doPrivileged(new PrivilegedAction<URL>() {
public URL run() {
final File file = new File(fileName);
if (file.isFile()) {
try {
return ParseUtil.fileToEncodedURL(file);
} catch (MalformedURLException e) {
}
}
return null;
}
});
}
public URL getURL() {
return url;
}
public Manifest getManifest() {
if (url == null) {
return EMPTY_MANIFEST;
}
Manifest m = manifest;
if (m != null) {
return m;
}
synchronized (this) {
m = manifest;
if (m != null) {
return m;
}
m = AccessController.doPrivileged(new PrivilegedAction<Manifest>() {
public Manifest run() {
try (FileInputStream fis = new FileInputStream(fileName);
JarInputStream jis = new JarInputStream(fis, false)) {
return jis.getManifest();
} catch (IOException e) {
return null;
}
}
});
manifest = m = (m == null ? EMPTY_MANIFEST : m);
}
return m;
}
}
private static native String getSystemPackage0(String name);
private static native String[] getSystemPackages0();

View File

@ -1388,16 +1388,26 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
Object a4, Object a5, Object a6, Object a7,
Object a8, Object a9)
{ return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
private static final int ARRAYS_COUNT = 11;
private static MethodHandle[] makeArrays() {
ArrayList<MethodHandle> mhs = new ArrayList<>();
for (;;) {
MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
if (mh == null) break;
MethodHandle[] mhs = new MethodHandle[MAX_ARITY + 1];
for (int i = 0; i < ARRAYS_COUNT; i++) {
MethodHandle mh = findCollector("array", i, Object[].class);
mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
mhs.add(mh);
mhs[i] = mh;
}
assert(mhs.size() == 11); // current number of methods
return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
assert(assertArrayMethodCount(mhs));
return mhs;
}
private static boolean assertArrayMethodCount(MethodHandle[] mhs) {
assert(findCollector("array", ARRAYS_COUNT, Object[].class) == null);
for (int i = 0; i < ARRAYS_COUNT; i++) {
assert(mhs[i] != null);
}
return true;
}
// filling versions of the above:
@ -1449,15 +1459,22 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
private static final int FILL_ARRAYS_COUNT = 11; // current number of fillArray methods
private static MethodHandle[] makeFillArrays() {
ArrayList<MethodHandle> mhs = new ArrayList<>();
mhs.add(null); // there is no empty fill; at least a0 is required
for (;;) {
MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
if (mh == null) break;
mhs.add(mh);
MethodHandle[] mhs = new MethodHandle[FILL_ARRAYS_COUNT];
mhs[0] = null; // there is no empty fill; at least a0 is required
for (int i = 1; i < FILL_ARRAYS_COUNT; i++) {
MethodHandle mh = findCollector("fillArray", i, Object[].class, Integer.class, Object[].class);
mhs[i] = mh;
}
assert(mhs.size() == FILL_ARRAYS_COUNT);
return mhs.toArray(new MethodHandle[0]);
assert(assertFillArrayMethodCount(mhs));
return mhs;
}
private static boolean assertFillArrayMethodCount(MethodHandle[] mhs) {
assert(findCollector("fillArray", FILL_ARRAYS_COUNT, Object[].class, Integer.class, Object[].class) == null);
for (int i = 1; i < FILL_ARRAYS_COUNT; i++) {
assert(mhs[i] != null);
}
return true;
}
private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
@ -1472,9 +1489,6 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
static MethodHandle varargsArray(int nargs) {
MethodHandle mh = Lazy.ARRAYS[nargs];
if (mh != null) return mh;
mh = findCollector("array", nargs, Object[].class);
if (mh != null) mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
if (mh != null) return Lazy.ARRAYS[nargs] = mh;
mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
assert(assertCorrectArity(mh, nargs));
mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);

View File

@ -122,18 +122,18 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
AccessController.doPrivileged(
new PrivilegedAction<Void>() {
public Void run() {
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread sft = new Thread(tg, proc, "Secondary finalizer");
sft.start();
try {
sft.join();
} catch (InterruptedException x) {
/* Ignore */
}
return null;
ThreadGroup tg = Thread.currentThread().getThreadGroup();
for (ThreadGroup tgn = tg;
tgn != null;
tg = tgn, tgn = tg.getParent());
Thread sft = new Thread(tg, proc, "Secondary finalizer");
sft.start();
try {
sft.join();
} catch (InterruptedException x) {
Thread.currentThread().interrupt();
}
return null;
}});
}
@ -146,6 +146,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() {
// in case of recursive call to run()
if (running)
return;
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
@ -168,6 +169,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
forkSecondaryFinalizer(new Runnable() {
private volatile boolean running;
public void run() {
// in case of recursive call to run()
if (running)
return;
final JavaLangAccess jla = SharedSecrets.getJavaLangAccess();
@ -189,6 +191,7 @@ final class Finalizer extends FinalReference<Object> { /* Package-private; must
super(g, "Finalizer");
}
public void run() {
// in case of recursive call to run()
if (running)
return;

View File

@ -446,6 +446,7 @@ public abstract class SocketImpl implements SocketOptions {
serverSocketOptions.add(StandardSocketOptions.SO_RCVBUF);
serverSocketOptions.add(StandardSocketOptions.SO_REUSEADDR);
serverSocketOptions.add(StandardSocketOptions.IP_TOS);
};
/**

View File

@ -303,7 +303,7 @@ public final class Files {
* is a {@link java.nio.channels.FileChannel}.
*
* <p> <b>Usage Examples:</b>
* <pre>
* <pre>{@code
* Path path = ...
*
* // open file for reading
@ -314,9 +314,10 @@ public final class Files {
* WritableByteChannel wbc = Files.newByteChannel(path, EnumSet.of(CREATE,APPEND));
*
* // create file with initial permissions, opening it for both reading and writing
* {@code FileAttribute<Set<PosixFilePermission>> perms = ...}
* SeekableByteChannel sbc = Files.newByteChannel(path, EnumSet.of(CREATE_NEW,READ,WRITE), perms);
* </pre>
* FileAttribute<Set<PosixFilePermission>> perms = ...
* SeekableByteChannel sbc =
* Files.newByteChannel(path, EnumSet.of(CREATE_NEW,READ,WRITE), perms);
* }</pre>
*
* @param path
* the path to the file to open or create
@ -1702,7 +1703,8 @@ public final class Files {
* Alternatively, suppose we want to read file's POSIX attributes without
* following symbolic links:
* <pre>
* PosixFileAttributes attrs = Files.readAttributes(path, PosixFileAttributes.class, NOFOLLOW_LINKS);
* PosixFileAttributes attrs =
* Files.readAttributes(path, PosixFileAttributes.class, NOFOLLOW_LINKS);
* </pre>
*
* @param <A>
@ -2840,6 +2842,8 @@ public final class Files {
* @return a new buffered writer, with default buffer size, to write text
* to the file
*
* @throws IllegalArgumentException
* if {@code options} contains an invalid combination of options
* @throws IOException
* if an I/O error occurs opening or creating the file
* @throws UnsupportedOperationException
@ -2880,6 +2884,8 @@ public final class Files {
* @return a new buffered writer, with default buffer size, to write text
* to the file
*
* @throws IllegalArgumentException
* if {@code options} contains an invalid combination of options
* @throws IOException
* if an I/O error occurs opening or creating the file
* @throws UnsupportedOperationException
@ -2891,7 +2897,9 @@ public final class Files {
*
* @since 1.8
*/
public static BufferedWriter newBufferedWriter(Path path, OpenOption... options) throws IOException {
public static BufferedWriter newBufferedWriter(Path path, OpenOption... options)
throws IOException
{
return newBufferedWriter(path, StandardCharsets.UTF_8, options);
}
@ -3273,6 +3281,8 @@ public final class Files {
*
* @return the path
*
* @throws IllegalArgumentException
* if {@code options} contains an invalid combination of options
* @throws IOException
* if an I/O error occurs writing to or creating the file
* @throws UnsupportedOperationException
@ -3330,6 +3340,8 @@ public final class Files {
*
* @return the path
*
* @throws IllegalArgumentException
* if {@code options} contains an invalid combination of options
* @throws IOException
* if an I/O error occurs writing to or creating the file, or the
* text cannot be encoded using the specified charset
@ -3376,6 +3388,8 @@ public final class Files {
*
* @return the path
*
* @throws IllegalArgumentException
* if {@code options} contains an invalid combination of options
* @throws IOException
* if an I/O error occurs writing to or creating the file, or the
* text cannot be encoded as {@code UTF-8}
@ -3452,7 +3466,7 @@ public final class Files {
final Iterator<Path> delegate = ds.iterator();
// Re-wrap DirectoryIteratorException to UncheckedIOException
Iterator<Path> it = new Iterator<Path>() {
Iterator<Path> iterator = new Iterator<Path>() {
@Override
public boolean hasNext() {
try {
@ -3471,7 +3485,9 @@ public final class Files {
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(it, Spliterator.DISTINCT), false)
Spliterator<Path> spliterator =
Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT);
return StreamSupport.stream(spliterator, false)
.onClose(asUncheckedRunnable(ds));
} catch (Error|RuntimeException e) {
try {
@ -3572,7 +3588,9 @@ public final class Files {
{
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
try {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
Spliterator<FileTreeWalker.Event> spliterator =
Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT);
return StreamSupport.stream(spliterator, false)
.onClose(iterator::close)
.map(entry -> entry.file());
} catch (Error|RuntimeException e) {
@ -3685,7 +3703,9 @@ public final class Files {
{
FileTreeIterator iterator = new FileTreeIterator(start, maxDepth, options);
try {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT), false)
Spliterator<FileTreeWalker.Event> spliterator =
Spliterators.spliteratorUnknownSize(iterator, Spliterator.DISTINCT);
return StreamSupport.stream(spliterator, false)
.onClose(iterator::close)
.filter(entry -> matcher.test(entry.file(), entry.attributes()))
.map(entry -> entry.file());

View File

@ -86,8 +86,8 @@
* <p> Unless otherwise noted, passing a {@code null} argument to a constructor
* or method of any class or interface in this package will cause a {@link
* java.lang.NullPointerException NullPointerException} to be thrown. Additionally,
* invoking a method with a collection containing a {@code null} element will
* cause a {@code NullPointerException}, unless otherwise specified. </p>
* invoking a method with an array or collection containing a {@code null} element
* will cause a {@code NullPointerException}, unless otherwise specified. </p>
*
* <p> Unless otherwise noted, methods that attempt to access the file system
* will throw {@link java.nio.file.ClosedFileSystemException} when invoked on

View File

@ -276,6 +276,7 @@ public class Sockets {
set = new HashSet<>();
set.add(StandardSocketOptions.SO_RCVBUF);
set.add(StandardSocketOptions.SO_REUSEADDR);
set.add(StandardSocketOptions.IP_TOS);
set = Collections.unmodifiableSet(set);
options.put(ServerSocket.class, set);

View File

@ -1608,7 +1608,7 @@ public final class Main {
private static String getCompatibleSigAlgName(String keyAlgName)
throws Exception {
if ("DSA".equalsIgnoreCase(keyAlgName)) {
return "SHA1WithDSA";
return "SHA256WithDSA";
} else if ("RSA".equalsIgnoreCase(keyAlgName)) {
return "SHA256WithRSA";
} else if ("EC".equalsIgnoreCase(keyAlgName)) {
@ -1628,10 +1628,8 @@ public final class Main {
if (keysize == -1) {
if ("EC".equalsIgnoreCase(keyAlgName)) {
keysize = 256;
} else if ("RSA".equalsIgnoreCase(keyAlgName)) {
keysize = 2048;
} else {
keysize = 1024;
keysize = 2048; // RSA and DSA
}
}

View File

@ -205,28 +205,4 @@ public class JmxProperties {
*/
public static final Logger MISC_LOGGER =
Logger.getLogger(MISC_LOGGER_NAME);
/**
* Logger name for SNMP.
*/
public static final String SNMP_LOGGER_NAME =
"javax.management.snmp";
/**
* Logger for SNMP.
*/
public static final Logger SNMP_LOGGER =
Logger.getLogger(SNMP_LOGGER_NAME);
/**
* Logger name for SNMP Adaptor.
*/
public static final String SNMP_ADAPTOR_LOGGER_NAME =
"javax.management.snmp.daemon";
/**
* Logger for SNMP Adaptor.
*/
public static final Logger SNMP_ADAPTOR_LOGGER =
Logger.getLogger(SNMP_ADAPTOR_LOGGER_NAME);
}

View File

@ -2358,7 +2358,7 @@ class SignatureFile {
if (sigalg == null) {
if (keyAlgorithm.equalsIgnoreCase("DSA"))
signatureAlgorithm = "SHA1withDSA";
signatureAlgorithm = "SHA256withDSA";
else if (keyAlgorithm.equalsIgnoreCase("RSA"))
signatureAlgorithm = "SHA256withRSA";
else if (keyAlgorithm.equalsIgnoreCase("EC"))

View File

@ -138,9 +138,6 @@ com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java
# 8058492
java/lang/management/ThreadMXBean/FindDeadlocks.java generic-all
# 8058506
java/lang/management/ThreadMXBean/ThreadMXBeanStateTest.java generic-all
############################################################################
# jdk_jmx
@ -285,6 +282,9 @@ com/sun/jdi/JdbReadTwiceTest.sh generic-all
# 8058616
com/sun/jdi/RedefinePop.sh generic-all
# 8061114
com/sun/jdi/Redefine-g.sh generic-all
############################################################################
# jdk_util
@ -318,4 +318,7 @@ sun/tools/jps/TestJpsJarRelative.java generic-all
# 8057732
sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java generic-all
# 8060736
sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
############################################################################

View File

@ -0,0 +1,249 @@
/*
* Copyright (c) 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 8060130
* @library /lib/testlibrary
* @build package2.Class2 GetSystemPackage jdk.testlibrary.*
* @summary Test if getSystemPackage() return consistent values for cases
* where a manifest is provided or not and ensure only jars on
* bootclasspath gets resolved via Package.getSystemPackage
* @run main GetSystemPackage
*/
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import jdk.testlibrary.ProcessTools;
public class GetSystemPackage {
static final String testClassesDir = System.getProperty("test.classes", ".");
static final File tmpFolder = new File(testClassesDir);
static final String manifestTitle = "Special JAR";
public static void main(String ... args) throws Exception {
if (args.length == 0) {
buildJarsAndInitiateSystemPackageTest();
return;
}
switch (args[0]) {
case "system-manifest":
verifyPackage(true, true);
break;
case "system-no-manifest":
verifyPackage(false, true);
break;
case "non-system-manifest":
verifyPackage(true, false);
break;
case "non-system-no-manifest":
default:
verifyPackage(false, false);
break;
}
}
private static void buildJarsAndInitiateSystemPackageTest()
throws Exception
{
Manifest m = new Manifest();
// not setting MANIFEST_VERSION prevents META-INF/MANIFEST.MF from
// getting written
m.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
m.getMainAttributes().put(Attributes.Name.SPECIFICATION_TITLE,
manifestTitle);
buildJar("manifest.jar", m);
buildJar("no-manifest.jar", null);
runSubProcess("System package with manifest improperly resolved.",
"-Xbootclasspath/p:" + testClassesDir + "/manifest.jar",
"GetSystemPackage", "system-manifest");
runSubProcess("System package from directory improperly resolved.",
"-Xbootclasspath/p:" + testClassesDir, "GetSystemPackage",
"system-no-manifest");
runSubProcess("System package with no manifest improperly resolved",
"-Xbootclasspath/p:" + testClassesDir + "/no-manifest.jar",
"GetSystemPackage", "system-no-manifest");
runSubProcess("Classpath package with manifest improperly resolved",
"-cp", testClassesDir + "/manifest.jar", "GetSystemPackage",
"non-system-manifest");
runSubProcess("Classpath package with no manifest improperly resolved",
"-cp", testClassesDir + "/no-manifest.jar", "GetSystemPackage",
"non-system-no-manifest");
}
private static void buildJar(String name, Manifest man) throws Exception {
JarBuilder jar = new JarBuilder(tmpFolder, name, man);
jar.addClassFile("package2/Class2.class",
testClassesDir + "/package2/Class2.class");
jar.addClassFile("GetSystemPackage.class",
testClassesDir + "/GetSystemPackage.class");
jar.addClassFile("GetSystemPackageClassLoader.class",
testClassesDir + "/GetSystemPackageClassLoader.class");
jar.build();
}
private static void runSubProcess(String messageOnError, String ... args)
throws Exception
{
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(args);
int res = pb.directory(tmpFolder).inheritIO().start().waitFor();
if (res != 0) {
throw new RuntimeException(messageOnError);
}
}
private static void verifyPackage(boolean hasManifest,
boolean isSystemPackage) throws Exception
{
Class c = Class.forName("package2.Class2");
Package pkg = c.getPackage();
if (pkg == null || pkg != Package.getPackage("package2") ||
!"package2".equals(pkg.getName())) {
fail("package2 not found via Package.getPackage()");
}
String specificationTitle = pkg.getSpecificationTitle();
if (!"package2".equals(pkg.getName())) {
fail("Invalid package for Class2");
}
if (hasManifest && (specificationTitle == null
|| !manifestTitle.equals(specificationTitle))) {
fail("Invalid manifest for package " + pkg.getName());
}
if (!hasManifest && specificationTitle != null) {
fail("Invalid manifest for package " + pkg.getName() + ": was " +
specificationTitle + " expected: null");
}
// force the use of a classloader with no parent, then retrieve the
// package in a way that bypasses the classloader pkg maps
GetSystemPackageClassLoader classLoader =
new GetSystemPackageClassLoader();
Package systemPkg = classLoader.getSystemPackage("package2");
if (findPackage("java.lang") == null) {
fail("java.lang not found via Package.getPackages()");
}
Package foundPackage = findPackage("package2");
if (isSystemPackage) {
if (systemPkg == null) {
fail("System package could not be found via getSystemPackage");
}
if (foundPackage != systemPkg || systemPkg != pkg) {
fail("Inconsistent package found via Package.getPackages()");
}
} else {
if (systemPkg != null) {
fail("Non-system package could be found via getSystemPackage");
}
if (foundPackage == null) {
fail("Non-system package not found via Package.getPackages()");
}
}
}
private static Package findPackage(String name) {
Package[] packages = Package.getPackages();
for (Package p : packages) {
System.out.println(p);
if (p.getName().equals(name)) {
return p;
}
}
return null;
}
private static void fail(String message) {
throw new RuntimeException(message);
}
}
/*
* This classloader bypasses the system classloader to give as direct access
* to Package.getSystemPackage() as possible
*/
class GetSystemPackageClassLoader extends ClassLoader {
public GetSystemPackageClassLoader() {
super(null);
}
public Package getSystemPackage(String name) {
return super.getPackage(name);
}
}
/*
* Helper class for building jar files
*/
class JarBuilder {
private JarOutputStream os;
public JarBuilder(File tmpFolder, String jarName, Manifest manifest)
throws FileNotFoundException, IOException
{
File jarFile = new File(tmpFolder, jarName);
if (manifest != null) {
this.os = new JarOutputStream(new FileOutputStream(jarFile),
manifest);
} else {
this.os = new JarOutputStream(new FileOutputStream(jarFile));
}
}
public void addClassFile(String pathFromRoot, String file)
throws IOException
{
byte[] buf = new byte[1024];
try (FileInputStream in = new FileInputStream(file)) {
JarEntry entry = new JarEntry(pathFromRoot);
os.putNextEntry(entry);
int len;
while ((len = in.read(buf)) > 0) {
os.write(buf, 0, len);
}
os.closeEntry();
}
}
public void build() throws IOException {
os.close();
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 4354680
* @summary runFinalization() should not clear or ignore interrupt bit
* @run main FinInterrupt
*/
public class FinInterrupt {
public static void main(String[] args) throws Exception {
Thread.currentThread().interrupt();
System.runFinalization();
if (Thread.interrupted()) {
System.out.println("Passed: interrupt bit was still set.");
} else {
throw new AssertionError("interrupt bit was cleared");
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2014 Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -27,6 +27,8 @@ import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import jdk.testlibrary.LockFreeLogManager;
/**
* ThreadStateController allows a thread to request this thread to transition
* to a specific thread state. The {@linkplain #transitionTo request} is
@ -94,8 +96,12 @@ public class ThreadStateController extends Thread {
private static final int S_TERMINATE = 8;
// for debugging
private AtomicInteger iterations = new AtomicInteger();
private AtomicInteger interrupted = new AtomicInteger();
private final AtomicInteger iterations = new AtomicInteger();
private final AtomicInteger interrupted = new AtomicInteger();
private final LockFreeLogManager logManager = new LockFreeLogManager();
@Override
public void run() {
// this thread has started
while (!done) {
@ -119,13 +125,13 @@ public class ThreadStateController extends Thread {
break;
}
case S_BLOCKED: {
System.out.format("%d: %s is going to block (interations %d)%n",
getId(), getName(), iterations.get());
log("%d: %s is going to block (iterations %d)%n",
getId(), getName(), iterations.get());
stateChange(nextState);
// going to block on lock
synchronized (lock) {
System.out.format("%d: %s acquired the lock (interations %d)%n",
getId(), getName(), iterations.get());
log("%d: %s acquired the lock (iterations %d)%n",
getId(), getName(), iterations.get());
try {
// this thread has escaped the BLOCKED state
// release the lock and a short wait before continue
@ -139,13 +145,13 @@ public class ThreadStateController extends Thread {
}
case S_WAITING: {
synchronized (lock) {
System.out.format("%d: %s is going to waiting (interations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
log("%d: %s is going to waiting (iterations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
try {
stateChange(nextState);
lock.wait();
System.out.format("%d: %s wakes up from waiting (interations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
log("%d: %s wakes up from waiting (iterations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
} catch (InterruptedException e) {
// ignore
interrupted.incrementAndGet();
@ -155,13 +161,13 @@ public class ThreadStateController extends Thread {
}
case S_TIMED_WAITING: {
synchronized (lock) {
System.out.format("%d: %s is going to timed waiting (interations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
log("%d: %s is going to timed waiting (iterations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
try {
stateChange(nextState);
lock.wait(10000);
System.out.format("%d: %s wakes up from timed waiting (interations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
log("%d: %s wakes up from timed waiting (iterations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
} catch (InterruptedException e) {
// ignore
interrupted.incrementAndGet();
@ -170,23 +176,23 @@ public class ThreadStateController extends Thread {
break;
}
case S_PARKED: {
System.out.format("%d: %s is going to park (interations %d)%n",
getId(), getName(), iterations.get());
log("%d: %s is going to park (iterations %d)%n",
getId(), getName(), iterations.get());
stateChange(nextState);
LockSupport.park();
break;
}
case S_TIMED_PARKED: {
System.out.format("%d: %s is going to timed park (interations %d)%n",
getId(), getName(), iterations.get());
log("%d: %s is going to timed park (iterations %d)%n",
getId(), getName(), iterations.get());
long deadline = System.currentTimeMillis() + 10000*1000;
stateChange(nextState);
LockSupport.parkUntil(deadline);
break;
}
case S_SLEEPING: {
System.out.format("%d: %s is going to sleep (interations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
log("%d: %s is going to sleep (iterations %d interrupted %d)%n",
getId(), getName(), iterations.get(), interrupted.get());
try {
stateChange(nextState);
Thread.sleep(1000000);
@ -219,8 +225,8 @@ public class ThreadStateController extends Thread {
if (newState == nextState) {
state = nextState;
phaser.arrive();
System.out.format("%d: state change: %s %s%n",
getId(), toStateName(nextState), phaserToString(phaser));
log("%d: state change: %s %s%n",
getId(), toStateName(nextState), phaserToString(phaser));
return;
}
@ -270,12 +276,12 @@ public class ThreadStateController extends Thread {
private void nextState(int s) throws InterruptedException {
final long id = Thread.currentThread().getId();
System.out.format("%d: wait until the thread transitions to %s %s%n",
id, toStateName(s), phaserToString(phaser));
log("%d: wait until the thread transitions to %s %s%n",
id, toStateName(s), phaserToString(phaser));
this.newState = s;
int phase = phaser.arrive();
System.out.format("%d: awaiting party arrive %s %s%n",
id, toStateName(s), phaserToString(phaser));
log("%d: awaiting party arrive %s %s%n",
id, toStateName(s), phaserToString(phaser));
for (;;) {
// when this thread has changed its state before it waits or parks
// on a lock, a potential race might happen if it misses the notify
@ -301,20 +307,22 @@ public class ThreadStateController extends Thread {
}
try {
phaser.awaitAdvanceInterruptibly(phase, 100, TimeUnit.MILLISECONDS);
System.out.format("%d: arrived at %s %s%n",
id, toStateName(s), phaserToString(phaser));
log("%d: arrived at %s %s%n",
id, toStateName(s), phaserToString(phaser));
return;
} catch (TimeoutException ex) {
// this thread hasn't arrived at this phase
System.out.format("%d: Timeout: %s%n", id, phaser);
log("%d: Timeout: %s%n", id, phaser);
}
}
}
private String phaserToString(Phaser p) {
return "[phase = " + p.getPhase() +
" parties = " + p.getRegisteredParties() +
" arrived = " + p.getArrivedParties() + "]";
}
private String toStateName(int state) {
switch (state) {
case S_RUNNABLE:
@ -337,4 +345,20 @@ public class ThreadStateController extends Thread {
return "unknown " + state;
}
}
private void log(String msg, Object ... params) {
logManager.log(msg, params);
}
/**
* Waits for the controller to complete the test run and returns the
* generated log
* @return The controller log
* @throws InterruptedException
*/
public String getLog() throws InterruptedException {
this.join();
return logManager.toString();
}
}

View File

@ -30,6 +30,8 @@ import static java.lang.Thread.State.*;
* Thread.getState().
*
* @author Mandy Chung
* @library /lib/testlibrary
* @build jdk.testlibrary.*
* @build ThreadStateTest ThreadStateController
* @run main/othervm -Xmixed ThreadStateTest
*/

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -31,6 +31,8 @@
* @author Mandy Chung
*
* @library ../../Thread
* @library /lib/testlibrary
* @build jdk.testlibrary.*
* @build ThreadMXBeanStateTest ThreadStateController
* @run main ThreadMXBeanStateTest
*/
@ -44,15 +46,17 @@ public class ThreadMXBeanStateTest {
private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
static class Lock {
private String name;
private final String name;
Lock(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
private static Lock globalLock = new Lock("my lock");
private static final Lock globalLock = new Lock("my lock");
public static void main(String[] argv) throws Exception {
// Force thread state initialization now before the test
@ -109,7 +113,7 @@ public class ThreadMXBeanStateTest {
thread.checkThreadState(TERMINATED);
try {
thread.join();
System.out.println(thread.getLog());
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("TEST FAILED: Unexpected exception.");

View File

@ -35,6 +35,7 @@ import java.sql.SQLPermission;
import java.util.Enumeration;
import java.util.PropertyPermission;
import java.util.StringJoiner;
import java.util.logging.LoggingPermission;
/*
* Simple Policy class that supports the required Permissions to validate the
@ -57,7 +58,8 @@ public class TestPolicy extends Policy {
* Policy used by the JDBC tests Possible values are: all (ALLPermissions),
* setLog (SQLPemission("setLog"), deregisterDriver
* (SQLPermission("deregisterDriver") (SQLPermission("deregisterDriver"),
* and setSyncFactory(SQLPermission(setSyncFactory),
* setSyncFactory(SQLPermission(setSyncFactory), and also
* LoggerPermission("control", null) when setting a Level
*
* @param policy Permissions to set
*/
@ -79,6 +81,11 @@ public class TestPolicy extends Policy {
setMinimalPermissions();
permissions.add(new SQLPermission("setSyncFactory"));
break;
case "setSyncFactoryLogger":
setMinimalPermissions();
permissions.add(new SQLPermission("setSyncFactory"));
permissions.add(new LoggingPermission("control", null));
break;
default:
setMinimalPermissions();
}

View File

@ -68,10 +68,9 @@ public class InitialContextTest {
Path dst = tmp.resolve("Test.java");
Files.copy(src, dst);
javac(tmp, dst);
Path build = Files.createDirectory(tmp.resolve("build"));
Files.copy(tmp.resolve("Test.class"), build.resolve("Test.class"));
javac(build, dst);
Map<String, String> props
= singletonMap(Context.INITIAL_CONTEXT_FACTORY, factoryClassFqn);
@ -107,13 +106,13 @@ public class InitialContextTest {
Path dst1 = createFactoryFrom(templatesHome().resolve("factory.template"),
factoryClassFqn, tmp);
javac(tmp, dst);
Path build = Files.createDirectory(tmp.resolve("build"));
javac(build, dst);
Path explodedJar = Files.createDirectory(tmp.resolve("exploded-jar"));
javac(explodedJar, dst1);
jar(tmp.resolve("test.jar"), explodedJar);
Path build = Files.createDirectory(tmp.resolve("build"));
Files.copy(tmp.resolve("Test.class"), build.resolve("Test.class"));
Files.copy(tmp.resolve("test.jar"), build.resolve("test.jar"));
Map<String, String> props
@ -191,7 +190,9 @@ public class InitialContextTest {
Path dst1 = createFactoryFrom(templatesHome().resolve("broken_factory.template"),
factoryClassFqn, tmp);
javac(tmp, dst);
Path build = Files.createDirectory(tmp.resolve("build"));
javac(build, dst);
Path explodedJar = Files.createDirectory(tmp.resolve("exploded-jar"));
Path services = Files.createDirectories(explodedJar.resolve("META-INF")
@ -208,15 +209,12 @@ public class InitialContextTest {
javac(explodedJar, dst1);
jar(tmp.resolve("test.jar"), explodedJar);
Path build = Files.createDirectory(tmp.resolve("build"));
Files.copy(tmp.resolve("Test.class"), build.resolve("Test.class"));
Files.copy(tmp.resolve("test.jar"), build.resolve("test.jar"));
Map<String, String> props = new HashMap<>();
props.put("java.ext.dirs", build.toString());
props.put(Context.INITIAL_CONTEXT_FACTORY, factoryClassFqn);
Map<String, String> props
= singletonMap(Context.INITIAL_CONTEXT_FACTORY, factoryClassFqn);
Result r = java(props, singleton(build), "Test");
Result r = java(props, asList(build.resolve("test.jar"), build), "Test");
if (r.exitValue == 0 || !verifyOutput(r.output, factoryClassFqn))
throw new RuntimeException(r.output);

View File

@ -0,0 +1,113 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package test.rowset.spi;
import java.sql.SQLException;
import javax.sql.rowset.spi.SyncFactoryException;
import static org.testng.Assert.*;
import org.testng.annotations.Test;
import util.BaseTest;
public class SyncFactoryExceptionTests extends BaseTest {
/*
* Create SyncFactoryException with no-arg constructor
*/
@Test
public void test01() {
SyncFactoryException ex = new SyncFactoryException();
assertTrue(ex.getMessage() == null
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0);
}
/*
* Create SyncFactoryException with message
*/
@Test
public void test02() {
SyncFactoryException ex = new SyncFactoryException(reason);
assertTrue(ex.getMessage().equals(reason)
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0);
}
/*
* Validate that the ordering of the returned Exceptions is correct using
* for-each loop
*/
@Test
public void test03() {
SyncFactoryException ex = new SyncFactoryException("Exception 1");
ex.initCause(t1);
SyncFactoryException ex1 = new SyncFactoryException("Exception 2");
SyncFactoryException ex2 = new SyncFactoryException("Exception 3");
ex2.initCause(t2);
ex.setNextException(ex1);
ex.setNextException(ex2);
int num = 0;
for (Throwable e : ex) {
assertTrue(msgs[num++].equals(e.getMessage()));
}
}
/*
* Validate that the ordering of the returned Exceptions is correct using
* traditional while loop
*/
@Test
public void test04() {
SQLException ex = new SyncFactoryException("Exception 1");
ex.initCause(t1);
SyncFactoryException ex1 = new SyncFactoryException("Exception 2");
SyncFactoryException ex2 = new SyncFactoryException("Exception 3");
ex2.initCause(t2);
ex.setNextException(ex1);
ex.setNextException(ex2);
int num = 0;
while (ex != null) {
assertTrue(msgs[num++].equals(ex.getMessage()));
Throwable c = ex.getCause();
while (c != null) {
assertTrue(msgs[num++].equals(c.getMessage()));
c = c.getCause();
}
ex = ex.getNextException();
}
}
/*
* Serialize a SyncFactoryException and make sure you can read it back properly
*/
@Test
public void test05() throws Exception {
SyncFactoryException e = new SyncFactoryException(reason);
SyncFactoryException ex1 = createSerializedException(e);
assertTrue(ex1.getMessage().equals(reason)
&& ex1.getSQLState() == null
&& ex1.getCause() == null
&& ex1.getErrorCode() == 0);
}
}

View File

@ -27,13 +27,13 @@ import java.security.Policy;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.rowset.spi.SyncFactory;
import javax.sql.rowset.spi.SyncFactoryException;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import util.BaseTest;
import util.StubContext;
import util.TestPolicy;
public class SyncFactoryPermissionsTests extends BaseTest {
@ -41,6 +41,7 @@ public class SyncFactoryPermissionsTests extends BaseTest {
Context ctx;
private static Policy policy;
private static SecurityManager sm;
private final Logger alogger = Logger.getLogger(this.getClass().getName());
/*
* Install a SeeurityManager along with a base Policy to allow testNG to run
@ -67,13 +68,7 @@ public class SyncFactoryPermissionsTests extends BaseTest {
public SyncFactoryPermissionsTests() {
policy = Policy.getPolicy();
sm = System.getSecurityManager();
try {
ctx = new InitialContext();
} catch (NamingException ex) {
Logger.getLogger(SyncFactoryPermissionsTests.class.getName()).
log(Level.SEVERE, null, ex);
}
ctx = new StubContext();
}
/*
@ -86,13 +81,21 @@ public class SyncFactoryPermissionsTests extends BaseTest {
SyncFactory.setJNDIContext(ctx);
}
/*
* Validate that a SyncFactoryException is thrown if the Logger is null
*/
@Test(expectedExceptions = SyncFactoryException.class)
public void test00() throws SyncFactoryException {
Logger l = SyncFactory.getLogger();
}
/*
* Validate that setJNDIContext succeeds if SQLPermission("setSyncFactory")
* has been granted
*/
@Test
public void test1() throws Exception {
Policy.setPolicy(new TestPolicy("setSyncFactory"));
public void test01() throws Exception {
setPolicy(new TestPolicy("setSyncFactory"));
SyncFactory.setJNDIContext(ctx);
}
@ -100,8 +103,77 @@ public class SyncFactoryPermissionsTests extends BaseTest {
* Validate that setJNDIContext succeeds if AllPermissions has been granted
*/
@Test
public void test2() throws Exception {
public void test02() throws Exception {
setPolicy(new TestPolicy("all"));
SyncFactory.setJNDIContext(ctx);
}
/*
* Validate that AccessControlException is thrown if
* SQLPermission("setSyncFactory") has not been granted
*/
@Test(expectedExceptions = AccessControlException.class)
public void test03() throws Exception {
setPolicy(new TestPolicy());
SyncFactory.setLogger(alogger);
}
/*
* Validate that setLogger succeeds if SQLPermission("setSyncFactory")
* has been granted
*/
@Test
public void test04() throws Exception {
setPolicy(new TestPolicy("setSyncFactory"));
SyncFactory.setLogger(alogger);
}
/*
* Validate that setLogger succeeds if AllPermissions has been granted
*/
@Test
public void test05() throws Exception {
setPolicy(new TestPolicy("all"));
SyncFactory.setLogger(alogger);
}
/*
* Validate that AccessControlException is thrown if
* SQLPermission("setSyncFactory") has not been granted
*/
@Test(expectedExceptions = AccessControlException.class)
public void test06() throws Exception {
setPolicy(new TestPolicy());
SyncFactory.setLogger(alogger, Level.INFO);
}
/*
* Validate that AccessControlException is thrown if
* SQLPermission("setSyncFactory") and LoggingPermission("control", null)
* have not been granted
*/
@Test(expectedExceptions = AccessControlException.class)
public void test07() throws Exception {
setPolicy(new TestPolicy("setSyncFactory"));
SyncFactory.setLogger(alogger, Level.INFO);
}
/*
* Validate that setLogger succeeds if SQLPermission("setSyncFactory")
* has been granted
*/
@Test
public void test08() throws Exception {
setPolicy(new TestPolicy("setSyncFactoryLogger"));
SyncFactory.setLogger(alogger, Level.INFO);
}
/*
* Validate that setLogger succeeds if AllPermissions has been granted
*/
@Test
public void test09() throws Exception {
setPolicy(new TestPolicy("all"));
SyncFactory.setLogger(alogger, Level.INFO);
}
}

View File

@ -0,0 +1,220 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package test.rowset.spi;
import com.sun.rowset.providers.RIOptimisticProvider;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.Context;
import javax.sql.rowset.spi.SyncFactory;
import javax.sql.rowset.spi.SyncFactoryException;
import javax.sql.rowset.spi.SyncProvider;
import static org.testng.Assert.*;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import util.PropertyStubProvider;
import util.StubSyncProvider;
import util.StubContext;
//com.sun.jndi.ldap.LdapCtxFactory
public class SyncFactoryTests {
private static String origFactory;
private final String stubProvider = "util.StubSyncProvider";
private final String propertyStubProvider = "util.PropertyStubProvider";
private final Logger alogger = Logger.getLogger(this.getClass().getName());
// Initial providers including those set via a property
List<String> initialProviders;
// All providers including those specifically registered
List<String> allProviders;
private Context ctx= null;
public SyncFactoryTests() {
// Add a provider via a property
System.setProperty("rowset.provider.classname", propertyStubProvider);
initialProviders = Arrays.asList(
"com.sun.rowset.providers.RIOptimisticProvider",
"com.sun.rowset.providers.RIXMLProvider",
propertyStubProvider);
allProviders = new ArrayList<>();
allProviders.addAll(initialProviders);
allProviders.add(stubProvider);
ctx = new StubContext();
}
@BeforeMethod
public void setUpMethod() throws Exception {
// Make sure the provider provider that is registered is removed
// before each run
SyncFactory.unregisterProvider(stubProvider);
}
/*
* Validate a non-null factory is returned
*/
@Test
public void test() throws SyncFactoryException {
SyncFactory syncFactory = SyncFactory.getSyncFactory();
assertTrue(syncFactory != null);
}
/*
* Check that the correct SyncProvider is returned for the specified
* providerID for the provider registered via a property
*/
@Test
public void test00() throws SyncFactoryException {
SyncProvider p = SyncFactory.getInstance(propertyStubProvider);
assertTrue(p instanceof PropertyStubProvider);
}
/*
* Check that the correct SyncProvider is returned for the specified
* providerID
*/
@Test
public void test01() throws SyncFactoryException {
SyncFactory.registerProvider(stubProvider);
SyncProvider p = SyncFactory.getInstance(stubProvider);
assertTrue(p instanceof StubSyncProvider);
}
/*
* Check that the Default SyncProvider is returned if an empty String is
* passed or if an invalid providerID is specified
*/
@Test
public void test02() throws SyncFactoryException {
SyncProvider p = SyncFactory.getInstance("");
assertTrue(p instanceof RIOptimisticProvider);
// Attempt to get an invalid provider and get the default provider
p = SyncFactory.getInstance("util.InvalidSyncProvider");
assertTrue(p instanceof RIOptimisticProvider);
}
/*
* Validate that a SyncFactoryException is thrown if the ProviderID is null
*/
@Test(expectedExceptions = SyncFactoryException.class)
public void test03() throws SyncFactoryException {
SyncProvider p = SyncFactory.getInstance(null);
}
/*
* Validate that a SyncFactoryException is thrown if the Logger is null
*/
@Test(expectedExceptions = SyncFactoryException.class,enabled=true)
public void test04() throws SyncFactoryException {
Logger l = SyncFactory.getLogger();
}
/*
* Validate that the correct logger is returned by getLogger
*/
@Test
public void test05() throws SyncFactoryException {
SyncFactory.setLogger(alogger);
Logger l = SyncFactory.getLogger();
assertTrue(l.equals(alogger));
}
/*
* Validate that the correct logger is returned by getLogger
*/
@Test
public void test06() throws SyncFactoryException {
SyncFactory.setLogger(alogger, Level.INFO);
Logger l = SyncFactory.getLogger();
assertTrue(l.equals(alogger));
}
/*
* Validate that a driver that is registered is returned by
* getRegisteredProviders and if it is unregistered, that it is
* not returned by getRegisteredProviders
*/
@Test
public void test07() throws SyncFactoryException {
// Validate that only the default providers and any specified via
// a System property are available
validateProviders(initialProviders);
// Register a provider and make sure it is avaiable
SyncFactory.registerProvider(stubProvider);
validateProviders(allProviders);
// Check that if a provider is unregistered, it does not show as
// registered
SyncFactory.unregisterProvider(stubProvider);
validateProviders(initialProviders);
}
/*
* Validate that setJNDIContext throws a SyncFactoryException if the
* context is null
*/
@Test(expectedExceptions = SyncFactoryException.class, enabled=true)
public void test08() throws Exception {
SyncFactory.setJNDIContext(null);
}
/*
* Validate that setJNDIContext succeeds
*/
@Test(enabled=true)
public void test09() throws Exception {
SyncFactory.setJNDIContext(ctx);
}
/*
* Utility method to validate the expected providers are regsitered
*/
private void validateProviders(List<String> expectedProviders)
throws SyncFactoryException {
List<String> results = new ArrayList<>();
Enumeration<SyncProvider> providers = SyncFactory.getRegisteredProviders();
while (providers.hasMoreElements()) {
SyncProvider p = providers.nextElement();
results.add(p.getProviderID());
}
assertTrue(expectedProviders.containsAll(results)
&& results.size() == expectedProviders.size());
}
/*
* Utility method to dump out SyncProvider info for a registered provider
*/
private void showImpl(SyncProvider impl) {
System.out.println("Provider implementation:"
+ "\nVendor: " + impl.getVendor()
+ "\nVersion: " + impl.getVersion()
+ "\nProviderID: " + impl.getProviderID());
}
}

View File

@ -0,0 +1,187 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package test.rowset.spi;
import com.sun.rowset.internal.SyncResolverImpl;
import java.sql.SQLException;
import javax.sql.rowset.spi.SyncProviderException;
import static org.testng.Assert.*;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
import util.BaseTest;
import util.StubSyncResolver;
public class SyncProviderExceptionTests extends BaseTest {
@BeforeClass
public static void setUpClass() throws Exception {
System.out.println(System.getProperty("java.naming.factory.initial"));
}
@AfterClass
public static void tearDownClass() throws Exception {
}
/*
* Create SyncProviderException with no-arg constructor
*/
@Test
public void test() {
SyncProviderException ex = new SyncProviderException();
assertTrue(ex.getMessage() == null
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0
&& ex.getSyncResolver() instanceof SyncResolverImpl);
}
/*
* Create SyncProviderException with no-arg constructor and
* call setSyncResolver to indicate the SyncResolver to use
*/
@Test
public void test01() {
SyncProviderException ex = new SyncProviderException();
ex.setSyncResolver(new StubSyncResolver());
assertTrue(ex.getMessage() == null
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0
&& ex.getSyncResolver() instanceof StubSyncResolver);
}
/*
* Create SyncProviderException with message
*/
@Test
public void test02() {
SyncProviderException ex = new SyncProviderException(reason);
assertTrue(ex.getMessage().equals(reason)
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0
&& ex.getSyncResolver() instanceof SyncResolverImpl);
}
/*
* Create SyncProviderException with message and
* call setSyncResolver to indicate the SyncResolver to use
*/
@Test
public void test03() {
SyncProviderException ex = new SyncProviderException(reason);
ex.setSyncResolver(new StubSyncResolver());
assertTrue(ex.getMessage().equals(reason)
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0
&& ex.getSyncResolver() instanceof StubSyncResolver);
}
/*
* Create SyncProviderException with and specify the SyncResolver to use
*/
@Test
public void test04() {
SyncProviderException ex = new SyncProviderException(new StubSyncResolver());
assertTrue(ex.getMessage() == null
&& ex.getSQLState() == null
&& ex.getCause() == null
&& ex.getErrorCode() == 0
&& ex.getSyncResolver() instanceof StubSyncResolver);
}
/*
* Validate that the ordering of the returned Exceptions is correct using
* for-each loop
*/
@Test
public void test05() {
SyncProviderException ex = new SyncProviderException("Exception 1");
ex.initCause(t1);
SyncProviderException ex1 = new SyncProviderException("Exception 2");
SyncProviderException ex2 = new SyncProviderException("Exception 3");
ex2.initCause(t2);
ex.setNextException(ex1);
ex.setNextException(ex2);
int num = 0;
for (Throwable e : ex) {
assertTrue(msgs[num++].equals(e.getMessage()));
}
}
/*
* Validate that the ordering of the returned Exceptions is correct using
* traditional while loop
*/
@Test
public void test06() {
SQLException ex = new SyncProviderException("Exception 1");
ex.initCause(t1);
SyncProviderException ex1 = new SyncProviderException("Exception 2");
SyncProviderException ex2 = new SyncProviderException("Exception 3");
ex2.initCause(t2);
ex.setNextException(ex1);
ex.setNextException(ex2);
int num = 0;
while (ex != null) {
assertTrue(msgs[num++].equals(ex.getMessage()));
Throwable c = ex.getCause();
while (c != null) {
assertTrue(msgs[num++].equals(c.getMessage()));
c = c.getCause();
}
ex = ex.getNextException();
}
}
/*
* Serialize a SyncProviderException and make sure you can read it back properly
*/
@Test
public void test07() throws Exception {
SyncProviderException e = new SyncProviderException(reason);
SyncProviderException ex1 = createSerializedException(e);
assertTrue(ex1.getMessage().equals(reason)
&& ex1.getSQLState() == null
&& ex1.getCause() == null
&& ex1.getErrorCode() == 0
&& ex1.getSyncResolver() instanceof SyncResolverImpl, ex1.getSyncResolver().getClass().getName());
}
/*
* Serialize a SyncProviderException and make sure you can read it back properly
*/
@Test
public void test08() throws Exception {
SyncProviderException e = new SyncProviderException(reason);
e.setSyncResolver(new StubSyncResolver());
SyncProviderException ex1 = createSerializedException(e);
assertTrue(ex1.getMessage().equals(reason)
&& ex1.getSQLState() == null
&& ex1.getCause() == null
&& ex1.getErrorCode() == 0
&& ex1.getSyncResolver() instanceof StubSyncResolver);
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 util;
public class PropertyStubProvider extends StubSyncProvider {
}

View File

@ -0,0 +1,220 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 util;
import java.util.Hashtable;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
@SuppressWarnings("unchecked")
public class StubContext implements Context {
@Override
public Object lookup(Name name) throws NamingException {
return null;
}
@Override
public Object lookup(String name) throws NamingException {
return null;
}
@Override
public void bind(Name name, Object obj) throws NamingException {
}
@Override
public void bind(String name, Object obj) throws NamingException {
}
@Override
public void rebind(Name name, Object obj) throws NamingException {
}
@Override
public void rebind(String name, Object obj) throws NamingException {
}
@Override
public void unbind(Name name) throws NamingException {
}
@Override
public void unbind(String name) throws NamingException {
}
@Override
public void rename(Name oldName, Name newName) throws NamingException {
}
@Override
public void rename(String oldName, String newName) throws NamingException {
}
@Override
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException {
return new NamingEnumerationStub();
}
@Override
public NamingEnumeration<NameClassPair> list(String name) throws NamingException {
return new NamingEnumerationStub();
}
@Override
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException {
return new NamingEnumerationStub();
}
@Override
public NamingEnumeration<Binding> listBindings(String name) throws NamingException {
return new NamingEnumerationStub();
}
@Override
public void destroySubcontext(Name name) throws NamingException {
}
@Override
public void destroySubcontext(String name) throws NamingException {
}
@Override
public Context createSubcontext(Name name) throws NamingException {
return null;
}
@Override
public Context createSubcontext(String name) throws NamingException {
return null;
}
@Override
public Object lookupLink(Name name) throws NamingException {
return null;
}
@Override
public Object lookupLink(String name) throws NamingException {
return null;
}
@Override
public NameParser getNameParser(Name name) throws NamingException {
return new NameParserStub();
}
@Override
public NameParser getNameParser(String name) throws NamingException {
return new NameParserStub();
}
@Override
public Name composeName(Name name, Name prefix) throws NamingException {
return null;
}
@Override
public String composeName(String name, String prefix) throws NamingException {
return null;
}
@Override
public Object addToEnvironment(String propName, Object propVal) throws NamingException {
return null;
}
@Override
public Object removeFromEnvironment(String propName) throws NamingException {
return null;
}
@Override
public Hashtable<?, ?> getEnvironment() throws NamingException {
return new Hashtable();
}
@Override
public void close() throws NamingException {
}
@Override
public String getNameInNamespace() throws NamingException {
return null;
}
class NamingEnumerationStub implements NamingEnumeration {
@Override
public Object next() throws NamingException {
return null;
}
@Override
public boolean hasMore() throws NamingException {
return false;
}
@Override
public void close() throws NamingException {
}
@Override
public boolean hasMoreElements() {
return false;
}
@Override
public Object nextElement() {
return null;
}
}
class NameParserStub implements NameParser {
@Override
public Name parse(String name) throws NamingException {
return null;
}
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 util;
import javax.sql.RowSetReader;
import javax.sql.RowSetWriter;
import javax.sql.rowset.spi.SyncProvider;
import javax.sql.rowset.spi.SyncProviderException;
public class StubSyncProvider extends SyncProvider {
/**
* The unique provider identifier.
*/
private String providerID = "util.StubSyncProvider";
/**
* The vendor name of this SyncProvider implementation
*/
private String vendorName = "Oracle Corporation";
/**
* The version number of this SyncProvider implementation
*/
private String versionNumber = "1.0";
@Override
public String getProviderID() {
return providerID;
}
@Override
public RowSetReader getRowSetReader() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public RowSetWriter getRowSetWriter() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getProviderGrade() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public void setDataSourceLock(int datasource_lock) throws SyncProviderException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int getDataSourceLock() throws SyncProviderException {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public int supportsUpdatableView() {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public String getVersion() {
return versionNumber;
}
@Override
public String getVendor() {
return vendorName;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,116 @@
package parse;
import java.io.IOException;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import static org.testng.Assert.assertEquals;
import org.testng.annotations.Test;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.ext.DefaultHandler2;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* JDK-6770436: Entity callback order differs between Java1.5 and Java1.6
* https://bugs.openjdk.java.net/browse/JDK-6770436
*
*/
public class EntityCharacterEventOrder {
protected final static String xmlEncoding = "ISO-8859-15";
protected static Charset xmlEncodingCharset = null;
String _xml;
static {
xmlEncodingCharset = Charset.forName(xmlEncoding);
}
/**
public static void main(String[] args) {
TestRunner.run(JDK6770436Test.class);
}
*/
@Test
public void entityCallbackOrderJava() throws SAXException, IOException {
final String input = "<element> &amp; some more text</element>";
final MockContentHandler handler = new MockContentHandler();
final XMLReader xmlReader = XMLReaderFactory.createXMLReader();
xmlReader.setContentHandler(handler);
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
xmlReader.parse(new InputSource(new StringReader(input)));
final List<String> events = handler.getEvents();
printEvents(events);
assertCallbackOrder(events); //regression from JDK5
}
private void assertCallbackOrder(final List<String> events) {
assertEquals("startDocument", events.get(0));
assertEquals("startElement 'element'", events.get(1));
assertEquals("characters ' '", events.get(2));
assertEquals("startEntity 'amp'", events.get(3));
assertEquals("characters '&'", events.get(4));
assertEquals("endEntity 'amp'", events.get(5));
assertEquals("characters ' some more text'", events.get(6));
assertEquals("endElement 'element'", events.get(7));
assertEquals("endDocument", events.get(8));
}
private void printEvents(final List<String> events) {
events.stream().forEach((e) -> {
System.out.println(e);
});
}
private class MockContentHandler extends DefaultHandler2 {
private List<String> events;
public List<String> getEvents() {
return events;
}
@Override
public void startDocument() throws SAXException {
events = new ArrayList<String>();
events.add("startDocument");
}
@Override
public void characters(char[] ch, int start, int length) throws SAXException {
events.add("characters '" + new String(ch, start, length) + "'");
}
@Override
public void startElement(String uri, String localName, String name, Attributes atts) throws SAXException {
events.add("startElement '" + name + "'");
}
@Override
public void endElement(String uri, String localName, String name) throws SAXException {
events.add("endElement '" + name + "'");
}
@Override
public void endDocument() throws SAXException {
events.add("endDocument");
}
@Override
public void startEntity(String name) throws SAXException {
events.add("startEntity '" + name + "'");
}
@Override
public void endEntity(String name) throws SAXException {
events.add("endEntity '" + name + "'");
}
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 8062744
* @run main SupportedOptions
*/
import java.net.*;
import java.io.IOException;
import jdk.net.*;
public class SupportedOptions {
public static void main(String[] args) throws Exception {
if (!Sockets.supportedOptions(ServerSocket.class)
.contains(StandardSocketOptions.IP_TOS)) {
throw new RuntimeException("Test failed");
}
// Now set the option
ServerSocket ss = new ServerSocket();
if (!ss.supportedOptions().contains(StandardSocketOptions.IP_TOS)) {
throw new RuntimeException("Test failed");
}
Sockets.setOption(ss, java.net.StandardSocketOptions.IP_TOS, 128);
}
}

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.testlibrary;
import java.util.Collection;
import java.util.Formatter;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* A log manager designed specifically to allow collecting ordered log messages
* in a multi-threaded environment without involving any kind of locking.
* <p>
* It is particularly useful in situations when one needs to assert various
* details about the tested thread state or the locks it hold while also wanting
* to produce diagnostic log messages.
* <p>
* The log manager does not provide any guarantees about the completness of the
* logs written from different threads - it is up to the caller to make sure
* {@code toString()} method is called only when all the activity has ceased
* and the per-thread logs contain all the necessary data.
*
* @author Jaroslav Bachorik
**/
public class LockFreeLogManager {
private final AtomicInteger logCntr = new AtomicInteger(0);
private final Collection<Map<Integer, String>> allRecords = new ConcurrentLinkedQueue<>();
private final ThreadLocal<Map<Integer, String>> records = new ThreadLocal<Map<Integer, String>>() {
@Override
protected Map<Integer, String> initialValue() {
Map<Integer, String> m = new ConcurrentHashMap<>();
allRecords.add(m);
return m;
}
};
/**
* Log a message
* @param format Message format
* @param params Message parameters
*/
public void log(String format, Object ... params) {
int id = logCntr.getAndIncrement();
try (Formatter formatter = new Formatter()) {
records.get().put(id, formatter.format(format, params).toString());
}
}
/**
* Will generate an aggregated log of chronologically ordered messages.
* <p>
* Make sure that you call this method only when all the related threads
* have finished; otherwise you might get incomplete data.
*
* @return An aggregated log of chronologically ordered messages
*/
@Override
public String toString() {
return allRecords.stream()
.flatMap(m->m.entrySet().stream())
.sorted((l, r)->l.getKey().compareTo(r.getKey()))
.map(e->e.getValue())
.collect(Collectors.joining());
}
}

View File

@ -0,0 +1,106 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please 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 8057810
* @summary New defaults for DSA keys in jarsigner and keytool
*/
import sun.security.pkcs.PKCS7;
import sun.security.util.KeyUtil;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import java.util.jar.JarFile;
public class DefaultSigalg {
public static void main(String[] args) throws Exception {
// Three test cases
String[] keyalgs = {"DSA", "RSA", "EC"};
// Expected default keytool sigalg
String[] sigalgs = {"SHA256withDSA", "SHA256withRSA", "SHA256withECDSA"};
// Expected keysizes
int[] keysizes = {2048, 2048, 256};
// Expected jarsigner digest alg used in signature
String[] digestalgs = {"SHA-256", "SHA-256", "SHA-256"};
// Create a jar file
sun.tools.jar.Main m =
new sun.tools.jar.Main(System.out, System.err, "jar");
Files.write(Paths.get("x"), new byte[10]);
if (!m.run("cvf a.jar x".split(" "))) {
throw new Exception("jar creation failed");
}
// Generate keypairs and sign the jar
Files.deleteIfExists(Paths.get("jks"));
for (String keyalg: keyalgs) {
sun.security.tools.keytool.Main.main(
("-keystore jks -storepass changeit -keypass changeit " +
"-dname CN=A -alias " + keyalg + " -genkeypair " +
"-keyalg " + keyalg).split(" "));
sun.security.tools.jarsigner.Main.main(
("-keystore jks -storepass changeit a.jar " + keyalg).split(" "));
}
// Check result
KeyStore ks = KeyStore.getInstance("JKS");
try (FileInputStream jks = new FileInputStream("jks");
JarFile jf = new JarFile("a.jar")) {
ks.load(jks, null);
for (int i = 0; i<keyalgs.length; i++) {
String keyalg = keyalgs[i];
// keytool
X509Certificate c = (X509Certificate) ks.getCertificate(keyalg);
String sigalg = c.getSigAlgName();
if (!sigalg.equals(sigalgs[i])) {
throw new Exception(
"keytool sigalg for " + keyalg + " is " + sigalg);
}
int keysize = KeyUtil.getKeySize(c.getPublicKey());
if (keysize != keysizes[i]) {
throw new Exception(
"keytool keysize for " + keyalg + " is " + keysize);
}
// jarsigner
String bk = "META-INF/" + keyalg + "." + keyalg;
try (InputStream is = jf.getInputStream(jf.getEntry(bk))) {
String digestalg = new PKCS7(is).getSignerInfos()[0]
.getDigestAlgorithmId().toString();
if (!digestalg.equals(digestalgs[i])) {
throw new Exception(
"jarsigner digest of sig for " + keyalg
+ " is " + digestalg);
}
}
}
}
}
}

View File

@ -170,6 +170,13 @@ public class KeyToolTest {
*/
void testOK(String input, String cmd) throws Exception {
try {
// Workaround for "8057810: Make SHA256withDSA the default
// jarsigner and keytool algorithm for DSA keys". Unfortunately
// SunPKCS11-NSS does not support SHA256withDSA yet.
if (cmd.contains("p11-nss.txt") && cmd.contains("-genkey")
&& !cmd.contains("-keyalg")) {
cmd += " -sigalg SHA1withDSA -keysize 1024";
}
test(input, cmd);
} catch(Exception e) {
afterFail(input, cmd, "OK");
@ -245,6 +252,9 @@ public class KeyToolTest {
* Helper method, print some output after a test does not do as expected
*/
void afterFail(String input, String cmd, String should) {
if (cmd.contains("p11-nss.txt")) {
cmd = "-J-Dnss.lib=" + System.getProperty("nss.lib") + " " + cmd;
}
System.err.println("\nTest fails for the command ---\n" +
"keytool " + cmd + "\nOr its debug version ---\n" +
"keytool -debug " + cmd);
@ -799,7 +809,7 @@ public class KeyToolTest {
remove("x.jks.p1.cert");
remove("csr1");
// PrivateKeyEntry can do certreq
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala");
testOK("", "-keystore x.jks -storepass changeit -keypass changeit -genkeypair -dname CN=olala -keysize 1024");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -alias mykey");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1");
testOK("", "-keystore x.jks -storepass changeit -certreq -file csr1 -sigalg SHA1withDSA");

View File

@ -118,13 +118,4 @@ echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dnss \
KeyToolTest
status=$?
rm -f p11-nss.txt
rm -f cert8.db
rm -f key3.db
rm -f secmod.db
rm HumanInputStream*.class
rm KeyToolTest*.class
rm TestException.class
exit $status

View File

@ -62,9 +62,5 @@ ${COMPILEJAVA}${FS}bin${FS}javac ${TESTJAVACOPTS} ${TESTTOOLVMOPTS} -d . -XDigno
echo | ${TESTJAVA}${FS}bin${FS}java ${TESTVMOPTS} -Dfile KeyToolTest
status=$?
rm HumanInputStream*.class
rm KeyToolTest*.class
rm TestException.class
exit $status

View File

@ -1,4 +1,4 @@
# Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -335,6 +335,14 @@ endif
#################################################################
#
# Load custom Javadoc rules
#
$(eval $(call IncludeCustomExtension, , Javadoc.gmk))
#################################################################
#
# Default target is same as docs target, create core api and all others it can
#

View File

@ -514,7 +514,7 @@ clean-docs: clean-docstemp
# If the output directory was created by configure and now becomes empty, remove it as well.
dist-clean: clean
($(CD) $(OUTPUT_ROOT) && $(RM) -r *spec.gmk config.* configure-arguments \
Makefile compare.sh spec.sh tmp javacservers)
Makefile compare.sh tmp javacservers)
$(if $(filter $(CONF_NAME),$(notdir $(OUTPUT_ROOT))), \
if test "x`$(LS) $(OUTPUT_ROOT)`" != x; then \
$(ECHO) "Warning: Not removing non-empty configuration directory for '$(CONF_NAME)'" ; \

View File

@ -791,18 +791,9 @@
<export>
<name>javax.management.timer</name>
</export>
<export>
<name>com.sun.jmx.defaults</name>
<to>jdk.snmp</to>
</export>
<export>
<name>com.sun.jmx.mbeanserver</name>
<to>jdk.snmp</to>
</export>
<export>
<name>sun.management</name>
<to>jdk.jconsole</to>
<to>jdk.snmp</to>
</export>
</module>
<module>

View File

@ -271,3 +271,4 @@ b374d8910e7f8de2b7ecacee9ae4cad88f23feab jdk9-b33
63b8da4c958c3bbadfff082c547983f5daa50c0f jdk9-b35
10fe62bc188476abb025e55f55128cbfecf24584 jdk9-b36
dd7bbdf81a537106cfa9227d1a9a57849cb26b4d jdk9-b37
365f55e7b3c45637bf912c88d31b32a127ad7429 jdk9-b38

View File

@ -29,14 +29,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class EvalFile {
public static void main(String[] args) throws Exception {
public static void main(final String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngineManager factory = new ScriptEngineManager();
// create JavaScript engine
ScriptEngine engine = factory.getEngineByName("nashorn");
final ScriptEngine engine = factory.getEngineByName("nashorn");
// evaluate JavaScript code from given file - specified by first argument
engine.eval(new java.io.FileReader(args[0]));
}

View File

@ -29,14 +29,16 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class EvalScript {
public static void main(String[] args) throws Exception {
public static void main(final String[] args) throws Exception {
// create a script engine manager
ScriptEngineManager factory = new ScriptEngineManager();
final ScriptEngineManager factory = new ScriptEngineManager();
// create a JavaScript engine
ScriptEngine engine = factory.getEngineByName("nashorn");
final ScriptEngine engine = factory.getEngineByName("nashorn");
// evaluate JavaScript code from String
engine.eval("print('Hello, World')");
}

View File

@ -29,22 +29,25 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class InvokeScriptFunction {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
String script = "function hello(name) { print('Hello, ' + name); }";
final String script = "function hello(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
Invocable inv = (Invocable) engine;
final Invocable inv = (Invocable) engine;
// invoke the global function named "hello"
inv.invokeFunction("hello", "Scripting!!" );

View File

@ -29,26 +29,29 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class InvokeScriptMethod {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String. This code defines a script object 'obj'
// with one method called 'hello'.
String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
final String script = "var obj = new Object(); obj.hello = function(name) { print('Hello, ' + name); }";
// evaluate script
engine.eval(script);
// javax.script.Invocable is an optional interface.
// Check whether your script engine implements or not!
// Note that the JavaScript engine implements Invocable interface.
Invocable inv = (Invocable) engine;
final Invocable inv = (Invocable) engine;
// get script object on which we want to call the method
Object obj = engine.get("obj");
final Object obj = engine.get("obj");
// invoke the method named "hello" on the script object "obj"
inv.invokeMethod(obj, "hello", "Script Method !!" );

View File

@ -29,12 +29,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.Bindings;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.SimpleScriptContext;
@SuppressWarnings("javadoc")
public class MultiScopes {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
engine.put("x", "hello");
// print global variable "x"
@ -42,9 +47,9 @@ public class MultiScopes {
// the above line prints "hello"
// Now, pass a different script context
ScriptContext newContext = new SimpleScriptContext();
final ScriptContext newContext = new SimpleScriptContext();
newContext.setBindings(engine.createBindings(), ScriptContext.ENGINE_SCOPE);
Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
final Bindings engineScope = newContext.getBindings(ScriptContext.ENGINE_SCOPE);
// add new variable "x" to the new engineScope
engineScope.put("x", "world");

View File

@ -29,28 +29,31 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class RunnableImpl {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
String script = "function run() { print('run called'); }";
final String script = "function run() { print('run called'); }";
// evaluate script
engine.eval(script);
Invocable inv = (Invocable) engine;
final Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script functions with the matching name.
Runnable r = inv.getInterface(Runnable.class);
final Runnable r = inv.getInterface(Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
Thread th = new Thread(r);
final Thread th = new Thread(r);
th.start();
th.join();
}

View File

@ -29,31 +29,34 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class RunnableImplObject {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
// JavaScript code in a String
String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
final String script = "var obj = new Object(); obj.run = function() { print('run method called'); }";
// evaluate script
engine.eval(script);
// get script object on which we want to implement the interface with
Object obj = engine.get("obj");
final Object obj = engine.get("obj");
Invocable inv = (Invocable) engine;
final Invocable inv = (Invocable) engine;
// get Runnable interface object from engine. This interface methods
// are implemented by script methods of object 'obj'
Runnable r = inv.getInterface(obj, Runnable.class);
final Runnable r = inv.getInterface(obj, Runnable.class);
// start a new thread that runs the script implemented
// runnable interface
Thread th = new Thread(r);
final Thread th = new Thread(r);
th.start();
th.join();
}

View File

@ -29,15 +29,17 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
import javax.script.*;
import java.io.*;
import java.io.File;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
@SuppressWarnings("javadoc")
public class ScriptVars {
public static void main(String[] args) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("nashorn");
public static void main(final String[] args) throws Exception {
final ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByName("nashorn");
File f = new File("test.txt");
final File f = new File("test.txt");
// expose File object as variable to script
engine.put("file", f);

View File

@ -97,6 +97,7 @@ import jdk.internal.dynalink.beans.BeansLinker;
import jdk.internal.dynalink.linker.GuardingDynamicLinker;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
import jdk.internal.dynalink.support.AutoDiscovery;
import jdk.internal.dynalink.support.BottomGuardingDynamicLinker;
import jdk.internal.dynalink.support.ClassLoaderGetterContextProvider;
@ -105,6 +106,7 @@ import jdk.internal.dynalink.support.CompositeTypeBasedGuardingDynamicLinker;
import jdk.internal.dynalink.support.DefaultPrelinkFilter;
import jdk.internal.dynalink.support.LinkerServicesImpl;
import jdk.internal.dynalink.support.TypeConverterFactory;
import jdk.internal.dynalink.support.TypeUtilities;
/**
* A factory class for creating {@link DynamicLinker}s. The most usual dynamic linker is a linker that is a composition
@ -115,7 +117,6 @@ import jdk.internal.dynalink.support.TypeConverterFactory;
* @author Attila Szegedi
*/
public class DynamicLinkerFactory {
/**
* Default value for {@link #setUnstableRelinkThreshold(int) unstable relink threshold}.
*/
@ -130,6 +131,7 @@ public class DynamicLinkerFactory {
private boolean syncOnRelink = false;
private int unstableRelinkThreshold = DEFAULT_UNSTABLE_RELINK_THRESHOLD;
private GuardedInvocationFilter prelinkFilter;
private MethodTypeConversionStrategy autoConversionStrategy;
/**
* Sets the class loader for automatic discovery of available linkers. If not set explicitly, then the thread
@ -258,6 +260,29 @@ public class DynamicLinkerFactory {
this.prelinkFilter = prelinkFilter;
}
/**
* Sets an object representing the conversion strategy for automatic type conversions. After
* {@link TypeConverterFactory#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has
* applied all custom conversions to a method handle, it still needs to effect
* {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that
* can usually be automatically applied as per
* {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}.
* However, sometimes language runtimes will want to customize even those conversions for their own call
* sites. A typical example is allowing unboxing of null return values, which is by default prohibited by
* ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom
* automatic conversion strategy, that can deal with null values. Note that when the strategy's
* {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)}
* is invoked, the custom language conversions will already have been applied to the method handle, so by
* design the difference between the handle's current method type and the desired final type will always
* only be ones that can be subjected to method invocation conversions. The strategy also doesn't need to
* invoke a final {@code MethodHandle.asType()} as the converter factory will do that as the final step.
* @param autoConversionStrategy the strategy for applying method invocation conversions for the linker
* created by this factory.
*/
public void setAutoConversionStrategy(final MethodTypeConversionStrategy autoConversionStrategy) {
this.autoConversionStrategy = autoConversionStrategy;
}
/**
* Creates a new dynamic linker consisting of all the prioritized, autodiscovered, and fallback linkers as well as
* the pre-link filter.
@ -324,8 +349,9 @@ public class DynamicLinkerFactory {
prelinkFilter = new DefaultPrelinkFilter();
}
return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters), composite),
prelinkFilter, runtimeContextArgCount, syncOnRelink, unstableRelinkThreshold);
return new DynamicLinker(new LinkerServicesImpl(new TypeConverterFactory(typeConverters,
autoConversionStrategy), composite), prelinkFilter, runtimeContextArgCount, syncOnRelink,
unstableRelinkThreshold);
}
private static ClassLoader getThreadContextClassLoader() {

View File

@ -287,10 +287,21 @@ abstract class AbstractJavaLinker implements GuardingDynamicLinker {
*/
private static SingleDynamicMethod createDynamicMethod(final AccessibleObject m) {
if(CallerSensitiveDetector.isCallerSensitive(m)) {
// Method has @CallerSensitive annotation
return new CallerSensitiveDynamicMethod(m);
}
// Method has no @CallerSensitive annotation
final MethodHandle mh;
try {
mh = unreflectSafely(m);
} catch (final IllegalAccessError e) {
// java.lang.invoke can in some case conservatively treat as caller sensitive methods that aren't
// marked with the annotation. In this case, we'll fall back to treating it as caller sensitive.
return new CallerSensitiveDynamicMethod(m);
}
// Proceed with non-caller sensitive
final Member member = (Member)m;
return new SimpleDynamicMethod(unreflectSafely(m), member.getDeclaringClass(), member.getName(), m instanceof Constructor);
return new SimpleDynamicMethod(mh, member.getDeclaringClass(), member.getName(), m instanceof Constructor);
}
/**

View File

@ -0,0 +1,100 @@
/*
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute 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.
*/
/*
* This file is available under and governed by the GNU General Public
* License version 2 only, as published by the Free Software Foundation.
* However, the following notice accompanied the original version of this
* file, and Oracle licenses the original version of this file under the BSD
* license:
*/
/*
Copyright 2014 Attila Szegedi
Licensed under both the Apache License, Version 2.0 (the "Apache License")
and the BSD License (the "BSD License"), with licensee being free to
choose either of the two at their discretion.
You may not use this file except in compliance with either the Apache
License or the BSD License.
If you choose to use this file in compliance with the Apache License, the
following notice applies to you:
You may obtain a copy of the Apache License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied. See the License for the specific language governing
permissions and limitations under the License.
If you choose to use this file in compliance with the BSD License, the
following notice applies to you:
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package jdk.internal.dynalink.linker;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodType;
/**
* Interface for objects representing a strategy for converting a method handle to a new type.
*/
public interface MethodTypeConversionStrategy {
/**
* Converts a method handle to a new type.
* @param target target method handle
* @param newType new type
* @return target converted to the new type.
*/
public MethodHandle asType(final MethodHandle target, final MethodType newType);
}

View File

@ -97,6 +97,7 @@ import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.GuardedTypeConversion;
import jdk.internal.dynalink.linker.GuardingTypeConverterFactory;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
/**
* A factory for type converters. This class is the main implementation behind the
@ -109,6 +110,7 @@ public class TypeConverterFactory {
private final GuardingTypeConverterFactory[] factories;
private final ConversionComparator[] comparators;
private final MethodTypeConversionStrategy autoConversionStrategy;
private final ClassValue<ClassMap<MethodHandle>> converterMap = new ClassValue<ClassMap<MethodHandle>>() {
@Override
@ -177,8 +179,24 @@ public class TypeConverterFactory {
* Creates a new type converter factory from the available {@link GuardingTypeConverterFactory} instances.
*
* @param factories the {@link GuardingTypeConverterFactory} instances to compose.
* @param autoConversionStrategy conversion strategy for automatic type conversions. After
* {@link #asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)} has applied all custom
* conversions to a method handle, it still needs to effect
* {@link TypeUtilities#isMethodInvocationConvertible(Class, Class) method invocation conversions} that
* can usually be automatically applied as per
* {@link java.lang.invoke.MethodHandle#asType(java.lang.invoke.MethodType)}.
* However, sometimes language runtimes will want to customize even those conversions for their own call
* sites. A typical example is allowing unboxing of null return values, which is by default prohibited by
* ordinary {@code MethodHandles.asType}. In this case, a language runtime can install its own custom
* automatic conversion strategy, that can deal with null values. Note that when the strategy's
* {@link MethodTypeConversionStrategy#asType(java.lang.invoke.MethodHandle, java.lang.invoke.MethodType)}
* is invoked, the custom language conversions will already have been applied to the method handle, so by
* design the difference between the handle's current method type and the desired final type will always
* only be ones that can be subjected to method invocation conversions. Can be null, in which case no
* custom strategy is employed.
*/
public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories) {
public TypeConverterFactory(final Iterable<? extends GuardingTypeConverterFactory> factories,
final MethodTypeConversionStrategy autoConversionStrategy) {
final List<GuardingTypeConverterFactory> l = new LinkedList<>();
final List<ConversionComparator> c = new LinkedList<>();
for(final GuardingTypeConverterFactory factory: factories) {
@ -189,20 +207,24 @@ public class TypeConverterFactory {
}
this.factories = l.toArray(new GuardingTypeConverterFactory[l.size()]);
this.comparators = c.toArray(new ConversionComparator[c.size()]);
this.autoConversionStrategy = autoConversionStrategy;
}
/**
* Similar to {@link MethodHandle#asType(MethodType)} except it also hooks in method handles produced by
* {@link GuardingTypeConverterFactory} implementations, providing for language-specific type coercing of
* parameters. It will apply {@link MethodHandle#asType(MethodType)} for all primitive-to-primitive,
* wrapper-to-primitive, primitive-to-wrapper conversions as well as for all upcasts. For all other conversions,
* it'll insert {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
* provided by {@link GuardingTypeConverterFactory} implementations.
* parameters. For all conversions that are not a JLS method invocation conversion it'll insert
* {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with composite filters
* provided by {@link GuardingTypeConverterFactory} implementations. For the remaining JLS method invocation
* conversions, it will invoke {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)} first
* if an automatic conversion strategy was specified in the
* {@link #TypeConverterFactory(Iterable, MethodTypeConversionStrategy) constructor}, and finally apply
* {@link MethodHandle#asType(MethodType)} for any remaining conversions.
*
* @param handle target method handle
* @param fromType the types of source arguments
* @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)} and
* @return a method handle that is a suitable combination of {@link MethodHandle#asType(MethodType)},
* {@link MethodTypeConversionStrategy#asType(MethodHandle, MethodType)}, and
* {@link MethodHandles#filterArguments(MethodHandle, int, MethodHandle...)} with
* {@link GuardingTypeConverterFactory} produced type converters as filters.
*/
@ -246,8 +268,12 @@ public class TypeConverterFactory {
}
}
// Take care of automatic conversions
return newHandle.asType(fromType);
// Give change to automatic conversion strategy, if one is present.
final MethodHandle autoConvertedHandle =
autoConversionStrategy != null ? autoConversionStrategy.asType(newHandle, fromType) : newHandle;
// Do a final asType for any conversions that remain.
return autoConvertedHandle.asType(fromType);
}
private static MethodHandle applyConverters(final MethodHandle handle, final int pos, final List<MethodHandle> converters) {

View File

@ -520,4 +520,13 @@ public class TypeUtilities {
public static Class<?> getWrapperType(final Class<?> primitiveType) {
return WRAPPER_TYPES.get(primitiveType);
}
/**
* Returns true if the passed type is a wrapper for a primitive type.
* @param type the examined type
* @return true if the passed type is a wrapper for a primitive type.
*/
public static boolean isWrapperType(final Class<?> type) {
return PRIMITIVE_TYPES.containsKey(type);
}
}

View File

@ -27,8 +27,8 @@ package jdk.nashorn.internal;
/**
* Class that exposes the current state of asserts.
*
*/
@SuppressWarnings("all")
public final class AssertsEnabled {
private static boolean assertsEnabled = false;
static {

View File

@ -29,6 +29,7 @@ import static jdk.nashorn.internal.codegen.CompilerConstants.ARGUMENTS_VAR;
import static jdk.nashorn.internal.codegen.CompilerConstants.EXPLODED_ARGUMENT_PREFIX;
import java.lang.invoke.MethodType;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
@ -93,6 +94,8 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
private final Deque<List<IdentNode>> explodedArguments = new ArrayDeque<>();
private final Deque<MethodType> callSiteTypes = new ArrayDeque<>();
private static final String ARGUMENTS = ARGUMENTS_VAR.symbolName();
/**
@ -118,86 +121,108 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
return context.getLogger(this.getClass());
}
@SuppressWarnings("serial")
private static class TransformFailedException extends RuntimeException {
TransformFailedException(final FunctionNode fn, final String message) {
super(massageURL(fn.getSource().getURL()) + '.' + fn.getName() + " => " + message, null, false, false);
}
}
@SuppressWarnings("serial")
private static class AppliesFoundException extends RuntimeException {
AppliesFoundException() {
super("applies_found", null, false, false);
}
}
private static final AppliesFoundException HAS_APPLIES = new AppliesFoundException();
private boolean hasApplies(final FunctionNode functionNode) {
try {
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
@Override
public boolean enterCallNode(final CallNode callNode) {
if (isApply(callNode)) {
throw HAS_APPLIES;
}
return true;
}
});
} catch (final AppliesFoundException e) {
return true;
}
log.fine("There are no applies in ", DebugLogger.quote(functionNode.getName()), " - nothing to do.");
return false; // no applies
}
/**
* Arguments may only be used as args to the apply. Everything else is disqualified
* We cannot control arguments if they escape from the method and go into an unknown
* scope, thus we are conservative and treat any access to arguments outside the
* apply call as a case of "we cannot apply the optimization".
*
* @return true if arguments escape
*/
private boolean argumentsEscape(final FunctionNode functionNode) {
@SuppressWarnings("serial")
final UnsupportedOperationException uoe = new UnsupportedOperationException() {
@Override
public synchronized Throwable fillInStackTrace() {
return null;
}
};
private void checkValidTransform(final FunctionNode functionNode) {
final Set<Expression> argumentsFound = new HashSet<>();
final Deque<Set<Expression>> stack = new ArrayDeque<>();
//ensure that arguments is only passed as arg to apply
try {
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private boolean isCurrentArg(final Expression expr) {
return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
}
private boolean isArguments(final Expression expr) {
if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) {
argumentsFound.add(expr);
//ensure that arguments is only passed as arg to apply
functionNode.accept(new NodeVisitor<LexicalContext>(new LexicalContext()) {
private boolean isCurrentArg(final Expression expr) {
return !stack.isEmpty() && stack.peek().contains(expr); //args to current apply call
}
private boolean isArguments(final Expression expr) {
if (expr instanceof IdentNode && ARGUMENTS.equals(((IdentNode)expr).getName())) {
argumentsFound.add(expr);
return true;
}
return false;
}
private boolean isParam(final String name) {
for (final IdentNode param : functionNode.getParameters()) {
if (param.getName().equals(name)) {
return true;
}
return false;
}
private boolean isParam(final String name) {
for (final IdentNode param : functionNode.getParameters()) {
if (param.getName().equals(name)) {
return true;
}
}
return false;
}
@Override
public Node leaveIdentNode(final IdentNode identNode) {
if (isParam(identNode.getName()) || isArguments(identNode) && !isCurrentArg(identNode)) {
throw uoe; //avoid filling in stack trace
}
return identNode;
}
@Override
public boolean enterCallNode(final CallNode callNode) {
final Set<Expression> callArgs = new HashSet<>();
if (isApply(callNode)) {
final List<Expression> argList = callNode.getArgs();
if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) {
throw new UnsupportedOperationException();
}
callArgs.addAll(callNode.getArgs());
}
stack.push(callArgs);
return true;
}
@Override
public Node leaveCallNode(final CallNode callNode) {
stack.pop();
return callNode;
}
});
} catch (final UnsupportedOperationException e) {
if (!argumentsFound.isEmpty()) {
log.fine("'arguments' is used but escapes, or is reassigned in '" + functionNode.getName() + "'. Aborting");
return false;
}
return true; //bad
}
return false;
@Override
public Node leaveIdentNode(final IdentNode identNode) {
if (isParam(identNode.getName())) {
throw new TransformFailedException(lc.getCurrentFunction(), "parameter: " + identNode.getName());
}
// it's OK if 'argument' occurs as the current argument of an apply
if (isArguments(identNode) && !isCurrentArg(identNode)) {
throw new TransformFailedException(lc.getCurrentFunction(), "is 'arguments': " + identNode.getName());
}
return identNode;
}
@Override
public boolean enterCallNode(final CallNode callNode) {
final Set<Expression> callArgs = new HashSet<>();
if (isApply(callNode)) {
final List<Expression> argList = callNode.getArgs();
if (argList.size() != 2 || !isArguments(argList.get(argList.size() - 1))) {
throw new TransformFailedException(lc.getCurrentFunction(), "argument pattern not matched: " + argList);
}
callArgs.addAll(callNode.getArgs());
}
stack.push(callArgs);
return true;
}
@Override
public Node leaveCallNode(final CallNode callNode) {
stack.pop();
return callNode;
}
});
}
@Override
@ -224,12 +249,14 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
final CallNode newCallNode = callNode.setArgs(newArgs).setIsApplyToCall();
log.fine("Transformed ",
callNode,
" from apply to call => ",
newCallNode,
" in ",
DebugLogger.quote(lc.getCurrentFunction().getName()));
if (log.isEnabled()) {
log.fine("Transformed ",
callNode,
" from apply to call => ",
newCallNode,
" in ",
DebugLogger.quote(lc.getCurrentFunction().getName()));
}
return newCallNode;
}
@ -237,12 +264,12 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
return callNode;
}
private boolean pushExplodedArgs(final FunctionNode functionNode) {
private void pushExplodedArgs(final FunctionNode functionNode) {
int start = 0;
final MethodType actualCallSiteType = compiler.getCallSiteType(functionNode);
if (actualCallSiteType == null) {
return false;
throw new TransformFailedException(lc.getCurrentFunction(), "No callsite type");
}
assert actualCallSiteType.parameterType(actualCallSiteType.parameterCount() - 1) != Object[].class : "error vararg callsite passed to apply2call " + functionNode.getName() + " " + actualCallSiteType;
@ -264,8 +291,8 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
}
}
callSiteTypes.push(actualCallSiteType);
explodedArguments.push(newParams);
return true;
}
@Override
@ -288,11 +315,30 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
return false;
}
if (argumentsEscape(functionNode)) {
if (!hasApplies(functionNode)) {
return false;
}
return pushExplodedArgs(functionNode);
if (log.isEnabled()) {
log.info("Trying to specialize apply to call in '",
functionNode.getName(),
"' params=",
functionNode.getParameters(),
" id=",
functionNode.getId(),
" source=",
massageURL(functionNode.getSource().getURL()));
}
try {
checkValidTransform(functionNode);
pushExplodedArgs(functionNode);
} catch (final TransformFailedException e) {
log.info("Failure: ", e.getMessage());
return false;
}
return true;
}
/**
@ -300,8 +346,8 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
* @return true if successful, false otherwise
*/
@Override
public Node leaveFunctionNode(final FunctionNode functionNode0) {
FunctionNode newFunctionNode = functionNode0;
public Node leaveFunctionNode(final FunctionNode functionNode) {
FunctionNode newFunctionNode = functionNode;
final String functionName = newFunctionNode.getName();
if (changed.contains(newFunctionNode.getId())) {
@ -310,17 +356,18 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
setParameters(lc, explodedArguments.peek());
if (log.isEnabled()) {
log.info("Successfully specialized apply to call in '",
log.info("Success: ",
massageURL(newFunctionNode.getSource().getURL()),
'.',
functionName,
" params=",
explodedArguments.peek(),
"' id=",
newFunctionNode.getId(),
" source=",
newFunctionNode.getSource().getURL());
" params=",
callSiteTypes.peek());
}
}
callSiteTypes.pop();
explodedArguments.pop();
return newFunctionNode.setState(lc, CompilationState.BUILTINS_TRANSFORMED);
@ -331,4 +378,15 @@ public final class ApplySpecialization extends NodeVisitor<LexicalContext> imple
return f instanceof AccessNode && "apply".equals(((AccessNode)f).getProperty());
}
private static String massageURL(final URL url) {
if (url == null) {
return "<null>";
}
final String str = url.toString();
final int slash = str.lastIndexOf('/');
if (slash == -1) {
return str;
}
return str.substring(slash + 1);
}
}

View File

@ -615,7 +615,6 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
static final TypeBounds UNBOUNDED = new TypeBounds(Type.UNKNOWN, Type.OBJECT);
static final TypeBounds INT = exact(Type.INT);
static final TypeBounds NUMBER = exact(Type.NUMBER);
static final TypeBounds OBJECT = exact(Type.OBJECT);
static final TypeBounds BOOLEAN = exact(Type.BOOLEAN);
@ -3569,7 +3568,8 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
operandBounds = new TypeBounds(binaryNode.getType(), Type.OBJECT);
} else {
// Non-optimistic, non-FP +. Allow it to overflow.
operandBounds = new TypeBounds(binaryNode.getWidestOperandType(), Type.OBJECT);
operandBounds = new TypeBounds(Type.narrowest(binaryNode.getWidestOperandType(), resultBounds.widest),
Type.OBJECT);
forceConversionSeparation = binaryNode.getWidestOperationType().narrowerThan(resultBounds.widest);
}
loadBinaryOperands(binaryNode.lhs(), binaryNode.rhs(), operandBounds, false, forceConversionSeparation);
@ -3856,12 +3856,8 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
operandBounds = numericBounds;
} else {
final boolean isOptimistic = isValid(getProgramPoint());
if(isOptimistic) {
if(isOptimistic || node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
operandBounds = new TypeBounds(node.getType(), Type.NUMBER);
} else if(node.isTokenType(TokenType.DIV) || node.isTokenType(TokenType.MOD)) {
// Non-optimistic division must always take double arguments as its result must also be
// double.
operandBounds = TypeBounds.NUMBER;
} else {
// Non-optimistic, non-FP subtraction or multiplication. Allow them to overflow.
operandBounds = new TypeBounds(Type.narrowest(node.getWidestOperandType(),
@ -3897,7 +3893,7 @@ final class CodeGenerator extends NodeOperatorVisitor<CodeGeneratorLexicalContex
private static boolean isRhsZero(final BinaryNode binaryNode) {
final Expression rhs = binaryNode.rhs();
return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode)rhs).getValue());
return rhs instanceof LiteralNode && INT_ZERO.equals(((LiteralNode<?>)rhs).getValue());
}
private void loadBIT_XOR(final BinaryNode binaryNode) {

View File

@ -31,7 +31,6 @@ import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Map;
import jdk.nashorn.internal.IntDeque;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.ir.Block;
@ -250,7 +249,7 @@ final class CodeGeneratorLexicalContext extends LexicalContext {
static Type getTypeForSlotDescriptor(final char typeDesc) {
// Recognizing both lowercase and uppercase as we're using both to signify symbol boundaries; see
// MethodEmitter.markSymbolBoundariesInLvarTypesDescriptor().
switch(typeDesc) {
switch (typeDesc) {
case 'I':
case 'i':
return Type.INT;

View File

@ -389,6 +389,7 @@ public final class Compiler implements Loggable {
* @param continuationEntryPoints continuation entry points for restof method
* @param runtimeScope runtime scope for recompilation type lookup in {@code TypeEvaluator}
*/
@SuppressWarnings("unused")
public Compiler(
final Context context,
final ScriptEnvironment env,

View File

@ -28,7 +28,6 @@ package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.CompilerConstants.RETURN;
import static jdk.nashorn.internal.ir.Expression.isAlwaysFalse;
import static jdk.nashorn.internal.ir.Expression.isAlwaysTrue;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
@ -236,12 +235,12 @@ final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
private byte conversions;
void recordConversion(final LvarType from, final LvarType to) {
switch(from) {
switch (from) {
case UNDEFINED:
return;
case INT:
case BOOLEAN:
switch(to) {
switch (to) {
case LONG:
recordConversion(I2L);
return;
@ -256,7 +255,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
return;
}
case LONG:
switch(to) {
switch (to) {
case DOUBLE:
recordConversion(L2D);
return;
@ -1425,6 +1424,7 @@ final class LocalVariableTypesCalculator extends NodeVisitor<LexicalContext>{
* @param symbol the symbol representing the variable
* @param type the type
*/
@SuppressWarnings("unused")
private void setType(final Symbol symbol, final LvarType type) {
if(getLocalVariableTypeOrNull(symbol) == type) {
return;

View File

@ -1591,7 +1591,7 @@ public class MethodEmitter implements Emitter {
/**
* Abstraction for performing a conditional jump of any type
*
* @see MethodEmitter.Condition
* @see Condition
*
* @param cond the condition to test
* @param trueLabel the destination label is condition is true
@ -2217,6 +2217,10 @@ public class MethodEmitter implements Emitter {
* @return the method emitter
*/
MethodEmitter dynamicGet(final Type valueType, final String name, final int flags, final boolean isMethod) {
if (name.length() > LARGE_STRING_THRESHOLD) { // use getIndex for extremely long names
return load(name).dynamicGetIndex(valueType, flags, isMethod);
}
debug("dynamic_get", name, valueType, getProgramPoint(flags));
Type type = valueType;
@ -2240,9 +2244,14 @@ public class MethodEmitter implements Emitter {
* @param name name of property
* @param flags call site flags
*/
void dynamicSet(final String name, final int flags) {
assert !isOptimistic(flags);
debug("dynamic_set", name, peekType());
void dynamicSet(final String name, final int flags) {
if (name.length() > LARGE_STRING_THRESHOLD) { // use setIndex for extremely long names
load(name).swap().dynamicSetIndex(flags);
return;
}
assert !isOptimistic(flags);
debug("dynamic_set", name, peekType());
Type type = peekType();
if (type.isObject() || type.isBoolean()) { //promote strings to objects etc

View File

@ -25,6 +25,8 @@
package jdk.nashorn.internal.codegen;
import static jdk.nashorn.internal.codegen.MethodEmitter.LARGE_STRING_THRESHOLD;
import java.util.HashMap;
/**
@ -66,27 +68,28 @@ public class Namespace {
}
/**
* Create a uniqueName name in the namespace in the form base$n where n varies
* .
* @param base Base of name. Base will be returned if uniqueName.
* Create a uniqueName name in the namespace in the form base$n where n varies.
* Also truncates very long names that would otherwise break ASM.
*
* @param base Base of name. Base will be returned if uniqueName.
* @return Generated uniqueName name.
*/
public String uniqueName(final String base) {
final String truncatedBase = base.length() > LARGE_STRING_THRESHOLD ? base.substring(0, LARGE_STRING_THRESHOLD) : base;
for (Namespace namespace = this; namespace != null; namespace = namespace.getParent()) {
final HashMap<String, Integer> namespaceDirectory = namespace.directory;
final Integer counter = namespaceDirectory.get(base);
final Integer counter = namespaceDirectory.get(truncatedBase);
if (counter != null) {
final int count = counter + 1;
namespaceDirectory.put(base, count);
return base + '-' + count;
namespaceDirectory.put(truncatedBase, count);
return truncatedBase + '-' + count;
}
}
directory.put(base, 0);
directory.put(truncatedBase, 0);
return base;
return truncatedBase;
}
@Override

View File

@ -323,9 +323,11 @@ public final class OptimisticTypesPersistence {
* per-code-version directory. Normally, this will create the SHA-1 digest of the nashorn.jar. In case the classpath
* for nashorn is local directory (e.g. during development), this will create the string "dev-" followed by the
* timestamp of the most recent .class file.
* @return
*
* @return digest of currently running nashorn
* @throws Exception if digest could not be created
*/
private static String getVersionDirName() throws Exception {
public static String getVersionDirName() throws Exception {
final URL url = OptimisticTypesPersistence.class.getResource("");
final String protocol = url.getProtocol();
if (protocol.equals("jar")) {

View File

@ -55,6 +55,7 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_
import jdk.internal.org.objectweb.asm.MethodVisitor;
import jdk.nashorn.internal.codegen.CompilerConstants;
import jdk.nashorn.internal.runtime.JSType;
/**
* Type class: INT
@ -230,19 +231,21 @@ class IntType extends BitwiseType {
@Override
public Type div(final MethodVisitor method, final int programPoint) {
// Never perform non-optimistic integer division in JavaScript.
assert programPoint != INVALID_PROGRAM_POINT;
method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
if (programPoint == INVALID_PROGRAM_POINT) {
JSType.DIV_ZERO.invoke(method);
} else {
method.visitInvokeDynamicInsn("idiv", "(II)I", MATHBOOTSTRAP, programPoint);
}
return INT;
}
@Override
public Type rem(final MethodVisitor method, final int programPoint) {
// Never perform non-optimistic integer remainder in JavaScript.
assert programPoint != INVALID_PROGRAM_POINT;
method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
if (programPoint == INVALID_PROGRAM_POINT) {
JSType.REM_ZERO.invoke(method);
} else {
method.visitInvokeDynamicInsn("irem", "(II)I", MATHBOOTSTRAP, programPoint);
}
return INT;
}

View File

@ -170,19 +170,21 @@ class LongType extends BitwiseType {
@Override
public Type div(final MethodVisitor method, final int programPoint) {
// Never perform non-optimistic integer division in JavaScript.
assert programPoint != INVALID_PROGRAM_POINT;
method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint);
if (programPoint == INVALID_PROGRAM_POINT) {
JSType.DIV_ZERO_LONG.invoke(method);
} else {
method.visitInvokeDynamicInsn("ldiv", "(JJ)J", MATHBOOTSTRAP, programPoint);
}
return LONG;
}
@Override
public Type rem(final MethodVisitor method, final int programPoint) {
// Never perform non-optimistic integer remainder in JavaScript.
assert programPoint != INVALID_PROGRAM_POINT;
method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
if (programPoint == INVALID_PROGRAM_POINT) {
JSType.REM_ZERO_LONG.invoke(method);
} else {
method.visitInvokeDynamicInsn("lrem", "(JJ)J", MATHBOOTSTRAP, programPoint);
}
return LONG;
}

View File

@ -356,7 +356,7 @@ public abstract class Type implements Comparable<Type>, BytecodeOps, Serializabl
final int pp = input.readInt();
final int typeChar = input.readByte();
final Type type;
switch(typeChar) {
switch (typeChar) {
case 'L': type = Type.OBJECT; break;
case 'D': type = Type.NUMBER; break;
case 'J': type = Type.LONG; break;
@ -376,13 +376,13 @@ public abstract class Type implements Comparable<Type>, BytecodeOps, Serializabl
}
private static jdk.internal.org.objectweb.asm.Type lookupInternalType(final Class<?> type) {
final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> cache = INTERNAL_TYPE_CACHE;
jdk.internal.org.objectweb.asm.Type itype = cache.get(type);
final Map<Class<?>, jdk.internal.org.objectweb.asm.Type> c = INTERNAL_TYPE_CACHE;
jdk.internal.org.objectweb.asm.Type itype = c.get(type);
if (itype != null) {
return itype;
}
itype = jdk.internal.org.objectweb.asm.Type.getType(type);
cache.put(type, itype);
c.put(type, itype);
return itype;
}
@ -1155,6 +1155,10 @@ public abstract class Type implements Comparable<Type>, BytecodeOps, Serializabl
return type;
}
/**
* Read resolve
* @return resolved type
*/
protected final Object readResolve() {
return Type.typeFor(clazz);
}

View File

@ -28,7 +28,6 @@ package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.rangeError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import jdk.internal.dynalink.CallSiteDescriptor;
@ -44,6 +43,9 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
import jdk.nashorn.internal.runtime.arrays.ArrayData;
import jdk.nashorn.internal.runtime.arrays.TypedArrayData;
/**
* ArrayBufferView, es6 class or TypedArray implementation
*/
@ScriptClass("ArrayBufferView")
public abstract class ArrayBufferView extends ScriptObject {
private final NativeArrayBuffer buffer;
@ -71,6 +73,13 @@ public abstract class ArrayBufferView extends ScriptObject {
setArray(data);
}
/**
* Constructor
*
* @param buffer underlying NativeArrayBuffer
* @param byteOffset byte offset for buffer
* @param elementLength element length in bytes
*/
protected ArrayBufferView(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength) {
this(buffer, byteOffset, elementLength, Global.instance());
}
@ -89,22 +98,42 @@ public abstract class ArrayBufferView extends ScriptObject {
return factory().bytesPerElement;
}
/**
* Buffer getter as per spec
* @param self ArrayBufferView instance
* @return buffer
*/
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static Object buffer(final Object self) {
return ((ArrayBufferView)self).buffer;
}
/**
* Buffer offset getter as per spec
* @param self ArrayBufferView instance
* @return buffer offset
*/
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static int byteOffset(final Object self) {
return ((ArrayBufferView)self).byteOffset;
}
/**
* Byte length getter as per spec
* @param self ArrayBufferView instance
* @return array buffer view length in bytes
*/
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static int byteLength(final Object self) {
final ArrayBufferView view = (ArrayBufferView)self;
return ((TypedArrayData<?>)view.getArray()).getElementLength() * view.bytesPerElement();
}
/**
* Length getter as per spec
* @param self ArrayBufferView instance
* @return length in elements
*/
@Getter(attributes = Attribute.NOT_ENUMERABLE | Attribute.NOT_WRITABLE | Attribute.NOT_CONFIGURABLE)
public static int length(final Object self) {
return ((ArrayBufferView)self).elementLength();
@ -119,15 +148,29 @@ public abstract class ArrayBufferView extends ScriptObject {
return ((TypedArrayData<?>)getArray()).getElementLength();
}
/**
* Factory class for byte ArrayBufferViews
*/
protected static abstract class Factory {
final int bytesPerElement;
final int maxElementLength;
/**
* Constructor
*
* @param bytesPerElement number of bytes per element for this buffer
*/
public Factory(final int bytesPerElement) {
this.bytesPerElement = bytesPerElement;
this.maxElementLength = Integer.MAX_VALUE / bytesPerElement;
}
/**
* Factory method
*
* @param elementLength number of elements
* @return new ArrayBufferView
*/
public final ArrayBufferView construct(final int elementLength) {
if (elementLength > maxElementLength) {
throw rangeError("inappropriate.array.buffer.length", JSType.toString(elementLength));
@ -135,15 +178,47 @@ public abstract class ArrayBufferView extends ScriptObject {
return construct(new NativeArrayBuffer(elementLength * bytesPerElement), 0, elementLength);
}
public abstract ArrayBufferView construct(NativeArrayBuffer buffer, int byteOffset, int elementLength);
/**
* Factory method
*
* @param buffer underlying buffer
* @param byteOffset byte offset
* @param elementLength number of elements
*
* @return new ArrayBufferView
*/
public abstract ArrayBufferView construct(final NativeArrayBuffer buffer, final int byteOffset, final int elementLength);
public abstract TypedArrayData<?> createArrayData(ByteBuffer nb, int start, int end);
/**
* Factory method for array data
*
* @param nb underlying nativebuffer
* @param start start element
* @param end end element
*
* @return new array data
*/
public abstract TypedArrayData<?> createArrayData(final ByteBuffer nb, final int start, final int end);
/**
* Get the class name for this type of buffer
*
* @return class name
*/
public abstract String getClassName();
}
/**
* Get the factor for this kind of buffer
* @return Factory
*/
protected abstract Factory factory();
/**
* Get the prototype for this ArrayBufferView
* @param global global instance
* @return prototype
*/
protected abstract ScriptObject getPrototype(final Global global);
@Override
@ -151,10 +226,23 @@ public abstract class ArrayBufferView extends ScriptObject {
return factory().getClassName();
}
/**
* Check if this array contains floats
* @return true if float array (or double)
*/
protected boolean isFloatArray() {
return false;
}
/**
* Inheritable constructor implementation
*
* @param newObj is this a new constructor
* @param args arguments
* @param factory factory
*
* @return new ArrayBufferView
*/
protected static ArrayBufferView constructorImpl(final boolean newObj, final Object[] args, final Factory factory) {
final Object arg0 = args.length != 0 ? args[0] : 0;
final ArrayBufferView dest;
@ -200,6 +288,15 @@ public abstract class ArrayBufferView extends ScriptObject {
return dest;
}
/**
* Inheritable implementation of set, if no efficient implementation is available
*
* @param self ArrayBufferView instance
* @param array array
* @param offset0 array offset
*
* @return result of setter
*/
protected static Object setImpl(final Object self, final Object array, final Object offset0) {
final ArrayBufferView dest = (ArrayBufferView)self;
final int length;
@ -244,6 +341,15 @@ public abstract class ArrayBufferView extends ScriptObject {
return (int)(length & Integer.MAX_VALUE);
}
/**
* Implementation of subarray if no efficient override exists
*
* @param self ArrayBufferView instance
* @param begin0 begin index
* @param end0 end index
*
* @return sub array
*/
protected static ScriptObject subarrayImpl(final Object self, final Object begin0, final Object end0) {
final ArrayBufferView arrayView = (ArrayBufferView)self;
final int byteOffset = arrayView.byteOffset;

View File

@ -29,6 +29,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.referenceError;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.invoke.MethodHandle;
@ -41,7 +42,6 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
import javax.script.ScriptContext;
import javax.script.ScriptEngine;
import jdk.internal.dynalink.linker.GuardedInvocation;
@ -54,7 +54,6 @@ import jdk.nashorn.internal.objects.annotations.Property;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.runtime.ConsString;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.GlobalConstants;
import jdk.nashorn.internal.runtime.GlobalFunctions;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.NativeJavaPackage;
@ -438,9 +437,6 @@ public final class Global extends ScriptObject implements Scope {
this.scontext = scontext;
}
// global constants for this global - they can be replaced with MethodHandle.constant until invalidated
private static AtomicReference<GlobalConstants> gcsInstance = new AtomicReference<>();
@Override
protected Context getContext() {
return context;
@ -470,11 +466,6 @@ public final class Global extends ScriptObject implements Scope {
super(checkAndGetMap(context));
this.context = context;
this.setIsScope();
//we can only share one instance of Global constants between globals, or we consume way too much
//memory - this is good enough for most programs
while (gcsInstance.get() == null) {
gcsInstance.compareAndSet(null, new GlobalConstants(context.getLogger(GlobalConstants.class)));
}
}
/**
@ -492,15 +483,6 @@ public final class Global extends ScriptObject implements Scope {
return self instanceof Global? (Global)self : instance();
}
/**
* Return the global constants map for fields that
* can be accessed as MethodHandle.constant
* @return constant map
*/
public static GlobalConstants getConstants() {
return gcsInstance.get();
}
/**
* Check if we have a Global instance
* @return true if one exists
@ -559,16 +541,16 @@ public final class Global extends ScriptObject implements Scope {
* as well as our extension builtin objects like "Java", "JSAdapter" as properties
* of the global scope object.
*
* @param engine ScriptEngine to initialize
* @param eng ScriptEngine to initialize
*/
public void initBuiltinObjects(final ScriptEngine engine) {
public void initBuiltinObjects(final ScriptEngine eng) {
if (this.builtinObject != null) {
// already initialized, just return
return;
}
this.engine = engine;
init(engine);
this.engine = eng;
init(eng);
}
/**
@ -1717,7 +1699,7 @@ public final class Global extends ScriptObject implements Scope {
return func;
}
private void init(final ScriptEngine engine) {
private void init(final ScriptEngine eng) {
assert Context.getGlobal() == this : "this global is not set as current";
final ScriptEnvironment env = getContext().getEnv();
@ -1835,7 +1817,7 @@ public final class Global extends ScriptObject implements Scope {
addOwnProperty("$ARG", Attribute.NOT_ENUMERABLE, arguments);
}
if (engine != null) {
if (eng != null) {
// default file name
addOwnProperty(ScriptEngine.FILENAME, Attribute.NOT_ENUMERABLE, null);
// __noSuchProperty__ hook for ScriptContext search of missing variables

View File

@ -26,7 +26,6 @@
package jdk.nashorn.internal.objects;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import java.nio.ByteBuffer;
import jdk.nashorn.internal.objects.annotations.Attribute;
import jdk.nashorn.internal.objects.annotations.Constructor;
@ -34,6 +33,7 @@ import jdk.nashorn.internal.objects.annotations.Function;
import jdk.nashorn.internal.objects.annotations.Getter;
import jdk.nashorn.internal.objects.annotations.ScriptClass;
import jdk.nashorn.internal.objects.annotations.SpecializedFunction;
import jdk.nashorn.internal.objects.annotations.Where;
import jdk.nashorn.internal.runtime.JSType;
import jdk.nashorn.internal.runtime.PropertyMap;
import jdk.nashorn.internal.runtime.ScriptObject;
@ -137,6 +137,19 @@ public final class NativeArrayBuffer extends ScriptObject {
return ((NativeArrayBuffer)self).getByteLength();
}
/**
* Returns true if an object is an ArrayBufferView
*
* @param self self
* @param obj object to check
*
* @return true if obj is an ArrayBufferView
*/
@Function(attributes = Attribute.NOT_ENUMERABLE, where = Where.CONSTRUCTOR)
public static boolean isView(final Object self, final Object obj) {
return obj instanceof ArrayBufferView;
}
/**
* Slice function
* @param self native array buffer

View File

@ -29,6 +29,7 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.JSType.isRepresentableAsInt;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@ -572,7 +573,7 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
try {
return ((CharSequence)self).charAt(pos);
} catch (final IndexOutOfBoundsException e) {
throw new ClassCastException();
throw new ClassCastException(); //invalid char, out of bounds, force relink
}
}
@ -1380,7 +1381,6 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
* sequence and that we are in range
*/
private static final class CharCodeAtLinkLogic extends SpecializedFunction.LinkLogic {
private static final CharCodeAtLinkLogic INSTANCE = new CharCodeAtLinkLogic();
@Override
@ -1389,7 +1389,7 @@ public final class NativeString extends ScriptObject implements OptimisticBuilti
//check that it's a char sequence or throw cce
final CharSequence cs = (CharSequence)self;
//check that the index, representable as an int, is inside the array
final int intIndex = JSType.toInteger(request.getArguments()[1]);
final int intIndex = JSType.toInteger(request.getArguments()[2]);
return intIndex >= 0 && intIndex < cs.length(); //can link
} catch (final ClassCastException | IndexOutOfBoundsException e) {
//fallthru

View File

@ -141,9 +141,8 @@ class ParserContext {
return breakable;
}
return null;
} else {
return getBreakable();
}
return getBreakable();
}
/**

View File

@ -56,7 +56,7 @@ abstract class ParserContextBaseNode implements ParserContextNode {
/**
* Returns a single flag
* @param flag
* @param flag flag
* @return A single flag
*/
protected int getFlag(final int flag) {
@ -64,7 +64,7 @@ abstract class ParserContextBaseNode implements ParserContextNode {
}
/**
* @param flag
* @param flag flag
* @return the new flags
*/
@Override
@ -82,7 +82,7 @@ abstract class ParserContextBaseNode implements ParserContextNode {
}
/**
* @param statements
* @param statements statements
*/
@Override
public void setStatements(final List<Statement> statements) {

View File

@ -41,6 +41,7 @@ import java.security.PrivilegedExceptionAction;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceLoader;
import jdk.nashorn.internal.codegen.OptimisticTypesPersistence;
import jdk.nashorn.internal.codegen.types.Type;
import jdk.nashorn.internal.runtime.logging.DebugLogger;
import jdk.nashorn.internal.runtime.logging.Loggable;
@ -102,7 +103,7 @@ public abstract class CodeStore implements Loggable {
} catch (final AccessControlException e) {
context.getLogger(CodeStore.class).warning("failed to load code store provider ", e);
}
final CodeStore store = new DirectoryCodeStore();
final CodeStore store = new DirectoryCodeStore(context);
store.initLogger(context);
return store;
}
@ -210,32 +211,34 @@ public abstract class CodeStore implements Loggable {
/**
* Constructor
*
* @param context the current context
* @throws IOException if there are read/write problems with the cache and cache directory
*/
public DirectoryCodeStore() throws IOException {
this(Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE);
public DirectoryCodeStore(final Context context) throws IOException {
this(context, Options.getStringProperty("nashorn.persistent.code.cache", "nashorn_code_cache"), false, DEFAULT_MIN_SIZE);
}
/**
* Constructor
*
* @param context the current context
* @param path directory to store code in
* @param readOnly is this a read only code store
* @param minSize minimum file size for caching scripts
* @throws IOException if there are read/write problems with the cache and cache directory
*/
public DirectoryCodeStore(final String path, final boolean readOnly, final int minSize) throws IOException {
this.dir = checkDirectory(path, readOnly);
public DirectoryCodeStore(final Context context, final String path, final boolean readOnly, final int minSize) throws IOException {
this.dir = checkDirectory(path, context.getEnv(), readOnly);
this.readOnly = readOnly;
this.minSize = minSize;
}
private static File checkDirectory(final String path, final boolean readOnly) throws IOException {
private static File checkDirectory(final String path, final ScriptEnvironment env, final boolean readOnly) throws IOException {
try {
return AccessController.doPrivileged(new PrivilegedExceptionAction<File>() {
@Override
public File run() throws IOException {
final File dir = new File(path).getAbsoluteFile();
final File dir = new File(path, getVersionDir(env)).getAbsoluteFile();
if (readOnly) {
if (!dir.exists() || !dir.isDirectory()) {
throw new IOException("Not a directory: " + dir.getPath());
@ -257,6 +260,15 @@ public abstract class CodeStore implements Loggable {
}
}
private static String getVersionDir(final ScriptEnvironment env) throws IOException {
try {
final String versionDir = OptimisticTypesPersistence.getVersionDirName();
return env._optimistic_types ? versionDir + "_opt" : versionDir;
} catch (final Exception e) {
throw new IOException(e);
}
}
@Override
public StoredScript load(final Source source, final String functionKey) {
if (source.getLength() < minSize) {

View File

@ -27,7 +27,6 @@ package jdk.nashorn.internal.runtime;
import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
import java.lang.invoke.CallSite;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
@ -777,7 +776,7 @@ final class CompiledFunction {
// Compiler needs a call site type as its input, which always has a callee parameter, so we must add it if
// this function doesn't have a callee parameter.
final MethodType callSiteType = type.parameterType(0) == ScriptFunction.class ?
final MethodType ct = type.parameterType(0) == ScriptFunction.class ?
type :
type.insertParameterTypes(0, ScriptFunction.class);
final OptimismInfo currentOptInfo = optimismInfo;
@ -788,29 +787,29 @@ final class CompiledFunction {
final OptimismInfo effectiveOptInfo = currentOptInfo != null ? currentOptInfo : oldOptInfo;
FunctionNode fn = effectiveOptInfo.reparse();
final boolean serialized = effectiveOptInfo.isSerialized();
final Compiler compiler = effectiveOptInfo.getCompiler(fn, callSiteType, re); //set to non rest-of
final Compiler compiler = effectiveOptInfo.getCompiler(fn, ct, re); //set to non rest-of
if (!shouldRecompile) {
// It didn't necessarily recompile, e.g. for an outer invocation of a recursive function if we already
// recompiled a deoptimized version for an inner invocation.
// We still need to do the rest of from the beginning
logRecompile("Rest-of compilation [STANDALONE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
logRecompile("Rest-of compilation [STANDALONE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
return restOfHandle(effectiveOptInfo, compiler.compile(fn, serialized ? CompilationPhases.COMPILE_SERIALIZED_RESTOF : CompilationPhases.COMPILE_ALL_RESTOF), currentOptInfo != null);
}
logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
logRecompile("Deoptimizing recompilation (up to bytecode) ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
fn = compiler.compile(fn, serialized ? CompilationPhases.RECOMPILE_SERIALIZED_UPTO_BYTECODE : CompilationPhases.COMPILE_UPTO_BYTECODE);
log.info("Reusable IR generated");
// compile the rest of the function, and install it
log.info("Generating and installing bytecode from reusable IR...");
logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, callSiteType, effectiveOptInfo.invalidatedProgramPoints);
logRecompile("Rest-of compilation [CODE PIPELINE REUSE] ", fn, ct, effectiveOptInfo.invalidatedProgramPoints);
final FunctionNode normalFn = compiler.compile(fn, CompilationPhases.GENERATE_BYTECODE_AND_INSTALL);
if (effectiveOptInfo.data.usePersistentCodeCache()) {
final RecompilableScriptFunctionData data = effectiveOptInfo.data;
final int functionNodeId = data.getFunctionNodeId();
final TypeMap typeMap = data.typeMap(callSiteType);
final TypeMap typeMap = data.typeMap(ct);
final Type[] paramTypes = typeMap == null ? null : typeMap.getParameterTypes(functionNodeId);
final String cacheKey = CodeStore.getCacheKey(functionNodeId, paramTypes);
compiler.persistClassInfo(cacheKey, normalFn);
@ -871,6 +870,7 @@ final class CompiledFunction {
private SwitchPoint optimisticAssumptions;
private final DebugLogger log;
@SuppressWarnings("unused")
OptimismInfo(final RecompilableScriptFunctionData data, final Map<Integer, Type> invalidatedProgramPoints) {
this.data = data;
this.log = data.getLogger();

View File

@ -33,6 +33,7 @@ import static jdk.nashorn.internal.runtime.CodeStore.newCodeStore;
import static jdk.nashorn.internal.runtime.ECMAErrors.typeError;
import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED;
import static jdk.nashorn.internal.runtime.Source.sourceFor;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
@ -60,6 +61,7 @@ import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
import java.util.function.Supplier;
import java.util.logging.Level;
@ -262,6 +264,10 @@ public final class Context {
// persistent code store
private CodeStore codeStore;
// A factory for linking global properties as constant method handles. It is created when the first Global
// is created, and invalidated forever once the second global is created.
private final AtomicReference<GlobalConstants> globalConstantsRef = new AtomicReference<>();
/**
* Get the current global scope
* @return the current global scope
@ -293,7 +299,10 @@ public final class Context {
assert getGlobal() != global;
//same code can be cached between globals, then we need to invalidate method handle constants
if (global != null) {
Global.getConstants().invalidateAll();
final GlobalConstants globalConstants = getContext(global).getGlobalConstants();
if (globalConstants != null) {
globalConstants.invalidateAll();
}
}
currentGlobal.set(global);
}
@ -528,6 +537,15 @@ public final class Context {
return classFilter;
}
/**
* Returns the factory for constant method handles for global properties. The returned factory can be
* invalidated if this Context has more than one Global.
* @return the factory for constant method handles for global properties.
*/
GlobalConstants getGlobalConstants() {
return globalConstantsRef.get();
}
/**
* Get the error manager for this context
* @return error manger
@ -1016,9 +1034,32 @@ public final class Context {
* @return the global script object
*/
public Global newGlobal() {
createOrInvalidateGlobalConstants();
return new Global(this);
}
private void createOrInvalidateGlobalConstants() {
for (;;) {
final GlobalConstants currentGlobalConstants = getGlobalConstants();
if (currentGlobalConstants != null) {
// Subsequent invocation; we're creating our second or later Global. GlobalConstants is not safe to use
// with more than one Global, as the constant method handle linkages it creates create a coupling
// between the Global and the call sites in the compiled code.
currentGlobalConstants.invalidateForever();
return;
}
final GlobalConstants newGlobalConstants = new GlobalConstants(getLogger(GlobalConstants.class));
if (globalConstantsRef.compareAndSet(null, newGlobalConstants)) {
// First invocation; we're creating the first Global in this Context. Create the GlobalConstants object
// for this Context.
return;
}
// If we reach here, then we started out as the first invocation, but another concurrent invocation won the
// CAS race. We'll just let the loop repeat and invalidate the CAS race winner.
}
}
/**
* Initialize given global scope object.
*
@ -1057,12 +1098,19 @@ public final class Context {
* @return current global's context
*/
static Context getContextTrusted() {
return ((ScriptObject)Context.getGlobal()).getContext();
return getContext(getGlobal());
}
static Context getContextTrustedOrNull() {
final Global global = Context.getGlobal();
return global == null ? null : ((ScriptObject)global).getContext();
return global == null ? null : getContext(global);
}
private static Context getContext(final Global global) {
// We can't invoke Global.getContext() directly, as it's a protected override, and Global isn't in our package.
// In order to access the method, we must cast it to ScriptObject first (which is in our package) and then let
// virtual invocation do its thing.
return ((ScriptObject)global).getContext();
}
/**
@ -1150,9 +1198,8 @@ public final class Context {
StoredScript storedScript = null;
FunctionNode functionNode = null;
// We only use the code store here if optimistic types are disabled. With optimistic types,
// code is stored per function in RecompilableScriptFunctionData.
// TODO: This should really be triggered by lazy compilation, not optimistic types.
// We only use the code store here if optimistic types are disabled. With optimistic types, initial compilation
// just creates a thin wrapper, and actual code is stored per function in RecompilableScriptFunctionData.
final boolean useCodeStore = env._persistent_cache && !env._parse_only && !env._optimistic_types;
final String cacheKey = useCodeStore ? CodeStore.getCacheKey(0, null) : null;

View File

@ -96,15 +96,17 @@ public final class ECMAException extends NashornException {
// If thrown object is an Error or sub-object like TypeError, then
// an ECMAException object has been already initialized at constructor.
if (thrown instanceof ScriptObject) {
final ScriptObject sobj = (ScriptObject)thrown;
final Object exception = getException(sobj);
final Object exception = getException((ScriptObject)thrown);
if (exception instanceof ECMAException) {
// copy over file name, line number and column number.
final ECMAException ee = (ECMAException)exception;
ee.setFileName(fileName);
ee.setLineNumber(line);
ee.setColumnNumber(column);
return ee;
// Make sure exception has correct thrown reference because that's what will end up getting caught.
if (ee.getThrown() == thrown) {
// copy over file name, line number and column number.
ee.setFileName(fileName);
ee.setLineNumber(line);
ee.setColumnNumber(column);
return ee;
}
}
}
@ -154,7 +156,11 @@ public final class ECMAException extends NashornException {
* @return a {@link ECMAException}
*/
public static Object getException(final ScriptObject errObj) {
return errObj.get(ECMAException.EXCEPTION_PROPERTY);
// Exclude inherited properties that may belong to errors in the prototype chain.
if (errObj.hasOwnProperty(ECMAException.EXCEPTION_PROPERTY)) {
return errObj.get(ECMAException.EXCEPTION_PROPERTY);
}
return null;
}
/**

View File

@ -31,12 +31,14 @@ import static jdk.nashorn.internal.lookup.Lookup.MH;
import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.INVALID_PROGRAM_POINT;
import static jdk.nashorn.internal.runtime.linker.NashornCallSiteDescriptor.getProgramPoint;
import static jdk.nashorn.internal.runtime.logging.DebugLogger.quote;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.SwitchPoint;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import jdk.internal.dynalink.CallSiteDescriptor;
import jdk.internal.dynalink.DynamicLinker;
@ -50,7 +52,7 @@ import jdk.nashorn.internal.runtime.logging.Loggable;
import jdk.nashorn.internal.runtime.logging.Logger;
/**
* Each global owns one of these. This is basically table of accessors
* Each context owns one of these. This is basically table of accessors
* for global properties. A global constant is evaluated to a MethodHandle.constant
* for faster access and to avoid walking to proto chain looking for it.
*
@ -67,12 +69,19 @@ import jdk.nashorn.internal.runtime.logging.Logger;
* reregister the switchpoint. Set twice or more - don't try again forever, or we'd
* just end up relinking our way into megamorphisism.
*
* Also it has to be noted that this kind of linking creates a coupling between a Global
* and the call sites in compiled code belonging to the Context. For this reason, the
* linkage becomes incorrect as soon as the Context has more than one Global. The
* {@link #invalidateForever()} is invoked by the Context to invalidate all linkages and
* turn off the functionality of this object as soon as the Context's {@link Context#newGlobal()} is invoked
* for second time.
*
* We can extend this to ScriptObjects in general (GLOBAL_ONLY=false), which requires
* a receiver guard on the constant getter, but it currently leaks memory and its benefits
* have not yet been investigated property.
*
* As long as all Globals share the same constant instance, we need synchronization
* whenever we access the instance.
* As long as all Globals in a Context share the same GlobalConstants instance, we need synchronization
* whenever we access it.
*/
@Logger(name="const")
public final class GlobalConstants implements Loggable {
@ -82,7 +91,7 @@ public final class GlobalConstants implements Loggable {
* Script objects require a receiver guard, which is memory intensive, so this is currently
* disabled. We might implement a weak reference based approach to this later.
*/
private static final boolean GLOBAL_ONLY = true;
public static final boolean GLOBAL_ONLY = true;
private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
@ -98,6 +107,8 @@ public final class GlobalConstants implements Loggable {
*/
private final Map<String, Access> map = new HashMap<>();
private final AtomicBoolean invalidatedForever = new AtomicBoolean(false);
/**
* Constructor - used only by global
* @param log logger, or null if none
@ -216,10 +227,34 @@ public final class GlobalConstants implements Loggable {
* the same class for a new global, but the builtins and global scoped variables
* will have changed.
*/
public synchronized void invalidateAll() {
log.info("New global created - invalidating all constant callsites without increasing invocation count.");
for (final Access acc : map.values()) {
acc.invalidateUncounted();
public void invalidateAll() {
if (!invalidatedForever.get()) {
log.info("New global created - invalidating all constant callsites without increasing invocation count.");
synchronized (this) {
for (final Access acc : map.values()) {
acc.invalidateUncounted();
}
}
}
}
/**
* To avoid an expensive global guard "is this the same global", similar to the
* receiver guard on the ScriptObject level, we invalidate all getters when the
* second Global is created by the Context owning this instance. After this
* method is invoked, this GlobalConstants instance will both invalidate all the
* switch points it produced, and it will stop handing out new method handles
* altogether.
*/
public void invalidateForever() {
if (invalidatedForever.compareAndSet(false, true)) {
log.info("New global created - invalidating all constant callsites.");
synchronized (this) {
for (final Access acc : map.values()) {
acc.invalidateForever();
}
map.clear();
}
}
}
@ -251,7 +286,7 @@ public final class GlobalConstants implements Loggable {
return obj;
}
private synchronized Access getOrCreateSwitchPoint(final String name) {
private Access getOrCreateSwitchPoint(final String name) {
Access acc = map.get(name);
if (acc != null) {
return acc;
@ -267,9 +302,13 @@ public final class GlobalConstants implements Loggable {
* @param name name of property
*/
void delete(final String name) {
final Access acc = map.get(name);
if (acc != null) {
acc.invalidateForever();
if (!invalidatedForever.get()) {
synchronized (this) {
final Access acc = map.get(name);
if (acc != null) {
acc.invalidateForever();
}
}
}
}
@ -313,45 +352,45 @@ public final class GlobalConstants implements Loggable {
*
* @return null if failed to set up constant linkage
*/
synchronized GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) {
if (GLOBAL_ONLY && !isGlobalSetter(receiver, find)) {
GuardedInvocation findSetMethod(final FindProperty find, final ScriptObject receiver, final GuardedInvocation inv, final CallSiteDescriptor desc, final LinkRequest request) {
if (invalidatedForever.get() || (GLOBAL_ONLY && !isGlobalSetter(receiver, find))) {
return null;
}
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Access acc = getOrCreateSwitchPoint(name);
synchronized (this) {
final Access acc = getOrCreateSwitchPoint(name);
if (log.isEnabled()) {
log.fine("Trying to link constant SETTER ", acc);
}
if (!acc.mayRetry()) {
if (log.isEnabled()) {
log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
log.fine("Trying to link constant SETTER ", acc);
}
return null;
if (!acc.mayRetry() || invalidatedForever.get()) {
if (log.isEnabled()) {
log.fine("*** SET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
}
return null;
}
if (acc.hasBeenInvalidated()) {
log.info("New chance for " + acc);
acc.newSwitchPoint();
}
assert !acc.hasBeenInvalidated();
// if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter
final MethodHandle target = inv.getInvocation();
final Class<?> receiverType = target.type().parameterType(0);
final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP, this);
final MethodHandle invalidator = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType));
final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc));
assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints());
log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint());
return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException());
}
assert acc.mayRetry();
if (acc.hasBeenInvalidated()) {
log.info("New chance for " + acc);
acc.newSwitchPoint();
}
assert !acc.hasBeenInvalidated();
// if we haven't given up on this symbol, add a switchpoint invalidation filter to the receiver parameter
final MethodHandle target = inv.getInvocation();
final Class<?> receiverType = target.type().parameterType(0);
final MethodHandle boundInvalidator = MH.bindTo(INVALIDATE_SP, this);
final MethodHandle invalidator = MH.asType(boundInvalidator, boundInvalidator.type().changeParameterType(0, receiverType).changeReturnType(receiverType));
final MethodHandle mh = MH.filterArguments(inv.getInvocation(), 0, MH.insertArguments(invalidator, 1, acc));
assert inv.getSwitchPoints() == null : Arrays.asList(inv.getSwitchPoints());
log.info("Linked setter " + quote(name) + " " + acc.getSwitchPoint());
return new GuardedInvocation(mh, inv.getGuard(), acc.getSwitchPoint(), inv.getException());
}
/**
@ -380,11 +419,11 @@ public final class GlobalConstants implements Loggable {
*
* @return resulting getter, or null if failed to create constant
*/
synchronized GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
GuardedInvocation findGetMethod(final FindProperty find, final ScriptObject receiver, final CallSiteDescriptor desc) {
// Only use constant getter for fast scope access, because the receiver may change between invocations
// for slow-scope and non-scope callsites.
// Also return null for user accessor properties as they may have side effects.
if (!NashornCallSiteDescriptor.isFastScope(desc)
if (invalidatedForever.get() || !NashornCallSiteDescriptor.isFastScope(desc)
|| (GLOBAL_ONLY && !find.getOwner().isGlobal())
|| find.getProperty() instanceof UserAccessorProperty) {
return null;
@ -395,51 +434,53 @@ public final class GlobalConstants implements Loggable {
final Class<?> retType = desc.getMethodType().returnType();
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
final Access acc = getOrCreateSwitchPoint(name);
synchronized (this) {
final Access acc = getOrCreateSwitchPoint(name);
log.fine("Starting to look up object value " + name);
final Object c = find.getObjectValue();
log.fine("Starting to look up object value " + name);
final Object c = find.getObjectValue();
if (log.isEnabled()) {
log.fine("Trying to link constant GETTER " + acc + " value = " + c);
}
if (acc.hasBeenInvalidated() || acc.guardFailed()) {
if (log.isEnabled()) {
log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
log.fine("Trying to link constant GETTER " + acc + " value = " + c);
}
return null;
}
final MethodHandle cmh = constantGetter(c);
if (acc.hasBeenInvalidated() || acc.guardFailed() || invalidatedForever.get()) {
if (log.isEnabled()) {
log.info("*** GET: Giving up on " + quote(name) + " - retry count has exceeded " + DynamicLinker.getLinkedCallSiteLocation());
}
return null;
}
MethodHandle mh;
MethodHandle guard;
final MethodHandle cmh = constantGetter(c);
if (isOptimistic) {
if (JSType.getAccessorTypeIndex(cmh.type().returnType()) <= JSType.getAccessorTypeIndex(retType)) {
//widen return type - this is pessimistic, so it will always work
mh = MH.asType(cmh, cmh.type().changeReturnType(retType));
MethodHandle mh;
MethodHandle guard;
if (isOptimistic) {
if (JSType.getAccessorTypeIndex(cmh.type().returnType()) <= JSType.getAccessorTypeIndex(retType)) {
//widen return type - this is pessimistic, so it will always work
mh = MH.asType(cmh, cmh.type().changeReturnType(retType));
} else {
//immediately invalidate - we asked for a too wide constant as a narrower one
mh = MH.dropArguments(MH.insertArguments(JSType.THROW_UNWARRANTED.methodHandle(), 0, c, programPoint), 0, Object.class);
}
} else {
//immediately invalidate - we asked for a too wide constant as a narrower one
mh = MH.dropArguments(MH.insertArguments(JSType.THROW_UNWARRANTED.methodHandle(), 0, c, programPoint), 0, Object.class);
//pessimistic return type filter
mh = Lookup.filterReturnType(cmh, retType);
}
} else {
//pessimistic return type filter
mh = Lookup.filterReturnType(cmh, retType);
}
if (find.getOwner().isGlobal()) {
guard = null;
} else {
guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver);
}
if (find.getOwner().isGlobal()) {
guard = null;
} else {
guard = MH.insertArguments(RECEIVER_GUARD, 0, acc, receiver);
}
if (log.isEnabled()) {
log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint());
mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc);
}
if (log.isEnabled()) {
log.info("Linked getter " + quote(name) + " as MethodHandle.constant() -> " + c + " " + acc.getSwitchPoint());
mh = MethodHandleFactory.addDebugPrintout(log, Level.FINE, mh, "get const " + acc);
}
return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null);
return new GuardedInvocation(mh, guard, acc.getSwitchPoint(), null);
}
}
}

View File

@ -150,6 +150,12 @@ public enum JSType {
/** Div exact wrapper for potentially integer division that turns into float point */
public static final Call DIV_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", int.class, int.class, int.class, int.class);
/** Div zero wrapper for integer division that handles (0/0)|0 == 0 */
public static final Call DIV_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", int.class, int.class, int.class);
/** Mod zero wrapper for integer division that handles (0%0)|0 == 0 */
public static final Call REM_ZERO = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", int.class, int.class, int.class);
/** Mod exact wrapper for potentially integer remainders that turns into float point */
public static final Call REM_EXACT = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", int.class, int.class, int.class, int.class);
@ -174,6 +180,12 @@ public enum JSType {
/** Div exact wrapper for potentially integer division that turns into float point */
public static final Call DIV_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divExact", long.class, long.class, long.class, int.class);
/** Div zero wrapper for long division that handles (0/0) >>> 0 == 0 */
public static final Call DIV_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "divZero", long.class, long.class, long.class);
/** Mod zero wrapper for long division that handles (0%0) >>> 0 == 0 */
public static final Call REM_ZERO_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remZero", long.class, long.class, long.class);
/** Mod exact wrapper for potentially integer remainders that turns into float point */
public static final Call REM_EXACT_LONG = staticCall(JSTYPE_LOOKUP, JSType.class, "remExact", long.class, long.class, long.class, int.class);
@ -1485,6 +1497,28 @@ public enum JSType {
throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
}
/**
* Implements int division but allows {@code x / 0} to be represented as 0. Basically equivalent to
* {@code (x / y)|0} JavaScript expression (division of two ints coerced to int).
* @param x the dividend
* @param y the divisor
* @return the result
*/
public static int divZero(final int x, final int y) {
return y == 0 ? 0 : x / y;
}
/**
* Implements int remainder but allows {@code x % 0} to be represented as 0. Basically equivalent to
* {@code (x % y)|0} JavaScript expression (remainder of two ints coerced to int).
* @param x the dividend
* @param y the divisor
* @return the remainder
*/
public static int remZero(final int x, final int y) {
return y == 0 ? 0 : x % y;
}
/**
* Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
*
@ -1528,6 +1562,28 @@ public enum JSType {
throw new UnwarrantedOptimismException((double)x / (double)y, programPoint);
}
/**
* Implements long division but allows {@code x / 0} to be represented as 0. Useful when division of two longs
* is coerced to long.
* @param x the dividend
* @param y the divisor
* @return the result
*/
public static long divZero(final long x, final long y) {
return y == 0L ? 0L : x / y;
}
/**
* Implements long remainder but allows {@code x % 0} to be represented as 0. Useful when remainder of two longs
* is coerced to long.
* @param x the dividend
* @param y the divisor
* @return the remainder
*/
public static long remZero(final long x, final long y) {
return y == 0L ? 0L : x % y;
}
/**
* Wrapper for modExact. Throws UnwarrantedOptimismException if the modulo can't be represented as int.
*

View File

@ -84,7 +84,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
private transient WeakHashMap<Property, SoftReference<PropertyMap>> history;
/** History of prototypes, used to limit map duplication. */
private transient WeakHashMap<PropertyMap, SoftReference<PropertyMap>> protoHistory;
private transient WeakHashMap<ScriptObject, SoftReference<PropertyMap>> protoHistory;
/** property listeners */
private transient PropertyListeners listeners;
@ -677,14 +677,14 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
/**
* Check prototype history for an existing property map with specified prototype.
*
* @param parentMap New prototype object.
* @param proto New prototype object.
*
* @return Existing {@link PropertyMap} or {@code null} if not found.
*/
private PropertyMap checkProtoHistory(final PropertyMap parentMap) {
private PropertyMap checkProtoHistory(final ScriptObject proto) {
final PropertyMap cachedMap;
if (protoHistory != null) {
final SoftReference<PropertyMap> weakMap = protoHistory.get(parentMap);
final SoftReference<PropertyMap> weakMap = protoHistory.get(proto);
cachedMap = (weakMap != null ? weakMap.get() : null);
} else {
cachedMap = null;
@ -700,15 +700,15 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
/**
* Add a map to the prototype history.
*
* @param parentMap Prototype to add (key.)
* @param newProto Prototype to add (key.)
* @param newMap {@link PropertyMap} associated with prototype.
*/
private void addToProtoHistory(final PropertyMap parentMap, final PropertyMap newMap) {
private void addToProtoHistory(final ScriptObject newProto, final PropertyMap newMap) {
if (protoHistory == null) {
protoHistory = new WeakHashMap<>();
}
protoHistory.put(parentMap, new SoftReference<>(newMap));
protoHistory.put(newProto, new SoftReference<>(newMap));
}
/**
@ -883,8 +883,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
*/
public PropertyMap changeProto(final ScriptObject newProto) {
final PropertyMap parentMap = newProto == null ? null : newProto.getMap();
final PropertyMap nextMap = checkProtoHistory(parentMap);
final PropertyMap nextMap = checkProtoHistory(newProto);
if (nextMap != null) {
return nextMap;
}
@ -894,7 +893,7 @@ public final class PropertyMap implements Iterable<Object>, Serializable {
}
final PropertyMap newMap = new PropertyMap(this);
addToProtoHistory(parentMap, newMap);
addToProtoHistory(newProto, newMap);
return newMap;
}

View File

@ -475,6 +475,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
* @return either the existing map, or a loaded map from the persistent type info cache, or a new empty map if
* neither an existing map or a persistent cached type info is available.
*/
@SuppressWarnings("unused")
private static Map<Integer, Type> getEffectiveInvalidatedProgramPoints(
final Map<Integer, Type> invalidatedProgramPoints, final Object typeInformationFile) {
if(invalidatedProgramPoints != null) {
@ -727,7 +728,7 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
assert existingBest != null;
//we are calling a vararg method with real args
boolean applyToCall = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
boolean varArgWithRealArgs = existingBest.isVarArg() && !CompiledFunction.isVarArgsType(callSiteType);
//if the best one is an apply to call, it has to match the callsite exactly
//or we need to regenerate
@ -736,14 +737,16 @@ public final class RecompilableScriptFunctionData extends ScriptFunctionData imp
if (best != null) {
return best;
}
applyToCall = true;
varArgWithRealArgs = true;
}
if (applyToCall) {
if (varArgWithRealArgs) {
// special case: we had an apply to call, but we failed to make it fit.
// Try to generate a specialized one for this callsite. It may
// be another apply to call specialization, or it may not, but whatever
// it is, it is a specialization that is guaranteed to fit
final FunctionInitializer fnInit = compileTypeSpecialization(callSiteType, runtimeScope, false);
if ((fnInit.getFlags() & FunctionNode.HAS_APPLY_TO_CALL_SPECIALIZATION) != 0) { //did the specialization work
existingBest = addCode(fnInit, callSiteType);
}
existingBest = addCode(fnInit, callSiteType);
}
return existingBest;

View File

@ -212,6 +212,7 @@ public final class ScriptEnvironment {
* @param out output print writer
* @param err error print writer
*/
@SuppressWarnings("unused")
public ScriptEnvironment(final Options options, final PrintWriter out, final PrintWriter err) {
this.out = out;
this.err = err;

View File

@ -47,6 +47,7 @@ import static jdk.nashorn.internal.runtime.UnwarrantedOptimismException.isValid;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.getArrayIndex;
import static jdk.nashorn.internal.runtime.arrays.ArrayIndex.isValidArrayIndex;
import static jdk.nashorn.internal.runtime.linker.NashornGuards.explicitInstanceOfCheck;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
@ -922,7 +923,10 @@ public abstract class ScriptObject implements PropertyAccess {
if (property instanceof UserAccessorProperty) {
((UserAccessorProperty)property).setAccessors(this, getMap(), null);
}
Global.getConstants().delete(property.getKey());
final GlobalConstants globalConstants = getGlobalConstants();
if (globalConstants != null) {
globalConstants.delete(property.getKey());
}
return true;
}
}
@ -1983,9 +1987,12 @@ public abstract class ScriptObject implements PropertyAccess {
}
}
final GuardedInvocation cinv = Global.getConstants().findGetMethod(find, this, desc);
if (cinv != null) {
return cinv;
final GlobalConstants globalConstants = getGlobalConstants();
if (globalConstants != null) {
final GuardedInvocation cinv = globalConstants.findGetMethod(find, this, desc);
if (cinv != null) {
return cinv;
}
}
final Class<?> returnType = desc.getMethodType().returnType();
@ -2183,14 +2190,22 @@ public abstract class ScriptObject implements PropertyAccess {
final GuardedInvocation inv = new SetMethodCreator(this, find, desc, request).createGuardedInvocation(findBuiltinSwitchPoint(name));
final GuardedInvocation cinv = Global.getConstants().findSetMethod(find, this, inv, desc, request);
if (cinv != null) {
return cinv;
final GlobalConstants globalConstants = getGlobalConstants();
if (globalConstants != null) {
final GuardedInvocation cinv = globalConstants.findSetMethod(find, this, inv, desc, request);
if (cinv != null) {
return cinv;
}
}
return inv;
}
private GlobalConstants getGlobalConstants() {
// Avoid hitting getContext() which might be costly for a non-Global unless needed.
return GlobalConstants.GLOBAL_ONLY && !isGlobal() ? null : getContext().getGlobalConstants();
}
private GuardedInvocation createEmptySetMethod(final CallSiteDescriptor desc, final boolean explicitInstanceOfCheck, final String strictErrorMessage, final boolean canBeFastScope) {
final String name = desc.getNameToken(CallSiteDescriptor.NAME_OPERAND);
if (NashornCallSiteDescriptor.isStrict(desc)) {

View File

@ -98,6 +98,10 @@ public abstract class ArrayData {
@Override
public ArrayData ensure(final long safeIndex) {
if (safeIndex > 0L) {
if (safeIndex >= SparseArrayData.MAX_DENSE_LENGTH) {
return new SparseArrayData(this, safeIndex + 1);
}
//known to fit in int
return toRealArrayData((int)safeIndex).ensure(safeIndex);
}
return this;

View File

@ -36,7 +36,7 @@ import jdk.nashorn.internal.runtime.ScriptRuntime;
* Handle arrays where the index is very large.
*/
class SparseArrayData extends ArrayData {
static final long MAX_DENSE_LENGTH = 16 * 512 * 1024;
static final int MAX_DENSE_LENGTH = 8 * 1024 * 1024;
/** Underlying array. */
private ArrayData underlying;

View File

@ -47,10 +47,9 @@ public final class RecompilationEvent extends RuntimeEvent<RewriteException> {
* @param level logging level
* @param rewriteException rewriteException wrapped by this RuntimEvent
* @param returnValue rewriteException return value - as we don't want to make
* {@link RewriteException#getReturnValueNonDestructive()} public, we pass it as
* {@code RewriteException.getReturnValueNonDestructive()} public, we pass it as
* an extra parameter, rather than querying the getter from another package.
*/
@SuppressWarnings("javadoc")
public RecompilationEvent(final Level level, final RewriteException rewriteException, final Object returnValue) {
super(level, rewriteException);
assert Context.getContext().getLogger(RecompilableScriptFunctionData.class).isEnabled() :

View File

@ -42,6 +42,8 @@ import jdk.internal.dynalink.beans.StaticClass;
import jdk.internal.dynalink.linker.GuardedInvocation;
import jdk.internal.dynalink.linker.LinkRequest;
import jdk.internal.dynalink.linker.LinkerServices;
import jdk.internal.dynalink.linker.MethodTypeConversionStrategy;
import jdk.internal.dynalink.support.TypeUtilities;
import jdk.nashorn.api.scripting.JSObject;
import jdk.nashorn.internal.codegen.CompilerConstants.Call;
import jdk.nashorn.internal.codegen.ObjectClassGenerator;
@ -106,6 +108,12 @@ public final class Bootstrap {
return OptimisticReturnFilters.filterOptimisticReturnValue(inv, desc).asType(linkerServices, desc.getMethodType());
}
});
factory.setAutoConversionStrategy(new MethodTypeConversionStrategy() {
@Override
public MethodHandle asType(final MethodHandle target, final MethodType newType) {
return unboxReturnType(target, newType);
}
});
final int relinkThreshold = Options.getIntProperty("nashorn.unstable.relink.threshold", NASHORN_DEFAULT_UNSTABLE_RELINK_THRESHOLD);
if (relinkThreshold > -1) {
factory.setUnstableRelinkThreshold(relinkThreshold);
@ -420,4 +428,29 @@ public final class Bootstrap {
static GuardedInvocation asTypeSafeReturn(final GuardedInvocation inv, final LinkerServices linkerServices, final CallSiteDescriptor desc) {
return inv == null ? null : inv.asTypeSafeReturn(linkerServices, desc.getMethodType());
}
/**
* Adapts the return type of the method handle with {@code explicitCastArguments} when it is an unboxing
* conversion. This will ensure that nulls are unwrapped to false or 0.
* @param target the target method handle
* @param newType the desired new type. Note that this method does not adapt the method handle completely to the
* new type, it only adapts the return type; this is allowed as per
* {@link DynamicLinkerFactory#setAutoConversionStrategy(MethodTypeConversionStrategy)}, which is what this method
* is used for.
* @return the method handle with adapted return type, if it required an unboxing conversion.
*/
private static MethodHandle unboxReturnType(final MethodHandle target, final MethodType newType) {
final MethodType targetType = target.type();
final Class<?> oldReturnType = targetType.returnType();
if (TypeUtilities.isWrapperType(oldReturnType)) {
final Class<?> newReturnType = newType.returnType();
if (newReturnType.isPrimitive()) {
// The contract of setAutoConversionStrategy is such that the difference between newType and targetType
// can only be JLS method invocation conversions.
assert TypeUtilities.isMethodInvocationConvertible(oldReturnType, newReturnType);
return MethodHandles.explicitCastArguments(target, targetType.changeReturnType(newReturnType));
}
}
return target;
}
}

View File

@ -25,8 +25,10 @@
package jdk.nashorn.internal.runtime.linker;
import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.*;
import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETMEMBER;
import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_GETSLOT;
import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETMEMBER;
import static jdk.nashorn.internal.runtime.linker.BrowserJSObjectLinker.JSObjectHandles.JSOBJECT_SETSLOT;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import jdk.internal.dynalink.CallSiteDescriptor;
@ -114,12 +116,10 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
case "getMethod":
if (c > 2) {
return findGetMethod(desc);
} else {
// For indexed get, we want GuardedInvocation from beans linker and pass it.
// BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access.
final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
return findGetIndexMethod(beanInv);
}
// For indexed get, we want GuardedInvocation from beans linker and pass it.
// BrowserJSObjectLinker.get uses this fallback getter for explicit signature method access.
return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
case "setProp":
case "setElem":
return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
@ -166,9 +166,8 @@ final class BrowserJSObjectLinker implements TypeBasedGuardingDynamicLinker {
final String name = (String)key;
if (name.indexOf('(') != -1) {
return fallback.invokeExact(jsobj, key);
} else {
return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key);
}
return JSOBJECT_GETMEMBER.invokeExact(jsobj, (String)key);
}
return null;
}

View File

@ -120,12 +120,10 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
case "getMethod":
if (c > 2) {
return findGetMethod(desc);
} else {
// For indexed get, we want get GuardedInvocation beans linker and pass it.
// JSObjectLinker.get uses this fallback getter for explicit signature method access.
final GuardedInvocation beanInv = nashornBeansLinker.getGuardedInvocation(request, linkerServices);
return findGetIndexMethod(beanInv);
}
// For indexed get, we want get GuardedInvocation beans linker and pass it.
// JSObjectLinker.get uses this fallback getter for explicit signature method access.
return findGetIndexMethod(nashornBeansLinker.getGuardedInvocation(request, linkerServices));
case "setProp":
case "setElem":
return c > 2 ? findSetMethod(desc) : findSetIndexMethod();
@ -192,9 +190,8 @@ final class JSObjectLinker implements TypeBasedGuardingDynamicLinker, GuardingTy
// get with method name and signature. delegate it to beans linker!
if (name.indexOf('(') != -1) {
return fallback.invokeExact(jsobj, key);
} else {
return ((JSObject)jsobj).getMember(name);
}
return ((JSObject)jsobj).getMember(name);
}
return null;
}

View File

@ -53,15 +53,34 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
// Object type arguments of Java method calls, field set and array set.
private static final boolean MIRROR_ALWAYS = Options.getBooleanProperty("nashorn.mirror.always", true);
private static final MethodHandle EXPORT_ARGUMENT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportArgument", Object.class, Object.class);
private static final MethodHandle EXPORT_NATIVE_ARRAY = new Lookup(MethodHandles.lookup()).findOwnStatic("exportNativeArray", Object.class, NativeArray.class);
private static final MethodHandle EXPORT_SCRIPT_OBJECT = new Lookup(MethodHandles.lookup()).findOwnStatic("exportScriptObject", Object.class, ScriptObject.class);
private static final MethodHandle IMPORT_RESULT = new Lookup(MethodHandles.lookup()).findOwnStatic("importResult", Object.class, Object.class);
private static final MethodHandle EXPORT_ARGUMENT;
private static final MethodHandle EXPORT_NATIVE_ARRAY;
private static final MethodHandle EXPORT_SCRIPT_OBJECT;
private static final MethodHandle IMPORT_RESULT;
private static final MethodHandle FILTER_CONSSTRING;
static {
final Lookup lookup = new Lookup(MethodHandles.lookup());
EXPORT_ARGUMENT = lookup.findOwnStatic("exportArgument", Object.class, Object.class);
EXPORT_NATIVE_ARRAY = lookup.findOwnStatic("exportNativeArray", Object.class, NativeArray.class);
EXPORT_SCRIPT_OBJECT = lookup.findOwnStatic("exportScriptObject", Object.class, ScriptObject.class);
IMPORT_RESULT = lookup.findOwnStatic("importResult", Object.class, Object.class);
FILTER_CONSSTRING = lookup.findOwnStatic("consStringFilter", Object.class, Object.class);
}
private final BeansLinker beansLinker = new BeansLinker();
@Override
public GuardedInvocation getGuardedInvocation(final LinkRequest linkRequest, final LinkerServices linkerServices) throws Exception {
if (linkRequest.getReceiver() instanceof ConsString) {
// In order to treat ConsString like a java.lang.String we need a link request with a string receiver.
final Object[] arguments = linkRequest.getArguments();
arguments[0] = "";
final LinkRequest forgedLinkRequest = linkRequest.replaceArguments(linkRequest.getCallSiteDescriptor(), arguments);
final GuardedInvocation invocation = getGuardedInvocation(beansLinker, forgedLinkRequest, linkerServices);
// If an invocation is found we add a filter that makes it work for both Strings and ConsStrings.
return invocation == null ? null : invocation.filterArguments(0, FILTER_CONSSTRING);
}
return getGuardedInvocation(beansLinker, linkRequest, linkerServices);
}
@ -113,6 +132,11 @@ public class NashornBeansLinker implements GuardingDynamicLinker {
return ScriptUtils.unwrap(arg);
}
@SuppressWarnings("unused")
private static Object consStringFilter(final Object arg) {
return arg instanceof ConsString ? arg.toString() : arg;
}
private static class NashornBeansLinkerServices implements LinkerServices {
private final LinkerServices linkerServices;

Some files were not shown because too many files have changed in this diff Show More