mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-13 11:55:38 +00:00
Merge
This commit is contained in:
commit
75a2a53eb5
@ -280,3 +280,4 @@ e4ba01b726e263953ae129be37c94de6ed145b1d jdk9-b33
|
||||
c173ba994245380fb11ef077d1e59823386840eb jdk9-b35
|
||||
201d4e235d597a25a2d3ee1404394789ba386119 jdk9-b36
|
||||
723a67b0c442391447b1d8aad8b249d06d1032e8 jdk9-b37
|
||||
d42c0a90afc3c66ca87543076ec9aafd4b4680de jdk9-b38
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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@"
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
@ -280,3 +280,4 @@ cfdac5887952c2dd73c73a1d8d9aa880d0539bbf jdk9-b33
|
||||
9bc2dbd3dfb8c9fa88e00056b8b93a81ee6d306e jdk9-b35
|
||||
ffd90c81d4ef9d94d880fc852e2fc482ecd9b374 jdk9-b36
|
||||
7e9add74ad50841fb39dae75db56374aefa1de4c jdk9-b37
|
||||
8acf056126e819cf536eef02aee0f61f207a6b52 jdk9-b38
|
||||
|
||||
@ -440,3 +440,4 @@ af46576a8d7cb4003028b8ee8bf408cfe227315b jdk9-b32
|
||||
438cb613151c4bd290bb732697517cba1cafcb04 jdk9-b35
|
||||
464ab653fbb17eb518d8ef60f8df301de7ef00d0 jdk9-b36
|
||||
b1c2dd843f247a1db19e1e85eb62ca405f72dc26 jdk9-b37
|
||||
c363a8b87e477ee45d6d3cb2a36cb365141bc596 jdk9-b38
|
||||
|
||||
@ -280,3 +280,4 @@ b940ca3d2c7e8a279ca850706b89c2ad3a841e82 jdk9-b32
|
||||
b9370464572fc663a38956047aa612d6e7854c3d jdk9-b35
|
||||
61b4c9acaa58e482db6601ec5dc4fc3d2d8dbb55 jdk9-b36
|
||||
48e4ec70cc1c8651e4a0324d91f193c4edd83af9 jdk9-b37
|
||||
6c6b34477e93e6fb350035f73ed7c02266b78380 jdk9-b38
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -283,3 +283,4 @@ e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30
|
||||
afe0c89e2edbdfb1a7ceff3d9b3ff46c4186202f jdk9-b35
|
||||
84803c3be7f79d29c7dc40749d7743675f64107a jdk9-b36
|
||||
90de6ecbff46386a3f9d6f7ca876e7aa6381f50a jdk9-b37
|
||||
dd4ba422dba858b1c3c4b38f49a3e514be4e2790 jdk9-b38
|
||||
|
||||
@ -280,3 +280,4 @@ f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27
|
||||
e549291a0227031310fa91c574891f892d27f959 jdk9-b35
|
||||
cdcf2e599e42935c2d1d19a24bb19e808aeb43b5 jdk9-b36
|
||||
27c3345d6dce39a22c262f30bb1f0e0b00c3709e jdk9-b37
|
||||
d2d745313c81d1fc01f426983b9f784ab1f750e8 jdk9-b38
|
||||
|
||||
@ -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()]);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@ -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());
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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"))
|
||||
|
||||
@ -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
|
||||
|
||||
############################################################################
|
||||
|
||||
249
jdk/test/java/lang/ClassLoader/GetSystemPackage.java
Normal file
249
jdk/test/java/lang/ClassLoader/GetSystemPackage.java
Normal 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();
|
||||
}
|
||||
}
|
||||
41
jdk/test/java/lang/System/finalization/FinInterrupt.java
Normal file
41
jdk/test/java/lang/System/finalization/FinInterrupt.java
Normal 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
*/
|
||||
|
||||
@ -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.");
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
220
jdk/test/javax/sql/testng/test/rowset/spi/SyncFactoryTests.java
Normal file
220
jdk/test/javax/sql/testng/test/rowset/spi/SyncFactoryTests.java
Normal 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());
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
27
jdk/test/javax/sql/testng/util/PropertyStubProvider.java
Normal file
27
jdk/test/javax/sql/testng/util/PropertyStubProvider.java
Normal 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 {
|
||||
|
||||
}
|
||||
220
jdk/test/javax/sql/testng/util/StubContext.java
Normal file
220
jdk/test/javax/sql/testng/util/StubContext.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
92
jdk/test/javax/sql/testng/util/StubSyncProvider.java
Normal file
92
jdk/test/javax/sql/testng/util/StubSyncProvider.java
Normal 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;
|
||||
}
|
||||
|
||||
}
|
||||
1616
jdk/test/javax/sql/testng/util/StubSyncResolver.java
Normal file
1616
jdk/test/javax/sql/testng/util/StubSyncResolver.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -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> & 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 + "'");
|
||||
}
|
||||
}
|
||||
}
|
||||
48
jdk/test/jdk/net/Sockets/SupportedOptions.java
Normal file
48
jdk/test/jdk/net/Sockets/SupportedOptions.java
Normal 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);
|
||||
}
|
||||
}
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
106
jdk/test/sun/security/tools/jarsigner/DefaultSigalg.java
Normal file
106
jdk/test/sun/security/tools/jarsigner/DefaultSigalg.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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");
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
#
|
||||
|
||||
@ -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)'" ; \
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -271,3 +271,4 @@ b374d8910e7f8de2b7ecacee9ae4cad88f23feab jdk9-b33
|
||||
63b8da4c958c3bbadfff082c547983f5daa50c0f jdk9-b35
|
||||
10fe62bc188476abb025e55f55128cbfecf24584 jdk9-b36
|
||||
dd7bbdf81a537106cfa9227d1a9a57849cb26b4d jdk9-b37
|
||||
365f55e7b3c45637bf912c88d31b32a127ad7429 jdk9-b38
|
||||
|
||||
@ -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]));
|
||||
}
|
||||
|
||||
@ -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')");
|
||||
}
|
||||
|
||||
@ -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!!" );
|
||||
|
||||
@ -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 !!" );
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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();
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
}
|
||||
@ -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) {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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")) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -141,9 +141,8 @@ class ParserContext {
|
||||
return breakable;
|
||||
}
|
||||
return null;
|
||||
} else {
|
||||
return getBreakable();
|
||||
}
|
||||
return getBreakable();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.
|
||||
*
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() :
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user