mirror of
https://github.com/openjdk/jdk.git
synced 2026-04-14 08:58:46 +00:00
Merge
This commit is contained in:
commit
76863b84de
2
.hgtags
2
.hgtags
@ -185,3 +185,5 @@ ffe6bce5a521be40146af2ac03c509b7bac30595 jdk8-b56
|
||||
cdaa6122185f9bf512dcd6600f56bfccc4824e8c jdk8-b61
|
||||
8d9d430b4244b95f5cf1ebe719f834a1ac5d6cd5 jdk8-b62
|
||||
21ee1dd7b809639284900a128b9b656a592ebc7a jdk8-b63
|
||||
70fa4b11f26522e69b51fd652215f60ce350bac3 jdk8-b64
|
||||
a2cf4d4a484378caea2e827ed604b2bbae58bdba jdk8-b65
|
||||
|
||||
@ -185,3 +185,5 @@ e07f499b9dccb529ecf74172cf6ac11a195ec57a jdk8-b60
|
||||
20ff117b509075c3aec4ee3a57990ecd5db5df9c jdk8-b61
|
||||
8a3fe0ae06a8cc21347da5a18384b0aa6c2349f5 jdk8-b62
|
||||
3229597524cab4239325bc3602df6c486397a511 jdk8-b63
|
||||
1c8370a55b305d35353346202bde042ba9e8a9fd jdk8-b64
|
||||
b772de306dc24c17f7bd1398531ddeb58723b804 jdk8-b65
|
||||
|
||||
@ -345,7 +345,13 @@ AC_ARG_WITH(conf-name, [AS_HELP_STRING([--with-conf-name],
|
||||
[ CONF_NAME=${with_conf_name} ])
|
||||
|
||||
# Test from where we are running configure, in or outside of src root.
|
||||
if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" || test "x$CURDIR" = "x$SRC_ROOT/common/autoconf" || test "x$CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
|
||||
# To enable comparison of directories, CURDIR needs to be symlink free
|
||||
# just like SRC_ROOT already is
|
||||
NOSYM_CURDIR="$CURDIR"
|
||||
BASIC_REMOVE_SYMBOLIC_LINKS(NOSYM_CURDIR)
|
||||
if test "x$NOSYM_CURDIR" = "x$SRC_ROOT" || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common" \
|
||||
|| test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/autoconf" \
|
||||
|| test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
|
||||
# We are running configure from the src root.
|
||||
# Create a default ./build/target-variant-debuglevel output root.
|
||||
if test "x${CONF_NAME}" = x; then
|
||||
|
||||
@ -204,7 +204,7 @@ AC_DEFUN_ONCE([BPERF_SETUP_PRECOMPILED_HEADERS],
|
||||
#
|
||||
AC_ARG_ENABLE([precompiled-headers], [AS_HELP_STRING([--disable-precompiled-headers],
|
||||
[disable using precompiled headers when compiling C++ @<:@enabled@:>@])],
|
||||
[ENABLE_PRECOMPH=${enable_precompiled-headers}], [ENABLE_PRECOMPH=yes])
|
||||
[ENABLE_PRECOMPH=${enable_precompiled_headers}], [ENABLE_PRECOMPH=yes])
|
||||
|
||||
USE_PRECOMPILED_HEADER=1
|
||||
if test "x$ENABLE_PRECOMPH" = xno; then
|
||||
@ -214,17 +214,16 @@ fi
|
||||
if test "x$ENABLE_PRECOMPH" = xyes; then
|
||||
# Check that the compiler actually supports precomp headers.
|
||||
if test "x$GCC" = xyes; then
|
||||
AC_MSG_CHECKING([that precompiled headers work])
|
||||
AC_MSG_CHECKING([that precompiled headers work])
|
||||
echo "int alfa();" > conftest.h
|
||||
$CXX -x c++-header conftest.h -o conftest.hpp.gch
|
||||
$CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&AS_MESSAGE_LOG_FD >&AS_MESSAGE_LOG_FD
|
||||
if test ! -f conftest.hpp.gch; then
|
||||
echo Precompiled header is not working!
|
||||
USE_PRECOMPILED_HEADER=0
|
||||
AC_MSG_RESULT([no])
|
||||
else
|
||||
AC_MSG_RESULT([yes])
|
||||
fi
|
||||
rm -f conftest.h
|
||||
rm -f conftest.h conftest.hpp.gch
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@ -730,6 +730,8 @@ AR_OUT_OPTION
|
||||
LD_OUT_OPTION
|
||||
EXE_OUT_OPTION
|
||||
CC_OUT_OPTION
|
||||
BUILD_HOTSPOT
|
||||
HOTSPOT_DIST
|
||||
BUILD_OUTPUT
|
||||
OVERRIDE_SRC_ROOT
|
||||
ADD_SRC_ROOT
|
||||
@ -975,6 +977,7 @@ with_override_jaxp
|
||||
with_override_jaxws
|
||||
with_override_hotspot
|
||||
with_override_jdk
|
||||
with_import_hotspot
|
||||
with_msvcr_dll
|
||||
with_extra_cflags
|
||||
with_extra_cxxflags
|
||||
@ -990,7 +993,7 @@ with_alsa
|
||||
with_alsa_include
|
||||
with_alsa_lib
|
||||
with_zlib
|
||||
enable_static_link_stdc__
|
||||
with_stdc__lib
|
||||
with_num_cores
|
||||
with_memory_size
|
||||
with_sjavac_server_java
|
||||
@ -1657,9 +1660,6 @@ Optional Features:
|
||||
--disable-macosx-runtime-support
|
||||
disable the use of MacOSX Java runtime support
|
||||
framework [enabled]
|
||||
--disable-static-link-stdc++
|
||||
disable static linking of the C++ runtime on Linux
|
||||
[enabled]
|
||||
--enable-sjavac use sjavac to do fast incremental compiles
|
||||
[disabled]
|
||||
--disable-precompiled-headers
|
||||
@ -1719,6 +1719,9 @@ Optional Packages:
|
||||
--with-override-jaxws use this jaxws dir for the build
|
||||
--with-override-hotspot use this hotspot dir for the build
|
||||
--with-override-jdk use this jdk dir for the build
|
||||
--with-import-hotspot import hotspot binaries from this jdk image or
|
||||
hotspot build dist dir instead of building from
|
||||
source
|
||||
--with-msvcr-dll copy this msvcr100.dll into the built JDK (Windows
|
||||
only) [probed]
|
||||
--with-extra-cflags extra flags to be used when compiling jdk c-files
|
||||
@ -1738,6 +1741,10 @@ Optional Packages:
|
||||
--with-alsa-lib specify directory for the alsa library
|
||||
--with-zlib use zlib from build system or OpenJDK source
|
||||
(system, bundled) [bundled]
|
||||
--with-stdc++lib=<static>,<dynamic>,<default>
|
||||
force linking of the C++ runtime on Linux to either
|
||||
static or dynamic, default is static with dynamic as
|
||||
fallback
|
||||
--with-num-cores number of cores in the build system, e.g.
|
||||
--with-num-cores=8 [probed]
|
||||
--with-memory-size memory (in MB) available in the build system, e.g.
|
||||
@ -3665,7 +3672,7 @@ fi
|
||||
#CUSTOM_AUTOCONF_INCLUDE
|
||||
|
||||
# Do not change or remove the following line, it is needed for consistency checks:
|
||||
DATE_WHEN_GENERATED=1351854415
|
||||
DATE_WHEN_GENERATED=1354106772
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
@ -7575,7 +7582,56 @@ fi
|
||||
|
||||
|
||||
# Test from where we are running configure, in or outside of src root.
|
||||
if test "x$CURDIR" = "x$SRC_ROOT" || test "x$CURDIR" = "x$SRC_ROOT/common" || test "x$CURDIR" = "x$SRC_ROOT/common/autoconf" || test "x$CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
|
||||
# To enable comparison of directories, CURDIR needs to be symlink free
|
||||
# just like SRC_ROOT already is
|
||||
NOSYM_CURDIR="$CURDIR"
|
||||
|
||||
if test "x$OPENJDK_BUILD_OS" != xwindows; then
|
||||
# Follow a chain of symbolic links. Use readlink
|
||||
# where it exists, else fall back to horribly
|
||||
# complicated shell code.
|
||||
if test "x$READLINK_TESTED" != yes; then
|
||||
# On MacOSX there is a readlink tool with a different
|
||||
# purpose than the GNU readlink tool. Check the found readlink.
|
||||
ISGNU=`$READLINK --help 2>&1 | $GREP GNU`
|
||||
if test "x$ISGNU" = x; then
|
||||
# A readlink that we do not know how to use.
|
||||
# Are there other non-GNU readlinks out there?
|
||||
READLINK_TESTED=yes
|
||||
READLINK=
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$READLINK" != x; then
|
||||
NOSYM_CURDIR=`$READLINK -f $NOSYM_CURDIR`
|
||||
else
|
||||
STARTDIR=$PWD
|
||||
COUNTER=0
|
||||
sym_link_dir=`$DIRNAME $NOSYM_CURDIR`
|
||||
sym_link_file=`$BASENAME $NOSYM_CURDIR`
|
||||
while test $COUNTER -lt 20; do
|
||||
ISLINK=`$LS -l $sym_link_dir/$sym_link_file | $GREP '\->' | $SED -e 's/.*-> \(.*\)/\1/'`
|
||||
if test "x$ISLINK" == x; then
|
||||
# This is not a symbolic link! We are done!
|
||||
break
|
||||
fi
|
||||
# The link might be relative! We have to use cd to travel safely.
|
||||
cd $sym_link_dir
|
||||
# ... and we must get the to the absolute path, not one using symbolic links.
|
||||
cd `pwd -P`
|
||||
cd `$DIRNAME $ISLINK`
|
||||
sym_link_dir=`$THEPWDCMD`
|
||||
sym_link_file=`$BASENAME $ISLINK`
|
||||
let COUNTER=COUNTER+1
|
||||
done
|
||||
cd $STARTDIR
|
||||
NOSYM_CURDIR=$sym_link_dir/$sym_link_file
|
||||
fi
|
||||
fi
|
||||
|
||||
if test "x$NOSYM_CURDIR" = "x$SRC_ROOT" || test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common" \
|
||||
|| test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/autoconf" \
|
||||
|| test "x$NOSYM_CURDIR" = "x$SRC_ROOT/common/makefiles" ; then
|
||||
# We are running configure from the src root.
|
||||
# Create a default ./build/target-variant-debuglevel output root.
|
||||
if test "x${CONF_NAME}" = x; then
|
||||
@ -15582,6 +15638,31 @@ fi
|
||||
BUILD_OUTPUT="$OUTPUT_ROOT"
|
||||
|
||||
|
||||
HOTSPOT_DIST="$OUTPUT_ROOT/hotspot/dist"
|
||||
BUILD_HOTSPOT=true
|
||||
|
||||
|
||||
|
||||
# Check whether --with-import-hotspot was given.
|
||||
if test "${with_import_hotspot+set}" = set; then :
|
||||
withval=$with_import_hotspot;
|
||||
fi
|
||||
|
||||
if test "x$with_import_hotspot" != x; then
|
||||
CURDIR="$PWD"
|
||||
cd "$with_import_hotspot"
|
||||
HOTSPOT_DIST="`pwd`"
|
||||
cd "$CURDIR"
|
||||
if ! (test -d $HOTSPOT_DIST/lib && test -d $HOTSPOT_DIST/jre/lib); then
|
||||
as_fn_error $? "You have to import hotspot from a full jdk image or hotspot build dist dir!" "$LINENO" 5
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if hotspot should be imported" >&5
|
||||
$as_echo_n "checking if hotspot should be imported... " >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes from $HOTSPOT_DIST" >&5
|
||||
$as_echo "yes from $HOTSPOT_DIST" >&6; }
|
||||
BUILD_HOTSPOT=false
|
||||
fi
|
||||
|
||||
JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
|
||||
|
||||
|
||||
@ -25583,6 +25664,8 @@ esac
|
||||
fi
|
||||
fi
|
||||
|
||||
# Only call fixup if objcopy was found.
|
||||
if test -n "$OBJCOPY"; then
|
||||
|
||||
if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then
|
||||
|
||||
@ -25838,6 +25921,7 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow
|
||||
$as_echo "$as_me: Rewriting OBJCOPY to \"$new_complete\"" >&6;}
|
||||
fi
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
if test -n "$ac_tool_prefix"; then
|
||||
@ -27498,10 +27582,19 @@ else
|
||||
fi
|
||||
fi
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDK} $SHARED_LIBRARY_FLAGS \
|
||||
-L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server \
|
||||
-L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/client \
|
||||
-L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}"
|
||||
|
||||
# On some platforms (mac) the linker warns about non existing -L dirs.
|
||||
# Add server first if available. Linking aginst client does not always produce the same results.
|
||||
# Only add client dir if client is being built. Default to server for other variants.
|
||||
if test "x$JVM_VARIANT_SERVER" = xtrue; then
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server"
|
||||
elif test "x$JVM_VARIANT_CLIENT" = xtrue; then
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/client"
|
||||
else
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server"
|
||||
fi
|
||||
|
||||
LDFLAGS_JDKLIB_SUFFIX="-ljava -ljvm"
|
||||
if test "x$COMPILER_NAME" = xossc; then
|
||||
LDFLAGS_JDKLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX -lc"
|
||||
@ -30159,12 +30252,17 @@ LIBS="$save_LIBS"
|
||||
# statically link libstdc++ before C++ ABI is stablized on Linux unless
|
||||
# dynamic build is configured on command line.
|
||||
#
|
||||
# Check whether --enable-static-link-stdc++ was given.
|
||||
if test "${enable_static_link_stdc__+set}" = set; then :
|
||||
enableval=$enable_static_link_stdc__;
|
||||
else
|
||||
|
||||
enable_static_link_stdc__=yes
|
||||
# Check whether --with-stdc++lib was given.
|
||||
if test "${with_stdc__lib+set}" = set; then :
|
||||
withval=$with_stdc__lib;
|
||||
if test "x$with_stdc__lib" != xdynamic && test "x$with_stdc__lib" != xstatic \
|
||||
&& test "x$with_stdc__lib" != xdefault; then
|
||||
as_fn_error $? "Bad parameter value --with-stdc++lib=$with_stdc__lib!" "$LINENO" 5
|
||||
fi
|
||||
|
||||
else
|
||||
with_stdc__lib=default
|
||||
|
||||
fi
|
||||
|
||||
@ -30252,36 +30350,34 @@ ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $has_static_libstdcxx" >&5
|
||||
$as_echo "$has_static_libstdcxx" >&6; }
|
||||
|
||||
if test "x$has_static_libcxx" = xno && test "x$has_dynamic_libcxx" = xno; then
|
||||
as_fn_error $? "I cannot link to stdc++! Neither dynamically nor statically." "$LINENO" 5
|
||||
if test "x$has_static_libstdcxx" = xno && test "x$has_dynamic_libstdcxx" = xno; then
|
||||
as_fn_error $? "Cannot link to stdc++, neither dynamically nor statically!" "$LINENO" 5
|
||||
fi
|
||||
|
||||
if test "x$enable_static_link_stdc__" = xyes && test "x$has_static_libstdcxx" = xno; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Static linking of libstdc++ was not possible reverting to dynamic linking." >&5
|
||||
$as_echo "$as_me: Static linking of libstdc++ was not possible reverting to dynamic linking." >&6;}
|
||||
enable_static_link_stdc__=no
|
||||
if test "x$with_stdc__lib" = xstatic && test "x$has_static_libstdcxx" = xno; then
|
||||
as_fn_error $? "Static linking of libstdc++ was not possible!" "$LINENO" 5
|
||||
fi
|
||||
|
||||
if test "x$enable_static_link_stdc__" = xno && test "x$has_dynamic_libstdcxx" = xno; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: Dynamic linking of libstdc++ was not possible reverting to static linking." >&5
|
||||
$as_echo "$as_me: Dynamic linking of libstdc++ was not possible reverting to static linking." >&6;}
|
||||
enable_static_link_stdc__=yes
|
||||
if test "x$with_stdc__lib" = xdynamic && test "x$has_dynamic_libstdcxx" = xno; then
|
||||
as_fn_error $? "Dynamic linking of libstdc++ was not possible!" "$LINENO" 5
|
||||
fi
|
||||
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to link with libstdc++" >&5
|
||||
$as_echo_n "checking how to link with libstdc++... " >&6; }
|
||||
if test "x$enable_static_link_stdc__" = xyes; then
|
||||
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
|
||||
LDCXX="$CC"
|
||||
STATIC_CXX_SETTING="STATIC_CXX=true"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
|
||||
$as_echo "static" >&6; }
|
||||
else
|
||||
# If dynamic was requested, it's available since it would fail above otherwise.
|
||||
# If dynamic wasn't requested, go with static unless it isn't available.
|
||||
if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno; then
|
||||
LIBCXX="$LIBCXX -lstdc++"
|
||||
LDCXX="$CXX"
|
||||
STATIC_CXX_SETTING="STATIC_CXX=false"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: dynamic" >&5
|
||||
$as_echo "dynamic" >&6; }
|
||||
else
|
||||
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
|
||||
LDCXX="$CC"
|
||||
STATIC_CXX_SETTING="STATIC_CXX=true"
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: static" >&5
|
||||
$as_echo "static" >&6; }
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -30733,7 +30829,7 @@ fi
|
||||
#
|
||||
# Check whether --enable-precompiled-headers was given.
|
||||
if test "${enable_precompiled_headers+set}" = set; then :
|
||||
enableval=$enable_precompiled_headers; ENABLE_PRECOMPH=${enable_precompiled-headers}
|
||||
enableval=$enable_precompiled_headers; ENABLE_PRECOMPH=${enable_precompiled_headers}
|
||||
else
|
||||
ENABLE_PRECOMPH=yes
|
||||
fi
|
||||
@ -30750,9 +30846,8 @@ if test "x$ENABLE_PRECOMPH" = xyes; then
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking that precompiled headers work" >&5
|
||||
$as_echo_n "checking that precompiled headers work... " >&6; }
|
||||
echo "int alfa();" > conftest.h
|
||||
$CXX -x c++-header conftest.h -o conftest.hpp.gch
|
||||
$CXX -x c++-header conftest.h -o conftest.hpp.gch 2>&5 >&5
|
||||
if test ! -f conftest.hpp.gch; then
|
||||
echo Precompiled header is not working!
|
||||
USE_PRECOMPILED_HEADER=0
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
|
||||
$as_echo "no" >&6; }
|
||||
@ -30760,7 +30855,7 @@ $as_echo "no" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
|
||||
$as_echo "yes" >&6; }
|
||||
fi
|
||||
rm -f conftest.h
|
||||
rm -f conftest.h conftest.hpp.gch
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@ -95,6 +95,8 @@ EXTRA_CFLAGS=@LEGACY_EXTRA_CFLAGS@
|
||||
EXTRA_CXXFLAGS=@LEGACY_EXTRA_CXXFLAGS@
|
||||
EXTRA_LDFLAGS=@LEGACY_EXTRA_LDFLAGS@
|
||||
|
||||
USE_PRECOMPILED_HEADER=@USE_PRECOMPILED_HEADER@
|
||||
|
||||
# Sneak this in via the spec.gmk file, since we don't want to mess around too much with the Hotspot make files.
|
||||
# This is needed to get the LOG setting to work properly.
|
||||
include $(SRC_ROOT)/common/makefiles/MakeBase.gmk
|
||||
|
||||
@ -601,11 +601,16 @@ AC_DEFUN_ONCE([LIB_SETUP_STATIC_LINK_LIBSTDCPP],
|
||||
# statically link libstdc++ before C++ ABI is stablized on Linux unless
|
||||
# dynamic build is configured on command line.
|
||||
#
|
||||
AC_ARG_ENABLE([static-link-stdc++], [AS_HELP_STRING([--disable-static-link-stdc++],
|
||||
[disable static linking of the C++ runtime on Linux @<:@enabled@:>@])],,
|
||||
[
|
||||
enable_static_link_stdc__=yes
|
||||
])
|
||||
AC_ARG_WITH([stdc++lib], [AS_HELP_STRING([--with-stdc++lib=<static>,<dynamic>,<default>],
|
||||
[force linking of the C++ runtime on Linux to either static or dynamic, default is static with dynamic as fallback])],
|
||||
[
|
||||
if test "x$with_stdc__lib" != xdynamic && test "x$with_stdc__lib" != xstatic \
|
||||
&& test "x$with_stdc__lib" != xdefault; then
|
||||
AC_MSG_ERROR([Bad parameter value --with-stdc++lib=$with_stdc__lib!])
|
||||
fi
|
||||
],
|
||||
[with_stdc__lib=default]
|
||||
)
|
||||
|
||||
if test "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
# Test if -lstdc++ works.
|
||||
@ -636,31 +641,31 @@ if test "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
AC_LANG_POP(C++)
|
||||
AC_MSG_RESULT([$has_static_libstdcxx])
|
||||
|
||||
if test "x$has_static_libcxx" = xno && test "x$has_dynamic_libcxx" = xno; then
|
||||
AC_MSG_ERROR([I cannot link to stdc++! Neither dynamically nor statically.])
|
||||
if test "x$has_static_libstdcxx" = xno && test "x$has_dynamic_libstdcxx" = xno; then
|
||||
AC_MSG_ERROR([Cannot link to stdc++, neither dynamically nor statically!])
|
||||
fi
|
||||
|
||||
if test "x$enable_static_link_stdc__" = xyes && test "x$has_static_libstdcxx" = xno; then
|
||||
AC_MSG_NOTICE([Static linking of libstdc++ was not possible reverting to dynamic linking.])
|
||||
enable_static_link_stdc__=no
|
||||
if test "x$with_stdc__lib" = xstatic && test "x$has_static_libstdcxx" = xno; then
|
||||
AC_MSG_ERROR([Static linking of libstdc++ was not possible!])
|
||||
fi
|
||||
|
||||
if test "x$enable_static_link_stdc__" = xno && test "x$has_dynamic_libstdcxx" = xno; then
|
||||
AC_MSG_NOTICE([Dynamic linking of libstdc++ was not possible reverting to static linking.])
|
||||
enable_static_link_stdc__=yes
|
||||
if test "x$with_stdc__lib" = xdynamic && test "x$has_dynamic_libstdcxx" = xno; then
|
||||
AC_MSG_ERROR([Dynamic linking of libstdc++ was not possible!])
|
||||
fi
|
||||
|
||||
AC_MSG_CHECKING([how to link with libstdc++])
|
||||
if test "x$enable_static_link_stdc__" = xyes; then
|
||||
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
|
||||
LDCXX="$CC"
|
||||
STATIC_CXX_SETTING="STATIC_CXX=true"
|
||||
AC_MSG_RESULT([static])
|
||||
else
|
||||
# If dynamic was requested, it's available since it would fail above otherwise.
|
||||
# If dynamic wasn't requested, go with static unless it isn't available.
|
||||
if test "x$with_stdc__lib" = xdynamic || test "x$has_static_libstdcxx" = xno; then
|
||||
LIBCXX="$LIBCXX -lstdc++"
|
||||
LDCXX="$CXX"
|
||||
STATIC_CXX_SETTING="STATIC_CXX=false"
|
||||
AC_MSG_RESULT([dynamic])
|
||||
else
|
||||
LIBCXX="$LIBCXX $STATIC_STDCXX_FLAGS"
|
||||
LDCXX="$CC"
|
||||
STATIC_CXX_SETTING="STATIC_CXX=true"
|
||||
AC_MSG_RESULT([static])
|
||||
fi
|
||||
fi
|
||||
AC_SUBST(STATIC_CXX_SETTING)
|
||||
|
||||
@ -253,5 +253,24 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
||||
BUILD_OUTPUT="$OUTPUT_ROOT"
|
||||
AC_SUBST(BUILD_OUTPUT)
|
||||
|
||||
HOTSPOT_DIST="$OUTPUT_ROOT/hotspot/dist"
|
||||
BUILD_HOTSPOT=true
|
||||
AC_SUBST(HOTSPOT_DIST)
|
||||
AC_SUBST(BUILD_HOTSPOT)
|
||||
AC_ARG_WITH(import-hotspot, [AS_HELP_STRING([--with-import-hotspot],
|
||||
[import hotspot binaries from this jdk image or hotspot build dist dir instead of building from source])])
|
||||
if test "x$with_import_hotspot" != x; then
|
||||
CURDIR="$PWD"
|
||||
cd "$with_import_hotspot"
|
||||
HOTSPOT_DIST="`pwd`"
|
||||
cd "$CURDIR"
|
||||
if ! (test -d $HOTSPOT_DIST/lib && test -d $HOTSPOT_DIST/jre/lib); then
|
||||
AC_MSG_ERROR([You have to import hotspot from a full jdk image or hotspot build dist dir!])
|
||||
fi
|
||||
AC_MSG_CHECKING([if hotspot should be imported])
|
||||
AC_MSG_RESULT([yes from $HOTSPOT_DIST])
|
||||
BUILD_HOTSPOT=false
|
||||
fi
|
||||
|
||||
JDK_OUTPUTDIR="$OUTPUT_ROOT/jdk"
|
||||
])
|
||||
|
||||
@ -224,7 +224,9 @@ LANGTOOLS_DIST=$(LANGTOOLS_OUTPUTDIR)/dist
|
||||
CORBA_DIST=$(CORBA_OUTPUTDIR)/dist
|
||||
JAXP_DIST=$(JAXP_OUTPUTDIR)/dist
|
||||
JAXWS_DIST=$(JAXWS_OUTPUTDIR)/dist
|
||||
HOTSPOT_DIST=$(HOTSPOT_OUTPUTDIR)/dist
|
||||
HOTSPOT_DIST=@HOTSPOT_DIST@
|
||||
|
||||
BUILD_HOTSPOT=@BUILD_HOTSPOT@
|
||||
|
||||
# The boot jdk to use
|
||||
BOOT_JDK:=@BOOT_JDK@
|
||||
@ -244,12 +246,6 @@ ENABLE_SJAVAC:=@ENABLE_SJAVAC@
|
||||
# Store sjavac server synchronization files here, and
|
||||
# the sjavac server log files.
|
||||
SJAVAC_SERVER_DIR:=@SJAVAC_SERVER_DIR@
|
||||
# We can block the Javac server to never use more cores than this.
|
||||
# This is not for performance reasons, but for memory usage, since each
|
||||
# core requires its own JavaCompiler. We might have 64 cores and 4GB
|
||||
# of memory, 64 JavaCompilers will currently not fit in a 3GB heap.
|
||||
# Since there is no sharing of data between the JavaCompilers.
|
||||
SJAVAC_SERVER_CORES:=@SJAVAC_SERVER_CORES@
|
||||
|
||||
# The OpenJDK makefiles should be changed to using the standard
|
||||
# configure output ..._CFLAGS and ..._LIBS. In the meantime we
|
||||
@ -494,7 +490,14 @@ FIXPATH:=@FIXPATH@
|
||||
# Where the build output is stored for your convenience.
|
||||
BUILD_LOG:=@BUILD_LOG@
|
||||
BUILD_LOG_PREVIOUS:=@BUILD_LOG_PREVIOUS@
|
||||
BUILD_LOG_WRAPPER:=@BUILD_LOG_WRAPPER@
|
||||
# Disable the build log wrapper on sjavac+winapi until
|
||||
# we have solved how to prevent the log wrapper to wait
|
||||
# for the background sjavac server process.
|
||||
ifeq (@ENABLE_SJAVAC@X@OPENJDK_BUILD_OS_API@,yesXwinapi)
|
||||
BUILD_LOG_WRAPPER:=
|
||||
else
|
||||
BUILD_LOG_WRAPPER:=@BUILD_LOG_WRAPPER@
|
||||
endif
|
||||
|
||||
# Build setup
|
||||
ENABLE_JFR=@ENABLE_JFR@
|
||||
|
||||
@ -437,7 +437,10 @@ fi
|
||||
# full debug symbols are enabled.
|
||||
if test "x$OPENJDK_TARGET_OS" = xsolaris || test "x$OPENJDK_TARGET_OS" = xlinux; then
|
||||
AC_CHECK_TOOLS(OBJCOPY, [gobjcopy objcopy])
|
||||
BASIC_FIXUP_EXECUTABLE(OBJCOPY)
|
||||
# Only call fixup if objcopy was found.
|
||||
if test -n "$OBJCOPY"; then
|
||||
BASIC_FIXUP_EXECUTABLE(OBJCOPY)
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_CHECK_TOOLS(OBJDUMP, [gobjdump objdump])
|
||||
@ -935,10 +938,19 @@ else
|
||||
fi
|
||||
fi
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDK} $SHARED_LIBRARY_FLAGS \
|
||||
-L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server \
|
||||
-L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/client \
|
||||
-L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}"
|
||||
|
||||
# On some platforms (mac) the linker warns about non existing -L dirs.
|
||||
# Add server first if available. Linking aginst client does not always produce the same results.
|
||||
# Only add client dir if client is being built. Default to server for other variants.
|
||||
if test "x$JVM_VARIANT_SERVER" = xtrue; then
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server"
|
||||
elif test "x$JVM_VARIANT_CLIENT" = xtrue; then
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/client"
|
||||
else
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${JDK_OUTPUTDIR}/lib${OPENJDK_TARGET_CPU_LIBDIR}/server"
|
||||
fi
|
||||
|
||||
LDFLAGS_JDKLIB_SUFFIX="-ljava -ljvm"
|
||||
if test "x$COMPILER_NAME" = xossc; then
|
||||
LDFLAGS_JDKLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX -lc"
|
||||
|
||||
@ -283,13 +283,14 @@ compare_general_files() {
|
||||
! -name "*.debuginfo" ! -name "*.dylib" ! -name "jexec" \
|
||||
! -name "ct.sym" ! -name "*.diz" ! -name "*.dll" \
|
||||
! -name "*.pdb" ! -name "*.exp" ! -name "*.ilk" \
|
||||
! -name "*.lib" ! -name "*.war" \
|
||||
! -name "*.lib" ! -name "*.war" ! -name "JavaControlPanel" \
|
||||
| $GREP -v "./bin/" | $SORT | $FILTER)
|
||||
|
||||
echo General files...
|
||||
for f in $GENERAL_FILES
|
||||
do
|
||||
if [ -e $OTHER_DIR/$f ]; then
|
||||
SUFFIX="${f##*.}"
|
||||
if [ "$(basename $f)" = "release" ]; then
|
||||
# Ignore differences in change numbers in release file.
|
||||
OTHER_FILE=$WORK_DIR/$f.other
|
||||
@ -298,6 +299,22 @@ compare_general_files() {
|
||||
$MKDIR -p $(dirname $THIS_FILE)
|
||||
$CAT $OTHER_DIR/$f | $SED 's/\:[0-9a-f]\{12,12\}/:CHANGE/g' > $OTHER_FILE
|
||||
$CAT $THIS_DIR/$f | $SED 's/\:[0-9a-f]\{12,12\}/:CHANGE/g' > $THIS_FILE
|
||||
elif [ "x$SUFFIX" = "xhtml" ]; then
|
||||
# Ignore time stamps in docs files
|
||||
OTHER_FILE=$WORK_DIR/$f.other
|
||||
THIS_FILE=$WORK_DIR/$f.this
|
||||
$MKDIR -p $(dirname $OTHER_FILE)
|
||||
$MKDIR -p $(dirname $THIS_FILE)
|
||||
$CAT $OTHER_DIR/$f | $SED -e 's/\(-- Generated by javadoc \).*\( --\)/\1(removed)\2/' \
|
||||
-e 's/\(<meta name="date" content="\).*\(">\)/\1(removed)\2/' \
|
||||
-e 's/\(Monday\|Tuesday\|Wednesday\|Thursday\|Friday\|Saturday\|Sunday\), [A-Z][a-z]* [0-9][0-9]*, [12][0-9]* [0-9][0-9:]* \(AM\|PM\) [A-Z][A-Z]*/(removed)/' \
|
||||
-e 's/^\( from \).*\(\.idl\)$/\1(removed)\2/' \
|
||||
> $OTHER_FILE
|
||||
$CAT $THIS_DIR/$f | $SED -e 's/\(-- Generated by javadoc \).*\( --\)/\1(removed)\2/' \
|
||||
-e 's/\(<meta name="date" content="\).*\(">\)/\1(removed)\2/' \
|
||||
-e 's/\(Monday\|Tuesday\|Wednesday\|Thursday\|Friday\|Saturday\|Sunday\), [A-Z][a-z]* [0-9][0-9]*, [12][0-9]* [0-9][0-9:]* \(AM\|PM\) [A-Z][A-Z]*/(removed)/' \
|
||||
-e 's/^\( from \).*\(\.idl\)$/\1(removed)\2/' \
|
||||
> $THIS_FILE
|
||||
else
|
||||
OTHER_FILE=$OTHER_DIR/$f
|
||||
THIS_FILE=$THIS_DIR/$f
|
||||
@ -611,10 +628,19 @@ compare_bin_file() {
|
||||
DIFF_SIZE_NUM=$($EXPR $THIS_SIZE - $OTHER_SIZE)
|
||||
DIFF_SIZE_REL=$($EXPR $THIS_SIZE \* 100 / $OTHER_SIZE)
|
||||
SIZE_MSG=$($PRINTF "%3d%% %4d" $DIFF_SIZE_REL $DIFF_SIZE_NUM)
|
||||
if [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] && [ "$DIFF_SIZE_REL" -gt 98 ] && [ "$DIFF_SIZE_REL" -lt 102 ]; then
|
||||
if [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] && [ "$DIFF_SIZE_REL" -gt 98 ] \
|
||||
&& [ "$DIFF_SIZE_REL" -lt 102 ]; then
|
||||
SIZE_MSG="($SIZE_MSG)"
|
||||
DIFF_SIZE=
|
||||
elif [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] && [ "$DIFF_SIZE_NUM" = 512 ]; then
|
||||
elif [ "$OPENJDK_TARGET_OS" = "windows" ] \
|
||||
&& [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] \
|
||||
&& [ "$DIFF_SIZE_NUM" = 512 ]; then
|
||||
# On windows, size of binaries increase in 512 increments.
|
||||
SIZE_MSG="($SIZE_MSG)"
|
||||
DIFF_SIZE=
|
||||
elif [ "$OPENJDK_TARGET_OS" = "windows" ] \
|
||||
&& [[ "$ACCEPTED_SMALL_SIZE_DIFF" = *"$BIN_FILE"* ]] \
|
||||
&& [ "$DIFF_SIZE_NUM" = -512 ]; then
|
||||
# On windows, size of binaries increase in 512 increments.
|
||||
SIZE_MSG="($SIZE_MSG)"
|
||||
DIFF_SIZE=
|
||||
@ -840,7 +866,7 @@ compare_all_libs() {
|
||||
OTHER_DIR=$2
|
||||
WORK_DIR=$3
|
||||
|
||||
LIBS=$(cd $THIS_DIR && $FIND . -type f \( -name 'lib*.so' -o -name '*.dylib' -o -name '*.dll' \) | $SORT | $FILTER)
|
||||
LIBS=$(cd $THIS_DIR && $FIND . -type f \( -name 'lib*.so' -o -name '*.dylib' -o -name '*.dll' -o -name 'JavaControlPanel' \) | $SORT | $FILTER)
|
||||
|
||||
if [ -n "$LIBS" ]; then
|
||||
echo Libraries...
|
||||
@ -1102,6 +1128,22 @@ if [ -z "$THIS_J2SDK_BUNDLE" ] && [ -n "$OTHER_J2SDK_BUNDLE" ]; then
|
||||
echo "Skipping bundle compare!"
|
||||
fi
|
||||
|
||||
if [ -d "$THIS/docs" ]; then
|
||||
THIS_DOCS="$THIS/docs"
|
||||
fi
|
||||
|
||||
if [ -d "$OTHER/docs" ]; then
|
||||
OTHER_DOCS="$OTHER/docs"
|
||||
fi
|
||||
|
||||
if [ -z "$THIS_DOCS" ]; then
|
||||
echo "WARNING! Docs haven't been built and won't be compared."
|
||||
fi
|
||||
|
||||
if [ -z "$OTHER_DOCS" ]; then
|
||||
echo "WARNING! Other build doesn't contain docs, skipping doc compare."
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Do the work
|
||||
|
||||
@ -1139,6 +1181,12 @@ if [ "$CMP_NAMES" = "true" ]; then
|
||||
echo -n "J2RE Bundle "
|
||||
compare_files $THIS_J2RE_BUNDLE $OTHER_J2RE_BUNDLE $COMPARE_ROOT/j2re-bundle
|
||||
fi
|
||||
if [ -n "$THIS_DOCS" ] && [ -n "$OTHER_DOCS" ]; then
|
||||
echo -n "Docs "
|
||||
compare_dirs $THIS_DOCS $OTHER_DOCS $COMPARE_ROOT/docs
|
||||
echo -n "Docs "
|
||||
compare_files $THIS_DOCS $OTHER_DOCS $COMPARE_ROOT/docs
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$CMP_PERMS" = "true" ]; then
|
||||
@ -1202,6 +1250,10 @@ if [ "$CMP_GENERAL" = "true" ]; then
|
||||
echo -n "J2RE Bundle "
|
||||
compare_general_files $THIS_J2RE_BUNDLE $OTHER_J2RE_BUNDLE $COMPARE_ROOT/j2re-bundle
|
||||
fi
|
||||
if [ -n "$THIS_DOCS" ] && [ -n "$OTHER_DOCS" ]; then
|
||||
echo -n "Docs "
|
||||
compare_general_files $THIS_DOCS $OTHER_DOCS $COMPARE_ROOT/docs
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$CMP_ZIPS" = "true" ]; then
|
||||
@ -1218,7 +1270,12 @@ fi
|
||||
|
||||
if [ "$CMP_LIBS" = "true" ]; then
|
||||
if [ -n "$THIS_J2SDK" ] && [ -n "$OTHER_J2SDK" ]; then
|
||||
echo -n "J2SDK "
|
||||
compare_all_libs $THIS_J2SDK $OTHER_J2SDK $COMPARE_ROOT/j2sdk
|
||||
if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then
|
||||
echo -n "J2RE "
|
||||
compare_all_libs $THIS_J2RE $OTHER_J2RE $COMPARE_ROOT/j2re
|
||||
fi
|
||||
fi
|
||||
if [ -n "$THIS_J2SDK_OVERLAY" ] && [ -n "$OTHER_J2SDK_OVERLAY" ]; then
|
||||
echo -n "Bundle "
|
||||
|
||||
@ -291,6 +291,14 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./jre/plugin/i386/ns4/libjavaplugin.so
|
||||
./jre/plugin/i386/ns7/libjavaplugin_oji.so
|
||||
./jre/lib/i386/server/libjvm.so
|
||||
./jre/lib/i386/client/64/libjvm_db.so
|
||||
./jre/lib/i386/client/64/libjvm_dtrace.so
|
||||
./jre/lib/i386/client/libjvm_db.so
|
||||
./jre/lib/i386/client/libjvm_dtrace.so
|
||||
./jre/lib/i386/server/64/libjvm_db.so
|
||||
./jre/lib/i386/server/64/libjvm_dtrace.so
|
||||
./jre/lib/i386/server/libjvm_db.so
|
||||
./jre/lib/i386/server/libjvm_dtrace.so
|
||||
./bin/appletviewer
|
||||
./bin/extcheck
|
||||
./bin/idlj
|
||||
@ -348,7 +356,9 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
SKIP_FULLDUMP_DIFF="true"
|
||||
|
||||
# Filter random C++ symbol strings.
|
||||
DIS_DIFF_FILTER="$SED -e s/\.[a-zA-Z0-9_\$]\{15,15\}/<SYM>/g"
|
||||
# Some numbers differ randomly.
|
||||
# Can't use space in these expressions as the shell will mess with them.
|
||||
DIS_DIFF_FILTER="$SED -e s/\.[a-zA-Z0-9_\$]\{15,15\}/<SYM>/g -e s/\([0-9a-f][0-9a-f].\)\{2,8\}[0-9a-f][0-9a-f]/<NUMS>/g -e s/\(0x\)[0-9a-f]*\([,(>]\)/\1<HEX>\2/g -e s/\(0x\)[0-9a-f]*$/\1<HEX>/g -e s/\(\#.\)[0-9a-f]*\(.<\)/\1<HEX>\2/g -e s/[\.A-Za-z0-9%]\{16,16\}$/<BIN>/g"
|
||||
|
||||
fi
|
||||
|
||||
@ -426,6 +436,9 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
./jre/lib/amd64/libzip.so
|
||||
./jre/lib/amd64/server/64/libjvm_db.so
|
||||
./jre/lib/amd64/server/64/libjvm_dtrace.so
|
||||
./jre/lib/amd64/server/libjvm.so
|
||||
./jre/lib/amd64/server/libjvm_db.so
|
||||
./jre/lib/amd64/server/libjvm_dtrace.so
|
||||
./bin/amd64/appletviewer
|
||||
./bin/amd64/extcheck
|
||||
./bin/amd64/idlj
|
||||
@ -480,7 +493,9 @@ ACCEPTED_SMALL_SIZE_DIFF="
|
||||
SKIP_FULLDUMP_DIFF="true"
|
||||
|
||||
# Filter random C++ symbol strings.
|
||||
DIS_DIFF_FILTER="$SED -e s/\.[a-zA-Z0-9_\$]\{15,15\}/<SYM>/g"
|
||||
# Some numbers differ randomly.
|
||||
# Can't use space in these expressions as the shell will mess with them.
|
||||
DIS_DIFF_FILTER="$SED -e s/\.[a-zA-Z0-9_\$]\{15,15\}/<SYM>/g -e s/\([0-9a-f][0-9a-f].\)\{2,8\}[0-9a-f][0-9a-f]/<NUMS>/g -e s/\(0x\)[0-9a-f]*\([,(>]\)/\1<HEX>\2/g -e s/\(0x\)[0-9a-f]*$/\1<HEX>/g -e s/\(\#.\)[0-9a-f]*\(.<\)/\1<HEX>\2/g -e s/[\.A-Za-z0-9%]\{16,16\}$/<BIN>/g"
|
||||
|
||||
fi
|
||||
|
||||
@ -881,6 +896,7 @@ ACCEPTED_JARZIP_CONTENTS="
|
||||
|
||||
KNOWN_BIN_DIFF="
|
||||
./jre/lib/libJObjC.dylib
|
||||
./lib/libJObjC.dylib
|
||||
"
|
||||
|
||||
ACCEPTED_BIN_DIFF="
|
||||
@ -932,26 +948,34 @@ ACCEPTED_BIN_DIFF="
|
||||
./jre/bin/tnameserv
|
||||
./jre/lib/libsaproc.dylib
|
||||
./jre/lib/server/libjvm.dylib
|
||||
./lib/libsaproc.dylib
|
||||
./lib/server/libjvm.dylib
|
||||
./lib/deploy/JavaControlPanel.prefPane/Contents/MacOS/JavaControlPanel
|
||||
"
|
||||
|
||||
KNOWN_SIZE_DIFF="
|
||||
./jre/lib/libJObjC.dylib
|
||||
./lib/libJObjC.dylib
|
||||
"
|
||||
|
||||
SORT_SYMBOLS="
|
||||
./jre/lib/libJObjC.dylib
|
||||
./lib/libJObjC.dylib
|
||||
"
|
||||
|
||||
KNOWN_SYM_DIFF="
|
||||
./jre/lib/libJObjC.dylib
|
||||
./lib/libJObjC.dylib
|
||||
"
|
||||
|
||||
KNOWN_ELF_DIFF="
|
||||
./jre/lib/libJObjC.dylib
|
||||
./lib/libJObjC.dylib
|
||||
"
|
||||
|
||||
KNOWN_DIS_DIFF="
|
||||
./jre/lib/libJObjC.dylib
|
||||
./lib/libJObjC.dylib
|
||||
"
|
||||
|
||||
fi
|
||||
|
||||
@ -111,7 +111,7 @@ define SetupArchive
|
||||
ifeq ($$(word 20,$$($1_GREP_INCLUDE_PATTERNS)),)
|
||||
$1_GREP_INCLUDES:=| $(GREP) $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_INCLUDE_PATTERNS))
|
||||
else
|
||||
$$(shell $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include)
|
||||
$$(shell $(MKDIR) -p $$($1_BIN) && $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_include)
|
||||
$$(eval $$(call ListPathsSafelyNow,$1_GREP_INCLUDE_PATTERNS,\n, \
|
||||
>> $$($1_BIN)/_the.$$($1_JARNAME)_include))
|
||||
$1_GREP_INCLUDES:=| $(GREP) -f $$($1_BIN)/_the.$$($1_JARNAME)_include
|
||||
@ -124,7 +124,7 @@ define SetupArchive
|
||||
ifeq ($$(word 20,$$($1_GREP_EXCLUDE_PATTERNS)),)
|
||||
$1_GREP_EXCLUDES:=| $(GREP) -v $$(patsubst %,$(SPACE)-e$(SPACE)$(DQUOTE)%$(DQUOTE),$$($1_GREP_EXCLUDE_PATTERNS))
|
||||
else
|
||||
$$(shell $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
|
||||
$$(shell $(MKDIR) -p $$($1_BIN) && $(RM) $$($1_BIN)/_the.$$($1_JARNAME)_exclude)
|
||||
$$(eval $$(call ListPathsSafelyNow,$1_GREP_EXCLUDE_PATTERNS,\n, \
|
||||
>> $$($1_BIN)/_the.$$($1_JARNAME)_exclude))
|
||||
$1_GREP_EXCLUDES:=| $(GREP) -v -f $$($1_BIN)/_the.$$($1_JARNAME)_exclude
|
||||
@ -170,9 +170,10 @@ define SetupArchive
|
||||
# tells us what to remove from the jar-file.
|
||||
$1_CAPTURE_DELETES=$$(foreach src,$$($1_SRCS),($(FIND) $$(src) -name _the.package.deleted -newer $$@ -exec $(SED) 's|$$(src)||g' \{\} >> $$($1_DELETES_FILE) \;) $$(NEWLINE))
|
||||
# The update contents macro updates the jar file with the previously capture contents.
|
||||
# xargs is used to trim the whitespace from the contents file, to see if it is empty.
|
||||
$1_UPDATE_CONTENTS=$$(foreach src,$$($1_SRCS),\
|
||||
(cd $$(src) && \
|
||||
if [ -s _the.$$($1_JARNAME)_contents ]; then \
|
||||
if [ -n "`$(CAT) _the.$$($1_JARNAME)_contents | $(XARGS)`" ]; then \
|
||||
$(ECHO) " updating" `$(WC) -l _the.$$($1_JARNAME)_contents | $(AWK) '{ print $$$$1 }'` files && \
|
||||
$(JAR) $$($1_JAR_UPDATE_OPTIONS) $$@ @_the.$$($1_JARNAME)_contents; \
|
||||
fi) $$(NEWLINE))
|
||||
|
||||
@ -94,11 +94,13 @@ jaxws-only: start-make
|
||||
@($(CD) $(JAXWS_TOPDIR)/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f BuildJaxws.gmk)
|
||||
@$(call TargetExit)
|
||||
|
||||
ifeq ($(BUILD_HOTSPOT),true)
|
||||
hotspot: hotspot-only
|
||||
hotspot-only: start-make
|
||||
@$(call TargetEnter)
|
||||
@($(CD) $(SRC_ROOT)/common/makefiles && $(BUILD_LOG_WRAPPER) $(MAKE) $(MAKE_ARGS) -f HotspotWrapper.gmk)
|
||||
@$(call TargetExit)
|
||||
endif
|
||||
|
||||
jdk: langtools hotspot corba jaxp jaxws jdk-only
|
||||
jdk-only: start-make
|
||||
@ -163,7 +165,7 @@ $(OUTPUT_ROOT)/source_tips: FRC
|
||||
|
||||
|
||||
# Remove everything, except the output from configure.
|
||||
clean: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-images clean-overlay-images clean-bootcycle-build
|
||||
clean: clean-langtools clean-corba clean-jaxp clean-jaxws clean-hotspot clean-jdk clean-images clean-overlay-images clean-bootcycle-build clean-docs
|
||||
@($(CD) $(OUTPUT_ROOT) && $(RM) -r tmp source_tips build.log* build-trace*.log*)
|
||||
@$(ECHO) Cleaned all build artifacts.
|
||||
|
||||
@ -199,6 +201,9 @@ clean-overlay-images:
|
||||
$(call CleanComponent,overlay-images)
|
||||
clean-bootcycle-build:
|
||||
$(call CleanComponent,bootcycle-build)
|
||||
clean-docs:
|
||||
$(call CleanComponent,docs)
|
||||
$(call CleanComponent,docstemp)
|
||||
|
||||
.PHONY: langtools corba jaxp jaxws hotspot jdk images overlay-images install
|
||||
.PHONY: langtools-only corba-only jaxp-only jaxws-only hotspot-only jdk-only images-only overlay-images-only install-only
|
||||
|
||||
@ -142,7 +142,7 @@ endef
|
||||
define TargetExit
|
||||
$(call RecordEndTime,$(patsubst %-only,%,$@))
|
||||
$(BUILD_LOG_WRAPPER) $(PRINTF) "## Finished $(patsubst %-only,%,$@) (build time %s)\n\n" \
|
||||
"`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d " "`"
|
||||
"`$(CAT) $(BUILDTIMESDIR)/build_time_diff_$(patsubst %-only,%,$@) | $(CUT) -f 1 -d ' '`"
|
||||
$(call CheckIfMakeAtEnd)
|
||||
endef
|
||||
|
||||
@ -157,7 +157,7 @@ endef
|
||||
|
||||
# Hook to be called as the very last thing for targets that are "top level" targets
|
||||
define AtMakeEnd
|
||||
$(if $(SJAVAC_SERVER_DIR),@$(RM) -rf $(SJAVAC_SERVER_DIR)/*.port)
|
||||
[ -f $(SJAVAC_SERVER_DIR)/server.port ] && echo Stopping sjavac server && $(TOUCH) $(SJAVAC_SERVER_DIR)/server.port.stop; true
|
||||
$(call StopGlobalTimer)
|
||||
$(call ReportBuildTimes)
|
||||
@$(PRINTF) "Finished building $(PRODUCT_NAME) for target '$(call GetRealTarget)'\n"
|
||||
@ -174,8 +174,8 @@ endef
|
||||
define ParseLogLevel
|
||||
ifeq ($$(origin VERBOSE),undefined)
|
||||
# Setup logging according to LOG (but only if VERBOSE is not given)
|
||||
|
||||
# If the "nofile" argument is given, act on it and strip it away
|
||||
|
||||
# If the "nofile" argument is given, act on it and strip it away
|
||||
ifneq ($$(findstring nofile,$$(LOG)),)
|
||||
# Reset the build log wrapper, regardless of other values
|
||||
override BUILD_LOG_WRAPPER=
|
||||
|
||||
@ -50,17 +50,12 @@ BUILD_NUMBER=$(JDK_BUILD_NUMBER)
|
||||
|
||||
BOOT_JAVA_CMD=$(JAVA)
|
||||
|
||||
# Langtools
|
||||
JAVAC_JAR = $(LANGTOOLS_DIST)/bootstrap/lib/javac.jar
|
||||
JAVADOC_JAR = $(LANGTOOLS_DIST)/bootstrap/lib/javadoc.jar
|
||||
DOCLETS_JAR = $(LANGTOOLS_DIST)/bootstrap/lib/doclets.jar
|
||||
JAVADOC_CMD = $(BOOT_JAVA_CMD) \
|
||||
-Xmx1024m \
|
||||
-Djava.awt.headless=true \
|
||||
"-Xbootclasspath/p:$(JAVADOC_JAR)$(CLASSPATH_SEPARATOR)$(JAVAC_JAR)$(CLASSPATH_SEPARATOR)$(DOCLETS_JAR)" \
|
||||
-jar $(JAVADOC_JAR)
|
||||
|
||||
JAVADOC_CMD = javadoc
|
||||
"-Xbootclasspath/p:$(JAVADOC_JAR)" \
|
||||
-jar $(JAVADOC_JAR) -bootclasspath $(JDK_OUTPUTDIR)/classes
|
||||
|
||||
# Copyright year for beginning of Java and some of the apis
|
||||
# (Needed when creating the javadocs)
|
||||
@ -113,7 +108,8 @@ DOCSDIR_URL = {@docroot}/$(GET2DOCSDIR)
|
||||
|
||||
# Url to copyright html file
|
||||
COPYRIGHT_URL-7 = $(DOCSDIR_URL)/legal/cpyr.html
|
||||
COPYRIGHT_URL-8 = $(DOCSDIR_URL)/legal/cpyr.html
|
||||
# This isn't added in old build yet.
|
||||
#COPYRIGHT_URL-8 = $(DOCSDIR_URL)/legal/cpyr.html
|
||||
COPYRIGHT_URL = $(COPYRIGHT_URL-$(JDK_MINOR_VERSION))
|
||||
|
||||
# Url to bug filing site
|
||||
@ -125,7 +121,8 @@ BUG_SUBMIT_LINE = <a href="$(BUG_SUBMIT_URL)">Submit a bug or feature</a>
|
||||
# Url to devdocs page
|
||||
# Was: http://java.sun.com/javase/6/webnotes/devdocs-vs-specs.html
|
||||
DEV_DOCS_URL-7 = http://download.oracle.com/javase/7/docs/index.html
|
||||
DEV_DOCS_URL-8 = http://download.oracle.com/javase/7/docs/index.html
|
||||
# This isn't added in old build yet.
|
||||
#DEV_DOCS_URL-8 = http://download.oracle.com/javase/7/docs/index.html
|
||||
DEV_DOCS_URL = $(DEV_DOCS_URL-$(JDK_MINOR_VERSION))
|
||||
DOCS_BASE_URL = http://download.oracle.com/javase/7/docs
|
||||
|
||||
@ -142,9 +139,10 @@ $(FULL_COMPANY_NAME) in the US and other countries.
|
||||
# Otherwise, you get "No packages or classes specified." due
|
||||
# to $(CLASSPATH_SEPARATOR) being interpreted as an end of
|
||||
# command (newline or shell ; character)
|
||||
ALL_SOURCE_DIRS = $(JDK_IMPSRC) \
|
||||
ALL_SOURCE_DIRS = $(JDK_SHARE_CLASSES) \
|
||||
$(JDK_IMPSRC) \
|
||||
$(JDK_GENSRC) \
|
||||
$(JDK_SHARE_CLASSES) \
|
||||
$(JDK_OUTPUTDIR)/gendocsrc_rmic \
|
||||
$(JDK_TOPDIR)/src/solaris/classes \
|
||||
$(JDK_TOPDIR)/src/windows/classes \
|
||||
$(JDK_SHARE_SRC)/doc/stub
|
||||
@ -440,7 +438,7 @@ docletapidocs: $(DOCLETAPI_INDEX_FILE)
|
||||
$(DOCLETAPI_INDEX_FILE): GET2DOCSDIR=$(DOCLETAPI2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(DOCLETAPI_INDEX_FILE): $(DOCLETAPI_OPTIONS_FILE) $(DOCLETAPI_PACKAGES_FILE)
|
||||
$(DOCLETAPI_INDEX_FILE): $(DOCLETAPI_OPTIONS_FILE) $(DOCLETAPI_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(DOCLETAPI_OPTIONS_FILE),$(DOCLETAPI_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -481,7 +479,7 @@ TAGLETAPI_BOTTOM := $(call CommonTrademarkBottom,$(TAGLETAPI_FIRST_COPYRIGHT_Y
|
||||
TAGLETAPI_TEMPDIR = $(DOCSTMPDIR)/taglets_temp
|
||||
|
||||
# The index.html, options, and packages files
|
||||
TAGLETAPI_INDEX_FILE = $(TAGLETAPI_DOCDIR)/com/sun/tools/doclets/Taglet.html
|
||||
TAGLETAPI_INDEX_FILE = $(TAGLETAPI_DOCDIR)/index.html
|
||||
TAGLETAPI_OPTIONS_FILE = $(DOCSTMPDIR)/tagletapi.options
|
||||
TAGLETAPI_PACKAGES_FILE = $(DOCSTMPDIR)/tagletapi.packages
|
||||
|
||||
@ -491,7 +489,7 @@ tagletapidocs: $(TAGLETAPI_INDEX_FILE)
|
||||
$(TAGLETAPI_INDEX_FILE): GET2DOCSDIR=$(TAGLETAPI2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(TAGLETAPI_INDEX_FILE): $(TAGLETAPI_OPTIONS_FILE) $(TAGLETAPI_PACKAGES_FILE)
|
||||
$(TAGLETAPI_INDEX_FILE): $(TAGLETAPI_OPTIONS_FILE) $(TAGLETAPI_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(RM) -r $(TAGLETAPI_TEMPDIR)
|
||||
$(MKDIR) -p $(TAGLETAPI_TEMPDIR)
|
||||
@ -517,9 +515,7 @@ $(TAGLETAPI_OPTIONS_FILE):
|
||||
# Create a file with the package names in it
|
||||
$(TAGLETAPI_PACKAGES_FILE): $(DIRECTORY_CACHE) $(call PackageDependencies,$(TAGLETAPI_PKGS))
|
||||
$(prep-target)
|
||||
$(call PackageFilter,$(TAGLETAPI_PKGS))
|
||||
$(GREP) "$(TAGLETAPI_FILE)" $@ > $@.tmp
|
||||
$(MV) $@.tmp $@
|
||||
@($(ECHO) "$(JDK_IMPSRC)/$(TAGLETAPI_FILE)" ) > $@
|
||||
|
||||
#############################################################
|
||||
#
|
||||
@ -549,7 +545,7 @@ domapidocs: $(DOMAPI_INDEX_FILE)
|
||||
$(DOMAPI_INDEX_FILE): GET2DOCSDIR=$(DOMAPI2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(DOMAPI_INDEX_FILE): $(DOMAPI_OPTIONS_FILE) $(DOMAPI_PACKAGES_FILE)
|
||||
$(DOMAPI_INDEX_FILE): $(DOMAPI_OPTIONS_FILE) $(DOMAPI_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(DOMAPI_OPTIONS_FILE),$(DOMAPI_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -611,7 +607,7 @@ jdidocs: $(JDI_INDEX_FILE)
|
||||
$(JDI_INDEX_FILE): GET2DOCSDIR=$(JDI2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(JDI_INDEX_FILE): $(JDI_OPTIONS_FILE) $(JDI_PACKAGES_FILE)
|
||||
$(JDI_INDEX_FILE): $(JDI_OPTIONS_FILE) $(JDI_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(JDI_OPTIONS_FILE),$(JDI_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -698,7 +694,7 @@ jaasdocs: $(JAAS_INDEX_FILE)
|
||||
$(JAAS_INDEX_FILE): GET2DOCSDIR=$(JAAS2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(JAAS_INDEX_FILE): $(JAAS_OPTIONS_FILE) $(JAAS_PACKAGES_FILE)
|
||||
$(JAAS_INDEX_FILE): $(JAAS_OPTIONS_FILE) $(JAAS_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(JAAS_OPTIONS_FILE),$(JAAS_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -750,7 +746,7 @@ jgssdocs: $(JGSS_INDEX_FILE)
|
||||
$(JGSS_INDEX_FILE): GET2DOCSDIR=$(JGSS2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(JGSS_INDEX_FILE): $(JGSS_OPTIONS_FILE) $(JGSS_PACKAGES_FILE)
|
||||
$(JGSS_INDEX_FILE): $(JGSS_OPTIONS_FILE) $(JGSS_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(JGSS_OPTIONS_FILE),$(JGSS_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -802,7 +798,7 @@ smartcardiodocs: $(SMARTCARDIO_INDEX_FILE)
|
||||
$(SMARTCARDIO_INDEX_FILE): GET2DOCSDIR=$(SMARTCARDIO2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(SMARTCARDIO_INDEX_FILE): $(SMARTCARDIO_OPTIONS_FILE) $(SMARTCARDIO_PACKAGES_FILE)
|
||||
$(SMARTCARDIO_INDEX_FILE): $(SMARTCARDIO_OPTIONS_FILE) $(SMARTCARDIO_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(SMARTCARDIO_OPTIONS_FILE),$(SMARTCARDIO_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -852,7 +848,7 @@ httpserverdocs: $(HTTPSERVER_INDEX_HTML)
|
||||
$(HTTPSERVER_INDEX_HTML): GET2DOCSDIR=$(HTTPSERVER2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(HTTPSERVER_INDEX_HTML): $(HTTPSERVER_OPTIONS_FILE) $(HTTPSERVER_PACKAGES_FILE)
|
||||
$(HTTPSERVER_INDEX_HTML): $(HTTPSERVER_OPTIONS_FILE) $(HTTPSERVER_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(HTTPSERVER_OPTIONS_FILE),$(HTTPSERVER_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -887,7 +883,7 @@ ALL_OTHER_TARGETS += mgmtdocs
|
||||
MGMT_DOCDIR := $(JRE_API_DOCSDIR)/management/extension
|
||||
MGMT2COREAPI := ../../$(JDKJRE2COREAPI)
|
||||
JVM_MIB_NAME := JVM-MANAGEMENT-MIB.mib
|
||||
JVM_MIB_SRC := $(CLOSED_SRC)/share/classes/sun/management/snmp/$(JVM_MIB_NAME)
|
||||
JVM_MIB_SRC := $(JDK_TOPDIR)/src/closed/share/classes/sun/management/snmp/$(JVM_MIB_NAME)
|
||||
MGMT_DOCTITLE := Monitoring and Management Interface for the Java$(TRADEMARK) Platform
|
||||
MGMT_WINDOWTITLE := Monitoring and Management Interface for the Java Platform
|
||||
MGMT_HEADER := <strong>Monitoring and Management Interface for the Java Platform</strong>
|
||||
@ -906,7 +902,7 @@ mgmtdocs: $(MGMT_INDEX_FILE)
|
||||
$(MGMT_INDEX_FILE): GET2DOCSDIR=$(MGMT2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(MGMT_INDEX_FILE): $(MGMT_OPTIONS_FILE) $(MGMT_PACKAGES_FILE)
|
||||
$(MGMT_INDEX_FILE): $(MGMT_OPTIONS_FILE) $(MGMT_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
@if [ -f $(JVM_MIB_SRC) ] ; then \
|
||||
$(ECHO) "$(CP) $(JVM_MIB_SRC) $(@D)/.."; \
|
||||
@ -963,7 +959,7 @@ attachdocs: $(ATTACH_INDEX_HTML)
|
||||
$(ATTACH_INDEX_HTML): GET2DOCSDIR=$(ATTACH2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(ATTACH_INDEX_HTML): $(ATTACH_OPTIONS_FILE) $(ATTACH_PACKAGES_FILE)
|
||||
$(ATTACH_INDEX_HTML): $(ATTACH_OPTIONS_FILE) $(ATTACH_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(ATTACH_OPTIONS_FILE),$(ATTACH_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -1013,7 +1009,7 @@ jconsoledocs: $(JCONSOLE_INDEX_HTML)
|
||||
$(JCONSOLE_INDEX_HTML): GET2DOCSDIR=$(JCONSOLE2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(JCONSOLE_INDEX_HTML): $(JCONSOLE_OPTIONS_FILE) $(JCONSOLE_PACKAGES_FILE)
|
||||
$(JCONSOLE_INDEX_HTML): $(JCONSOLE_OPTIONS_FILE) $(JCONSOLE_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(JCONSOLE_OPTIONS_FILE),$(JCONSOLE_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -1065,7 +1061,7 @@ treeapidocs: $(TREEAPI_INDEX_HTML)
|
||||
$(TREEAPI_INDEX_HTML): GET2DOCSDIR=$(TREEAPI2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(TREEAPI_INDEX_HTML): $(TREEAPI_OPTIONS_FILE) $(TREEAPI_PACKAGES_FILE)
|
||||
$(TREEAPI_INDEX_HTML): $(TREEAPI_OPTIONS_FILE) $(TREEAPI_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(TREEAPI_OPTIONS_FILE),$(TREEAPI_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
@ -1116,7 +1112,7 @@ sctpdocs: $(SCTPAPI_INDEX_HTML)
|
||||
$(SCTPAPI_INDEX_HTML): GET2DOCSDIR=$(SCTPAPI2COREAPI)/..
|
||||
|
||||
# Run javadoc if the index file is out of date or missing
|
||||
$(SCTPAPI_INDEX_HTML): $(SCTPAPI_OPTIONS_FILE) $(SCTPAPI_PACKAGES_FILE)
|
||||
$(SCTPAPI_INDEX_HTML): $(SCTPAPI_OPTIONS_FILE) $(SCTPAPI_PACKAGES_FILE) coredocs
|
||||
$(prep-javadoc)
|
||||
$(call JavadocSummary,$(SCTPAPI_OPTIONS_FILE),$(SCTPAPI_PACKAGES_FILE))
|
||||
$(JAVADOC_CMD) -d $(@D) \
|
||||
|
||||
@ -185,3 +185,5 @@ d54dc53e223ed9ce7d5f4d2cd02ad9d5def3c2db jdk8-b59
|
||||
0e08ba7648fb3faa0986cb217887d7c4990977f3 jdk8-b61
|
||||
08afb9c6f44f11c3595b01fd0985db64b29834dd jdk8-b62
|
||||
6ccbf67b68bfed1ab9c44ab8748a5bdc7df33506 jdk8-b63
|
||||
54d599a5b4aad83c235d590652fc81f41c2824fb jdk8-b64
|
||||
5132f7900a8f0c30c3ca7f7a32f9433f4fee7745 jdk8-b65
|
||||
|
||||
@ -291,3 +291,7 @@ dccd40de8db1fa96f186e6179907818d75320440 jdk8-b62
|
||||
dc16fe422c535ecd4e9f80fb814a1bb9704da6f5 hs25-b07
|
||||
acabb5c282f59be7e3238920b2ea06b684ab68f7 jdk8-b63
|
||||
8cb93eadfb6dcab88d91b8e2cd3e0e07d0ac4048 hs25-b08
|
||||
5920f72e799c8133d1066c4a62fa1fafcb729966 jdk8-b64
|
||||
b4ee7b773144a88af8b6b92e4384dea82cb948d8 hs25-b09
|
||||
0f7290a03b24bd562583fa325d3566c21c51fb94 jdk8-b65
|
||||
cfc5309f03b7bd6c1567618b63cf1fc74c0f2a8f hs25-b10
|
||||
|
||||
41
hotspot/agent/doc/c2replay.html
Normal file
41
hotspot/agent/doc/c2replay.html
Normal file
@ -0,0 +1,41 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>
|
||||
C2 Replay
|
||||
</title>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>C2 compiler replay</h1>
|
||||
<p>
|
||||
The C2 compiler replay is a function to repeat the compiling process from a crashed java process in compiled method<br>
|
||||
This function only exists in debug version of VM
|
||||
</p>
|
||||
<h2>Usage</h2>
|
||||
<pre>
|
||||
First, use SA to attach to the core file, if suceeded, do
|
||||
clhsdb>dumpreplaydata <address> | -a | <thread_id> [> replay.txt]
|
||||
create file replay.txt, address is address of Method, or nmethod(CodeBlob)
|
||||
clhsdb>buildreplayjars [all | boot | app]
|
||||
create files:
|
||||
all:
|
||||
app.jar, boot.jar
|
||||
boot:
|
||||
boot.jar
|
||||
app:
|
||||
app.jar
|
||||
exit SA now.
|
||||
Second, use the obtained replay text file, replay.txt and jar files, app.jar and boot.jar, using debug version of java
|
||||
java -Xbootclasspath/p:boot.jar -cp app.jar -XX:ReplayDataFile=<datafile> -XX:+ReplayCompiles ....
|
||||
This will replay the compiling process.
|
||||
|
||||
With ReplayCompiles, the replay will recompile all the methods in app.jar, and in boot.jar to emulate the process in java app.
|
||||
|
||||
notes:
|
||||
1) Most time, we don't need the boot.jar which is the classes loaded from JDK. It will be only modified when an agent(JVMDI) is running and modifies the classes.
|
||||
2) If encounter error as "<flag>" not found, that means the SA is using a VMStructs which is different from the one with corefile. In this case, SA has a utility tool vmstructsdump which is located at agent/src/os/<os>/proc/<os_platform>
|
||||
|
||||
Use this tool to dump VM type library:
|
||||
vmstructsdump libjvm.so > <type_name>.db
|
||||
|
||||
set env SA_TYPEDB=<type_name>.db (refer different shell for set envs)
|
||||
@ -37,12 +37,19 @@ Each CLHSDB command can have zero or more arguments and optionally end with outp
|
||||
Available commands:
|
||||
assert true | false <font color="red">turn on/off asserts in SA code</font>
|
||||
attach pid | exec core <font color="red">attach SA to a process or core</font>
|
||||
buildreplayjars [all | boot | app] <font color="red">build jars for replay, boot.jar for bootclasses, app.jar for application classes</font>
|
||||
class name <font color="red">find a Java class from debuggee and print oop</font>
|
||||
classes <font color="red">print all loaded Java classes with Klass*</font>
|
||||
detach <font color="red">detach SA from current target</font>
|
||||
dis address [ length ] <font color="red">disassemble (sparc/x86) specified number of instructions from given address</font>
|
||||
dissemble address <font color="red">disassemble nmethod</font>
|
||||
dumpcfg -a | id <font color="red">Dump the PhaseCFG for every compiler thread that has one live</font>
|
||||
dumpclass { address | name } [ directory ] <font color="red">dump .class file for given Klass* or class name</font>
|
||||
dumpcodecache <font color="red">dump codecache contents</font>
|
||||
dumpheap [ file ] <font color="red">dump heap in hprof binary format</font>
|
||||
dumpideal -a | id <font color="red">dump ideal graph like debug flag -XX:+PrintIdeal</font>
|
||||
dumpilt -a | id <font color="red">dump inline tree for C2 compilation</font>
|
||||
dumpreplaydata <address> | -a | <thread_id> [>replay.txt] <font color="red">dump replay data into a file</font>
|
||||
echo [ true | false ] <font color="red">turn on/off command echo mode</font>
|
||||
examine [ address/count ] | [ address,address] <font color="red">show contents of memory from given address</font>
|
||||
field [ type [ name fieldtype isStatic offset address ] ] <font color="red">print info about a field of HotSpot type</font>
|
||||
@ -51,29 +58,35 @@ Available commands:
|
||||
help [ command ] <font color="red">print help message for all commands or just given command</font>
|
||||
history <font color="red">show command history. usual !command-number syntax works.</font>
|
||||
inspect expression <font color="red">inspect a given oop</font>
|
||||
intConstant [ name [ value ] ] <font color="red">print out hotspot integer constant(s)</font>
|
||||
jdis address <font color="red">show bytecode disassembly of a given Method*</font>
|
||||
jhisto <font color="red">show Java heap histogram</font>
|
||||
jseval script <font color="red">evaluate a given string as JavaScript code</font>
|
||||
jsload file <font color="red">load and evaluate a JavaScript file</font>
|
||||
jstack [-v] <font color="red">show Java stack trace of all Java threads. -v is verbose mode</font>
|
||||
livenmethods <font color="red">show all live nmethods</font>
|
||||
longConstant [ name [ value ] ] <font color="red">print out hotspot long constant(s)s</font>
|
||||
mem address [ length ] <font color="red">show contents of memory -- also shows closest ELF/COFF symbol if found</font>
|
||||
pmap <font color="red">show Solaris pmap-like output</font>
|
||||
print expression <font color="red">print given Klass*, Method* or arbitrary address</font>
|
||||
printas type expression <font color="red">print given address as given HotSpot type. eg. print JavaThread <address></font>
|
||||
printmdo -a | expression <font color="red">print method data oop</font>
|
||||
printstatics [ type ] <font color="red">print static fields of given HotSpot type (or all types if none specified)</font>
|
||||
pstack [-v] <font color="red">show mixed mode stack trace for all Java, non-Java threads. -v is verbose mode</font>
|
||||
quit <font color="red">quit CLHSDB tool</font>
|
||||
reattach <font color="red">detach and re-attach SA to current target</font>
|
||||
revptrs <font color="red">find liveness of oops</font>
|
||||
scanoops start end [ type ] <font color="red">scan a Oop from given start to end address</font>
|
||||
search [ heap | codecache | threads ] value <font color="red">search a value in heap or codecache or threads</font>
|
||||
source filename <font color="red">load and execute CLHSDB commands from given file</font>
|
||||
symbol name <font color="red">show address of a given ELF/COFF symbol</font>
|
||||
sysprops <font color="red">show all Java System properties</font>
|
||||
thread id <font color="red">show thread of id</font>
|
||||
threads <font color="red">show all Java threads</font>
|
||||
tokenize ...
|
||||
type [ type [ name super isOop isInteger isUnsigned size ] ] <font color="red">show info. on HotSpot type</font>
|
||||
universe <font color="red">print gc universe</font>
|
||||
vmstructsdump <font color="red">dump hotspot type library in text</font>
|
||||
verbose true | false <font color="red">turn on/off verbose mode</font>
|
||||
versioncheck [ true | false ] <font color="red">turn on/off debuggee VM version check</font>
|
||||
whatis address <font color="red">print info about any arbitrary address</font>
|
||||
@ -114,5 +127,11 @@ hsdb> jsload test.js
|
||||
</code>
|
||||
</pre>
|
||||
|
||||
<h3>C2 Compilation Replay</h3>
|
||||
<p>
|
||||
When a java process crashes in compiled method, usually a core file is saved.
|
||||
The C2 replay function can reproduce the compiling process in the core.
|
||||
<a href="c2replay.html">c2replay.html</a>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@ -220,6 +220,12 @@ These scripts are used to run SA remotely.
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3>C2 Compilation Replay</h3>
|
||||
<p>
|
||||
When a java process crashes in compiled method, usually a core file is saved.
|
||||
The C2 replay function can reproduce the compiling process in the core.
|
||||
<a href="c2replay.html">c2replay.html</a>
|
||||
|
||||
<h3>Debugging transported core dumps</h3>
|
||||
<p>
|
||||
When a core dump is moved from the machine where it was produced to a
|
||||
|
||||
@ -58,10 +58,8 @@ sun.jvm.hotspot.debugger.cdbg.basic \
|
||||
sun.jvm.hotspot.debugger.cdbg.basic.amd64 \
|
||||
sun.jvm.hotspot.debugger.cdbg.basic.x86 \
|
||||
sun.jvm.hotspot.debugger.dummy \
|
||||
sun.jvm.hotspot.debugger.ia64 \
|
||||
sun.jvm.hotspot.debugger.linux \
|
||||
sun.jvm.hotspot.debugger.linux.amd64 \
|
||||
sun.jvm.hotspot.debugger.linux.ia64 \
|
||||
sun.jvm.hotspot.debugger.linux.x86 \
|
||||
sun.jvm.hotspot.debugger.posix \
|
||||
sun.jvm.hotspot.debugger.posix.elf \
|
||||
@ -77,7 +75,6 @@ sun.jvm.hotspot.debugger.sparc \
|
||||
sun.jvm.hotspot.debugger.win32.coff \
|
||||
sun.jvm.hotspot.debugger.windbg \
|
||||
sun.jvm.hotspot.debugger.windbg.amd64 \
|
||||
sun.jvm.hotspot.debugger.windbg.ia64 \
|
||||
sun.jvm.hotspot.debugger.windbg.x86 \
|
||||
sun.jvm.hotspot.debugger.x86 \
|
||||
sun.jvm.hotspot.gc_implementation \
|
||||
@ -97,10 +94,8 @@ sun.jvm.hotspot.runtime.amd64 \
|
||||
sun.jvm.hotspot.runtime.bsd \
|
||||
sun.jvm.hotspot.runtime.bsd_amd64 \
|
||||
sun.jvm.hotspot.runtime.bsd_x86 \
|
||||
sun.jvm.hotspot.runtime.ia64 \
|
||||
sun.jvm.hotspot.runtime.linux \
|
||||
sun.jvm.hotspot.runtime.linux_amd64 \
|
||||
sun.jvm.hotspot.runtime.linux_ia64 \
|
||||
sun.jvm.hotspot.runtime.linux_sparc \
|
||||
sun.jvm.hotspot.runtime.linux_x86 \
|
||||
sun.jvm.hotspot.runtime.posix \
|
||||
@ -109,7 +104,6 @@ sun.jvm.hotspot.runtime.solaris_sparc \
|
||||
sun.jvm.hotspot.runtime.solaris_x86 \
|
||||
sun.jvm.hotspot.runtime.sparc \
|
||||
sun.jvm.hotspot.runtime.win32_amd64 \
|
||||
sun.jvm.hotspot.runtime.win32_ia64 \
|
||||
sun.jvm.hotspot.runtime.win32_x86 \
|
||||
sun.jvm.hotspot.runtime.x86 \
|
||||
sun.jvm.hotspot.tools \
|
||||
@ -152,7 +146,6 @@ sun/jvm/hotspot/debugger/cdbg/basic/*.java \
|
||||
sun/jvm/hotspot/debugger/cdbg/basic/amd64/*.java \
|
||||
sun/jvm/hotspot/debugger/cdbg/basic/x86/*.java \
|
||||
sun/jvm/hotspot/debugger/dummy/*.java \
|
||||
sun/jvm/hotspot/debugger/ia64/*.java \
|
||||
sun/jvm/hotspot/debugger/linux/*.java \
|
||||
sun/jvm/hotspot/debugger/linux/x86/*.java \
|
||||
sun/jvm/hotspot/debugger/posix/*.java \
|
||||
@ -168,7 +161,6 @@ sun/jvm/hotspot/debugger/remote/x86/*.java \
|
||||
sun/jvm/hotspot/debugger/sparc/*.java \
|
||||
sun/jvm/hotspot/debugger/win32/coff/*.java \
|
||||
sun/jvm/hotspot/debugger/windbg/*.java \
|
||||
sun/jvm/hotspot/debugger/windbg/ia64/*.java \
|
||||
sun/jvm/hotspot/debugger/windbg/x86/*.java \
|
||||
sun/jvm/hotspot/debugger/x86/*.java \
|
||||
sun/jvm/hotspot/gc_implementation/g1/*.java \
|
||||
@ -186,10 +178,8 @@ sun/jvm/hotspot/runtime/amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/bsd/*.java \
|
||||
sun/jvm/hotspot/runtime/bsd_amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/bsd_x86/*.java \
|
||||
sun/jvm/hotspot/runtime/ia64/*.java \
|
||||
sun/jvm/hotspot/runtime/linux/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_ia64/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_sparc/*.java \
|
||||
sun/jvm/hotspot/runtime/linux_x86/*.java \
|
||||
sun/jvm/hotspot/runtime/posix/*.java \
|
||||
@ -198,7 +188,6 @@ sun/jvm/hotspot/runtime/solaris_sparc/*.java \
|
||||
sun/jvm/hotspot/runtime/solaris_x86/*.java \
|
||||
sun/jvm/hotspot/runtime/sparc/*.java \
|
||||
sun/jvm/hotspot/runtime/win32_amd64/*.java \
|
||||
sun/jvm/hotspot/runtime/win32_ia64/*.java \
|
||||
sun/jvm/hotspot/runtime/win32_x86/*.java \
|
||||
sun/jvm/hotspot/runtime/x86/*.java \
|
||||
sun/jvm/hotspot/tools/*.java \
|
||||
@ -258,6 +247,7 @@ SA_BUILD_VERSION_PROP = "sun.jvm.hotspot.runtime.VM.saBuildVersion=$(SA_BUILD_VE
|
||||
|
||||
SA_PROPERTIES = $(OUTPUT_DIR)/sa.properties
|
||||
JAVAC = $(JDK_HOME)/bin/javac
|
||||
JAVA = $(JDK_HOME)/bin/java
|
||||
JAVADOC = $(JDK_HOME)/bin/javadoc
|
||||
RMIC = $(JDK_HOME)/bin/rmic
|
||||
|
||||
@ -298,7 +288,7 @@ filelist: $(ALLFILES)
|
||||
|
||||
.PHONY: natives
|
||||
natives:
|
||||
cd ../src/os/`java -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) all
|
||||
cd ../src/os/`$(JAVA) -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) all
|
||||
|
||||
.PHONY: sa-jdi.jar
|
||||
sa-jdi.jar:
|
||||
@ -323,5 +313,5 @@ sa.jar:
|
||||
|
||||
clean::
|
||||
rm -rf filelist
|
||||
cd ../src/os/`java -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) clean
|
||||
cd ../src/os/`$(JAVA) -classpath $(OUTPUT_DIR) sun.jvm.hotspot.utilities.PlatformInfo`; $(MAKE) clean
|
||||
rm -rf $(BUILD_DIR)/*
|
||||
|
||||
@ -33,6 +33,7 @@ import sun.jvm.hotspot.types.Type;
|
||||
import sun.jvm.hotspot.types.Field;
|
||||
import sun.jvm.hotspot.HotSpotTypeDataBase;
|
||||
import sun.jvm.hotspot.types.basic.BasicType;
|
||||
import sun.jvm.hotspot.types.basic.BasicTypeDataBase;
|
||||
import sun.jvm.hotspot.types.CIntegerType;
|
||||
import sun.jvm.hotspot.code.*;
|
||||
import sun.jvm.hotspot.compiler.*;
|
||||
@ -448,6 +449,112 @@ public class CommandProcessor {
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("dumpreplaydata", "dumpreplaydata { <address > | -a | <thread_id> }", false) {
|
||||
// This is used to dump replay data from ciInstanceKlass, ciMethodData etc
|
||||
// default file name is replay.txt, also if java crashes in compiler
|
||||
// thread, this file will be dumped in error processing.
|
||||
public void doit(Tokens t) {
|
||||
if (t.countTokens() != 1) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
String name = t.nextToken();
|
||||
Address a = null;
|
||||
try {
|
||||
a = VM.getVM().getDebugger().parseAddress(name);
|
||||
} catch (NumberFormatException e) { }
|
||||
if (a != null) {
|
||||
// only nmethod, Method, MethodData and InstanceKlass needed to
|
||||
// dump replay data
|
||||
|
||||
CodeBlob cb = VM.getVM().getCodeCache().findBlob(a);
|
||||
if (cb != null && (cb instanceof NMethod)) {
|
||||
((NMethod)cb).dumpReplayData(out);
|
||||
return;
|
||||
}
|
||||
// assume it is Metadata
|
||||
Metadata meta = Metadata.instantiateWrapperFor(a);
|
||||
if (meta != null) {
|
||||
meta.dumpReplayData(out);
|
||||
} else {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Not an address
|
||||
boolean all = name.equals("-a");
|
||||
Threads threads = VM.getVM().getThreads();
|
||||
for (JavaThread thread = threads.first(); thread != null; thread = thread.next()) {
|
||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||
thread.printThreadIDOn(new PrintStream(bos));
|
||||
if (all || bos.toString().equals(name)) {
|
||||
if (thread instanceof CompilerThread) {
|
||||
CompilerThread ct = (CompilerThread)thread;
|
||||
ciEnv env = ct.env();
|
||||
if (env != null) {
|
||||
env.dumpReplayData(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("buildreplayjars", "buildreplayjars [ all | app | boot ] | [ prefix ]", false) {
|
||||
// This is used to dump jar files of all the classes
|
||||
// loaded in the core. Everything on the bootclasspath
|
||||
// will go in boot.jar and everything else will go in
|
||||
// app.jar. Then the classes can be loaded by the replay
|
||||
// jvm using -Xbootclasspath/p:boot.jar -cp app.jar. boot.jar usually
|
||||
// not needed, unless changed by jvmti.
|
||||
public void doit(Tokens t) {
|
||||
int tcount = t.countTokens();
|
||||
if (tcount > 2) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
try {
|
||||
String prefix = "";
|
||||
String option = "all"; // default
|
||||
switch(tcount) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
option = t.nextToken();
|
||||
if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") &&
|
||||
!option.equalsIgnoreCase("root")) {
|
||||
prefix = option;
|
||||
option = "all";
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
option = t.nextToken();
|
||||
prefix = t.nextToken();
|
||||
break;
|
||||
default:
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
if (!option.equalsIgnoreCase("all") && !option.equalsIgnoreCase("app") &&
|
||||
!option.equalsIgnoreCase("boot")) {
|
||||
usage();
|
||||
return;
|
||||
}
|
||||
ClassDump cd = new ClassDump();
|
||||
if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("boot")) {
|
||||
cd.setClassFilter(new BootFilter());
|
||||
cd.setJarOutput(prefix + "boot.jar");
|
||||
cd.run();
|
||||
}
|
||||
if (option.equalsIgnoreCase("all") || option.equalsIgnoreCase("app")) {
|
||||
cd.setClassFilter(new NonBootFilter());
|
||||
cd.setJarOutput(prefix + "app.jar");
|
||||
cd.run();
|
||||
}
|
||||
} catch (IOException ioe) {
|
||||
ioe.printStackTrace();
|
||||
}
|
||||
}
|
||||
},
|
||||
new Command("findpc", "findpc address", false) {
|
||||
public void doit(Tokens t) {
|
||||
if (t.countTokens() != 1) {
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -50,4 +50,8 @@ public class ciBaseObject extends VMObject {
|
||||
public ciBaseObject(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
out.println("# Unknown ci type " + getAddress().getAddressAt(0));
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -16,9 +16,9 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -60,4 +60,8 @@ public class ciConstant extends VMObject {
|
||||
public ciConstant(Address addr) {
|
||||
super(addr);
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
// Nothing to be done
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* 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
|
||||
@ -16,9 +16,9 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -74,4 +74,29 @@ public class ciEnv extends VMObject {
|
||||
public CompileTask task() {
|
||||
return new CompileTask(taskField.getValue(this.getAddress()));
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
out.println("JvmtiExport can_access_local_variables " +
|
||||
(JvmtiExport.canAccessLocalVariables() ? '1' : '0'));
|
||||
out.println("JvmtiExport can_hotswap_or_post_breakpoint " +
|
||||
(JvmtiExport.canHotswapOrPostBreakpoint() ? '1' : '0'));
|
||||
out.println("JvmtiExport can_post_on_exceptions " +
|
||||
(JvmtiExport.canPostOnExceptions() ? '1' : '0'));
|
||||
|
||||
GrowableArray<ciMetadata> objects = factory().objects();
|
||||
out.println("# " + objects.length() + " ciObject found");
|
||||
for (int i = 0; i < objects.length(); i++) {
|
||||
ciMetadata o = objects.at(i);
|
||||
out.println("# ciMetadata" + i + " @ " + o);
|
||||
o.dumpReplayData(out);
|
||||
}
|
||||
CompileTask task = task();
|
||||
Method method = task.method();
|
||||
int entryBci = task.osrBci();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.println("compile " + holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
entryBci);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -80,4 +80,84 @@ public class ciInstanceKlass extends ciKlass {
|
||||
public boolean isInitialized() {
|
||||
return initState() == CLASS_STATE_FULLY_INITIALIZED;
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
InstanceKlass ik = (InstanceKlass)getMetadata();
|
||||
ConstantPool cp = ik.getConstants();
|
||||
|
||||
// Try to record related loaded classes
|
||||
Klass sub = ik.getSubklassKlass();
|
||||
while (sub != null) {
|
||||
if (sub instanceof InstanceKlass) {
|
||||
out.println("instanceKlass " + sub.getName().asString());
|
||||
}
|
||||
sub = sub.getNextSiblingKlass();
|
||||
}
|
||||
|
||||
final int length = (int) cp.getLength();
|
||||
out.print("ciInstanceKlass " + name() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length);
|
||||
for (int index = 1; index < length; index++) {
|
||||
out.print(" " + cp.getTags().at(index));
|
||||
}
|
||||
out.println();
|
||||
if (isInitialized()) {
|
||||
Field[] staticFields = ik.getStaticFields();
|
||||
for (int i = 0; i < staticFields.length; i++) {
|
||||
Field f = staticFields[i];
|
||||
Oop mirror = ik.getJavaMirror();
|
||||
if (f.isFinal() && !f.hasInitialValue()) {
|
||||
out.print("staticfield " + name() + " " +
|
||||
OopUtilities.escapeString(f.getID().getName()) + " " +
|
||||
f.getFieldType().getSignature().asString() + " ");
|
||||
if (f instanceof ByteField) {
|
||||
ByteField bf = (ByteField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof BooleanField) {
|
||||
BooleanField bf = (BooleanField)f;
|
||||
out.println(bf.getValue(mirror) ? 1 : 0);
|
||||
} else if (f instanceof ShortField) {
|
||||
ShortField bf = (ShortField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof CharField) {
|
||||
CharField bf = (CharField)f;
|
||||
out.println(bf.getValue(mirror) & 0xffff);
|
||||
} else if (f instanceof IntField) {
|
||||
IntField bf = (IntField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof LongField) {
|
||||
LongField bf = (LongField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof FloatField) {
|
||||
FloatField bf = (FloatField)f;
|
||||
out.println(Float.floatToRawIntBits(bf.getValue(mirror)));
|
||||
} else if (f instanceof DoubleField) {
|
||||
DoubleField bf = (DoubleField)f;
|
||||
out.println(Double.doubleToRawLongBits(bf.getValue(mirror)));
|
||||
} else if (f instanceof OopField) {
|
||||
OopField bf = (OopField)f;
|
||||
Oop value = bf.getValue(mirror);
|
||||
if (value == null) {
|
||||
out.println("null");
|
||||
} else if (value.isInstance()) {
|
||||
Instance inst = (Instance)value;
|
||||
if (inst.isA(SystemDictionary.getStringKlass())) {
|
||||
out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\"");
|
||||
} else {
|
||||
out.println(inst.getKlass().getName().asString());
|
||||
}
|
||||
} else if (value.isObjArray()) {
|
||||
ObjArray oa = (ObjArray)value;
|
||||
Klass ek = (ObjArrayKlass)oa.getKlass();
|
||||
out.println(oa.getLength() + " " + ek.getName().asString());
|
||||
} else if (value.isTypeArray()) {
|
||||
TypeArray ta = (TypeArray)value;
|
||||
out.println(ta.getLength());
|
||||
} else {
|
||||
out.println(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -88,4 +88,19 @@ public class ciMethod extends ciMetadata {
|
||||
st.printf(" %s::%s", method.getMethodHolder().getName().asString().replace('/', '.'),
|
||||
method.getName().asString());
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
Method method = (Method)getMetadata();
|
||||
NMethod nm = method.getNativeMethod();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.println("ciMethod " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
method.getInvocationCounter() + " " +
|
||||
method.getBackedgeCounter() + " " +
|
||||
interpreterInvocationCount() + " " +
|
||||
interpreterThrowoutCount() + " " +
|
||||
instructionsSize());
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,9 +16,9 @@
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
|
||||
* CA 95054 USA or visit www.sun.com if you need additional information or
|
||||
* have any questions.
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
@ -174,4 +174,52 @@ public class ciMethodData extends ciMetadata {
|
||||
}
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
MethodData mdo = (MethodData)getMetadata();
|
||||
Method method = mdo.getMethod();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.print("ciMethodData " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
state() + " " + currentMileage());
|
||||
byte[] orig = orig();
|
||||
out.print(" orig " + orig.length);
|
||||
for (int i = 0; i < orig.length; i++) {
|
||||
out.print(" " + (orig[i] & 0xff));
|
||||
}
|
||||
|
||||
long[] data = data();
|
||||
out.print(" data " + data.length);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
out.print(" 0x" + Long.toHexString(data[i]));
|
||||
}
|
||||
int count = 0;
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out.print(" oops " + count);
|
||||
ProfileData pdata = firstData();
|
||||
for ( ; isValid(pdata); pdata = nextData(pdata)) {
|
||||
if (pdata instanceof ciReceiverTypeData) {
|
||||
ciReceiverTypeData vdata = (ciReceiverTypeData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
ciKlass k = vdata.receiverAt(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " + ((vdata.dp() + vdata.cellOffset(vdata.receiverCellIndex(i))) / MethodData.cellSize) + " " + k.name());
|
||||
}
|
||||
}
|
||||
} else if (pdata instanceof ciVirtualCallData) {
|
||||
ciVirtualCallData vdata = (ciVirtualCallData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
ciKlass k = vdata.receiverAt(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " + ((vdata.dp() + vdata.cellOffset(vdata.receiverCellIndex(i))) / MethodData.cellSize + " " + k.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
||||
@ -498,6 +498,42 @@ public class NMethod extends CodeBlob {
|
||||
method.getSignature().asString();
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
HashMap h = new HashMap();
|
||||
for (int i = 1; i < getMetadataLength(); i++) {
|
||||
Metadata meta = Metadata.instantiateWrapperFor(getMetadataAt(i));
|
||||
System.err.println(meta);
|
||||
if (h.get(meta) != null) continue;
|
||||
h.put(meta, meta);
|
||||
if (meta instanceof InstanceKlass) {
|
||||
((InstanceKlass)meta).dumpReplayData(out);
|
||||
} else if (meta instanceof Method) {
|
||||
((Method)meta).dumpReplayData(out);
|
||||
MethodData mdo = ((Method)meta).getMethodData();
|
||||
if (mdo != null) {
|
||||
mdo.dumpReplayData(out);
|
||||
}
|
||||
}
|
||||
}
|
||||
Method method = getMethod();
|
||||
if (h.get(method) == null) {
|
||||
method.dumpReplayData(out);
|
||||
MethodData mdo = method.getMethodData();
|
||||
if (mdo != null) {
|
||||
mdo.dumpReplayData(out);
|
||||
}
|
||||
}
|
||||
if (h.get(method.getMethodHolder()) == null) {
|
||||
((InstanceKlass)method.getMethodHolder()).dumpReplayData(out);
|
||||
}
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.println("compile " + holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
getEntryBCI());
|
||||
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------
|
||||
// Internals only below this point
|
||||
//
|
||||
|
||||
@ -56,7 +56,7 @@ public class CompileTask extends VMObject {
|
||||
}
|
||||
|
||||
public Method method() {
|
||||
Address oh = methodField.getValue(getAddress()).getAddressAt(0);
|
||||
Address oh = methodField.getValue(getAddress());
|
||||
return (Method)Metadata.instantiateWrapperFor(oh);
|
||||
}
|
||||
|
||||
|
||||
@ -121,7 +121,7 @@ public class ConstantPool extends Metadata implements ClassConstants {
|
||||
Address addr = cache.getValue(getAddress());
|
||||
return (ConstantPoolCache) VMObjectFactory.newObject(ConstantPoolCache.class, addr);
|
||||
}
|
||||
public Klass getPoolHolder() { return (Klass) poolHolder.getValue(this); }
|
||||
public InstanceKlass getPoolHolder() { return (InstanceKlass)poolHolder.getValue(this); }
|
||||
public int getLength() { return (int)length.getValue(getAddress()); }
|
||||
public Oop getResolvedReferences() {
|
||||
Address handle = resolvedReferences.getValue(getAddress());
|
||||
|
||||
@ -86,7 +86,7 @@ public class ConstantPoolCache extends Metadata {
|
||||
|
||||
|
||||
public void printValueOn(PrintStream tty) {
|
||||
tty.print("ConstantPoolCache for " + getConstants().getPoolHolder().getName().asString());
|
||||
tty.print("ConstantPoolCache for " + getConstants().getPoolHolder().getName().asString() + " address = " + getAddress() + " offset = " + baseOffset);
|
||||
}
|
||||
|
||||
public int getLength() {
|
||||
|
||||
@ -110,6 +110,8 @@ public class Field {
|
||||
public Symbol getSignature() { return signature; }
|
||||
public Symbol getGenericSignature() { return genericSignature; }
|
||||
|
||||
public boolean hasInitialValue() { return holder.getFieldInitialValueIndex(fieldIndex) != 0; }
|
||||
|
||||
//
|
||||
// Following acccessors are for named, non-VM fields only
|
||||
//
|
||||
|
||||
@ -278,7 +278,7 @@ public class InstanceKlass extends Klass {
|
||||
}
|
||||
|
||||
public short getFieldGenericSignatureIndex(int index) {
|
||||
int len = getFields().length();
|
||||
// int len = getFields().length();
|
||||
int allFieldsCount = getAllFieldsCount();
|
||||
int generic_signature_slot = allFieldsCount * FIELD_SLOTS;
|
||||
for (int i = 0; i < allFieldsCount; i++) {
|
||||
@ -325,7 +325,7 @@ public class InstanceKlass extends Klass {
|
||||
public KlassArray getTransitiveInterfaces() { return new KlassArray(transitiveInterfaces.getValue(getAddress())); }
|
||||
public int getJavaFieldsCount() { return (int) javaFieldsCount.getValue(this); }
|
||||
public int getAllFieldsCount() {
|
||||
int len = getFields().length();
|
||||
int len = getFields().length();
|
||||
int allFieldsCount = 0;
|
||||
for (; allFieldsCount*FIELD_SLOTS < len; allFieldsCount++) {
|
||||
short flags = getFieldAccessFlags(allFieldsCount);
|
||||
@ -581,6 +581,19 @@ public class InstanceKlass extends Klass {
|
||||
}
|
||||
}
|
||||
|
||||
public Field[] getStaticFields() {
|
||||
U2Array fields = getFields();
|
||||
int length = getJavaFieldsCount();
|
||||
ArrayList result = new ArrayList();
|
||||
for (int index = 0; index < length; index++) {
|
||||
Field f = newField(index);
|
||||
if (f.isStatic()) {
|
||||
result.add(f);
|
||||
}
|
||||
}
|
||||
return (Field[])result.toArray(new Field[result.size()]);
|
||||
}
|
||||
|
||||
public void iterateNonStaticFields(OopVisitor visitor, Oop obj) {
|
||||
if (getSuper() != null) {
|
||||
((InstanceKlass) getSuper()).iterateNonStaticFields(visitor, obj);
|
||||
@ -979,4 +992,84 @@ public class InstanceKlass extends Klass {
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
ConstantPool cp = getConstants();
|
||||
|
||||
// Try to record related loaded classes
|
||||
Klass sub = getSubklassKlass();
|
||||
while (sub != null) {
|
||||
if (sub instanceof InstanceKlass) {
|
||||
out.println("instanceKlass " + sub.getName().asString());
|
||||
}
|
||||
sub = sub.getNextSiblingKlass();
|
||||
}
|
||||
|
||||
final int length = (int) cp.getLength();
|
||||
out.print("ciInstanceKlass " + getName().asString() + " " + (isLinked() ? 1 : 0) + " " + (isInitialized() ? 1 : 0) + " " + length);
|
||||
for (int index = 1; index < length; index++) {
|
||||
out.print(" " + cp.getTags().at(index));
|
||||
}
|
||||
out.println();
|
||||
if (isInitialized()) {
|
||||
Field[] staticFields = getStaticFields();
|
||||
for (int i = 0; i < staticFields.length; i++) {
|
||||
Field f = staticFields[i];
|
||||
Oop mirror = getJavaMirror();
|
||||
if (f.isFinal() && !f.hasInitialValue()) {
|
||||
out.print("staticfield " + getName().asString() + " " +
|
||||
OopUtilities.escapeString(f.getID().getName()) + " " +
|
||||
f.getFieldType().getSignature().asString() + " ");
|
||||
if (f instanceof ByteField) {
|
||||
ByteField bf = (ByteField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof BooleanField) {
|
||||
BooleanField bf = (BooleanField)f;
|
||||
out.println(bf.getValue(mirror) ? 1 : 0);
|
||||
} else if (f instanceof ShortField) {
|
||||
ShortField bf = (ShortField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof CharField) {
|
||||
CharField bf = (CharField)f;
|
||||
out.println(bf.getValue(mirror) & 0xffff);
|
||||
} else if (f instanceof IntField) {
|
||||
IntField bf = (IntField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof LongField) {
|
||||
LongField bf = (LongField)f;
|
||||
out.println(bf.getValue(mirror));
|
||||
} else if (f instanceof FloatField) {
|
||||
FloatField bf = (FloatField)f;
|
||||
out.println(Float.floatToRawIntBits(bf.getValue(mirror)));
|
||||
} else if (f instanceof DoubleField) {
|
||||
DoubleField bf = (DoubleField)f;
|
||||
out.println(Double.doubleToRawLongBits(bf.getValue(mirror)));
|
||||
} else if (f instanceof OopField) {
|
||||
OopField bf = (OopField)f;
|
||||
|
||||
Oop value = bf.getValue(mirror);
|
||||
if (value == null) {
|
||||
out.println("null");
|
||||
} else if (value.isInstance()) {
|
||||
Instance inst = (Instance)value;
|
||||
if (inst.isA(SystemDictionary.getStringKlass())) {
|
||||
out.println("\"" + OopUtilities.stringOopToEscapedString(inst) + "\"");
|
||||
} else {
|
||||
out.println(inst.getKlass().getName().asString());
|
||||
}
|
||||
} else if (value.isObjArray()) {
|
||||
ObjArray oa = (ObjArray)value;
|
||||
Klass ek = (ObjArrayKlass)oa.getKlass();
|
||||
out.println(oa.getLength() + " " + ek.getName().asString());
|
||||
} else if (value.isTypeArray()) {
|
||||
TypeArray ta = (TypeArray)value;
|
||||
out.println(ta.getLength());
|
||||
} else {
|
||||
out.println(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,4 +79,7 @@ abstract public class Metadata extends VMObject {
|
||||
}
|
||||
|
||||
abstract public void printValueOn(PrintStream tty);
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
out.println("# Unknown Metadata");
|
||||
}
|
||||
}
|
||||
|
||||
@ -177,7 +177,7 @@ public class Method extends Metadata {
|
||||
bci. It is required that there is currently a bytecode at this
|
||||
bci. */
|
||||
public int getOrigBytecodeAt(int bci) {
|
||||
BreakpointInfo bp = ((InstanceKlass) getMethodHolder()).getBreakpoints();
|
||||
BreakpointInfo bp = getMethodHolder().getBreakpoints();
|
||||
for (; bp != null; bp = bp.getNext()) {
|
||||
if (bp.match(this, bci)) {
|
||||
return bp.getOrigBytecode();
|
||||
@ -238,7 +238,7 @@ public class Method extends Metadata {
|
||||
}
|
||||
|
||||
// Method holder (the Klass holding this method)
|
||||
public Klass getMethodHolder() { return getConstants().getPoolHolder(); }
|
||||
public InstanceKlass getMethodHolder() { return getConstants().getPoolHolder(); }
|
||||
|
||||
// Access flags
|
||||
public boolean isPublic() { return getAccessFlagsObj().isPublic(); }
|
||||
@ -358,6 +358,25 @@ public class Method extends Metadata {
|
||||
buf.append(")");
|
||||
return buf.toString().replace('/', '.');
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
NMethod nm = getNativeMethod();
|
||||
int code_size = 0;
|
||||
if (nm != null) {
|
||||
code_size = (int)nm.codeEnd().minus(nm.getVerifiedEntryPoint());
|
||||
}
|
||||
Klass holder = getMethodHolder();
|
||||
out.println("ciMethod " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(getName().asString()) + " " +
|
||||
getSignature().asString() + " " +
|
||||
getInvocationCounter() + " " +
|
||||
getBackedgeCounter() + " " +
|
||||
interpreterInvocationCount() + " " +
|
||||
interpreterThrowoutCount() + " " +
|
||||
code_size);
|
||||
}
|
||||
|
||||
public int interpreterThrowoutCount() {
|
||||
return (int) interpreterThrowoutCountField.getValue(this);
|
||||
}
|
||||
|
||||
@ -332,4 +332,59 @@ public class MethodData extends Metadata {
|
||||
public int currentMileage() {
|
||||
return 20000;
|
||||
}
|
||||
|
||||
public void dumpReplayData(PrintStream out) {
|
||||
Method method = getMethod();
|
||||
Klass holder = method.getMethodHolder();
|
||||
out.print("ciMethodData " +
|
||||
holder.getName().asString() + " " +
|
||||
OopUtilities.escapeString(method.getName().asString()) + " " +
|
||||
method.getSignature().asString() + " " +
|
||||
"2" + " " +
|
||||
currentMileage());
|
||||
byte[] orig = orig();
|
||||
out.print(" orig " + orig.length);
|
||||
for (int i = 0; i < orig.length; i++) {
|
||||
out.print(" " + (orig[i] & 0xff));
|
||||
}
|
||||
|
||||
long[] data = data();
|
||||
out.print(" data " + data.length);
|
||||
for (int i = 0; i < data.length; i++) {
|
||||
out.print(" 0x" + Long.toHexString(data[i]));
|
||||
}
|
||||
int count = 0;
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out.print(" oops " + count);
|
||||
ProfileData pdata = firstData();
|
||||
for ( ; isValid(pdata); pdata = nextData(pdata)) {
|
||||
if (pdata instanceof ReceiverTypeData) {
|
||||
ReceiverTypeData vdata = (ReceiverTypeData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
Klass k = vdata.receiver(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " +
|
||||
(dpToDi(vdata.dp() +
|
||||
vdata.cellOffset(vdata.receiverCellIndex(i))) / cellSize) + " " +
|
||||
k.getName().asString());
|
||||
}
|
||||
}
|
||||
} else if (pdata instanceof VirtualCallData) {
|
||||
VirtualCallData vdata = (VirtualCallData)pdata;
|
||||
for (int i = 0; i < vdata.rowLimit(); i++) {
|
||||
Klass k = vdata.receiver(i);
|
||||
if (k != null) {
|
||||
if (round == 0) count++;
|
||||
else out.print(" " +
|
||||
(dpToDi(vdata.dp() +
|
||||
vdata.cellOffset(vdata.receiverCellIndex(i))) / cellSize) + " " +
|
||||
k.getName().asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out.println();
|
||||
}
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ HOTSPOT_VM_COPYRIGHT=Copyright 2012
|
||||
|
||||
HS_MAJOR_VER=25
|
||||
HS_MINOR_VER=0
|
||||
HS_BUILD_NUMBER=08
|
||||
HS_BUILD_NUMBER=10
|
||||
|
||||
JDK_MAJOR_VER=1
|
||||
JDK_MINOR_VER=8
|
||||
|
||||
@ -170,68 +170,70 @@ ifeq ($(JDK6_OR_EARLIER),0)
|
||||
# overridden in some situations, e.g., a BUILD_FLAVOR != product
|
||||
# build.
|
||||
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from GNU Binutils on Linux:
|
||||
DEF_OBJCOPY=/usr/bin/objcopy
|
||||
ifdef CROSS_COMPILE_ARCH
|
||||
# don't try to generate .debuginfo files when cross compiling
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: cross compiling for ARCH $(CROSS_COMPILE_ARCH)," \
|
||||
"skipping .debuginfo generation.")
|
||||
OBJCOPY=
|
||||
# Due to the multiple sub-make processes that occur this logic gets
|
||||
# executed multiple times. We reduce the noise by at least checking that
|
||||
# BUILD_FLAVOR has been set.
|
||||
ifneq ($(BUILD_FLAVOR),)
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from GNU Binutils on Linux
|
||||
ifeq ($(CROSS_COMPILE_ARCH),)
|
||||
DEF_OBJCOPY=/usr/bin/objcopy
|
||||
else
|
||||
# Assume objcopy is part of the cross-compilation toolset
|
||||
ifneq ($(ALT_COMPILER_PATH),)
|
||||
DEF_OBJCOPY=$(ALT_COMPILER_PATH)/objcopy
|
||||
endif
|
||||
endif
|
||||
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
|
||||
ifneq ($(ALT_OBJCOPY),)
|
||||
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
|
||||
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
|
||||
endif
|
||||
endif
|
||||
else
|
||||
OBJCOPY=
|
||||
endif
|
||||
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files. You may need to set ALT_OBJCOPY.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif # ENABLE_FULL_DEBUG_SYMBOLS=1
|
||||
endif # BUILD_FLAVOR
|
||||
endif # JDK_6_OR_EARLIER
|
||||
|
||||
JDK_INCLUDE_SUBDIR=linux
|
||||
|
||||
|
||||
@ -336,24 +336,23 @@ $(LIBJVM): $(LIBJVM.o) $(LIBJVM_MAPFILE) $(LD_SCRIPT)
|
||||
fi \
|
||||
fi \
|
||||
}
|
||||
ifeq ($(CROSS_COMPILE_ARCH),)
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
$(QUIETLY) $(OBJCOPY) --only-keep-debug $@ $(LIBJVM_DEBUGINFO)
|
||||
$(QUIETLY) $(OBJCOPY) --add-gnu-debuglink=$(LIBJVM_DEBUGINFO) $@
|
||||
ifeq ($(STRIP_POLICY),all_strip)
|
||||
ifeq ($(STRIP_POLICY),all_strip)
|
||||
$(QUIETLY) $(STRIP) $@
|
||||
else
|
||||
ifeq ($(STRIP_POLICY),min_strip)
|
||||
else
|
||||
ifeq ($(STRIP_POLICY),min_strip)
|
||||
$(QUIETLY) $(STRIP) -g $@
|
||||
# implied else here is no stripping at all
|
||||
endif
|
||||
# implied else here is no stripping at all
|
||||
endif
|
||||
endif
|
||||
$(QUIETLY) [ -f $(LIBJVM_G_DEBUGINFO) ] || ln -s $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
|
||||
ifeq ($(ZIP_DEBUGINFO_FILES),1)
|
||||
ifeq ($(ZIP_DEBUGINFO_FILES),1)
|
||||
$(ZIPEXE) -q -y $(LIBJVM_DIZ) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
|
||||
$(RM) $(LIBJVM_DEBUGINFO) $(LIBJVM_G_DEBUGINFO)
|
||||
[ -f $(LIBJVM_G_DIZ) ] || { ln -s $(LIBJVM_DIZ) $(LIBJVM_G_DIZ); }
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
@ -109,60 +109,63 @@ ifeq ($(JDK6_OR_EARLIER),0)
|
||||
# overridden in some situations, e.g., a BUILD_FLAVOR != product
|
||||
# build.
|
||||
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from the SUNWbinutils package:
|
||||
DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
|
||||
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
|
||||
ifneq ($(ALT_OBJCOPY),)
|
||||
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
|
||||
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
|
||||
# Due to the multiple sub-make processes that occur this logic gets
|
||||
# executed multiple times. We reduce the noise by at least checking that
|
||||
# BUILD_FLAVOR has been set.
|
||||
ifneq ($(BUILD_FLAVOR),)
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
else
|
||||
OBJCOPY=
|
||||
endif
|
||||
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
# since objcopy is optional, we set ZIP_DEBUGINFO_FILES later
|
||||
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
# Default OBJCOPY comes from the SUNWbinutils package:
|
||||
DEF_OBJCOPY=/usr/sfw/bin/gobjcopy
|
||||
OBJCOPY=$(shell test -x $(DEF_OBJCOPY) && echo $(DEF_OBJCOPY))
|
||||
ifneq ($(ALT_OBJCOPY),)
|
||||
_JUNK_ := $(shell echo >&2 "INFO: ALT_OBJCOPY=$(ALT_OBJCOPY)")
|
||||
OBJCOPY=$(shell test -x $(ALT_OBJCOPY) && echo $(ALT_OBJCOPY))
|
||||
endif
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
ifeq ($(OBJCOPY),)
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: no objcopy cmd found so cannot create .debuginfo files.")
|
||||
ENABLE_FULL_DEBUG_SYMBOLS=0
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
else
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: $(OBJCOPY) cmd found so will create .debuginfo files.")
|
||||
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
# Library stripping policies for .debuginfo configs:
|
||||
# all_strip - strips everything from the library
|
||||
# min_strip - strips most stuff from the library; leaves minimum symbols
|
||||
# no_strip - does not strip the library at all
|
||||
#
|
||||
# Oracle security policy requires "all_strip". A waiver was granted on
|
||||
# 2011.09.01 that permits using "min_strip" in the Java JDK and Java JRE.
|
||||
#
|
||||
# Currently, STRIP_POLICY is only used when Full Debug Symbols is enabled.
|
||||
#
|
||||
STRIP_POLICY ?= min_strip
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: STRIP_POLICY=$(STRIP_POLICY)")
|
||||
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)")
|
||||
endif
|
||||
endif # ENABLE_FULL_DEBUG_SYMBOLS=1
|
||||
endif # BUILD_FLAVOR
|
||||
endif # JDK_6_OR_EARLIER
|
||||
|
||||
JDK_INCLUDE_SUBDIR=solaris
|
||||
|
||||
|
||||
@ -131,23 +131,29 @@ endif
|
||||
# overridden in some situations, e.g., a BUILD_FLAVOR != product
|
||||
# build.
|
||||
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
|
||||
# Due to the multiple sub-make processes that occur this logic gets
|
||||
# executed multiple times. We reduce the noise by at least checking that
|
||||
# BUILD_FLAVOR has been set.
|
||||
ifneq ($(BUILD_FLAVOR),)
|
||||
ifeq ($(BUILD_FLAVOR), product)
|
||||
FULL_DEBUG_SYMBOLS ?= 1
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = $(FULL_DEBUG_SYMBOLS)
|
||||
else
|
||||
# debug variants always get Full Debug Symbols (if available)
|
||||
ENABLE_FULL_DEBUG_SYMBOLS = 1
|
||||
endif
|
||||
_JUNK_ := $(shell \
|
||||
echo >&2 "INFO: ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)")
|
||||
MAKE_ARGS += ENABLE_FULL_DEBUG_SYMBOLS=$(ENABLE_FULL_DEBUG_SYMBOLS)
|
||||
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
else
|
||||
ZIP_DEBUGINFO_FILES=0
|
||||
ifeq ($(ENABLE_FULL_DEBUG_SYMBOLS),1)
|
||||
ZIP_DEBUGINFO_FILES ?= 1
|
||||
else
|
||||
ZIP_DEBUGINFO_FILES=0
|
||||
endif
|
||||
MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
|
||||
endif
|
||||
MAKE_ARGS += ZIP_DEBUGINFO_FILES=$(ZIP_DEBUGINFO_FILES)
|
||||
|
||||
MAKE_ARGS += RM="$(RM)"
|
||||
MAKE_ARGS += ZIPEXE=$(ZIPEXE)
|
||||
|
||||
|
||||
@ -2322,7 +2322,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
// Pre-load a static method's oop into O1. Used both by locking code and
|
||||
// the normal JNI call code.
|
||||
if (method->is_static() && !is_critical_native) {
|
||||
__ set_oop_constant(JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()), O1);
|
||||
__ set_oop_constant(JNIHandles::make_local(method->method_holder()->java_mirror()), O1);
|
||||
|
||||
// Now handlize the static class mirror in O1. It's known not-null.
|
||||
__ st_ptr(O1, SP, klass_offset + STACK_BIAS);
|
||||
|
||||
@ -1936,7 +1936,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
if (method->is_static() && !is_critical_native) {
|
||||
|
||||
// load opp into a register
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()));
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(method->method_holder()->java_mirror()));
|
||||
|
||||
// Now handlize the static class mirror it's known not-null.
|
||||
__ movptr(Address(rsp, klass_offset), oop_handle_reg);
|
||||
|
||||
@ -2179,7 +2179,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
if (method->is_static() && !is_critical_native) {
|
||||
|
||||
// load oop into a register
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(Klass::cast(method->method_holder())->java_mirror()));
|
||||
__ movoop(oop_handle_reg, JNIHandles::make_local(method->method_holder()->java_mirror()));
|
||||
|
||||
// Now handlize the static class mirror it's known not-null.
|
||||
__ movptr(Address(rsp, klass_offset), oop_handle_reg);
|
||||
|
||||
@ -488,8 +488,8 @@ void VM_Version::get_processor_features() {
|
||||
}
|
||||
|
||||
// The AES intrinsic stubs require AES instruction support (of course)
|
||||
// but also require AVX mode for misaligned SSE access
|
||||
if (UseAES && (UseAVX > 0)) {
|
||||
// but also require AVX and sse3 modes for instructions it use.
|
||||
if (UseAES && (UseAVX > 0) && (UseSSE > 2)) {
|
||||
if (FLAG_IS_DEFAULT(UseAESIntrinsics)) {
|
||||
UseAESIntrinsics = true;
|
||||
}
|
||||
|
||||
@ -1198,19 +1198,20 @@ static bool file_exists(const char* filename) {
|
||||
return os::stat(filename, &statbuf) == 0;
|
||||
}
|
||||
|
||||
void os::dll_build_name(char* buffer, size_t buflen,
|
||||
bool os::dll_build_name(char* buffer, size_t buflen,
|
||||
const char* pname, const char* fname) {
|
||||
bool retval = false;
|
||||
// Copied from libhpi
|
||||
const size_t pnamelen = pname ? strlen(pname) : 0;
|
||||
|
||||
// Quietly truncate on buffer overflow. Should be an error.
|
||||
// Return error on buffer overflow.
|
||||
if (pnamelen + strlen(fname) + strlen(JNI_LIB_PREFIX) + strlen(JNI_LIB_SUFFIX) + 2 > buflen) {
|
||||
*buffer = '\0';
|
||||
return;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (pnamelen == 0) {
|
||||
snprintf(buffer, buflen, JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, fname);
|
||||
retval = true;
|
||||
} else if (strchr(pname, *os::path_separator()) != NULL) {
|
||||
int n;
|
||||
char** pelements = split_path(pname, &n);
|
||||
@ -1222,6 +1223,7 @@ void os::dll_build_name(char* buffer, size_t buflen,
|
||||
snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX,
|
||||
pelements[i], fname);
|
||||
if (file_exists(buffer)) {
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1236,7 +1238,9 @@ void os::dll_build_name(char* buffer, size_t buflen,
|
||||
}
|
||||
} else {
|
||||
snprintf(buffer, buflen, "%s/" JNI_LIB_PREFIX "%s" JNI_LIB_SUFFIX, pname, fname);
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char* os::get_current_directory(char *buf, int buflen) {
|
||||
|
||||
@ -1650,19 +1650,20 @@ static bool file_exists(const char* filename) {
|
||||
return os::stat(filename, &statbuf) == 0;
|
||||
}
|
||||
|
||||
void os::dll_build_name(char* buffer, size_t buflen,
|
||||
bool os::dll_build_name(char* buffer, size_t buflen,
|
||||
const char* pname, const char* fname) {
|
||||
bool retval = false;
|
||||
// Copied from libhpi
|
||||
const size_t pnamelen = pname ? strlen(pname) : 0;
|
||||
|
||||
// Quietly truncate on buffer overflow. Should be an error.
|
||||
// Return error on buffer overflow.
|
||||
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
|
||||
*buffer = '\0';
|
||||
return;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (pnamelen == 0) {
|
||||
snprintf(buffer, buflen, "lib%s.so", fname);
|
||||
retval = true;
|
||||
} else if (strchr(pname, *os::path_separator()) != NULL) {
|
||||
int n;
|
||||
char** pelements = split_path(pname, &n);
|
||||
@ -1673,6 +1674,7 @@ void os::dll_build_name(char* buffer, size_t buflen,
|
||||
}
|
||||
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
|
||||
if (file_exists(buffer)) {
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1687,7 +1689,9 @@ void os::dll_build_name(char* buffer, size_t buflen,
|
||||
}
|
||||
} else {
|
||||
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char* os::get_current_directory(char *buf, int buflen) {
|
||||
|
||||
@ -1894,18 +1894,19 @@ static bool file_exists(const char* filename) {
|
||||
return os::stat(filename, &statbuf) == 0;
|
||||
}
|
||||
|
||||
void os::dll_build_name(char* buffer, size_t buflen,
|
||||
bool os::dll_build_name(char* buffer, size_t buflen,
|
||||
const char* pname, const char* fname) {
|
||||
bool retval = false;
|
||||
const size_t pnamelen = pname ? strlen(pname) : 0;
|
||||
|
||||
// Quietly truncate on buffer overflow. Should be an error.
|
||||
// Return error on buffer overflow.
|
||||
if (pnamelen + strlen(fname) + 10 > (size_t) buflen) {
|
||||
*buffer = '\0';
|
||||
return;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (pnamelen == 0) {
|
||||
snprintf(buffer, buflen, "lib%s.so", fname);
|
||||
retval = true;
|
||||
} else if (strchr(pname, *os::path_separator()) != NULL) {
|
||||
int n;
|
||||
char** pelements = split_path(pname, &n);
|
||||
@ -1916,6 +1917,7 @@ void os::dll_build_name(char* buffer, size_t buflen,
|
||||
}
|
||||
snprintf(buffer, buflen, "%s/lib%s.so", pelements[i], fname);
|
||||
if (file_exists(buffer)) {
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1930,7 +1932,9 @@ void os::dll_build_name(char* buffer, size_t buflen,
|
||||
}
|
||||
} else {
|
||||
snprintf(buffer, buflen, "%s/lib%s.so", pname, fname);
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
const char* os::get_current_directory(char *buf, int buflen) {
|
||||
|
||||
@ -1132,21 +1132,23 @@ static bool file_exists(const char* filename) {
|
||||
return GetFileAttributes(filename) != INVALID_FILE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
void os::dll_build_name(char *buffer, size_t buflen,
|
||||
bool os::dll_build_name(char *buffer, size_t buflen,
|
||||
const char* pname, const char* fname) {
|
||||
bool retval = false;
|
||||
const size_t pnamelen = pname ? strlen(pname) : 0;
|
||||
const char c = (pnamelen > 0) ? pname[pnamelen-1] : 0;
|
||||
|
||||
// Quietly truncates on buffer overflow. Should be an error.
|
||||
// Return error on buffer overflow.
|
||||
if (pnamelen + strlen(fname) + 10 > buflen) {
|
||||
*buffer = '\0';
|
||||
return;
|
||||
return retval;
|
||||
}
|
||||
|
||||
if (pnamelen == 0) {
|
||||
jio_snprintf(buffer, buflen, "%s.dll", fname);
|
||||
retval = true;
|
||||
} else if (c == ':' || c == '\\') {
|
||||
jio_snprintf(buffer, buflen, "%s%s.dll", pname, fname);
|
||||
retval = true;
|
||||
} else if (strchr(pname, *os::path_separator()) != NULL) {
|
||||
int n;
|
||||
char** pelements = split_path(pname, &n);
|
||||
@ -1164,6 +1166,7 @@ void os::dll_build_name(char *buffer, size_t buflen,
|
||||
jio_snprintf(buffer, buflen, "%s\\%s.dll", path, fname);
|
||||
}
|
||||
if (file_exists(buffer)) {
|
||||
retval = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -1178,7 +1181,9 @@ void os::dll_build_name(char *buffer, size_t buflen,
|
||||
}
|
||||
} else {
|
||||
jio_snprintf(buffer, buflen, "%s\\%s.dll", pname, fname);
|
||||
retval = true;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// Needs to be in os specific directory because windows requires another
|
||||
|
||||
@ -85,9 +85,11 @@ void end_of_file() { }
|
||||
|
||||
#include "dlfcn.h"
|
||||
|
||||
#define DECODE_INSTRUCTIONS_NAME "decode_instructions_virtual"
|
||||
#define DECODE_INSTRUCTIONS_VIRTUAL_NAME "decode_instructions_virtual"
|
||||
#define DECODE_INSTRUCTIONS_NAME "decode_instructions"
|
||||
#define HSDIS_NAME "hsdis"
|
||||
static void* decode_instructions_pv = 0;
|
||||
static void* decode_instructions_sv = 0;
|
||||
static const char* hsdis_path[] = {
|
||||
HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
"./" HSDIS_NAME"-"LIBARCH LIB_EXT,
|
||||
@ -101,11 +103,12 @@ static const char* load_decode_instructions() {
|
||||
void* dllib = NULL;
|
||||
const char* *next_in_path = hsdis_path;
|
||||
while (1) {
|
||||
decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
|
||||
if (decode_instructions_pv != NULL)
|
||||
decode_instructions_pv = dlsym(dllib, DECODE_INSTRUCTIONS_VIRTUAL_NAME);
|
||||
decode_instructions_sv = dlsym(dllib, DECODE_INSTRUCTIONS_NAME);
|
||||
if (decode_instructions_pv != NULL || decode_instructions_sv != NULL)
|
||||
return NULL;
|
||||
if (dllib != NULL)
|
||||
return "plugin does not defined "DECODE_INSTRUCTIONS_NAME;
|
||||
return "plugin does not defined "DECODE_INSTRUCTIONS_VIRTUAL_NAME" and "DECODE_INSTRUCTIONS_NAME;
|
||||
for (dllib = NULL; dllib == NULL; ) {
|
||||
const char* next_lib = (*next_in_path++);
|
||||
if (next_lib == NULL)
|
||||
@ -213,20 +216,44 @@ void disassemble(uintptr_t from, uintptr_t to) {
|
||||
printf("%s: %s\n", err, dlerror());
|
||||
exit(1);
|
||||
}
|
||||
printf("Decoding from %p to %p...\n", from, to);
|
||||
decode_instructions_ftype decode_instructions
|
||||
= (decode_instructions_ftype) decode_instructions_pv;
|
||||
decode_func_vtype decode_instructions_v
|
||||
= (decode_func_vtype) decode_instructions_pv;
|
||||
decode_func_stype decode_instructions_s
|
||||
= (decode_func_stype) decode_instructions_sv;
|
||||
void* res;
|
||||
if (raw && xml) {
|
||||
res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
|
||||
} else if (raw) {
|
||||
res = (*decode_instructions)(from, to, (unsigned char*)from, to - from, simple_handle_event, stdout, NULL, stdout, options);
|
||||
} else {
|
||||
res = (*decode_instructions)(from, to, (unsigned char*)from, to - from,
|
||||
handle_event, (void*) event_cookie,
|
||||
fprintf_callback, stdout,
|
||||
options);
|
||||
if (decode_instructions_pv != NULL) {
|
||||
printf("\nDecoding from %p to %p...with %s\n", from, to, DECODE_INSTRUCTIONS_VIRTUAL_NAME);
|
||||
if (raw) {
|
||||
res = (*decode_instructions_v)(from, to,
|
||||
(unsigned char*)from, to - from,
|
||||
simple_handle_event, stdout,
|
||||
NULL, stdout,
|
||||
options, 0);
|
||||
} else {
|
||||
res = (*decode_instructions_v)(from, to,
|
||||
(unsigned char*)from, to - from,
|
||||
handle_event, (void*) event_cookie,
|
||||
fprintf_callback, stdout,
|
||||
options, 0);
|
||||
}
|
||||
if (res != (void*)to)
|
||||
printf("*** Result was %p!\n", res);
|
||||
}
|
||||
void* sres;
|
||||
if (decode_instructions_sv != NULL) {
|
||||
printf("\nDecoding from %p to %p...with old decode_instructions\n", from, to, DECODE_INSTRUCTIONS_NAME);
|
||||
if (raw) {
|
||||
sres = (*decode_instructions_s)(from, to,
|
||||
simple_handle_event, stdout,
|
||||
NULL, stdout,
|
||||
options);
|
||||
} else {
|
||||
sres = (*decode_instructions_s)(from, to,
|
||||
handle_event, (void*) event_cookie,
|
||||
fprintf_callback, stdout,
|
||||
options);
|
||||
}
|
||||
if (sres != (void *)to)
|
||||
printf("*** Result of decode_instructions %p!\n", sres);
|
||||
}
|
||||
if (res != (void*)to)
|
||||
printf("*** Result was %p!\n", res);
|
||||
}
|
||||
|
||||
@ -99,7 +99,7 @@ decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
event_callback_t event_callback_arg, void* event_stream_arg,
|
||||
printf_callback_t printf_callback_arg, void* printf_stream_arg,
|
||||
const char* options) {
|
||||
const char* options, int newline) {
|
||||
struct hsdis_app_data app_data;
|
||||
memset(&app_data, 0, sizeof(app_data));
|
||||
app_data.start_va = start_va;
|
||||
@ -110,7 +110,7 @@ decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
|
||||
app_data.event_stream = event_stream_arg;
|
||||
app_data.printf_callback = printf_callback_arg;
|
||||
app_data.printf_stream = printf_stream_arg;
|
||||
app_data.do_newline = false;
|
||||
app_data.do_newline = newline == 0 ? false : true;
|
||||
|
||||
return decode(&app_data, options);
|
||||
}
|
||||
@ -132,7 +132,7 @@ decode_instructions(void* start_pv, void* end_pv,
|
||||
event_stream_arg,
|
||||
printf_callback_arg,
|
||||
printf_stream_arg,
|
||||
options);
|
||||
options, false);
|
||||
}
|
||||
|
||||
static void* decode(struct hsdis_app_data* app_data, const char* options) {
|
||||
@ -173,7 +173,7 @@ static void* decode(struct hsdis_app_data* app_data, const char* options) {
|
||||
if (!app_data->losing) {
|
||||
const char* insn_close = format_insn_close("/insn", &app_data->dinfo,
|
||||
buf, sizeof(buf));
|
||||
(*event_callback)(event_stream, insn_close, (void*) p) != NULL;
|
||||
(*event_callback)(event_stream, insn_close, (void*) p);
|
||||
|
||||
if (app_data->do_newline) {
|
||||
/* follow each complete insn by a nice newline */
|
||||
@ -182,13 +182,14 @@ static void* decode(struct hsdis_app_data* app_data, const char* options) {
|
||||
}
|
||||
}
|
||||
|
||||
(*event_callback)(event_stream, "/insns", (void*) p);
|
||||
if (app_data->losing) (*event_callback)(event_stream, "/insns", (void*) p);
|
||||
return (void*) p;
|
||||
}
|
||||
}
|
||||
|
||||
/* take the address of the function, for luck, and also test the typedef: */
|
||||
const decode_instructions_ftype decode_instructions_address = &decode_instructions_virtual;
|
||||
const decode_func_vtype decode_func_virtual_address = &decode_instructions_virtual;
|
||||
const decode_func_stype decode_func_address = &decode_instructions;
|
||||
|
||||
static const char* format_insn_close(const char* close,
|
||||
disassemble_info* dinfo,
|
||||
|
||||
@ -47,6 +47,9 @@
|
||||
where tag is a simple identifier, signifying (as in XML) a element start,
|
||||
element end, and standalone element. (To render as XML, add angle brackets.)
|
||||
*/
|
||||
#ifndef SHARED_TOOLS_HSDIS_H
|
||||
#define SHARED_TOOLS_HSDIS_H
|
||||
|
||||
extern
|
||||
#ifdef DLL_EXPORT
|
||||
DLL_EXPORT
|
||||
@ -57,16 +60,37 @@ void* decode_instructions_virtual(uintptr_t start_va, uintptr_t end_va,
|
||||
void* event_stream,
|
||||
int (*printf_callback)(void*, const char*, ...),
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
const char* options,
|
||||
int newline /* bool value for nice new line */);
|
||||
|
||||
/* This is the compatability interface for older versions of hotspot */
|
||||
extern
|
||||
#ifdef DLL_ENTRY
|
||||
DLL_ENTRY
|
||||
#endif
|
||||
void* decode_instructions(void* start_pv, void* end_pv,
|
||||
void* (*event_callback)(void*, const char*, void*),
|
||||
void* event_stream,
|
||||
int (*printf_callback)(void*, const char*, ...),
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
|
||||
/* convenience typedefs */
|
||||
|
||||
typedef void* (*decode_instructions_event_callback_ftype) (void*, const char*, void*);
|
||||
typedef int (*decode_instructions_printf_callback_ftype) (void*, const char*, ...);
|
||||
typedef void* (*decode_instructions_ftype) (uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
decode_instructions_event_callback_ftype event_callback,
|
||||
void* event_stream,
|
||||
decode_instructions_printf_callback_ftype printf_callback,
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
typedef void* (*decode_func_vtype) (uintptr_t start_va, uintptr_t end_va,
|
||||
unsigned char* buffer, uintptr_t length,
|
||||
decode_instructions_event_callback_ftype event_callback,
|
||||
void* event_stream,
|
||||
decode_instructions_printf_callback_ftype printf_callback,
|
||||
void* printf_stream,
|
||||
const char* options,
|
||||
int newline);
|
||||
typedef void* (*decode_func_stype) (void* start_pv, void* end_pv,
|
||||
decode_instructions_event_callback_ftype event_callback,
|
||||
void* event_stream,
|
||||
decode_instructions_printf_callback_ftype printf_callback,
|
||||
void* printf_stream,
|
||||
const char* options);
|
||||
#endif /* SHARED_TOOLS_HSDIS_H */
|
||||
|
||||
@ -1836,7 +1836,7 @@ void GraphBuilder::invoke(Bytecodes::Code code) {
|
||||
// check if we could do inlining
|
||||
if (!PatchALot && Inline && klass->is_loaded() &&
|
||||
(klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())
|
||||
&& target->will_link(klass, callee_holder, code)) {
|
||||
&& target->is_loaded()) {
|
||||
// callee is known => check if we have static binding
|
||||
assert(target->is_loaded(), "callee must be known");
|
||||
if (code == Bytecodes::_invokestatic ||
|
||||
|
||||
@ -374,7 +374,7 @@ JRT_END
|
||||
|
||||
JRT_ENTRY(void, Runtime1::throw_array_store_exception(JavaThread* thread, oopDesc* obj))
|
||||
ResourceMark rm(thread);
|
||||
const char* klass_name = Klass::cast(obj->klass())->external_name();
|
||||
const char* klass_name = obj->klass()->external_name();
|
||||
SharedRuntime::throw_and_post_jvmti_exception(thread, vmSymbols::java_lang_ArrayStoreException(), klass_name);
|
||||
JRT_END
|
||||
|
||||
@ -631,7 +631,7 @@ JRT_ENTRY(void, Runtime1::throw_class_cast_exception(JavaThread* thread, oopDesc
|
||||
NOT_PRODUCT(_throw_class_cast_exception_count++;)
|
||||
ResourceMark rm(thread);
|
||||
char* message = SharedRuntime::generate_class_cast_message(
|
||||
thread, Klass::cast(object->klass())->external_name());
|
||||
thread, object->klass()->external_name());
|
||||
SharedRuntime::throw_and_post_jvmti_exception(
|
||||
thread, vmSymbols::java_lang_ClassCastException(), message);
|
||||
JRT_END
|
||||
@ -876,7 +876,7 @@ JRT_ENTRY(void, Runtime1::patch_code(JavaThread* thread, Runtime1::StubID stub_i
|
||||
case Bytecodes::_anewarray:
|
||||
{ Bytecode_anewarray anew(caller_method(), caller_method->bcp_from(bci));
|
||||
Klass* ek = caller_method->constants()->klass_at(anew.index(), CHECK);
|
||||
k = Klass::cast(ek)->array_klass(CHECK);
|
||||
k = ek->array_klass(CHECK);
|
||||
}
|
||||
break;
|
||||
case Bytecodes::_ldc:
|
||||
@ -1236,7 +1236,7 @@ template <class T> int obj_arraycopy_work(oopDesc* src, T* src_addr,
|
||||
} else {
|
||||
Klass* bound = ObjArrayKlass::cast(dst->klass())->element_klass();
|
||||
Klass* stype = ObjArrayKlass::cast(src->klass())->element_klass();
|
||||
if (stype == bound || Klass::cast(stype)->is_subtype_of(bound)) {
|
||||
if (stype == bound || stype->is_subtype_of(bound)) {
|
||||
// Elements are guaranteed to be subtypes, so no check necessary
|
||||
bs->write_ref_array_pre(dst_addr, length);
|
||||
Copy::conjoint_oops_atomic(src_addr, dst_addr, length);
|
||||
|
||||
@ -282,7 +282,7 @@ void BCEscapeAnalyzer::invoke(StateInfo &state, Bytecodes::Code code, ciMethod*
|
||||
ciMethod* inline_target = NULL;
|
||||
if (target->is_loaded() && klass->is_loaded()
|
||||
&& (klass->is_initialized() || klass->is_interface() && target->holder()->is_initialized())
|
||||
&& target->will_link(klass, callee_holder, code)) {
|
||||
&& target->is_loaded()) {
|
||||
if (code == Bytecodes::_invokestatic
|
||||
|| code == Bytecodes::_invokespecial
|
||||
|| code == Bytecodes::_invokevirtual && target->is_final_method()) {
|
||||
|
||||
@ -106,6 +106,7 @@ friend class ciSymbol; \
|
||||
friend class ciArray; \
|
||||
friend class ciObjArray; \
|
||||
friend class ciMetadata; \
|
||||
friend class ciReplay; \
|
||||
friend class ciTypeArray; \
|
||||
friend class ciType; \
|
||||
friend class ciReturnAddress; \
|
||||
|
||||
@ -30,6 +30,7 @@
|
||||
#include "ci/ciInstanceKlass.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "ci/ciNullObject.hpp"
|
||||
#include "ci/ciReplay.hpp"
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "classfile/vmSymbols.hpp"
|
||||
@ -426,7 +427,7 @@ ciKlass* ciEnv::get_klass_by_name_impl(ciKlass* accessing_klass,
|
||||
for (int i = cpool->length() - 1; i >= 1; i--) {
|
||||
if (cpool->tag_at(i).is_klass()) {
|
||||
Klass* kls = cpool->resolved_klass_at(i);
|
||||
if (Klass::cast(kls)->name() == sym) {
|
||||
if (kls->name() == sym) {
|
||||
found_klass = KlassHandle(THREAD, kls);
|
||||
break;
|
||||
}
|
||||
@ -768,10 +769,15 @@ ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
|
||||
Method* m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
|
||||
if (m != NULL &&
|
||||
(bc == Bytecodes::_invokestatic
|
||||
? InstanceKlass::cast(m->method_holder())->is_not_initialized()
|
||||
: !InstanceKlass::cast(m->method_holder())->is_loaded())) {
|
||||
? m->method_holder()->is_not_initialized()
|
||||
: !m->method_holder()->is_loaded())) {
|
||||
m = NULL;
|
||||
}
|
||||
#ifdef ASSERT
|
||||
if (m != NULL && ReplayCompiles && !ciReplay::is_loaded(m)) {
|
||||
m = NULL;
|
||||
}
|
||||
#endif
|
||||
if (m != NULL) {
|
||||
// We found the method.
|
||||
return get_method(m);
|
||||
@ -1056,7 +1062,7 @@ void ciEnv::register_method(ciMethod* target,
|
||||
method_name,
|
||||
entry_bci);
|
||||
}
|
||||
InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
|
||||
method->method_holder()->add_osr_nmethod(nm);
|
||||
|
||||
}
|
||||
}
|
||||
@ -1144,3 +1150,43 @@ void ciEnv::record_out_of_memory_failure() {
|
||||
// If memory is low, we stop compiling methods.
|
||||
record_method_not_compilable("out of memory");
|
||||
}
|
||||
|
||||
fileStream* ciEnv::_replay_data_stream = NULL;
|
||||
|
||||
void ciEnv::dump_replay_data() {
|
||||
VM_ENTRY_MARK;
|
||||
MutexLocker ml(Compile_lock);
|
||||
if (_replay_data_stream == NULL) {
|
||||
_replay_data_stream = new (ResourceObj::C_HEAP, mtCompiler) fileStream(ReplayDataFile);
|
||||
if (_replay_data_stream == NULL) {
|
||||
fatal(err_msg("Can't open %s for replay data", ReplayDataFile));
|
||||
}
|
||||
}
|
||||
dump_replay_data(_replay_data_stream);
|
||||
}
|
||||
|
||||
|
||||
void ciEnv::dump_replay_data(outputStream* out) {
|
||||
ASSERT_IN_VM;
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
out->print_cr("JvmtiExport can_access_local_variables %d", _jvmti_can_access_local_variables);
|
||||
out->print_cr("JvmtiExport can_hotswap_or_post_breakpoint %d", _jvmti_can_hotswap_or_post_breakpoint);
|
||||
out->print_cr("JvmtiExport can_post_on_exceptions %d", _jvmti_can_post_on_exceptions);
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
GrowableArray<ciMetadata*>* objects = _factory->get_ci_metadata();
|
||||
out->print_cr("# %d ciObject found", objects->length());
|
||||
for (int i = 0; i < objects->length(); i++) {
|
||||
objects->at(i)->dump_replay_data(out);
|
||||
}
|
||||
Method* method = task()->method();
|
||||
int entry_bci = task()->osr_bci();
|
||||
// Klass holder = method->method_holder();
|
||||
out->print_cr("compile %s %s %s %d",
|
||||
method->klass_name()->as_quoted_ascii(),
|
||||
method->name()->as_quoted_ascii(),
|
||||
method->signature()->as_quoted_ascii(),
|
||||
entry_bci);
|
||||
out->flush();
|
||||
}
|
||||
|
||||
@ -46,6 +46,8 @@ class ciEnv : StackObj {
|
||||
friend class CompileBroker;
|
||||
friend class Dependencies; // for get_object, during logging
|
||||
|
||||
static fileStream* _replay_data_stream;
|
||||
|
||||
private:
|
||||
Arena* _arena; // Alias for _ciEnv_arena except in init_shared_objects()
|
||||
Arena _ciEnv_arena;
|
||||
@ -448,6 +450,13 @@ public:
|
||||
|
||||
// RedefineClasses support
|
||||
void metadata_do(void f(Metadata*)) { _factory->metadata_do(f); }
|
||||
|
||||
// Dump the compilation replay data for this ciEnv to
|
||||
// ReplayDataFile, creating the file if needed.
|
||||
void dump_replay_data();
|
||||
|
||||
// Dump the compilation replay data for the ciEnv to the stream.
|
||||
void dump_replay_data(outputStream* out);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CI_CIENV_HPP
|
||||
|
||||
@ -561,3 +561,114 @@ ciInstanceKlass* ciInstanceKlass::implementor() {
|
||||
}
|
||||
return impl;
|
||||
}
|
||||
|
||||
// Utility class for printing of the contents of the static fields for
|
||||
// use by compilation replay. It only prints out the information that
|
||||
// could be consumed by the compiler, so for primitive types it prints
|
||||
// out the actual value. For Strings it's the actual string value.
|
||||
// For array types it it's first level array size since that's the
|
||||
// only value which statically unchangeable. For all other reference
|
||||
// types it simply prints out the dynamic type.
|
||||
|
||||
class StaticFinalFieldPrinter : public FieldClosure {
|
||||
outputStream* _out;
|
||||
const char* _holder;
|
||||
public:
|
||||
StaticFinalFieldPrinter(outputStream* out, const char* holder) :
|
||||
_out(out),
|
||||
_holder(holder) {
|
||||
}
|
||||
void do_field(fieldDescriptor* fd) {
|
||||
if (fd->is_final() && !fd->has_initial_value()) {
|
||||
oop mirror = fd->field_holder()->java_mirror();
|
||||
_out->print("staticfield %s %s %s ", _holder, fd->name()->as_quoted_ascii(), fd->signature()->as_quoted_ascii());
|
||||
switch (fd->field_type()) {
|
||||
case T_BYTE: _out->print_cr("%d", mirror->byte_field(fd->offset())); break;
|
||||
case T_BOOLEAN: _out->print_cr("%d", mirror->bool_field(fd->offset())); break;
|
||||
case T_SHORT: _out->print_cr("%d", mirror->short_field(fd->offset())); break;
|
||||
case T_CHAR: _out->print_cr("%d", mirror->char_field(fd->offset())); break;
|
||||
case T_INT: _out->print_cr("%d", mirror->int_field(fd->offset())); break;
|
||||
case T_LONG: _out->print_cr(INT64_FORMAT, mirror->long_field(fd->offset())); break;
|
||||
case T_FLOAT: {
|
||||
float f = mirror->float_field(fd->offset());
|
||||
_out->print_cr("%d", *(int*)&f);
|
||||
break;
|
||||
}
|
||||
case T_DOUBLE: {
|
||||
double d = mirror->double_field(fd->offset());
|
||||
_out->print_cr(INT64_FORMAT, *(jlong*)&d);
|
||||
break;
|
||||
}
|
||||
case T_ARRAY: {
|
||||
oop value = mirror->obj_field_acquire(fd->offset());
|
||||
if (value == NULL) {
|
||||
_out->print_cr("null");
|
||||
} else {
|
||||
typeArrayOop ta = (typeArrayOop)value;
|
||||
_out->print("%d", ta->length());
|
||||
if (value->is_objArray()) {
|
||||
objArrayOop oa = (objArrayOop)value;
|
||||
const char* klass_name = value->klass()->name()->as_quoted_ascii();
|
||||
_out->print(" %s", klass_name);
|
||||
}
|
||||
_out->cr();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_OBJECT: {
|
||||
oop value = mirror->obj_field_acquire(fd->offset());
|
||||
if (value == NULL) {
|
||||
_out->print_cr("null");
|
||||
} else if (value->is_instance()) {
|
||||
if (value->is_a(SystemDictionary::String_klass())) {
|
||||
_out->print("\"");
|
||||
_out->print_raw(java_lang_String::as_quoted_ascii(value));
|
||||
_out->print_cr("\"");
|
||||
} else {
|
||||
const char* klass_name = value->klass()->name()->as_quoted_ascii();
|
||||
_out->print_cr(klass_name);
|
||||
}
|
||||
} else {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void ciInstanceKlass::dump_replay_data(outputStream* out) {
|
||||
ASSERT_IN_VM;
|
||||
InstanceKlass* ik = get_instanceKlass();
|
||||
ConstantPool* cp = ik->constants();
|
||||
|
||||
// Try to record related loaded classes
|
||||
Klass* sub = ik->subklass();
|
||||
while (sub != NULL) {
|
||||
if (sub->oop_is_instance()) {
|
||||
out->print_cr("instanceKlass %s", sub->name()->as_quoted_ascii());
|
||||
}
|
||||
sub = sub->next_sibling();
|
||||
}
|
||||
|
||||
// Dump out the state of the constant pool tags. During replay the
|
||||
// tags will be validated for things which shouldn't change and
|
||||
// classes will be resolved if the tags indicate that they were
|
||||
// resolved at compile time.
|
||||
out->print("ciInstanceKlass %s %d %d %d", ik->name()->as_quoted_ascii(),
|
||||
is_linked(), is_initialized(), cp->length());
|
||||
for (int index = 1; index < cp->length(); index++) {
|
||||
out->print(" %d", cp->tags()->at(index));
|
||||
}
|
||||
out->cr();
|
||||
if (is_initialized()) {
|
||||
// Dump out the static final fields in case the compilation relies
|
||||
// on their value for correct replay.
|
||||
StaticFinalFieldPrinter sffp(out, ik->name()->as_quoted_ascii());
|
||||
ik->do_local_static_fields(&sffp);
|
||||
}
|
||||
}
|
||||
|
||||
@ -230,6 +230,9 @@ public:
|
||||
// What kind of ciObject is this?
|
||||
bool is_instance_klass() const { return true; }
|
||||
bool is_java_klass() const { return true; }
|
||||
|
||||
// Dump the current state of this klass for compilation replay.
|
||||
virtual void dump_replay_data(outputStream* out);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CI_CIINSTANCEKLASS_HPP
|
||||
|
||||
@ -61,6 +61,7 @@ class ciMetadata: public ciBaseObject {
|
||||
virtual bool is_array_klass() const { return false; }
|
||||
virtual bool is_obj_array_klass() const { return false; }
|
||||
virtual bool is_type_array_klass() const { return false; }
|
||||
virtual void dump_replay_data(outputStream* st) { /* do nothing */ }
|
||||
|
||||
ciMethod* as_method() {
|
||||
assert(is_method(), "bad cast");
|
||||
|
||||
@ -31,6 +31,7 @@
|
||||
#include "ci/ciMethodData.hpp"
|
||||
#include "ci/ciStreams.hpp"
|
||||
#include "ci/ciSymbol.hpp"
|
||||
#include "ci/ciReplay.hpp"
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
@ -105,7 +106,7 @@ ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
|
||||
CHECK_UNHANDLED_OOPS_ONLY(Thread::current()->clear_unhandled_oops());
|
||||
}
|
||||
|
||||
if (InstanceKlass::cast(h_m()->method_holder())->is_linked()) {
|
||||
if (h_m()->method_holder()->is_linked()) {
|
||||
_can_be_statically_bound = h_m()->can_be_statically_bound();
|
||||
} else {
|
||||
// Have to use a conservative value in this case.
|
||||
@ -139,6 +140,12 @@ ciMethod::ciMethod(methodHandle h_m) : ciMetadata(h_m()) {
|
||||
}
|
||||
if (_interpreter_invocation_count == 0)
|
||||
_interpreter_invocation_count = 1;
|
||||
_instructions_size = -1;
|
||||
#ifdef ASSERT
|
||||
if (ReplayCompiles) {
|
||||
ciReplay::initialize(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -161,7 +168,8 @@ ciMethod::ciMethod(ciInstanceKlass* holder,
|
||||
#if defined(COMPILER2) || defined(SHARK)
|
||||
,
|
||||
_flow( NULL),
|
||||
_bcea( NULL)
|
||||
_bcea( NULL),
|
||||
_instructions_size(-1)
|
||||
#endif // COMPILER2 || SHARK
|
||||
{
|
||||
// Usually holder and accessor are the same type but in some cases
|
||||
@ -188,7 +196,7 @@ void ciMethod::load_code() {
|
||||
|
||||
// Revert any breakpoint bytecodes in ci's copy
|
||||
if (me->number_of_breakpoints() > 0) {
|
||||
BreakpointInfo* bp = InstanceKlass::cast(me->method_holder())->breakpoints();
|
||||
BreakpointInfo* bp = me->method_holder()->breakpoints();
|
||||
for (; bp != NULL; bp = bp->next()) {
|
||||
if (bp->match(me)) {
|
||||
code_at_put(bp->bci(), bp->orig_bytecode());
|
||||
@ -867,25 +875,6 @@ ciMethodData* ciMethod::method_data_or_null() {
|
||||
return md;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::will_link
|
||||
//
|
||||
// Will this method link in a specific calling context?
|
||||
bool ciMethod::will_link(ciKlass* accessing_klass,
|
||||
ciKlass* declared_method_holder,
|
||||
Bytecodes::Code bc) {
|
||||
if (!is_loaded()) {
|
||||
// Method lookup failed.
|
||||
return false;
|
||||
}
|
||||
|
||||
// The link checks have been front-loaded into the get_method
|
||||
// call. This method (ciMethod::will_link()) will be removed
|
||||
// in the future.
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::should_exclude
|
||||
//
|
||||
@ -1000,8 +989,7 @@ bool ciMethod::can_be_osr_compiled(int entry_bci) {
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::has_compiled_code
|
||||
bool ciMethod::has_compiled_code() {
|
||||
VM_ENTRY_MARK;
|
||||
return get_Method()->code() != NULL;
|
||||
return instructions_size() > 0;
|
||||
}
|
||||
|
||||
int ciMethod::comp_level() {
|
||||
@ -1039,14 +1027,18 @@ int ciMethod::code_size_for_inlining() {
|
||||
// junk like exception handler, stubs, and constant table, which are
|
||||
// not highly relevant to an inlined method. So we use the more
|
||||
// specific accessor nmethod::insts_size.
|
||||
int ciMethod::instructions_size(int comp_level) {
|
||||
GUARDED_VM_ENTRY(
|
||||
nmethod* code = get_Method()->code();
|
||||
if (code != NULL && (comp_level == CompLevel_any || comp_level == code->comp_level())) {
|
||||
return code->insts_end() - code->verified_entry_point();
|
||||
}
|
||||
return 0;
|
||||
)
|
||||
int ciMethod::instructions_size() {
|
||||
if (_instructions_size == -1) {
|
||||
GUARDED_VM_ENTRY(
|
||||
nmethod* code = get_Method()->code();
|
||||
if (code != NULL && (code->comp_level() == CompLevel_full_optimization)) {
|
||||
_instructions_size = code->insts_end() - code->verified_entry_point();
|
||||
} else {
|
||||
_instructions_size = 0;
|
||||
}
|
||||
);
|
||||
}
|
||||
return _instructions_size;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
@ -1166,6 +1158,20 @@ ciMethodBlocks *ciMethod::get_method_blocks() {
|
||||
|
||||
#undef FETCH_FLAG_FROM_VM
|
||||
|
||||
void ciMethod::dump_replay_data(outputStream* st) {
|
||||
ASSERT_IN_VM;
|
||||
Method* method = get_Method();
|
||||
Klass* holder = method->method_holder();
|
||||
st->print_cr("ciMethod %s %s %s %d %d %d %d %d",
|
||||
holder->name()->as_quoted_ascii(),
|
||||
method->name()->as_quoted_ascii(),
|
||||
method->signature()->as_quoted_ascii(),
|
||||
method->invocation_counter()->raw_counter(),
|
||||
method->backedge_counter()->raw_counter(),
|
||||
interpreter_invocation_count(),
|
||||
interpreter_throwout_count(),
|
||||
_instructions_size);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::print_codes
|
||||
|
||||
@ -51,6 +51,7 @@ class ciMethod : public ciMetadata {
|
||||
friend class ciExceptionHandlerStream;
|
||||
friend class ciBytecodeStream;
|
||||
friend class ciMethodHandle;
|
||||
friend class ciReplay;
|
||||
|
||||
private:
|
||||
// General method information.
|
||||
@ -69,6 +70,7 @@ class ciMethod : public ciMetadata {
|
||||
int _handler_count;
|
||||
int _interpreter_invocation_count;
|
||||
int _interpreter_throwout_count;
|
||||
int _instructions_size;
|
||||
|
||||
bool _uses_monitors;
|
||||
bool _balanced_monitors;
|
||||
@ -239,9 +241,6 @@ class ciMethod : public ciMetadata {
|
||||
int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
|
||||
|
||||
// Compilation directives
|
||||
bool will_link(ciKlass* accessing_klass,
|
||||
ciKlass* declared_method_holder,
|
||||
Bytecodes::Code bc);
|
||||
bool should_exclude();
|
||||
bool should_inline();
|
||||
bool should_not_inline();
|
||||
@ -252,7 +251,6 @@ class ciMethod : public ciMetadata {
|
||||
bool can_be_osr_compiled(int entry_bci);
|
||||
void set_not_compilable();
|
||||
bool has_compiled_code();
|
||||
int instructions_size(int comp_level = CompLevel_any);
|
||||
void log_nmethod_identity(xmlStream* log);
|
||||
bool is_not_reached(int bci);
|
||||
bool was_executed_more_than(int times);
|
||||
@ -260,6 +258,7 @@ class ciMethod : public ciMetadata {
|
||||
bool is_klass_loaded(int refinfo_index, bool must_be_resolved) const;
|
||||
bool check_call(int refinfo_index, bool is_static) const;
|
||||
bool ensure_method_data(); // make sure it exists in the VM also
|
||||
int instructions_size();
|
||||
int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
|
||||
|
||||
// JSR 292 support
|
||||
@ -291,6 +290,7 @@ class ciMethod : public ciMetadata {
|
||||
bool is_accessor () const;
|
||||
bool is_initializer () const;
|
||||
bool can_be_statically_bound() const { return _can_be_statically_bound; }
|
||||
void dump_replay_data(outputStream* st);
|
||||
|
||||
// Print the bytecodes of this method.
|
||||
void print_codes_on(outputStream* st);
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "ci/ciMetadata.hpp"
|
||||
#include "ci/ciMethodData.hpp"
|
||||
#include "ci/ciReplay.hpp"
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
@ -115,6 +116,11 @@ void ciMethodData::load_data() {
|
||||
_arg_local = mdo->arg_local();
|
||||
_arg_stack = mdo->arg_stack();
|
||||
_arg_returned = mdo->arg_returned();
|
||||
#ifndef PRODUCT
|
||||
if (ReplayCompiles) {
|
||||
ciReplay::initialize(this);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void ciReceiverTypeData::translate_receiver_data_from(ProfileData* data) {
|
||||
@ -366,6 +372,79 @@ void ciMethodData::print_impl(outputStream* st) {
|
||||
ciMetadata::print_impl(st);
|
||||
}
|
||||
|
||||
void ciMethodData::dump_replay_data(outputStream* out) {
|
||||
ASSERT_IN_VM;
|
||||
MethodData* mdo = get_MethodData();
|
||||
Method* method = mdo->method();
|
||||
Klass* holder = method->method_holder();
|
||||
out->print("ciMethodData %s %s %s %d %d",
|
||||
holder->name()->as_quoted_ascii(),
|
||||
method->name()->as_quoted_ascii(),
|
||||
method->signature()->as_quoted_ascii(),
|
||||
_state,
|
||||
current_mileage());
|
||||
|
||||
// dump the contents of the MDO header as raw data
|
||||
unsigned char* orig = (unsigned char*)&_orig;
|
||||
int length = sizeof(_orig);
|
||||
out->print(" orig %d", length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
out->print(" %d", orig[i]);
|
||||
}
|
||||
|
||||
// dump the MDO data as raw data
|
||||
int elements = data_size() / sizeof(intptr_t);
|
||||
out->print(" data %d", elements);
|
||||
for (int i = 0; i < elements; i++) {
|
||||
// We could use INTPTR_FORMAT here but that's a zero justified
|
||||
// which makes comparing it with the SA version of this output
|
||||
// harder.
|
||||
#ifdef _LP64
|
||||
out->print(" 0x%" FORMAT64_MODIFIER "x", data()[i]);
|
||||
#else
|
||||
out->print(" 0x%x", data()[i]);
|
||||
#endif
|
||||
}
|
||||
|
||||
// The MDO contained oop references as ciObjects, so scan for those
|
||||
// and emit pairs of offset and klass name so that they can be
|
||||
// reconstructed at runtime. The first round counts the number of
|
||||
// oop references and the second actually emits them.
|
||||
int count = 0;
|
||||
for (int round = 0; round < 2; round++) {
|
||||
if (round == 1) out->print(" oops %d", count);
|
||||
ProfileData* pdata = first_data();
|
||||
for ( ; is_valid(pdata); pdata = next_data(pdata)) {
|
||||
if (pdata->is_ReceiverTypeData()) {
|
||||
ciReceiverTypeData* vdata = (ciReceiverTypeData*)pdata;
|
||||
for (uint i = 0; i < vdata->row_limit(); i++) {
|
||||
ciKlass* k = vdata->receiver(i);
|
||||
if (k != NULL) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out->print(" %d %s", dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t), k->name()->as_quoted_ascii());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (pdata->is_VirtualCallData()) {
|
||||
ciVirtualCallData* vdata = (ciVirtualCallData*)pdata;
|
||||
for (uint i = 0; i < vdata->row_limit(); i++) {
|
||||
ciKlass* k = vdata->receiver(i);
|
||||
if (k != NULL) {
|
||||
if (round == 0) {
|
||||
count++;
|
||||
} else {
|
||||
out->print(" %d %s", dp_to_di(vdata->dp() + in_bytes(vdata->receiver_offset(i))) / sizeof(intptr_t), k->name()->as_quoted_ascii());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
out->cr();
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void ciMethodData::print() {
|
||||
print_data_on(tty);
|
||||
|
||||
@ -144,6 +144,7 @@ public:
|
||||
|
||||
class ciMethodData : public ciMetadata {
|
||||
CI_PACKAGE_ACCESS
|
||||
friend class ciReplay;
|
||||
|
||||
private:
|
||||
// Size in bytes
|
||||
@ -320,6 +321,7 @@ public:
|
||||
void print();
|
||||
void print_data_on(outputStream* st);
|
||||
#endif
|
||||
void dump_replay_data(outputStream* out);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CI_CIMETHODDATA_HPP
|
||||
|
||||
@ -131,6 +131,7 @@ public:
|
||||
// Is this a type or value which has no associated class?
|
||||
// It is true of primitive types and null objects.
|
||||
virtual bool is_classless() const { return false; }
|
||||
virtual void dump_replay_data(outputStream* st) { /* do nothing */ }
|
||||
|
||||
// Note: some ciObjects refer to oops which have yet to be created.
|
||||
// We refer to these as "unloaded". Specifically, there are
|
||||
|
||||
@ -137,6 +137,7 @@ public:
|
||||
|
||||
ciReturnAddress* get_return_address(int bci);
|
||||
|
||||
GrowableArray<ciMetadata*>* get_ci_metadata() const { return _ci_metadata; }
|
||||
// RedefineClasses support
|
||||
void metadata_do(void f(Metadata*));
|
||||
|
||||
|
||||
942
hotspot/src/share/vm/ci/ciReplay.cpp
Normal file
942
hotspot/src/share/vm/ci/ciReplay.cpp
Normal file
@ -0,0 +1,942 @@
|
||||
/* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "ci/ciMethodData.hpp"
|
||||
#include "ci/ciReplay.hpp"
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "utilities/copy.hpp"
|
||||
|
||||
#ifdef ASSERT
|
||||
|
||||
// ciReplay
|
||||
|
||||
typedef struct _ciMethodDataRecord {
|
||||
const char* klass;
|
||||
const char* method;
|
||||
const char* signature;
|
||||
int state;
|
||||
int current_mileage;
|
||||
intptr_t* data;
|
||||
int data_length;
|
||||
char* orig_data;
|
||||
int orig_data_length;
|
||||
int oops_length;
|
||||
jobject* oops_handles;
|
||||
int* oops_offsets;
|
||||
} ciMethodDataRecord;
|
||||
|
||||
typedef struct _ciMethodRecord {
|
||||
const char* klass;
|
||||
const char* method;
|
||||
const char* signature;
|
||||
int instructions_size;
|
||||
int interpreter_invocation_count;
|
||||
int interpreter_throwout_count;
|
||||
int invocation_counter;
|
||||
int backedge_counter;
|
||||
} ciMethodRecord;
|
||||
|
||||
class CompileReplay;
|
||||
static CompileReplay* replay_state;
|
||||
|
||||
class CompileReplay : public StackObj {
|
||||
private:
|
||||
FILE* stream;
|
||||
Thread* thread;
|
||||
Handle protection_domain;
|
||||
Handle loader;
|
||||
|
||||
GrowableArray<ciMethodRecord*> ci_method_records;
|
||||
GrowableArray<ciMethodDataRecord*> ci_method_data_records;
|
||||
|
||||
const char* _error_message;
|
||||
|
||||
char* bufptr;
|
||||
char* buffer;
|
||||
int buffer_length;
|
||||
int buffer_end;
|
||||
int line_no;
|
||||
|
||||
public:
|
||||
CompileReplay(const char* filename, TRAPS) {
|
||||
thread = THREAD;
|
||||
loader = Handle(thread, SystemDictionary::java_system_loader());
|
||||
stream = fopen(filename, "rt");
|
||||
if (stream == NULL) {
|
||||
fprintf(stderr, "Can't open replay file %s\n", filename);
|
||||
}
|
||||
buffer_length = 32;
|
||||
buffer = NEW_RESOURCE_ARRAY(char, buffer_length);
|
||||
_error_message = NULL;
|
||||
|
||||
test();
|
||||
}
|
||||
|
||||
~CompileReplay() {
|
||||
if (stream != NULL) fclose(stream);
|
||||
}
|
||||
|
||||
void test() {
|
||||
strcpy(buffer, "1 2 foo 4 bar 0x9 \"this is it\"");
|
||||
bufptr = buffer;
|
||||
assert(parse_int("test") == 1, "what");
|
||||
assert(parse_int("test") == 2, "what");
|
||||
assert(strcmp(parse_string(), "foo") == 0, "what");
|
||||
assert(parse_int("test") == 4, "what");
|
||||
assert(strcmp(parse_string(), "bar") == 0, "what");
|
||||
assert(parse_intptr_t("test") == 9, "what");
|
||||
assert(strcmp(parse_quoted_string(), "this is it") == 0, "what");
|
||||
}
|
||||
|
||||
bool had_error() {
|
||||
return _error_message != NULL || thread->has_pending_exception();
|
||||
}
|
||||
|
||||
bool can_replay() {
|
||||
return !(stream == NULL || had_error());
|
||||
}
|
||||
|
||||
void report_error(const char* msg) {
|
||||
_error_message = msg;
|
||||
// Restore the buffer contents for error reporting
|
||||
for (int i = 0; i < buffer_end; i++) {
|
||||
if (buffer[i] == '\0') buffer[i] = ' ';
|
||||
}
|
||||
}
|
||||
|
||||
int parse_int(const char* label) {
|
||||
if (had_error()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int v = 0;
|
||||
int read;
|
||||
if (sscanf(bufptr, "%i%n", &v, &read) != 1) {
|
||||
report_error(label);
|
||||
} else {
|
||||
bufptr += read;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
intptr_t parse_intptr_t(const char* label) {
|
||||
if (had_error()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
intptr_t v = 0;
|
||||
int read;
|
||||
if (sscanf(bufptr, INTPTR_FORMAT "%n", &v, &read) != 1) {
|
||||
report_error(label);
|
||||
} else {
|
||||
bufptr += read;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
void skip_ws() {
|
||||
// Skip any leading whitespace
|
||||
while (*bufptr == ' ' || *bufptr == '\t') {
|
||||
bufptr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char* scan_and_terminate(char delim) {
|
||||
char* str = bufptr;
|
||||
while (*bufptr != delim && *bufptr != '\0') {
|
||||
bufptr++;
|
||||
}
|
||||
if (*bufptr != '\0') {
|
||||
*bufptr++ = '\0';
|
||||
}
|
||||
if (bufptr == str) {
|
||||
// nothing here
|
||||
return NULL;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
char* parse_string() {
|
||||
if (had_error()) return NULL;
|
||||
|
||||
skip_ws();
|
||||
return scan_and_terminate(' ');
|
||||
}
|
||||
|
||||
char* parse_quoted_string() {
|
||||
if (had_error()) return NULL;
|
||||
|
||||
skip_ws();
|
||||
|
||||
if (*bufptr == '"') {
|
||||
bufptr++;
|
||||
return scan_and_terminate('"');
|
||||
} else {
|
||||
return scan_and_terminate(' ');
|
||||
}
|
||||
}
|
||||
|
||||
const char* parse_escaped_string() {
|
||||
char* result = parse_quoted_string();
|
||||
if (result != NULL) {
|
||||
unescape_string(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Look for the tag 'tag' followed by an
|
||||
bool parse_tag_and_count(const char* tag, int& length) {
|
||||
const char* t = parse_string();
|
||||
if (t == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcmp(tag, t) != 0) {
|
||||
report_error(tag);
|
||||
return false;
|
||||
}
|
||||
length = parse_int("parse_tag_and_count");
|
||||
return !had_error();
|
||||
}
|
||||
|
||||
// Parse a sequence of raw data encoded as bytes and return the
|
||||
// resulting data.
|
||||
char* parse_data(const char* tag, int& length) {
|
||||
if (!parse_tag_and_count(tag, length)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char * result = NEW_RESOURCE_ARRAY(char, length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
int val = parse_int("data");
|
||||
result[i] = val;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse a standard chunk of data emitted as:
|
||||
// 'tag' <length> # # ...
|
||||
// Where each # is an intptr_t item
|
||||
intptr_t* parse_intptr_data(const char* tag, int& length) {
|
||||
if (!parse_tag_and_count(tag, length)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
intptr_t* result = NEW_RESOURCE_ARRAY(intptr_t, length);
|
||||
for (int i = 0; i < length; i++) {
|
||||
skip_ws();
|
||||
intptr_t val = parse_intptr_t("data");
|
||||
result[i] = val;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Parse a possibly quoted version of a symbol into a symbolOop
|
||||
Symbol* parse_symbol(TRAPS) {
|
||||
const char* str = parse_escaped_string();
|
||||
if (str != NULL) {
|
||||
Symbol* sym = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL);
|
||||
return sym;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Parse a valid klass name and look it up
|
||||
Klass* parse_klass(TRAPS) {
|
||||
const char* str = parse_escaped_string();
|
||||
Symbol* klass_name = SymbolTable::lookup(str, (int)strlen(str), CHECK_NULL);
|
||||
if (klass_name != NULL) {
|
||||
Klass* k = SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
oop throwable = PENDING_EXCEPTION;
|
||||
java_lang_Throwable::print(throwable, tty);
|
||||
tty->cr();
|
||||
report_error(str);
|
||||
return NULL;
|
||||
}
|
||||
return k;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Lookup a klass
|
||||
Klass* resolve_klass(const char* klass, TRAPS) {
|
||||
Symbol* klass_name = SymbolTable::lookup(klass, (int)strlen(klass), CHECK_NULL);
|
||||
return SystemDictionary::resolve_or_fail(klass_name, loader, protection_domain, true, CHECK_NULL);
|
||||
}
|
||||
|
||||
// Parse the standard tuple of <klass> <name> <signature>
|
||||
Method* parse_method(TRAPS) {
|
||||
InstanceKlass* k = (InstanceKlass*)parse_klass(CHECK_NULL);
|
||||
Symbol* method_name = parse_symbol(CHECK_NULL);
|
||||
Symbol* method_signature = parse_symbol(CHECK_NULL);
|
||||
Method* m = k->find_method(method_name, method_signature);
|
||||
if (m == NULL) {
|
||||
report_error("can't find method");
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
// Process each line of the replay file executing each command until
|
||||
// the file ends.
|
||||
void process(TRAPS) {
|
||||
line_no = 1;
|
||||
int pos = 0;
|
||||
int c = getc(stream);
|
||||
while(c != EOF) {
|
||||
if (pos + 1 >= buffer_length) {
|
||||
int newl = buffer_length * 2;
|
||||
char* newb = NEW_RESOURCE_ARRAY(char, newl);
|
||||
memcpy(newb, buffer, pos);
|
||||
buffer = newb;
|
||||
buffer_length = newl;
|
||||
}
|
||||
if (c == '\n') {
|
||||
// null terminate it, reset the pointer and process the line
|
||||
buffer[pos] = '\0';
|
||||
buffer_end = pos++;
|
||||
bufptr = buffer;
|
||||
process_command(CHECK);
|
||||
if (had_error()) {
|
||||
tty->print_cr("Error while parsing line %d: %s\n", line_no, _error_message);
|
||||
tty->print_cr("%s", buffer);
|
||||
assert(false, "error");
|
||||
return;
|
||||
}
|
||||
pos = 0;
|
||||
buffer_end = 0;
|
||||
line_no++;
|
||||
} else if (c == '\r') {
|
||||
// skip LF
|
||||
} else {
|
||||
buffer[pos++] = c;
|
||||
}
|
||||
c = getc(stream);
|
||||
}
|
||||
}
|
||||
|
||||
void process_command(TRAPS) {
|
||||
char* cmd = parse_string();
|
||||
if (cmd == NULL) {
|
||||
return;
|
||||
}
|
||||
if (strcmp("#", cmd) == 0) {
|
||||
// ignore
|
||||
} else if (strcmp("compile", cmd) == 0) {
|
||||
process_compile(CHECK);
|
||||
} else if (strcmp("ciMethod", cmd) == 0) {
|
||||
process_ciMethod(CHECK);
|
||||
} else if (strcmp("ciMethodData", cmd) == 0) {
|
||||
process_ciMethodData(CHECK);
|
||||
} else if (strcmp("staticfield", cmd) == 0) {
|
||||
process_staticfield(CHECK);
|
||||
} else if (strcmp("ciInstanceKlass", cmd) == 0) {
|
||||
process_ciInstanceKlass(CHECK);
|
||||
} else if (strcmp("instanceKlass", cmd) == 0) {
|
||||
process_instanceKlass(CHECK);
|
||||
#if INCLUDE_JVMTI
|
||||
} else if (strcmp("JvmtiExport", cmd) == 0) {
|
||||
process_JvmtiExport(CHECK);
|
||||
#endif // INCLUDE_JVMTI
|
||||
} else {
|
||||
report_error("unknown command");
|
||||
}
|
||||
}
|
||||
|
||||
// compile <klass> <name> <signature> <entry_bci>
|
||||
void process_compile(TRAPS) {
|
||||
// methodHandle method;
|
||||
Method* method = parse_method(CHECK);
|
||||
int entry_bci = parse_int("entry_bci");
|
||||
Klass* k = method->method_holder();
|
||||
((InstanceKlass*)k)->initialize(THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
oop throwable = PENDING_EXCEPTION;
|
||||
java_lang_Throwable::print(throwable, tty);
|
||||
tty->cr();
|
||||
if (ReplayIgnoreInitErrors) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
((InstanceKlass*)k)->set_init_state(InstanceKlass::fully_initialized);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Make sure the existence of a prior compile doesn't stop this one
|
||||
nmethod* nm = (entry_bci != InvocationEntryBci) ? method->lookup_osr_nmethod_for(entry_bci, CompLevel_full_optimization, true) : method->code();
|
||||
if (nm != NULL) {
|
||||
nm->make_not_entrant();
|
||||
}
|
||||
replay_state = this;
|
||||
CompileBroker::compile_method(method, entry_bci, CompLevel_full_optimization,
|
||||
methodHandle(), 0, "replay", THREAD);
|
||||
replay_state = NULL;
|
||||
reset();
|
||||
}
|
||||
|
||||
// ciMethod <klass> <name> <signature> <invocation_counter> <backedge_counter> <interpreter_invocation_count> <interpreter_throwout_count> <instructions_size>
|
||||
//
|
||||
//
|
||||
void process_ciMethod(TRAPS) {
|
||||
Method* method = parse_method(CHECK);
|
||||
ciMethodRecord* rec = new_ciMethod(method);
|
||||
rec->invocation_counter = parse_int("invocation_counter");
|
||||
rec->backedge_counter = parse_int("backedge_counter");
|
||||
rec->interpreter_invocation_count = parse_int("interpreter_invocation_count");
|
||||
rec->interpreter_throwout_count = parse_int("interpreter_throwout_count");
|
||||
rec->instructions_size = parse_int("instructions_size");
|
||||
}
|
||||
|
||||
// ciMethodData <klass> <name> <signature> <state> <current mileage> orig <length> # # ... data <length> # # ... oops <length>
|
||||
void process_ciMethodData(TRAPS) {
|
||||
Method* method = parse_method(CHECK);
|
||||
/* jsut copied from Method, to build interpret data*/
|
||||
if (InstanceRefKlass::owns_pending_list_lock((JavaThread*)THREAD)) {
|
||||
return;
|
||||
}
|
||||
// methodOopDesc::build_interpreter_method_data(method, CHECK);
|
||||
{
|
||||
// Grab a lock here to prevent multiple
|
||||
// MethodData*s from being created.
|
||||
MutexLocker ml(MethodData_lock, THREAD);
|
||||
if (method->method_data() == NULL) {
|
||||
ClassLoaderData* loader_data = method->method_holder()->class_loader_data();
|
||||
MethodData* method_data = MethodData::allocate(loader_data, method, CHECK);
|
||||
method->set_method_data(method_data);
|
||||
}
|
||||
}
|
||||
|
||||
// collect and record all the needed information for later
|
||||
ciMethodDataRecord* rec = new_ciMethodData(method);
|
||||
rec->state = parse_int("state");
|
||||
rec->current_mileage = parse_int("current_mileage");
|
||||
|
||||
rec->orig_data = parse_data("orig", rec->orig_data_length);
|
||||
if (rec->orig_data == NULL) {
|
||||
return;
|
||||
}
|
||||
rec->data = parse_intptr_data("data", rec->data_length);
|
||||
if (rec->data == NULL) {
|
||||
return;
|
||||
}
|
||||
if (!parse_tag_and_count("oops", rec->oops_length)) {
|
||||
return;
|
||||
}
|
||||
rec->oops_handles = NEW_RESOURCE_ARRAY(jobject, rec->oops_length);
|
||||
rec->oops_offsets = NEW_RESOURCE_ARRAY(int, rec->oops_length);
|
||||
for (int i = 0; i < rec->oops_length; i++) {
|
||||
int offset = parse_int("offset");
|
||||
if (had_error()) {
|
||||
return;
|
||||
}
|
||||
Klass* k = parse_klass(CHECK);
|
||||
rec->oops_offsets[i] = offset;
|
||||
rec->oops_handles[i] = (jobject)(new KlassHandle(THREAD, k));
|
||||
}
|
||||
}
|
||||
|
||||
// instanceKlass <name>
|
||||
//
|
||||
// Loads and initializes the klass 'name'. This can be used to
|
||||
// create particular class loading environments
|
||||
void process_instanceKlass(TRAPS) {
|
||||
// just load the referenced class
|
||||
Klass* k = parse_klass(CHECK);
|
||||
}
|
||||
|
||||
// ciInstanceKlass <name> <is_linked> <is_initialized> <length> tag # # # ...
|
||||
//
|
||||
// Load the klass 'name' and link or initialize it. Verify that the
|
||||
// constant pool is the same length as 'length' and make sure the
|
||||
// constant pool tags are in the same state.
|
||||
void process_ciInstanceKlass(TRAPS) {
|
||||
InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
|
||||
int is_linked = parse_int("is_linked");
|
||||
int is_initialized = parse_int("is_initialized");
|
||||
int length = parse_int("length");
|
||||
if (is_initialized) {
|
||||
k->initialize(THREAD);
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
oop throwable = PENDING_EXCEPTION;
|
||||
java_lang_Throwable::print(throwable, tty);
|
||||
tty->cr();
|
||||
if (ReplayIgnoreInitErrors) {
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
k->set_init_state(InstanceKlass::fully_initialized);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else if (is_linked) {
|
||||
k->link_class(CHECK);
|
||||
}
|
||||
ConstantPool* cp = k->constants();
|
||||
if (length != cp->length()) {
|
||||
report_error("constant pool length mismatch: wrong class files?");
|
||||
return;
|
||||
}
|
||||
|
||||
int parsed_two_word = 0;
|
||||
for (int i = 1; i < length; i++) {
|
||||
int tag = parse_int("tag");
|
||||
if (had_error()) {
|
||||
return;
|
||||
}
|
||||
switch (cp->tag_at(i).value()) {
|
||||
case JVM_CONSTANT_UnresolvedClass: {
|
||||
if (tag == JVM_CONSTANT_Class) {
|
||||
tty->print_cr("Resolving klass %s at %d", cp->unresolved_klass_at(i)->as_utf8(), i);
|
||||
Klass* k = cp->klass_at(i, CHECK);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case JVM_CONSTANT_Long:
|
||||
case JVM_CONSTANT_Double:
|
||||
parsed_two_word = i + 1;
|
||||
|
||||
case JVM_CONSTANT_ClassIndex:
|
||||
case JVM_CONSTANT_StringIndex:
|
||||
case JVM_CONSTANT_String:
|
||||
case JVM_CONSTANT_UnresolvedClassInError:
|
||||
case JVM_CONSTANT_Fieldref:
|
||||
case JVM_CONSTANT_Methodref:
|
||||
case JVM_CONSTANT_InterfaceMethodref:
|
||||
case JVM_CONSTANT_NameAndType:
|
||||
case JVM_CONSTANT_Utf8:
|
||||
case JVM_CONSTANT_Integer:
|
||||
case JVM_CONSTANT_Float:
|
||||
if (tag != cp->tag_at(i).value()) {
|
||||
report_error("tag mismatch: wrong class files?");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case JVM_CONSTANT_Class:
|
||||
if (tag == JVM_CONSTANT_Class) {
|
||||
} else if (tag == JVM_CONSTANT_UnresolvedClass) {
|
||||
tty->print_cr("Warning: entry was unresolved in the replay data");
|
||||
} else {
|
||||
report_error("Unexpected tag");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0:
|
||||
if (parsed_two_word == i) continue;
|
||||
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize a class and fill in the value for a static field.
|
||||
// This is useful when the compile was dependent on the value of
|
||||
// static fields but it's impossible to properly rerun the static
|
||||
// initiailizer.
|
||||
void process_staticfield(TRAPS) {
|
||||
InstanceKlass* k = (InstanceKlass *)parse_klass(CHECK);
|
||||
|
||||
if (ReplaySuppressInitializers == 0 ||
|
||||
ReplaySuppressInitializers == 2 && k->class_loader() == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
assert(k->is_initialized(), "must be");
|
||||
|
||||
const char* field_name = parse_escaped_string();;
|
||||
const char* field_signature = parse_string();
|
||||
fieldDescriptor fd;
|
||||
Symbol* name = SymbolTable::lookup(field_name, (int)strlen(field_name), CHECK);
|
||||
Symbol* sig = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK);
|
||||
if (!k->find_local_field(name, sig, &fd) ||
|
||||
!fd.is_static() ||
|
||||
fd.has_initial_value()) {
|
||||
report_error(field_name);
|
||||
return;
|
||||
}
|
||||
|
||||
oop java_mirror = k->java_mirror();
|
||||
if (field_signature[0] == '[') {
|
||||
int length = parse_int("array length");
|
||||
oop value = NULL;
|
||||
|
||||
if (field_signature[1] == '[') {
|
||||
// multi dimensional array
|
||||
ArrayKlass* kelem = (ArrayKlass *)parse_klass(CHECK);
|
||||
int rank = 0;
|
||||
while (field_signature[rank] == '[') {
|
||||
rank++;
|
||||
}
|
||||
int* dims = NEW_RESOURCE_ARRAY(int, rank);
|
||||
dims[0] = length;
|
||||
for (int i = 1; i < rank; i++) {
|
||||
dims[i] = 1; // These aren't relevant to the compiler
|
||||
}
|
||||
value = kelem->multi_allocate(rank, dims, CHECK);
|
||||
} else {
|
||||
if (strcmp(field_signature, "[B") == 0) {
|
||||
value = oopFactory::new_byteArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[Z") == 0) {
|
||||
value = oopFactory::new_boolArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[C") == 0) {
|
||||
value = oopFactory::new_charArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[S") == 0) {
|
||||
value = oopFactory::new_shortArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[F") == 0) {
|
||||
value = oopFactory::new_singleArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[D") == 0) {
|
||||
value = oopFactory::new_doubleArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[I") == 0) {
|
||||
value = oopFactory::new_intArray(length, CHECK);
|
||||
} else if (strcmp(field_signature, "[J") == 0) {
|
||||
value = oopFactory::new_longArray(length, CHECK);
|
||||
} else if (field_signature[0] == '[' && field_signature[1] == 'L') {
|
||||
KlassHandle kelem = resolve_klass(field_signature + 1, CHECK);
|
||||
value = oopFactory::new_objArray(kelem(), length, CHECK);
|
||||
} else {
|
||||
report_error("unhandled array staticfield");
|
||||
}
|
||||
}
|
||||
java_mirror->obj_field_put(fd.offset(), value);
|
||||
} else {
|
||||
const char* string_value = parse_escaped_string();
|
||||
if (strcmp(field_signature, "I") == 0) {
|
||||
int value = atoi(string_value);
|
||||
java_mirror->int_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "B") == 0) {
|
||||
int value = atoi(string_value);
|
||||
java_mirror->byte_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "C") == 0) {
|
||||
int value = atoi(string_value);
|
||||
java_mirror->char_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "S") == 0) {
|
||||
int value = atoi(string_value);
|
||||
java_mirror->short_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "Z") == 0) {
|
||||
int value = atol(string_value);
|
||||
java_mirror->bool_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "J") == 0) {
|
||||
jlong value;
|
||||
if (sscanf(string_value, INT64_FORMAT, &value) != 1) {
|
||||
fprintf(stderr, "Error parsing long: %s\n", string_value);
|
||||
return;
|
||||
}
|
||||
java_mirror->long_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "F") == 0) {
|
||||
float value = atof(string_value);
|
||||
java_mirror->float_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "D") == 0) {
|
||||
double value = atof(string_value);
|
||||
java_mirror->double_field_put(fd.offset(), value);
|
||||
} else if (strcmp(field_signature, "Ljava/lang/String;") == 0) {
|
||||
Handle value = java_lang_String::create_from_str(string_value, CHECK);
|
||||
java_mirror->obj_field_put(fd.offset(), value());
|
||||
} else if (field_signature[0] == 'L') {
|
||||
Symbol* klass_name = SymbolTable::lookup(field_signature, (int)strlen(field_signature), CHECK);
|
||||
KlassHandle kelem = resolve_klass(field_signature, CHECK);
|
||||
oop value = ((InstanceKlass*)kelem())->allocate_instance(CHECK);
|
||||
java_mirror->obj_field_put(fd.offset(), value);
|
||||
} else {
|
||||
report_error("unhandled staticfield");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if INCLUDE_JVMTI
|
||||
void process_JvmtiExport(TRAPS) {
|
||||
const char* field = parse_string();
|
||||
bool value = parse_int("JvmtiExport flag") != 0;
|
||||
if (strcmp(field, "can_access_local_variables") == 0) {
|
||||
JvmtiExport::set_can_access_local_variables(value);
|
||||
} else if (strcmp(field, "can_hotswap_or_post_breakpoint") == 0) {
|
||||
JvmtiExport::set_can_hotswap_or_post_breakpoint(value);
|
||||
} else if (strcmp(field, "can_post_on_exceptions") == 0) {
|
||||
JvmtiExport::set_can_post_on_exceptions(value);
|
||||
} else {
|
||||
report_error("Unrecognized JvmtiExport directive");
|
||||
}
|
||||
}
|
||||
#endif // INCLUDE_JVMTI
|
||||
|
||||
// Create and initialize a record for a ciMethod
|
||||
ciMethodRecord* new_ciMethod(Method* method) {
|
||||
ciMethodRecord* rec = NEW_RESOURCE_OBJ(ciMethodRecord);
|
||||
rec->klass = method->method_holder()->name()->as_utf8();
|
||||
rec->method = method->name()->as_utf8();
|
||||
rec->signature = method->signature()->as_utf8();
|
||||
ci_method_records.append(rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
// Lookup data for a ciMethod
|
||||
ciMethodRecord* find_ciMethodRecord(Method* method) {
|
||||
const char* klass_name = method->method_holder()->name()->as_utf8();
|
||||
const char* method_name = method->name()->as_utf8();
|
||||
const char* signature = method->signature()->as_utf8();
|
||||
for (int i = 0; i < ci_method_records.length(); i++) {
|
||||
ciMethodRecord* rec = ci_method_records.at(i);
|
||||
if (strcmp(rec->klass, klass_name) == 0 &&
|
||||
strcmp(rec->method, method_name) == 0 &&
|
||||
strcmp(rec->signature, signature) == 0) {
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create and initialize a record for a ciMethodData
|
||||
ciMethodDataRecord* new_ciMethodData(Method* method) {
|
||||
ciMethodDataRecord* rec = NEW_RESOURCE_OBJ(ciMethodDataRecord);
|
||||
rec->klass = method->method_holder()->name()->as_utf8();
|
||||
rec->method = method->name()->as_utf8();
|
||||
rec->signature = method->signature()->as_utf8();
|
||||
ci_method_data_records.append(rec);
|
||||
return rec;
|
||||
}
|
||||
|
||||
// Lookup data for a ciMethodData
|
||||
ciMethodDataRecord* find_ciMethodDataRecord(Method* method) {
|
||||
const char* klass_name = method->method_holder()->name()->as_utf8();
|
||||
const char* method_name = method->name()->as_utf8();
|
||||
const char* signature = method->signature()->as_utf8();
|
||||
for (int i = 0; i < ci_method_data_records.length(); i++) {
|
||||
ciMethodDataRecord* rec = ci_method_data_records.at(i);
|
||||
if (strcmp(rec->klass, klass_name) == 0 &&
|
||||
strcmp(rec->method, method_name) == 0 &&
|
||||
strcmp(rec->signature, signature) == 0) {
|
||||
return rec;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char* error_message() {
|
||||
return _error_message;
|
||||
}
|
||||
|
||||
void reset() {
|
||||
_error_message = NULL;
|
||||
ci_method_records.clear();
|
||||
ci_method_data_records.clear();
|
||||
}
|
||||
|
||||
// Take an ascii string contain \u#### escapes and convert it to utf8
|
||||
// in place.
|
||||
static void unescape_string(char* value) {
|
||||
char* from = value;
|
||||
char* to = value;
|
||||
while (*from != '\0') {
|
||||
if (*from != '\\') {
|
||||
*from++ = *to++;
|
||||
} else {
|
||||
switch (from[1]) {
|
||||
case 'u': {
|
||||
from += 2;
|
||||
jchar value=0;
|
||||
for (int i=0; i<4; i++) {
|
||||
char c = *from++;
|
||||
switch (c) {
|
||||
case '0': case '1': case '2': case '3': case '4':
|
||||
case '5': case '6': case '7': case '8': case '9':
|
||||
value = (value << 4) + c - '0';
|
||||
break;
|
||||
case 'a': case 'b': case 'c':
|
||||
case 'd': case 'e': case 'f':
|
||||
value = (value << 4) + 10 + c - 'a';
|
||||
break;
|
||||
case 'A': case 'B': case 'C':
|
||||
case 'D': case 'E': case 'F':
|
||||
value = (value << 4) + 10 + c - 'A';
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
UNICODE::convert_to_utf8(&value, 1, to);
|
||||
to++;
|
||||
break;
|
||||
}
|
||||
case 't': *to++ = '\t'; from += 2; break;
|
||||
case 'n': *to++ = '\n'; from += 2; break;
|
||||
case 'r': *to++ = '\r'; from += 2; break;
|
||||
case 'f': *to++ = '\f'; from += 2; break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
}
|
||||
*from = *to;
|
||||
}
|
||||
};
|
||||
|
||||
void ciReplay::replay(TRAPS) {
|
||||
int exit_code = replay_impl(THREAD);
|
||||
|
||||
Threads::destroy_vm();
|
||||
|
||||
vm_exit(exit_code);
|
||||
}
|
||||
|
||||
int ciReplay::replay_impl(TRAPS) {
|
||||
HandleMark hm;
|
||||
ResourceMark rm;
|
||||
// Make sure we don't run with background compilation
|
||||
BackgroundCompilation = false;
|
||||
|
||||
if (ReplaySuppressInitializers > 2) {
|
||||
// ReplaySuppressInitializers > 2 means that we want to allow
|
||||
// normal VM bootstrap but once we get into the replay itself
|
||||
// don't allow any intializers to be run.
|
||||
ReplaySuppressInitializers = 1;
|
||||
}
|
||||
|
||||
// Load and parse the replay data
|
||||
CompileReplay rp(ReplayDataFile, THREAD);
|
||||
int exit_code = 0;
|
||||
if (rp.can_replay()) {
|
||||
rp.process(THREAD);
|
||||
} else {
|
||||
exit_code = 1;
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
if (HAS_PENDING_EXCEPTION) {
|
||||
oop throwable = PENDING_EXCEPTION;
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
java_lang_Throwable::print(throwable, tty);
|
||||
tty->cr();
|
||||
java_lang_Throwable::print_stack_trace(throwable, tty);
|
||||
tty->cr();
|
||||
exit_code = 2;
|
||||
}
|
||||
|
||||
if (rp.had_error()) {
|
||||
tty->print_cr("Failed on %s", rp.error_message());
|
||||
exit_code = 1;
|
||||
}
|
||||
return exit_code;
|
||||
}
|
||||
|
||||
|
||||
void ciReplay::initialize(ciMethodData* m) {
|
||||
if (replay_state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_IN_VM;
|
||||
ResourceMark rm;
|
||||
|
||||
Method* method = m->get_MethodData()->method();
|
||||
ciMethodDataRecord* rec = replay_state->find_ciMethodDataRecord(method);
|
||||
if (rec == NULL) {
|
||||
// This indicates some mismatch with the original environment and
|
||||
// the replay environment though it's not always enough to
|
||||
// interfere with reproducing a bug
|
||||
tty->print_cr("Warning: requesting ciMethodData record for method with no data: ");
|
||||
method->print_name(tty);
|
||||
tty->cr();
|
||||
} else {
|
||||
m->_state = rec->state;
|
||||
m->_current_mileage = rec->current_mileage;
|
||||
if (rec->data_length != 0) {
|
||||
assert(m->_data_size == rec->data_length * (int)sizeof(rec->data[0]), "must agree");
|
||||
|
||||
// Write the correct ciObjects back into the profile data
|
||||
ciEnv* env = ciEnv::current();
|
||||
for (int i = 0; i < rec->oops_length; i++) {
|
||||
KlassHandle *h = (KlassHandle *)rec->oops_handles[i];
|
||||
*(ciMetadata**)(rec->data + rec->oops_offsets[i]) =
|
||||
env->get_metadata((*h)());
|
||||
}
|
||||
// Copy the updated profile data into place as intptr_ts
|
||||
#ifdef _LP64
|
||||
Copy::conjoint_jlongs_atomic((jlong *)rec->data, (jlong *)m->_data, rec->data_length);
|
||||
#else
|
||||
Copy::conjoint_jints_atomic((jint *)rec->data, (jint *)m->_data, rec->data_length);
|
||||
#endif
|
||||
}
|
||||
|
||||
// copy in the original header
|
||||
Copy::conjoint_jbytes(rec->orig_data, (char*)&m->_orig, rec->orig_data_length);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool ciReplay::should_not_inline(ciMethod* method) {
|
||||
if (replay_state == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
VM_ENTRY_MARK;
|
||||
// ciMethod without a record shouldn't be inlined.
|
||||
return replay_state->find_ciMethodRecord(method->get_Method()) == NULL;
|
||||
}
|
||||
|
||||
|
||||
void ciReplay::initialize(ciMethod* m) {
|
||||
if (replay_state == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
ASSERT_IN_VM;
|
||||
ResourceMark rm;
|
||||
|
||||
Method* method = m->get_Method();
|
||||
ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
|
||||
if (rec == NULL) {
|
||||
// This indicates some mismatch with the original environment and
|
||||
// the replay environment though it's not always enough to
|
||||
// interfere with reproducing a bug
|
||||
tty->print_cr("Warning: requesting ciMethod record for method with no data: ");
|
||||
method->print_name(tty);
|
||||
tty->cr();
|
||||
} else {
|
||||
// m->_instructions_size = rec->instructions_size;
|
||||
m->_instructions_size = -1;
|
||||
m->_interpreter_invocation_count = rec->interpreter_invocation_count;
|
||||
m->_interpreter_throwout_count = rec->interpreter_throwout_count;
|
||||
method->invocation_counter()->_counter = rec->invocation_counter;
|
||||
method->backedge_counter()->_counter = rec->backedge_counter;
|
||||
}
|
||||
}
|
||||
|
||||
bool ciReplay::is_loaded(Method* method) {
|
||||
if (replay_state == NULL) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ASSERT_IN_VM;
|
||||
ResourceMark rm;
|
||||
|
||||
ciMethodRecord* rec = replay_state->find_ciMethodRecord(method);
|
||||
return rec != NULL;
|
||||
}
|
||||
#endif
|
||||
55
hotspot/src/share/vm/ci/ciReplay.hpp
Normal file
55
hotspot/src/share/vm/ci/ciReplay.hpp
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CI_CIREPLAY_HPP
|
||||
#define SHARE_VM_CI_CIREPLAY_HPP
|
||||
|
||||
#include "ci/ciMethod.hpp"
|
||||
|
||||
// ciReplay
|
||||
|
||||
class ciReplay {
|
||||
CI_PACKAGE_ACCESS
|
||||
|
||||
#ifdef ASSERT
|
||||
private:
|
||||
static int replay_impl(TRAPS);
|
||||
|
||||
public:
|
||||
static void replay(TRAPS);
|
||||
|
||||
// These are used by the CI to fill in the cached data from the
|
||||
// replay file when replaying compiles.
|
||||
static void initialize(ciMethodData* method);
|
||||
static void initialize(ciMethod* method);
|
||||
|
||||
static bool is_loaded(Method* method);
|
||||
static bool is_loaded(Klass* klass);
|
||||
|
||||
static bool should_not_inline(ciMethod* method);
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CI_CIREPLAY_HPP
|
||||
@ -63,6 +63,11 @@ const char* ciSymbol::as_utf8() {
|
||||
return s->as_utf8();
|
||||
}
|
||||
|
||||
// The text of the symbol as a null-terminated C string.
|
||||
const char* ciSymbol::as_quoted_ascii() {
|
||||
GUARDED_VM_QUICK_ENTRY(return get_symbol()->as_quoted_ascii();)
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciSymbol::base
|
||||
const jbyte* ciSymbol::base() {
|
||||
|
||||
@ -73,6 +73,9 @@ public:
|
||||
const char* as_utf8();
|
||||
int utf8_length();
|
||||
|
||||
// The text of the symbol as ascii with all non-printable characters quoted as \u####
|
||||
const char* as_quoted_ascii();
|
||||
|
||||
// Return the i-th utf8 byte, where i < utf8_length
|
||||
int byte_at(int i);
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ ciType::ciType(BasicType basic_type) : ciMetadata() {
|
||||
}
|
||||
|
||||
ciType::ciType(KlassHandle k) : ciMetadata(k()) {
|
||||
_basic_type = Klass::cast(k())->oop_is_array() ? T_ARRAY : T_OBJECT;
|
||||
_basic_type = k()->oop_is_array() ? T_ARRAY : T_OBJECT;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1999, 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
|
||||
@ -80,6 +80,9 @@
|
||||
#define GUARDED_VM_ENTRY(action) \
|
||||
{if (IS_IN_VM) { action } else { VM_ENTRY_MARK; { action }}}
|
||||
|
||||
#define GUARDED_VM_QUICK_ENTRY(action) \
|
||||
{if (IS_IN_VM) { action } else { VM_QUICK_ENTRY_MARK; { action }}}
|
||||
|
||||
// Redefine this later.
|
||||
#define KILL_COMPILE_ON_FATAL_(result) \
|
||||
THREAD); \
|
||||
|
||||
269
hotspot/src/share/vm/classfile/bytecodeAssembler.cpp
Normal file
269
hotspot/src/share/vm/classfile/bytecodeAssembler.cpp
Normal file
@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
|
||||
#include "classfile/bytecodeAssembler.hpp"
|
||||
#include "interpreter/bytecodes.hpp"
|
||||
#include "memory/oopFactory.hpp"
|
||||
#include "oops/constantPool.hpp"
|
||||
|
||||
#ifdef TARGET_ARCH_x86
|
||||
# include "bytes_x86.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_sparc
|
||||
# include "bytes_sparc.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_zero
|
||||
# include "bytes_zero.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_arm
|
||||
# include "bytes_arm.hpp"
|
||||
#endif
|
||||
#ifdef TARGET_ARCH_ppc
|
||||
# include "bytes_ppc.hpp"
|
||||
#endif
|
||||
|
||||
u2 BytecodeConstantPool::find_or_add(BytecodeCPEntry const& bcpe) {
|
||||
u2 index;
|
||||
u2* probe = _indices.get(bcpe);
|
||||
if (probe == NULL) {
|
||||
index = _entries.length();
|
||||
_entries.append(bcpe);
|
||||
_indices.put(bcpe, index);
|
||||
} else {
|
||||
index = *probe;
|
||||
}
|
||||
return index + _orig->length();
|
||||
}
|
||||
|
||||
ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const {
|
||||
if (_entries.length() == 0) {
|
||||
return _orig;
|
||||
}
|
||||
|
||||
ConstantPool* cp = ConstantPool::allocate(
|
||||
_orig->pool_holder()->class_loader_data(),
|
||||
_orig->length() + _entries.length(), CHECK_NULL);
|
||||
|
||||
cp->set_pool_holder(_orig->pool_holder());
|
||||
_orig->copy_cp_to(1, _orig->length() - 1, cp, 1, CHECK_NULL);
|
||||
|
||||
for (int i = 0; i < _entries.length(); ++i) {
|
||||
BytecodeCPEntry entry = _entries.at(i);
|
||||
int idx = i + _orig->length();
|
||||
switch (entry._tag) {
|
||||
case BytecodeCPEntry::UTF8:
|
||||
cp->symbol_at_put(idx, entry._u.utf8);
|
||||
entry._u.utf8->increment_refcount();
|
||||
break;
|
||||
case BytecodeCPEntry::KLASS:
|
||||
cp->unresolved_klass_at_put(
|
||||
idx, cp->symbol_at(entry._u.klass));
|
||||
break;
|
||||
case BytecodeCPEntry::STRING:
|
||||
cp->unresolved_string_at_put(
|
||||
idx, cp->symbol_at(entry._u.string));
|
||||
break;
|
||||
case BytecodeCPEntry::NAME_AND_TYPE:
|
||||
cp->name_and_type_at_put(idx,
|
||||
entry._u.name_and_type.name_index,
|
||||
entry._u.name_and_type.type_index);
|
||||
break;
|
||||
case BytecodeCPEntry::METHODREF:
|
||||
cp->method_at_put(idx,
|
||||
entry._u.methodref.class_index,
|
||||
entry._u.methodref.name_and_type_index);
|
||||
break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
return cp;
|
||||
}
|
||||
|
||||
void BytecodeAssembler::append(u1 imm_u1) {
|
||||
_code->append(imm_u1);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::append(u2 imm_u2) {
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
Bytes::put_Java_u2(_code->adr_at(_code->length() - 2), imm_u2);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::append(u4 imm_u4) {
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
_code->append(0);
|
||||
Bytes::put_Java_u4(_code->adr_at(_code->length() - 4), imm_u4);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::xload(u4 index, u1 onebyteop, u1 twobyteop) {
|
||||
if (index < 4) {
|
||||
_code->append(onebyteop + index);
|
||||
} else {
|
||||
_code->append(twobyteop);
|
||||
_code->append((u2)index);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeAssembler::dup() {
|
||||
_code->append(Bytecodes::_dup);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::_new(Symbol* sym) {
|
||||
u2 cpool_index = _cp->klass(sym);
|
||||
_code->append(Bytecodes::_new);
|
||||
append(cpool_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::load_string(Symbol* sym) {
|
||||
u2 cpool_index = _cp->string(sym);
|
||||
if (cpool_index < 0x100) {
|
||||
ldc(cpool_index);
|
||||
} else {
|
||||
ldc_w(cpool_index);
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeAssembler::ldc(u1 index) {
|
||||
_code->append(Bytecodes::_ldc);
|
||||
append(index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::ldc_w(u2 index) {
|
||||
_code->append(Bytecodes::_ldc_w);
|
||||
append(index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::athrow() {
|
||||
_code->append(Bytecodes::_athrow);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::iload(u4 index) {
|
||||
xload(index, Bytecodes::_iload_0, Bytecodes::_iload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::lload(u4 index) {
|
||||
xload(index, Bytecodes::_lload_0, Bytecodes::_lload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::fload(u4 index) {
|
||||
xload(index, Bytecodes::_fload_0, Bytecodes::_fload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::dload(u4 index) {
|
||||
xload(index, Bytecodes::_dload_0, Bytecodes::_dload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::aload(u4 index) {
|
||||
xload(index, Bytecodes::_aload_0, Bytecodes::_aload);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::load(BasicType bt, u4 index) {
|
||||
switch (bt) {
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
case T_INT: iload(index); break;
|
||||
case T_FLOAT: fload(index); break;
|
||||
case T_DOUBLE: dload(index); break;
|
||||
case T_LONG: lload(index); break;
|
||||
case T_OBJECT:
|
||||
case T_ARRAY: aload(index); break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
|
||||
void BytecodeAssembler::checkcast(Symbol* sym) {
|
||||
u2 cpool_index = _cp->klass(sym);
|
||||
_code->append(Bytecodes::_checkcast);
|
||||
append(cpool_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokespecial(Method* method) {
|
||||
invokespecial(method->klass_name(), method->name(), method->signature());
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokespecial(Symbol* klss, Symbol* name, Symbol* sig) {
|
||||
u2 methodref_index = _cp->methodref(klss, name, sig);
|
||||
_code->append(Bytecodes::_invokespecial);
|
||||
append(methodref_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokevirtual(Method* method) {
|
||||
invokevirtual(method->klass_name(), method->name(), method->signature());
|
||||
}
|
||||
|
||||
void BytecodeAssembler::invokevirtual(Symbol* klss, Symbol* name, Symbol* sig) {
|
||||
u2 methodref_index = _cp->methodref(klss, name, sig);
|
||||
_code->append(Bytecodes::_invokevirtual);
|
||||
append(methodref_index);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::ireturn() {
|
||||
_code->append(Bytecodes::_ireturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::lreturn() {
|
||||
_code->append(Bytecodes::_lreturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::freturn() {
|
||||
_code->append(Bytecodes::_freturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::dreturn() {
|
||||
_code->append(Bytecodes::_dreturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::areturn() {
|
||||
_code->append(Bytecodes::_areturn);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::_return() {
|
||||
_code->append(Bytecodes::_return);
|
||||
}
|
||||
|
||||
void BytecodeAssembler::_return(BasicType bt) {
|
||||
switch (bt) {
|
||||
case T_BOOLEAN:
|
||||
case T_CHAR:
|
||||
case T_BYTE:
|
||||
case T_SHORT:
|
||||
case T_INT: ireturn(); break;
|
||||
case T_FLOAT: freturn(); break;
|
||||
case T_DOUBLE: dreturn(); break;
|
||||
case T_LONG: lreturn(); break;
|
||||
case T_OBJECT:
|
||||
case T_ARRAY: areturn(); break;
|
||||
case T_VOID: _return(); break;
|
||||
default:
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
214
hotspot/src/share/vm/classfile/bytecodeAssembler.hpp
Normal file
214
hotspot/src/share/vm/classfile/bytecodeAssembler.hpp
Normal file
@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
|
||||
#define SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
|
||||
|
||||
#include "memory/allocation.hpp"
|
||||
#include "oops/method.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
|
||||
/**
|
||||
* Bytecode Assembler
|
||||
*
|
||||
* These classes are used to synthesize code for creating new methods from
|
||||
* within the VM. This is only a partial implementation of an assembler;
|
||||
* only the bytecodes that are needed by clients are implemented at this time.
|
||||
* This is used during default method analysis to create overpass methods
|
||||
* and add them to a call during parsing. Other uses (such as creating
|
||||
* bridges) may come later. Any missing bytecodes can be implemented on an
|
||||
* as-need basis.
|
||||
*/
|
||||
|
||||
class BytecodeBuffer : public GrowableArray<u1> {
|
||||
public:
|
||||
BytecodeBuffer() : GrowableArray<u1>(20) {}
|
||||
};
|
||||
|
||||
// Entries in a yet-to-be-created constant pool. Limited types for now.
|
||||
class BytecodeCPEntry VALUE_OBJ_CLASS_SPEC {
|
||||
public:
|
||||
enum tag {
|
||||
ERROR_TAG,
|
||||
UTF8,
|
||||
KLASS,
|
||||
STRING,
|
||||
NAME_AND_TYPE,
|
||||
METHODREF
|
||||
};
|
||||
|
||||
u1 _tag;
|
||||
union {
|
||||
Symbol* utf8;
|
||||
u2 klass;
|
||||
u2 string;
|
||||
struct {
|
||||
u2 name_index;
|
||||
u2 type_index;
|
||||
} name_and_type;
|
||||
struct {
|
||||
u2 class_index;
|
||||
u2 name_and_type_index;
|
||||
} methodref;
|
||||
uintptr_t hash;
|
||||
} _u;
|
||||
|
||||
BytecodeCPEntry() : _tag(ERROR_TAG) { _u.hash = 0; }
|
||||
BytecodeCPEntry(u1 tag) : _tag(tag) { _u.hash = 0; }
|
||||
|
||||
static BytecodeCPEntry utf8(Symbol* symbol) {
|
||||
BytecodeCPEntry bcpe(UTF8);
|
||||
bcpe._u.utf8 = symbol;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry klass(u2 index) {
|
||||
BytecodeCPEntry bcpe(KLASS);
|
||||
bcpe._u.klass = index;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry string(u2 index) {
|
||||
BytecodeCPEntry bcpe(STRING);
|
||||
bcpe._u.string = index;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry name_and_type(u2 name, u2 type) {
|
||||
BytecodeCPEntry bcpe(NAME_AND_TYPE);
|
||||
bcpe._u.name_and_type.name_index = name;
|
||||
bcpe._u.name_and_type.type_index = type;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static BytecodeCPEntry methodref(u2 class_index, u2 nat) {
|
||||
BytecodeCPEntry bcpe(METHODREF);
|
||||
bcpe._u.methodref.class_index = class_index;
|
||||
bcpe._u.methodref.name_and_type_index = nat;
|
||||
return bcpe;
|
||||
}
|
||||
|
||||
static bool equals(BytecodeCPEntry const& e0, BytecodeCPEntry const& e1) {
|
||||
return e0._tag == e1._tag && e0._u.hash == e1._u.hash;
|
||||
}
|
||||
|
||||
static unsigned hash(BytecodeCPEntry const& e0) {
|
||||
return (unsigned)(e0._tag ^ e0._u.hash);
|
||||
}
|
||||
};
|
||||
|
||||
class BytecodeConstantPool : ResourceObj {
|
||||
private:
|
||||
typedef ResourceHashtable<BytecodeCPEntry, u2,
|
||||
&BytecodeCPEntry::hash, &BytecodeCPEntry::equals> IndexHash;
|
||||
|
||||
ConstantPool* _orig;
|
||||
GrowableArray<BytecodeCPEntry> _entries;
|
||||
IndexHash _indices;
|
||||
|
||||
u2 find_or_add(BytecodeCPEntry const& bcpe);
|
||||
|
||||
public:
|
||||
|
||||
BytecodeConstantPool(ConstantPool* orig) : _orig(orig) {}
|
||||
|
||||
BytecodeCPEntry const& at(u2 index) const { return _entries.at(index); }
|
||||
|
||||
InstanceKlass* pool_holder() const {
|
||||
return InstanceKlass::cast(_orig->pool_holder());
|
||||
}
|
||||
|
||||
u2 utf8(Symbol* sym) {
|
||||
return find_or_add(BytecodeCPEntry::utf8(sym));
|
||||
}
|
||||
|
||||
u2 klass(Symbol* class_name) {
|
||||
return find_or_add(BytecodeCPEntry::klass(utf8(class_name)));
|
||||
}
|
||||
|
||||
u2 string(Symbol* str) {
|
||||
return find_or_add(BytecodeCPEntry::string(utf8(str)));
|
||||
}
|
||||
|
||||
u2 name_and_type(Symbol* name, Symbol* sig) {
|
||||
return find_or_add(BytecodeCPEntry::name_and_type(utf8(name), utf8(sig)));
|
||||
}
|
||||
|
||||
u2 methodref(Symbol* class_name, Symbol* name, Symbol* sig) {
|
||||
return find_or_add(BytecodeCPEntry::methodref(
|
||||
klass(class_name), name_and_type(name, sig)));
|
||||
}
|
||||
|
||||
ConstantPool* create_constant_pool(TRAPS) const;
|
||||
};
|
||||
|
||||
// Partial bytecode assembler - only what we need for creating
|
||||
// overpass methods for default methods is implemented
|
||||
class BytecodeAssembler : StackObj {
|
||||
private:
|
||||
BytecodeBuffer* _code;
|
||||
BytecodeConstantPool* _cp;
|
||||
|
||||
void append(u1 imm_u1);
|
||||
void append(u2 imm_u2);
|
||||
void append(u4 imm_u4);
|
||||
|
||||
void xload(u4 index, u1 quick, u1 twobyte);
|
||||
|
||||
public:
|
||||
BytecodeAssembler(BytecodeBuffer* buffer, BytecodeConstantPool* cp)
|
||||
: _code(buffer), _cp(cp) {}
|
||||
|
||||
void aload(u4 index);
|
||||
void areturn();
|
||||
void athrow();
|
||||
void checkcast(Symbol* sym);
|
||||
void dload(u4 index);
|
||||
void dreturn();
|
||||
void dup();
|
||||
void fload(u4 index);
|
||||
void freturn();
|
||||
void iload(u4 index);
|
||||
void invokespecial(Method* method);
|
||||
void invokespecial(Symbol* cls, Symbol* name, Symbol* sig);
|
||||
void invokevirtual(Method* method);
|
||||
void invokevirtual(Symbol* cls, Symbol* name, Symbol* sig);
|
||||
void ireturn();
|
||||
void ldc(u1 index);
|
||||
void ldc_w(u2 index);
|
||||
void lload(u4 index);
|
||||
void lreturn();
|
||||
void _new(Symbol* sym);
|
||||
void _return();
|
||||
|
||||
void load_string(Symbol* sym);
|
||||
void load(BasicType bt, u4 index);
|
||||
void _return(BasicType bt);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_BYTECODEASSEMBLER_HPP
|
||||
@ -27,6 +27,8 @@
|
||||
#include "classfile/classLoader.hpp"
|
||||
#include "classfile/classLoaderData.hpp"
|
||||
#include "classfile/classLoaderData.inline.hpp"
|
||||
#include "classfile/defaultMethods.hpp"
|
||||
#include "classfile/genericSignatures.hpp"
|
||||
#include "classfile/javaClasses.hpp"
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
@ -84,6 +86,9 @@
|
||||
// - to check NameAndType_info signatures more aggressively
|
||||
#define JAVA_7_VERSION 51
|
||||
|
||||
// Extension method support.
|
||||
#define JAVA_8_VERSION 52
|
||||
|
||||
|
||||
void ClassFileParser::parse_constant_pool_entries(ClassLoaderData* loader_data, constantPoolHandle cp, int length, TRAPS) {
|
||||
// Use a local copy of ClassFileStream. It helps the C++ compiler to optimize
|
||||
@ -785,6 +790,7 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
|
||||
ClassLoaderData* loader_data,
|
||||
Handle protection_domain,
|
||||
Symbol* class_name,
|
||||
bool* has_default_methods,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
assert(length > 0, "only called for length>0");
|
||||
@ -818,9 +824,12 @@ Array<Klass*>* ClassFileParser::parse_interfaces(constantPoolHandle cp,
|
||||
interf = KlassHandle(THREAD, k);
|
||||
}
|
||||
|
||||
if (!Klass::cast(interf())->is_interface()) {
|
||||
if (!interf()->is_interface()) {
|
||||
THROW_MSG_(vmSymbols::java_lang_IncompatibleClassChangeError(), "Implementing class", NULL);
|
||||
}
|
||||
if (InstanceKlass::cast(interf())->has_default_methods()) {
|
||||
*has_default_methods = true;
|
||||
}
|
||||
interfaces->at_put(index, interf());
|
||||
}
|
||||
|
||||
@ -1928,7 +1937,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
if (method_attribute_name == vmSymbols::tag_code()) {
|
||||
// Parse Code attribute
|
||||
if (_need_verify) {
|
||||
guarantee_property(!access_flags.is_native() && !access_flags.is_abstract(),
|
||||
guarantee_property(
|
||||
!access_flags.is_native() && !access_flags.is_abstract(),
|
||||
"Code attribute in native or abstract methods in class file %s",
|
||||
CHECK_(nullHandle));
|
||||
}
|
||||
@ -2125,7 +2135,9 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
runtime_visible_annotations_length = method_attribute_length;
|
||||
runtime_visible_annotations = cfs->get_u1_buffer();
|
||||
assert(runtime_visible_annotations != NULL, "null visible annotations");
|
||||
parse_annotations(runtime_visible_annotations, runtime_visible_annotations_length, cp, &parsed_annotations, CHECK_(nullHandle));
|
||||
parse_annotations(runtime_visible_annotations,
|
||||
runtime_visible_annotations_length, cp, &parsed_annotations,
|
||||
CHECK_(nullHandle));
|
||||
cfs->skip_u1(runtime_visible_annotations_length, CHECK_(nullHandle));
|
||||
} else if (PreserveAllAnnotations && method_attribute_name == vmSymbols::tag_runtime_invisible_annotations()) {
|
||||
runtime_invisible_annotations_length = method_attribute_length;
|
||||
@ -2169,12 +2181,10 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
}
|
||||
|
||||
// All sizing information for a Method* is finally available, now create it
|
||||
Method* m = Method::allocate(loader_data, code_length, access_flags,
|
||||
linenumber_table_length,
|
||||
total_lvt_length,
|
||||
exception_table_length,
|
||||
checked_exceptions_length,
|
||||
CHECK_(nullHandle));
|
||||
Method* m = Method::allocate(
|
||||
loader_data, code_length, access_flags, linenumber_table_length,
|
||||
total_lvt_length, exception_table_length, checked_exceptions_length,
|
||||
ConstMethod::NORMAL, CHECK_(nullHandle));
|
||||
|
||||
ClassLoadingService::add_class_method_size(m->size()*HeapWordSize);
|
||||
|
||||
@ -2204,7 +2214,6 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
|
||||
// Fill in code attribute information
|
||||
m->set_max_stack(max_stack);
|
||||
m->set_max_locals(max_locals);
|
||||
|
||||
m->constMethod()->set_stackmap_data(stackmap_data);
|
||||
|
||||
// Copy byte codes
|
||||
@ -2356,6 +2365,7 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
bool* has_default_methods,
|
||||
TRAPS) {
|
||||
ClassFileStream* cfs = stream();
|
||||
AnnotationArray* method_annotations = NULL;
|
||||
@ -2382,6 +2392,10 @@ Array<Method*>* ClassFileParser::parse_methods(ClassLoaderData* loader_data,
|
||||
if (method->is_final()) {
|
||||
*has_final_method = true;
|
||||
}
|
||||
if (is_interface && !method->is_abstract() && !method->is_static()) {
|
||||
// default method
|
||||
*has_default_methods = true;
|
||||
}
|
||||
methods->at_put(index, method());
|
||||
if (*methods_annotations == NULL) {
|
||||
*methods_annotations =
|
||||
@ -2907,6 +2921,34 @@ AnnotationArray* ClassFileParser::assemble_annotations(ClassLoaderData* loader_d
|
||||
}
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
static void parseAndPrintGenericSignatures(
|
||||
instanceKlassHandle this_klass, TRAPS) {
|
||||
assert(ParseAllGenericSignatures == true, "Shouldn't call otherwise");
|
||||
ResourceMark rm;
|
||||
|
||||
if (this_klass->generic_signature() != NULL) {
|
||||
using namespace generic;
|
||||
ClassDescriptor* spec = ClassDescriptor::parse_generic_signature(this_klass(), CHECK);
|
||||
|
||||
tty->print_cr("Parsing %s", this_klass->generic_signature()->as_C_string());
|
||||
spec->print_on(tty);
|
||||
|
||||
for (int i = 0; i < this_klass->methods()->length(); ++i) {
|
||||
Method* m = this_klass->methods()->at(i);
|
||||
MethodDescriptor* method_spec = MethodDescriptor::parse_generic_signature(m, spec);
|
||||
Symbol* sig = m->generic_signature();
|
||||
if (sig == NULL) {
|
||||
sig = m->signature();
|
||||
}
|
||||
tty->print_cr("Parsing %s", sig->as_C_string());
|
||||
method_spec->print_on(tty);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ndef PRODUCT
|
||||
|
||||
|
||||
instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
Handle class_loader,
|
||||
Handle protection_domain,
|
||||
@ -2923,6 +2965,8 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
unsigned char *cached_class_file_bytes = NULL;
|
||||
jint cached_class_file_length;
|
||||
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
|
||||
bool has_default_methods = false;
|
||||
ResourceMark rm(THREAD);
|
||||
|
||||
ClassFileStream* cfs = stream();
|
||||
// Timing
|
||||
@ -3138,7 +3182,9 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
if (itfs_len == 0) {
|
||||
local_interfaces = Universe::the_empty_klass_array();
|
||||
} else {
|
||||
local_interfaces = parse_interfaces(cp, itfs_len, loader_data, protection_domain, _class_name, CHECK_(nullHandle));
|
||||
local_interfaces = parse_interfaces(
|
||||
cp, itfs_len, loader_data, protection_domain, _class_name,
|
||||
&has_default_methods, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
u2 java_fields_count = 0;
|
||||
@ -3164,6 +3210,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
&methods_annotations,
|
||||
&methods_parameter_annotations,
|
||||
&methods_default_annotations,
|
||||
&has_default_methods,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
// Additional attributes
|
||||
@ -3193,6 +3240,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
super_klass = instanceKlassHandle(THREAD, kh());
|
||||
}
|
||||
if (super_klass.not_null()) {
|
||||
|
||||
if (super_klass->has_default_methods()) {
|
||||
has_default_methods = true;
|
||||
}
|
||||
|
||||
if (super_klass->is_interface()) {
|
||||
ResourceMark rm(THREAD);
|
||||
Exceptions::fthrow(
|
||||
@ -3229,14 +3281,11 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
int itable_size = 0;
|
||||
int num_miranda_methods = 0;
|
||||
|
||||
klassVtable::compute_vtable_size_and_num_mirandas(vtable_size,
|
||||
num_miranda_methods,
|
||||
super_klass(),
|
||||
methods,
|
||||
access_flags,
|
||||
class_loader,
|
||||
class_name,
|
||||
local_interfaces,
|
||||
GrowableArray<Method*> all_mirandas(20);
|
||||
|
||||
klassVtable::compute_vtable_size_and_num_mirandas(
|
||||
&vtable_size, &num_miranda_methods, &all_mirandas, super_klass(), methods,
|
||||
access_flags, class_loader, class_name, local_interfaces,
|
||||
CHECK_(nullHandle));
|
||||
|
||||
// Size of Java itable (in words)
|
||||
@ -3656,6 +3705,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
|
||||
this_klass->set_minor_version(minor_version);
|
||||
this_klass->set_major_version(major_version);
|
||||
this_klass->set_has_default_methods(has_default_methods);
|
||||
|
||||
// Set up Method*::intrinsic_id as soon as we know the names of methods.
|
||||
// (We used to do this lazily, but now we query it in Rewriter,
|
||||
@ -3673,6 +3723,16 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
cached_class_file_length);
|
||||
}
|
||||
|
||||
// Fill in field values obtained by parse_classfile_attributes
|
||||
if (parsed_annotations.has_any_annotations())
|
||||
parsed_annotations.apply_to(this_klass);
|
||||
// Create annotations
|
||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
this_klass->set_annotations(anno);
|
||||
}
|
||||
apply_parsed_class_attributes(this_klass);
|
||||
|
||||
// Miranda methods
|
||||
if ((num_miranda_methods > 0) ||
|
||||
// if this class introduced new miranda methods or
|
||||
@ -3682,18 +3742,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
this_klass->set_has_miranda_methods(); // then set a flag
|
||||
}
|
||||
|
||||
// Fill in field values obtained by parse_classfile_attributes
|
||||
if (parsed_annotations.has_any_annotations()) {
|
||||
parsed_annotations.apply_to(this_klass);
|
||||
}
|
||||
// Create annotations
|
||||
if (_annotations != NULL && this_klass->annotations() == NULL) {
|
||||
Annotations* anno = Annotations::allocate(loader_data, CHECK_NULL);
|
||||
this_klass->set_annotations(anno);
|
||||
}
|
||||
apply_parsed_class_attributes(this_klass);
|
||||
|
||||
// Compute transitive closure of interfaces this class implements
|
||||
this_klass->set_transitive_interfaces(transitive_interfaces);
|
||||
|
||||
// Fill in information needed to compute superclasses.
|
||||
@ -3702,6 +3750,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
// Initialize itable offset tables
|
||||
klassItable::setup_itable_offset_table(this_klass);
|
||||
|
||||
// Compute transitive closure of interfaces this class implements
|
||||
// Do final class setup
|
||||
fill_oop_maps(this_klass, nonstatic_oop_map_count, nonstatic_oop_offsets, nonstatic_oop_counts);
|
||||
|
||||
@ -3726,6 +3775,21 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
check_illegal_static_method(this_klass, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
|
||||
#ifdef ASSERT
|
||||
if (ParseAllGenericSignatures) {
|
||||
parseAndPrintGenericSignatures(this_klass, CHECK_(nullHandle));
|
||||
}
|
||||
#endif
|
||||
|
||||
// Generate any default methods - default methods are interface methods
|
||||
// that have a default implementation. This is new with Lambda project.
|
||||
if (has_default_methods && !access_flags.is_interface() &&
|
||||
local_interfaces->length() > 0) {
|
||||
DefaultMethods::generate_default_methods(
|
||||
this_klass(), &all_mirandas, CHECK_(nullHandle));
|
||||
}
|
||||
|
||||
// Allocate mirror and initialize static fields
|
||||
java_lang_Class::create_mirror(this_klass, CHECK_(nullHandle));
|
||||
|
||||
@ -3744,6 +3808,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
false /* not shared class */);
|
||||
|
||||
if (TraceClassLoading) {
|
||||
ResourceMark rm;
|
||||
// print in a single call to reduce interleaving of output
|
||||
if (cfs->source() != NULL) {
|
||||
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
|
||||
@ -3758,15 +3823,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
tty->print("[Loaded %s]\n", this_klass->external_name());
|
||||
}
|
||||
} else {
|
||||
ResourceMark rm;
|
||||
tty->print("[Loaded %s from %s]\n", this_klass->external_name(),
|
||||
InstanceKlass::cast(class_loader->klass())->external_name());
|
||||
}
|
||||
}
|
||||
|
||||
if (TraceClassResolution) {
|
||||
ResourceMark rm;
|
||||
// print out the superclass.
|
||||
const char * from = Klass::cast(this_klass())->external_name();
|
||||
const char * from = this_klass()->external_name();
|
||||
if (this_klass->java_super() != NULL) {
|
||||
tty->print("RESOLVE %s %s (super)\n", from, InstanceKlass::cast(this_klass->java_super())->external_name());
|
||||
}
|
||||
@ -3785,6 +3850,7 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
|
||||
#ifndef PRODUCT
|
||||
if( PrintCompactFieldsSavings ) {
|
||||
ResourceMark rm;
|
||||
if( nonstatic_field_size < orig_nonstatic_field_size ) {
|
||||
tty->print("[Saved %d of %d bytes in %s]\n",
|
||||
(orig_nonstatic_field_size - nonstatic_field_size)*heapOopSize,
|
||||
@ -3811,7 +3877,6 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||
return this_klass;
|
||||
}
|
||||
|
||||
|
||||
unsigned int
|
||||
ClassFileParser::compute_oop_map_count(instanceKlassHandle super,
|
||||
unsigned int nonstatic_oop_map_count,
|
||||
@ -3917,13 +3982,13 @@ void ClassFileParser::set_precomputed_flags(instanceKlassHandle k) {
|
||||
// java.lang.Object has empty default constructor
|
||||
k->set_has_vanilla_constructor();
|
||||
} else {
|
||||
if (Klass::cast(super)->has_vanilla_constructor() &&
|
||||
if (super->has_vanilla_constructor() &&
|
||||
_has_vanilla_constructor) {
|
||||
k->set_has_vanilla_constructor();
|
||||
}
|
||||
#ifdef ASSERT
|
||||
bool v = false;
|
||||
if (Klass::cast(super)->has_vanilla_constructor()) {
|
||||
if (super->has_vanilla_constructor()) {
|
||||
Method* constructor = k->find_method(vmSymbols::object_initializer_name(
|
||||
), vmSymbols::void_method_signature());
|
||||
if (constructor != NULL && constructor->is_vanilla_constructor()) {
|
||||
@ -4065,7 +4130,7 @@ void ClassFileParser::check_super_interface_access(instanceKlassHandle this_klas
|
||||
int lng = local_interfaces->length();
|
||||
for (int i = lng - 1; i >= 0; i--) {
|
||||
Klass* k = local_interfaces->at(i);
|
||||
assert (k != NULL && Klass::cast(k)->is_interface(), "invalid interface");
|
||||
assert (k != NULL && k->is_interface(), "invalid interface");
|
||||
if (!Reflection::verify_class_access(this_klass(), k, false)) {
|
||||
ResourceMark rm(THREAD);
|
||||
Exceptions::fthrow(
|
||||
@ -4128,7 +4193,7 @@ void ClassFileParser::check_final_method_override(instanceKlassHandle this_klass
|
||||
}
|
||||
|
||||
// continue to look from super_m's holder's super.
|
||||
k = InstanceKlass::cast(super_m->method_holder())->super();
|
||||
k = super_m->method_holder()->super();
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -4263,13 +4328,16 @@ void ClassFileParser::verify_legal_method_modifiers(
|
||||
const bool is_strict = (flags & JVM_ACC_STRICT) != 0;
|
||||
const bool is_synchronized = (flags & JVM_ACC_SYNCHRONIZED) != 0;
|
||||
const bool major_gte_15 = _major_version >= JAVA_1_5_VERSION;
|
||||
const bool major_gte_8 = _major_version >= JAVA_8_VERSION;
|
||||
const bool is_initializer = (name == vmSymbols::object_initializer_name());
|
||||
|
||||
bool is_illegal = false;
|
||||
|
||||
if (is_interface) {
|
||||
if (!is_abstract || !is_public || is_static || is_final ||
|
||||
is_native || (major_gte_15 && (is_synchronized || is_strict))) {
|
||||
if (!is_public || is_static || is_final || is_native ||
|
||||
((is_synchronized || is_strict) && major_gte_15 &&
|
||||
(!major_gte_8 || is_abstract)) ||
|
||||
(!major_gte_8 && !is_abstract)) {
|
||||
is_illegal = true;
|
||||
}
|
||||
} else { // not interface
|
||||
|
||||
@ -151,6 +151,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
ClassLoaderData* loader_data,
|
||||
Handle protection_domain,
|
||||
Symbol* class_name,
|
||||
bool* has_default_methods,
|
||||
TRAPS);
|
||||
void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
|
||||
|
||||
@ -188,6 +189,7 @@ class ClassFileParser VALUE_OBJ_CLASS_SPEC {
|
||||
Array<AnnotationArray*>** methods_annotations,
|
||||
Array<AnnotationArray*>** methods_parameter_annotations,
|
||||
Array<AnnotationArray*>** methods_default_annotations,
|
||||
bool* has_default_method,
|
||||
TRAPS);
|
||||
Array<int>* sort_methods(ClassLoaderData* loader_data,
|
||||
Array<Method*>* methods,
|
||||
|
||||
@ -605,8 +605,10 @@ void ClassLoader::load_zip_library() {
|
||||
// Load zip library
|
||||
char path[JVM_MAXPATHLEN];
|
||||
char ebuf[1024];
|
||||
os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip");
|
||||
void* handle = os::dll_load(path, ebuf, sizeof ebuf);
|
||||
void* handle = NULL;
|
||||
if (os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip")) {
|
||||
handle = os::dll_load(path, ebuf, sizeof ebuf);
|
||||
}
|
||||
if (handle == NULL) {
|
||||
vm_exit_during_initialization("Unable to load ZIP library", path);
|
||||
}
|
||||
|
||||
1387
hotspot/src/share/vm/classfile/defaultMethods.cpp
Normal file
1387
hotspot/src/share/vm/classfile/defaultMethods.cpp
Normal file
File diff suppressed because it is too large
Load Diff
58
hotspot/src/share/vm/classfile/defaultMethods.hpp
Normal file
58
hotspot/src/share/vm/classfile/defaultMethods.hpp
Normal file
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
|
||||
#define SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
|
||||
|
||||
#include "runtime/handles.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
|
||||
class InstanceKlass;
|
||||
class Symbol;
|
||||
class Method;
|
||||
|
||||
class DefaultMethods : AllStatic {
|
||||
public:
|
||||
|
||||
// Analyzes class and determines which default methods are inherited
|
||||
// from interfaces (and has no other implementation). For each method
|
||||
// (and each different signature the method could have), create an
|
||||
// "overpass" method that is an instance method that redirects to the
|
||||
// default method. Overpass methods are added to the methods lists for
|
||||
// the class.
|
||||
static void generate_default_methods(
|
||||
InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS);
|
||||
|
||||
|
||||
// Called during linking when an invokespecial to an direct interface
|
||||
// method is found. Selects and returns a method if there is a unique
|
||||
// default method in the 'super_iface' part of the hierarchy which is
|
||||
// also a candidate default for 'this_klass'. Otherwise throws an AME.
|
||||
static Method* find_super_default(
|
||||
Klass* this_klass, Klass* super_iface,
|
||||
Symbol* method_name, Symbol* method_sig, TRAPS);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
|
||||
@ -346,7 +346,7 @@ void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
|
||||
KlassHandle obj) {
|
||||
assert_locked_or_safepoint(SystemDictionary_lock);
|
||||
assert(obj() != NULL, "adding NULL obj");
|
||||
assert(Klass::cast(obj())->name() == class_name, "sanity check on name");
|
||||
assert(obj()->name() == class_name, "sanity check on name");
|
||||
|
||||
unsigned int hash = compute_hash(class_name, loader_data);
|
||||
int index = hash_to_index(hash);
|
||||
@ -553,7 +553,7 @@ void Dictionary::print() {
|
||||
bool is_defining_class =
|
||||
(loader_data == InstanceKlass::cast(e)->class_loader_data());
|
||||
tty->print("%s%s", is_defining_class ? " " : "^",
|
||||
Klass::cast(e)->external_name());
|
||||
e->external_name());
|
||||
|
||||
tty->print(", loader ");
|
||||
loader_data->print_value();
|
||||
@ -575,7 +575,7 @@ void Dictionary::verify() {
|
||||
probe = probe->next()) {
|
||||
Klass* e = probe->klass();
|
||||
ClassLoaderData* loader_data = probe->loader_data();
|
||||
guarantee(Klass::cast(e)->oop_is_instance(),
|
||||
guarantee(e->oop_is_instance(),
|
||||
"Verify of system dictionary failed");
|
||||
// class loader must be present; a null class loader is the
|
||||
// boostrap loader
|
||||
|
||||
1272
hotspot/src/share/vm/classfile/genericSignatures.cpp
Normal file
1272
hotspot/src/share/vm/classfile/genericSignatures.cpp
Normal file
File diff suppressed because it is too large
Load Diff
467
hotspot/src/share/vm/classfile/genericSignatures.hpp
Normal file
467
hotspot/src/share/vm/classfile/genericSignatures.hpp
Normal file
@ -0,0 +1,467 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
|
||||
#define SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
|
||||
|
||||
#include "classfile/symbolTable.hpp"
|
||||
#include "memory/allocation.hpp"
|
||||
#include "runtime/signature.hpp"
|
||||
#include "utilities/growableArray.hpp"
|
||||
#include "utilities/resourceHash.hpp"
|
||||
|
||||
class stringStream;
|
||||
|
||||
namespace generic {
|
||||
|
||||
class Identifier;
|
||||
class ClassDescriptor;
|
||||
class MethodDescriptor;
|
||||
|
||||
class TypeParameter; // a formal type parameter declared in generic signatures
|
||||
class TypeArgument; // The "type value" passed to fill parameters in supertypes
|
||||
class TypeVariable; // A usage of a type parameter as a value
|
||||
/**
|
||||
* Example:
|
||||
*
|
||||
* <T, V> class Foo extends Bar<String> { int m(V v) {} }
|
||||
* ^^^^^^ ^^^^^^ ^^
|
||||
* type parameters type argument type variable
|
||||
*
|
||||
* Note that a type variable could be passed as an argument too:
|
||||
* <T, V> class Foo extends Bar<T> { int m(V v) {} }
|
||||
* ^^^
|
||||
* type argument's value is a type variable
|
||||
*/
|
||||
|
||||
|
||||
class Type;
|
||||
class ClassType;
|
||||
class ArrayType;
|
||||
class PrimitiveType;
|
||||
class Context;
|
||||
class DescriptorCache;
|
||||
|
||||
class DescriptorStream;
|
||||
|
||||
class Identifier : public ResourceObj {
|
||||
private:
|
||||
Symbol* _sym;
|
||||
int _begin;
|
||||
int _end;
|
||||
|
||||
public:
|
||||
Identifier(Symbol* sym, int begin, int end) :
|
||||
_sym(sym), _begin(begin), _end(end) {}
|
||||
|
||||
bool equals(Identifier* other);
|
||||
bool equals(Symbol* sym);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif // ndef PRODUCT
|
||||
};
|
||||
|
||||
class Descriptor : public ResourceObj {
|
||||
protected:
|
||||
GrowableArray<TypeParameter*> _type_parameters;
|
||||
ClassDescriptor* _outer_class;
|
||||
|
||||
Descriptor(GrowableArray<TypeParameter*>& params,
|
||||
ClassDescriptor* outer)
|
||||
: _type_parameters(params), _outer_class(outer) {}
|
||||
|
||||
public:
|
||||
|
||||
ClassDescriptor* outer_class() { return _outer_class; }
|
||||
void set_outer_class(ClassDescriptor* sig) { _outer_class = sig; }
|
||||
|
||||
virtual ClassDescriptor* as_class_signature() { return NULL; }
|
||||
virtual MethodDescriptor* as_method_signature() { return NULL; }
|
||||
|
||||
bool is_class_signature() { return as_class_signature() != NULL; }
|
||||
bool is_method_signature() { return as_method_signature() != NULL; }
|
||||
|
||||
GrowableArray<TypeParameter*>& type_parameters() {
|
||||
return _type_parameters;
|
||||
}
|
||||
|
||||
TypeParameter* find_type_parameter(Identifier* id, int* param_depth);
|
||||
|
||||
virtual void bind_variables_to_parameters() = 0;
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void print_on(outputStream* str) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ClassDescriptor : public Descriptor {
|
||||
private:
|
||||
ClassType* _super;
|
||||
GrowableArray<ClassType*> _interfaces;
|
||||
MethodDescriptor* _outer_method;
|
||||
|
||||
ClassDescriptor(GrowableArray<TypeParameter*>& ftp, ClassType* scs,
|
||||
GrowableArray<ClassType*>& sis, ClassDescriptor* outer_class = NULL,
|
||||
MethodDescriptor* outer_method = NULL)
|
||||
: Descriptor(ftp, outer_class), _super(scs), _interfaces(sis),
|
||||
_outer_method(outer_method) {}
|
||||
|
||||
static u2 get_outer_class_index(InstanceKlass* k, TRAPS);
|
||||
static ClassDescriptor* parse_generic_signature(Klass* k, Symbol* original_name, TRAPS);
|
||||
|
||||
public:
|
||||
|
||||
virtual ClassDescriptor* as_class_signature() { return this; }
|
||||
|
||||
MethodDescriptor* outer_method() { return _outer_method; }
|
||||
void set_outer_method(MethodDescriptor* m) { _outer_method = m; }
|
||||
|
||||
ClassType* super() { return _super; }
|
||||
ClassType* interface_desc(Symbol* sym);
|
||||
|
||||
static ClassDescriptor* parse_generic_signature(Klass* k, TRAPS);
|
||||
static ClassDescriptor* parse_generic_signature(Symbol* sym);
|
||||
|
||||
// For use in superclass chains in positions where this is no generic info
|
||||
static ClassDescriptor* placeholder(InstanceKlass* klass);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
|
||||
ClassDescriptor* canonicalize(Context* ctx);
|
||||
|
||||
// Linking sets the position index in any contained TypeVariable type
|
||||
// to correspond to the location of that identifier in the formal type
|
||||
// parameters.
|
||||
void bind_variables_to_parameters();
|
||||
};
|
||||
|
||||
class MethodDescriptor : public Descriptor {
|
||||
private:
|
||||
GrowableArray<Type*> _parameters;
|
||||
Type* _return_type;
|
||||
GrowableArray<Type*> _throws;
|
||||
|
||||
MethodDescriptor(GrowableArray<TypeParameter*>& ftp, ClassDescriptor* outer,
|
||||
GrowableArray<Type*>& sigs, Type* rt, GrowableArray<Type*>& throws)
|
||||
: Descriptor(ftp, outer), _parameters(sigs), _return_type(rt),
|
||||
_throws(throws) {}
|
||||
|
||||
public:
|
||||
|
||||
static MethodDescriptor* parse_generic_signature(Method* m, ClassDescriptor* outer);
|
||||
static MethodDescriptor* parse_generic_signature(Symbol* sym, ClassDescriptor* outer);
|
||||
|
||||
MethodDescriptor* as_method_signature() { return this; }
|
||||
|
||||
// Performs generic analysis on the method parameters to determine
|
||||
// if both methods refer to the same argument types.
|
||||
bool covariant_match(MethodDescriptor* other, Context* ctx);
|
||||
|
||||
// Returns a new method descriptor with all generic variables
|
||||
// removed and replaced with whatever is indicated using the Context.
|
||||
MethodDescriptor* canonicalize(Context* ctx);
|
||||
|
||||
void bind_variables_to_parameters();
|
||||
|
||||
#ifndef PRODUCT
|
||||
TempNewSymbol reify_signature(Context* ctx, TRAPS);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TypeParameter : public ResourceObj {
|
||||
private:
|
||||
Identifier* _identifier;
|
||||
ClassType* _class_bound;
|
||||
GrowableArray<ClassType*> _interface_bounds;
|
||||
|
||||
// The position is the ordinal location of the parameter within the
|
||||
// formal parameter list (excluding outer classes). It is only set for
|
||||
// formal type parameters that are associated with a class -- method
|
||||
// type parameters are left as -1. When resolving a generic variable to
|
||||
// find the actual type, this index is used to access the generic type
|
||||
// argument in the provided context object.
|
||||
int _position; // Assigned during variable linking
|
||||
|
||||
TypeParameter(Identifier* id, ClassType* class_bound,
|
||||
GrowableArray<ClassType*>& interface_bounds) :
|
||||
_identifier(id), _class_bound(class_bound),
|
||||
_interface_bounds(interface_bounds), _position(-1) {}
|
||||
|
||||
public:
|
||||
static TypeParameter* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
ClassType* bound();
|
||||
int position() { return _position; }
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig, int position);
|
||||
Identifier* identifier() { return _identifier; }
|
||||
|
||||
Type* resolve(Context* ctx, int inner_depth, int ctx_depth);
|
||||
TypeParameter* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class Type : public ResourceObj {
|
||||
public:
|
||||
static Type* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
virtual ClassType* as_class() { return NULL; }
|
||||
virtual TypeVariable* as_variable() { return NULL; }
|
||||
virtual ArrayType* as_array() { return NULL; }
|
||||
virtual PrimitiveType* as_primitive() { return NULL; }
|
||||
|
||||
virtual bool covariant_match(Type* gt, Context* ctx) = 0;
|
||||
virtual Type* canonicalize(Context* ctx, int ctx_depth) = 0;
|
||||
|
||||
virtual void bind_variables_to_parameters(Descriptor* sig) = 0;
|
||||
|
||||
#ifndef PRODUCT
|
||||
virtual void reify_signature(stringStream* ss, Context* ctx) = 0;
|
||||
virtual void print_on(outputStream* str) const = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ClassType : public Type {
|
||||
friend class ClassDescriptor;
|
||||
protected:
|
||||
Identifier* _identifier;
|
||||
GrowableArray<TypeArgument*> _type_arguments;
|
||||
ClassType* _outer_class;
|
||||
|
||||
ClassType(Identifier* identifier,
|
||||
GrowableArray<TypeArgument*>& args,
|
||||
ClassType* outer)
|
||||
: _identifier(identifier), _type_arguments(args), _outer_class(outer) {}
|
||||
|
||||
// Returns true if there are inner classes to read
|
||||
static Identifier* parse_generic_signature_simple(
|
||||
GrowableArray<TypeArgument*>* args,
|
||||
bool* has_inner, DescriptorStream* str);
|
||||
|
||||
static ClassType* parse_generic_signature(ClassType* outer,
|
||||
DescriptorStream* str);
|
||||
static ClassType* from_symbol(Symbol* sym);
|
||||
|
||||
public:
|
||||
ClassType* as_class() { return this; }
|
||||
|
||||
static ClassType* parse_generic_signature(DescriptorStream* str);
|
||||
static ClassType* java_lang_Object();
|
||||
|
||||
Identifier* identifier() { return _identifier; }
|
||||
int type_arguments_length() { return _type_arguments.length(); }
|
||||
TypeArgument* type_argument_at(int i);
|
||||
|
||||
virtual ClassType* outer_class() { return _outer_class; }
|
||||
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
ClassType* canonicalize(Context* ctx, int context_depth);
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TypeVariable : public Type {
|
||||
private:
|
||||
Identifier* _id;
|
||||
TypeParameter* _parameter; // assigned during linking
|
||||
|
||||
// how many steps "out" from inner classes, -1 if method
|
||||
int _inner_depth;
|
||||
|
||||
TypeVariable(Identifier* id)
|
||||
: _id(id), _parameter(NULL), _inner_depth(0) {}
|
||||
|
||||
public:
|
||||
TypeVariable* as_variable() { return this; }
|
||||
|
||||
static TypeVariable* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
Identifier* identifier() { return _id; }
|
||||
TypeParameter* parameter() { return _parameter; }
|
||||
int inner_depth() { return _inner_depth; }
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
Type* resolve(Context* ctx, int ctx_depth);
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
Type* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class ArrayType : public Type {
|
||||
private:
|
||||
Type* _base;
|
||||
|
||||
ArrayType(Type* base) : _base(base) {}
|
||||
|
||||
public:
|
||||
ArrayType* as_array() { return this; }
|
||||
|
||||
static ArrayType* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
ArrayType* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class PrimitiveType : public Type {
|
||||
friend class Type;
|
||||
private:
|
||||
char _type; // includes V for void
|
||||
|
||||
PrimitiveType(char& type) : _type(type) {}
|
||||
|
||||
public:
|
||||
PrimitiveType* as_primitive() { return this; }
|
||||
|
||||
bool covariant_match(Type* gt, Context* ctx);
|
||||
PrimitiveType* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void reify_signature(stringStream* ss, Context* ctx);
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
class TypeArgument : public ResourceObj {
|
||||
private:
|
||||
Type* _lower_bound;
|
||||
Type* _upper_bound; // may be null or == _lower_bound
|
||||
|
||||
TypeArgument(Type* lower_bound, Type* upper_bound)
|
||||
: _lower_bound(lower_bound), _upper_bound(upper_bound) {}
|
||||
|
||||
public:
|
||||
|
||||
static TypeArgument* parse_generic_signature(DescriptorStream* str);
|
||||
|
||||
Type* lower_bound() { return _lower_bound; }
|
||||
Type* upper_bound() { return _upper_bound; }
|
||||
|
||||
void bind_variables_to_parameters(Descriptor* sig);
|
||||
TypeArgument* canonicalize(Context* ctx, int ctx_depth);
|
||||
|
||||
bool covariant_match(TypeArgument* a, Context* ctx);
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class Context : public ResourceObj {
|
||||
private:
|
||||
DescriptorCache* _cache;
|
||||
GrowableArray<ClassType*> _type_arguments;
|
||||
|
||||
void reset_to_mark(int size);
|
||||
|
||||
public:
|
||||
// When this object goes out of scope or 'destroy' is
|
||||
// called, then the application of the type to the
|
||||
// context is wound-back (unless it's been deactivated).
|
||||
class Mark : public StackObj {
|
||||
private:
|
||||
mutable Context* _context;
|
||||
int _marked_size;
|
||||
|
||||
bool is_active() const { return _context != NULL; }
|
||||
void deactivate() const { _context = NULL; }
|
||||
|
||||
public:
|
||||
Mark() : _context(NULL), _marked_size(0) {}
|
||||
Mark(Context* ctx, int sz) : _context(ctx), _marked_size(sz) {}
|
||||
Mark(const Mark& m) : _context(m._context), _marked_size(m._marked_size) {
|
||||
m.deactivate(); // Ownership is transferred
|
||||
}
|
||||
|
||||
Mark& operator=(const Mark& cm) {
|
||||
destroy();
|
||||
_context = cm._context;
|
||||
_marked_size = cm._marked_size;
|
||||
cm.deactivate();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void destroy();
|
||||
~Mark() { destroy(); }
|
||||
};
|
||||
|
||||
Context(DescriptorCache* cache) : _cache(cache) {}
|
||||
|
||||
Mark mark() { return Mark(this, _type_arguments.length()); }
|
||||
void apply_type_arguments(InstanceKlass* current, InstanceKlass* super,TRAPS);
|
||||
|
||||
ClassType* at_depth(int i) const;
|
||||
|
||||
#ifndef PRODUCT
|
||||
void print_on(outputStream* str) const;
|
||||
#endif
|
||||
};
|
||||
|
||||
/**
|
||||
* Contains a cache of descriptors for classes and methods so they can be
|
||||
* looked-up instead of reparsing each time they are needed.
|
||||
*/
|
||||
class DescriptorCache : public ResourceObj {
|
||||
private:
|
||||
ResourceHashtable<InstanceKlass*, ClassDescriptor*> _class_descriptors;
|
||||
ResourceHashtable<Method*, MethodDescriptor*> _method_descriptors;
|
||||
|
||||
public:
|
||||
ClassDescriptor* descriptor_for(InstanceKlass* ikh, TRAPS);
|
||||
|
||||
MethodDescriptor* descriptor_for(Method* mh, ClassDescriptor* cd, TRAPS);
|
||||
// Class descriptor derived from method holder
|
||||
MethodDescriptor* descriptor_for(Method* mh, TRAPS);
|
||||
};
|
||||
|
||||
} // namespace generic
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_GENERICSIGNATURES_HPP
|
||||
|
||||
@ -348,6 +348,22 @@ unsigned int java_lang_String::to_hash(oop java_string) {
|
||||
return java_lang_String::to_hash(value->char_at_addr(offset), length);
|
||||
}
|
||||
|
||||
char* java_lang_String::as_quoted_ascii(oop java_string) {
|
||||
typeArrayOop value = java_lang_String::value(java_string);
|
||||
int offset = java_lang_String::offset(java_string);
|
||||
int length = java_lang_String::length(java_string);
|
||||
|
||||
jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
|
||||
if (base == NULL) return NULL;
|
||||
|
||||
int result_length = UNICODE::quoted_ascii_length(base, length) + 1;
|
||||
char* result = NEW_RESOURCE_ARRAY(char, result_length);
|
||||
UNICODE::as_quoted_ascii(base, length, result, result_length);
|
||||
assert(result_length >= length + 1, "must not be shorter");
|
||||
assert(result_length == (int)strlen(result) + 1, "must match");
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned int java_lang_String::hash_string(oop java_string) {
|
||||
int length = java_lang_String::length(java_string);
|
||||
// Zero length string doesn't hash necessarily hash to zero.
|
||||
@ -545,7 +561,7 @@ oop java_lang_Class::create_mirror(KlassHandle k, TRAPS) {
|
||||
assert(k->oop_is_objArray(), "Must be");
|
||||
Klass* element_klass = ObjArrayKlass::cast(k())->element_klass();
|
||||
assert(element_klass != NULL, "Must have an element klass");
|
||||
comp_mirror = Klass::cast(element_klass)->java_mirror();
|
||||
comp_mirror = element_klass->java_mirror();
|
||||
}
|
||||
assert(comp_mirror.not_null(), "must have a mirror");
|
||||
|
||||
@ -628,8 +644,8 @@ void java_lang_Class::print_signature(oop java_class, outputStream* st) {
|
||||
name = vmSymbols::type_signature(primitive_type(java_class));
|
||||
} else {
|
||||
Klass* k = as_Klass(java_class);
|
||||
is_instance = Klass::cast(k)->oop_is_instance();
|
||||
name = Klass::cast(k)->name();
|
||||
is_instance = k->oop_is_instance();
|
||||
name = k->name();
|
||||
}
|
||||
if (name == NULL) {
|
||||
st->print("<null>");
|
||||
@ -651,12 +667,12 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found,
|
||||
name->increment_refcount();
|
||||
} else {
|
||||
Klass* k = as_Klass(java_class);
|
||||
if (!Klass::cast(k)->oop_is_instance()) {
|
||||
name = Klass::cast(k)->name();
|
||||
if (!k->oop_is_instance()) {
|
||||
name = k->name();
|
||||
name->increment_refcount();
|
||||
} else {
|
||||
ResourceMark rm;
|
||||
const char* sigstr = Klass::cast(k)->signature_name();
|
||||
const char* sigstr = k->signature_name();
|
||||
int siglen = (int) strlen(sigstr);
|
||||
if (!intern_if_not_found) {
|
||||
name = SymbolTable::probe(sigstr, siglen);
|
||||
@ -671,13 +687,13 @@ Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found,
|
||||
|
||||
Klass* java_lang_Class::array_klass(oop java_class) {
|
||||
Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
|
||||
assert(k == NULL || k->is_klass() && Klass::cast(k)->oop_is_array(), "should be array klass");
|
||||
assert(k == NULL || k->is_klass() && k->oop_is_array(), "should be array klass");
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
void java_lang_Class::set_array_klass(oop java_class, Klass* klass) {
|
||||
assert(klass->is_klass() && Klass::cast(klass)->oop_is_array(), "should be array klass");
|
||||
assert(klass->is_klass() && klass->oop_is_array(), "should be array klass");
|
||||
java_class->metadata_field_put(_array_klass_offset, klass);
|
||||
}
|
||||
|
||||
@ -1156,7 +1172,7 @@ void java_lang_Throwable::print(Handle throwable, outputStream* st) {
|
||||
// Print stack trace element to resource allocated buffer
|
||||
char* java_lang_Throwable::print_stack_element_to_buffer(Method* method, int bci) {
|
||||
// Get strings and string lengths
|
||||
InstanceKlass* klass = InstanceKlass::cast(method->method_holder());
|
||||
InstanceKlass* klass = method->method_holder();
|
||||
const char* klass_name = klass->external_name();
|
||||
int buf_len = (int)strlen(klass_name);
|
||||
char* source_file_name;
|
||||
@ -1747,14 +1763,14 @@ oop java_lang_StackTraceElement::create(methodHandle method, int bci, TRAPS) {
|
||||
Handle element = ik->allocate_instance_handle(CHECK_0);
|
||||
// Fill in class name
|
||||
ResourceMark rm(THREAD);
|
||||
const char* str = InstanceKlass::cast(method->method_holder())->external_name();
|
||||
const char* str = method->method_holder()->external_name();
|
||||
oop classname = StringTable::intern((char*) str, CHECK_0);
|
||||
java_lang_StackTraceElement::set_declaringClass(element(), classname);
|
||||
// Fill in method name
|
||||
oop methodname = StringTable::intern(method->name(), CHECK_0);
|
||||
java_lang_StackTraceElement::set_methodName(element(), methodname);
|
||||
// Fill in source file name
|
||||
Symbol* source = InstanceKlass::cast(method->method_holder())->source_file_name();
|
||||
Symbol* source = method->method_holder()->source_file_name();
|
||||
if (ShowHiddenFrames && source == NULL)
|
||||
source = vmSymbols::unknown_class_name();
|
||||
oop filename = StringTable::intern(source, CHECK_0);
|
||||
|
||||
@ -154,6 +154,8 @@ class java_lang_String : AllStatic {
|
||||
static char* as_utf8_string(oop java_string, int start, int len);
|
||||
static char* as_platform_dependent_str(Handle java_string, TRAPS);
|
||||
static jchar* as_unicode_string(oop java_string, int& length);
|
||||
// produce an ascii string with all other values quoted using \u####
|
||||
static char* as_quoted_ascii(oop java_string);
|
||||
|
||||
// Compute the hash value for a java.lang.String object which would
|
||||
// contain the characters passed in.
|
||||
@ -912,7 +914,7 @@ class java_lang_invoke_MethodHandle: AllStatic {
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MethodHandle_klass());
|
||||
return klass->is_subclass_of(SystemDictionary::MethodHandle_klass());
|
||||
}
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
@ -942,7 +944,7 @@ class java_lang_invoke_LambdaForm: AllStatic {
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return SystemDictionary::LambdaForm_klass() != NULL &&
|
||||
Klass::cast(klass)->is_subclass_of(SystemDictionary::LambdaForm_klass());
|
||||
klass->is_subclass_of(SystemDictionary::LambdaForm_klass());
|
||||
}
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
@ -1004,7 +1006,7 @@ class java_lang_invoke_MemberName: AllStatic {
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return Klass::cast(klass)->is_subclass_of(SystemDictionary::MemberName_klass());
|
||||
return klass->is_subclass_of(SystemDictionary::MemberName_klass());
|
||||
}
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
@ -1090,7 +1092,7 @@ public:
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass());
|
||||
return klass->is_subclass_of(SystemDictionary::CallSite_klass());
|
||||
}
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
@ -1160,7 +1162,7 @@ class java_lang_ClassLoader : AllStatic {
|
||||
|
||||
// Testers
|
||||
static bool is_subclass(Klass* klass) {
|
||||
return Klass::cast(klass)->is_subclass_of(SystemDictionary::ClassLoader_klass());
|
||||
return klass->is_subclass_of(SystemDictionary::ClassLoader_klass());
|
||||
}
|
||||
static bool is_instance(oop obj) {
|
||||
return obj != NULL && is_subclass(obj->klass());
|
||||
|
||||
@ -320,7 +320,7 @@ Klass* LoaderConstraintTable::find_constrained_klass(Symbol* name,
|
||||
Handle loader) {
|
||||
LoaderConstraintEntry *p = *(find_loader_constraint(name, loader));
|
||||
if (p != NULL && p->klass() != NULL) {
|
||||
if (Klass::cast(p->klass())->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) {
|
||||
if (p->klass()->oop_is_instance() && !InstanceKlass::cast(p->klass())->is_loaded()) {
|
||||
// Only return fully loaded classes. Classes found through the
|
||||
// constraints might still be in the process of loading.
|
||||
return NULL;
|
||||
|
||||
@ -45,7 +45,7 @@ PlaceholderEntry* PlaceholderTable::new_entry(int hash, Symbol* name,
|
||||
entry->set_loadInstanceThreadQ(NULL);
|
||||
entry->set_defineThreadQ(NULL);
|
||||
entry->set_definer(NULL);
|
||||
entry->set_instanceKlass(NULL);
|
||||
entry->set_instance_klass(NULL);
|
||||
return entry;
|
||||
}
|
||||
|
||||
@ -188,7 +188,7 @@ void PlaceholderTable::classes_do(KlassClosure* f) {
|
||||
void PlaceholderEntry::classes_do(KlassClosure* closure) {
|
||||
assert(klassname() != NULL, "should have a non-null klass");
|
||||
if (_instanceKlass != NULL) {
|
||||
closure->do_klass(InstanceKlass());
|
||||
closure->do_klass(instance_klass());
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,9 +220,9 @@ void PlaceholderEntry::print() const {
|
||||
tty->print(", definer ");
|
||||
definer()->print_value();
|
||||
}
|
||||
if (InstanceKlass() != NULL) {
|
||||
if (instance_klass() != NULL) {
|
||||
tty->print(", InstanceKlass ");
|
||||
InstanceKlass()->print_value();
|
||||
instance_klass()->print_value();
|
||||
}
|
||||
tty->print("\n");
|
||||
tty->print("loadInstanceThreadQ threads:");
|
||||
@ -241,9 +241,9 @@ void PlaceholderEntry::verify() const {
|
||||
guarantee(loader_data() != NULL, "Must have been setup.");
|
||||
guarantee(loader_data()->class_loader() == NULL || loader_data()->class_loader()->is_instance(),
|
||||
"checking type of _loader");
|
||||
guarantee(InstanceKlass() == NULL
|
||||
|| Klass::cast(InstanceKlass())->oop_is_instance(),
|
||||
"checking type of InstanceKlass result");
|
||||
guarantee(instance_klass() == NULL
|
||||
|| instance_klass()->oop_is_instance(),
|
||||
"checking type of instance_klass result");
|
||||
}
|
||||
|
||||
void PlaceholderTable::verify() {
|
||||
|
||||
@ -191,8 +191,8 @@ class PlaceholderEntry : public HashtableEntry<Symbol*, mtClass> {
|
||||
Thread* definer() const {return _definer; }
|
||||
void set_definer(Thread* definer) { _definer = definer; }
|
||||
|
||||
Klass* InstanceKlass() const {return _instanceKlass; }
|
||||
void set_instanceKlass(Klass* InstanceKlass) { _instanceKlass = InstanceKlass; }
|
||||
Klass* instance_klass() const {return _instanceKlass; }
|
||||
void set_instance_klass(Klass* ik) { _instanceKlass = ik; }
|
||||
|
||||
SeenThread* superThreadQ() const { return _superThreadQ; }
|
||||
void set_superThreadQ(SeenThread* SeenThread) { _superThreadQ = SeenThread; }
|
||||
|
||||
@ -262,19 +262,14 @@ public:
|
||||
// The string table
|
||||
static StringTable* the_table() { return _the_table; }
|
||||
|
||||
// Size of one bucket in the string table. Used when checking for rollover.
|
||||
static uint bucket_size() { return sizeof(HashtableBucket<mtSymbol>); }
|
||||
|
||||
static void create_table() {
|
||||
assert(_the_table == NULL, "One string table allowed.");
|
||||
_the_table = new StringTable();
|
||||
}
|
||||
|
||||
static void create_table(HashtableBucket<mtSymbol>* t, int length,
|
||||
int number_of_entries) {
|
||||
assert(_the_table == NULL, "One string table allowed.");
|
||||
assert((size_t)length == StringTableSize * sizeof(HashtableBucket<mtSymbol>),
|
||||
"bad shared string size.");
|
||||
_the_table = new StringTable(t, number_of_entries);
|
||||
}
|
||||
|
||||
// GC support
|
||||
// Delete pointers to otherwise-unreachable objects.
|
||||
static void unlink(BoolObjectClosure* cl);
|
||||
|
||||
@ -240,7 +240,7 @@ Klass* SystemDictionary::resolve_array_class_or_null(Symbol* class_name,
|
||||
protection_domain,
|
||||
CHECK_NULL);
|
||||
if (k != NULL) {
|
||||
k = Klass::cast(k)->array_klass(fd.dimension(), CHECK_NULL);
|
||||
k = k->array_klass(fd.dimension(), CHECK_NULL);
|
||||
}
|
||||
} else {
|
||||
k = Universe::typeArrayKlassObj(t);
|
||||
@ -328,8 +328,8 @@ Klass* SystemDictionary::resolve_super_or_fail(Symbol* child_name,
|
||||
if ((childk != NULL ) && (is_superclass) &&
|
||||
((quicksuperk = InstanceKlass::cast(childk)->super()) != NULL) &&
|
||||
|
||||
((Klass::cast(quicksuperk)->name() == class_name) &&
|
||||
(Klass::cast(quicksuperk)->class_loader() == class_loader()))) {
|
||||
((quicksuperk->name() == class_name) &&
|
||||
(quicksuperk->class_loader() == class_loader()))) {
|
||||
return quicksuperk;
|
||||
} else {
|
||||
PlaceholderEntry* probe = placeholders()->get_entry(p_index, p_hash, child_name, loader_data);
|
||||
@ -928,7 +928,7 @@ Klass* SystemDictionary::find_instance_or_array_klass(Symbol* class_name,
|
||||
k = SystemDictionary::find(fd.object_key(), class_loader, protection_domain, THREAD);
|
||||
}
|
||||
if (k != NULL) {
|
||||
k = Klass::cast(k)->array_klass_or_null(fd.dimension());
|
||||
k = k->array_klass_or_null(fd.dimension());
|
||||
}
|
||||
} else {
|
||||
k = find(class_name, class_loader, protection_domain, THREAD);
|
||||
@ -1537,7 +1537,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas
|
||||
// Only special cases allow parallel defines and can use other thread's results
|
||||
// Other cases fall through, and may run into duplicate defines
|
||||
// caught by finding an entry in the SystemDictionary
|
||||
if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->InstanceKlass() != NULL)) {
|
||||
if ((UnsyncloadClass || is_parallelDefine(class_loader)) && (probe->instance_klass() != NULL)) {
|
||||
probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS);
|
||||
placeholders()->find_and_remove(p_index, p_hash, name_h, loader_data, THREAD);
|
||||
SystemDictionary_lock->notify_all();
|
||||
@ -1545,7 +1545,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas
|
||||
Klass* check = find_class(d_index, d_hash, name_h, loader_data);
|
||||
assert(check != NULL, "definer missed recording success");
|
||||
#endif
|
||||
return(instanceKlassHandle(THREAD, probe->InstanceKlass()));
|
||||
return(instanceKlassHandle(THREAD, probe->instance_klass()));
|
||||
} else {
|
||||
// This thread will define the class (even if earlier thread tried and had an error)
|
||||
probe->set_definer(THREAD);
|
||||
@ -1566,7 +1566,7 @@ instanceKlassHandle SystemDictionary::find_or_define_instance_class(Symbol* clas
|
||||
linkage_exception = Handle(THREAD,PENDING_EXCEPTION);
|
||||
CLEAR_PENDING_EXCEPTION;
|
||||
} else {
|
||||
probe->set_instanceKlass(k());
|
||||
probe->set_instance_klass(k());
|
||||
}
|
||||
probe->set_definer(NULL);
|
||||
probe->remove_seen_thread(THREAD, PlaceholderTable::DEFINE_CLASS);
|
||||
@ -2149,7 +2149,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass(
|
||||
}
|
||||
// If element class already loaded, allocate array klass
|
||||
if (klass != NULL) {
|
||||
klass = Klass::cast(klass)->array_klass_or_null(fd.dimension());
|
||||
klass = klass->array_klass_or_null(fd.dimension());
|
||||
}
|
||||
} else {
|
||||
MutexLocker mu(SystemDictionary_lock, THREAD);
|
||||
@ -2466,9 +2466,9 @@ Handle SystemDictionary::find_method_handle_type(Symbol* signature,
|
||||
Klass* sel_klass = java_lang_Class::as_Klass(mirror);
|
||||
mirror = NULL; // safety
|
||||
// Emulate ConstantPool::verify_constant_pool_resolve.
|
||||
if (Klass::cast(sel_klass)->oop_is_objArray())
|
||||
if (sel_klass->oop_is_objArray())
|
||||
sel_klass = ObjArrayKlass::cast(sel_klass)->bottom_klass();
|
||||
if (Klass::cast(sel_klass)->oop_is_instance()) {
|
||||
if (sel_klass->oop_is_instance()) {
|
||||
KlassHandle sel_kh(THREAD, sel_klass);
|
||||
LinkResolver::check_klass_accessability(accessing_klass, sel_kh, CHECK_(empty));
|
||||
}
|
||||
|
||||
@ -137,6 +137,7 @@ class SymbolPropertyTable;
|
||||
/* NOTE: needed too early in bootstrapping process to have checks based on JDK version */ \
|
||||
/* Universe::is_gte_jdk14x_version() is not set up by this point. */ \
|
||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||
do_klass(lambda_MagicLambdaImpl_klass, java_lang_invoke_MagicLambdaImpl, Opt ) \
|
||||
do_klass(reflect_MagicAccessorImpl_klass, sun_reflect_MagicAccessorImpl, Opt ) \
|
||||
do_klass(reflect_MethodAccessorImpl_klass, sun_reflect_MethodAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
do_klass(reflect_ConstructorAccessorImpl_klass, sun_reflect_ConstructorAccessorImpl, Opt_Only_JDK14NewRef) \
|
||||
|
||||
@ -446,7 +446,7 @@ void ErrorContext::location_details(outputStream* ss, Method* method) const {
|
||||
bytecode_name = "<illegal>";
|
||||
}
|
||||
}
|
||||
InstanceKlass* ik = InstanceKlass::cast(method->method_holder());
|
||||
InstanceKlass* ik = method->method_holder();
|
||||
ss->indent().print_cr("Location:");
|
||||
streamIndentor si2(ss);
|
||||
ss->indent().print_cr("%s.%s%s @%d: %s",
|
||||
@ -555,9 +555,10 @@ void ClassVerifier::verify_class(TRAPS) {
|
||||
if (was_recursively_verified()) return;
|
||||
|
||||
Method* m = methods->at(index);
|
||||
if (m->is_native() || m->is_abstract()) {
|
||||
if (m->is_native() || m->is_abstract() || m->is_overpass()) {
|
||||
// If m is native or abstract, skip it. It is checked in class file
|
||||
// parser that methods do not override a final method.
|
||||
// parser that methods do not override a final method. Overpass methods
|
||||
// are trusted since the VM generates them.
|
||||
continue;
|
||||
}
|
||||
verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
|
||||
@ -1849,7 +1850,7 @@ void ClassVerifier::verify_cp_index(
|
||||
if ((index <= 0) || (index >= nconstants)) {
|
||||
verify_error(ErrorContext::bad_cp_index(bci, index),
|
||||
"Illegal constant pool index %d in class %s",
|
||||
index, InstanceKlass::cast(cp->pool_holder())->external_name());
|
||||
index, cp->pool_holder()->external_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1868,7 +1869,7 @@ void ClassVerifier::verify_cp_type(
|
||||
if ((types & (1 << tag)) == 0) {
|
||||
verify_error(ErrorContext::bad_cp_index(bci, index),
|
||||
"Illegal type at constant pool entry %d in class %s",
|
||||
index, InstanceKlass::cast(cp->pool_holder())->external_name());
|
||||
index, cp->pool_holder()->external_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1880,7 +1881,7 @@ void ClassVerifier::verify_cp_class_type(
|
||||
if (!tag.is_klass() && !tag.is_unresolved_klass()) {
|
||||
verify_error(ErrorContext::bad_cp_index(bci, index),
|
||||
"Illegal type at constant pool entry %d in class %s",
|
||||
index, InstanceKlass::cast(cp->pool_holder())->external_name());
|
||||
index, cp->pool_holder()->external_name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -2304,11 +2305,21 @@ void ClassVerifier::verify_invoke_instructions(
|
||||
// Make sure the constant pool item is the right type
|
||||
u2 index = bcs->get_index_u2();
|
||||
Bytecodes::Code opcode = bcs->raw_code();
|
||||
unsigned int types = (opcode == Bytecodes::_invokeinterface
|
||||
? 1 << JVM_CONSTANT_InterfaceMethodref
|
||||
: opcode == Bytecodes::_invokedynamic
|
||||
? 1 << JVM_CONSTANT_InvokeDynamic
|
||||
: 1 << JVM_CONSTANT_Methodref);
|
||||
unsigned int types;
|
||||
switch (opcode) {
|
||||
case Bytecodes::_invokeinterface:
|
||||
types = 1 << JVM_CONSTANT_InterfaceMethodref;
|
||||
break;
|
||||
case Bytecodes::_invokedynamic:
|
||||
types = 1 << JVM_CONSTANT_InvokeDynamic;
|
||||
break;
|
||||
case Bytecodes::_invokespecial:
|
||||
types = (1 << JVM_CONSTANT_InterfaceMethodref) |
|
||||
(1 << JVM_CONSTANT_Methodref);
|
||||
break;
|
||||
default:
|
||||
types = 1 << JVM_CONSTANT_Methodref;
|
||||
}
|
||||
verify_cp_type(bcs->bci(), index, cp, types, CHECK_VERIFY(this));
|
||||
|
||||
// Get method name and signature
|
||||
|
||||
@ -507,7 +507,7 @@ static vmIntrinsics::ID match_method_with_klass(Method* m, Symbol* mk) {
|
||||
}
|
||||
|
||||
void vmIntrinsics::verify_method(ID actual_id, Method* m) {
|
||||
Symbol* mk = Klass::cast(m->method_holder())->name();
|
||||
Symbol* mk = m->method_holder()->name();
|
||||
ID declared_id = match_method_with_klass(m, mk);
|
||||
|
||||
if (declared_id == actual_id) return; // success
|
||||
|
||||
@ -259,6 +259,7 @@
|
||||
template(java_lang_invoke_DontInline_signature, "Ljava/lang/invoke/DontInline;") \
|
||||
template(java_lang_invoke_LambdaForm_Compiled_signature, "Ljava/lang/invoke/LambdaForm$Compiled;") \
|
||||
template(java_lang_invoke_LambdaForm_Hidden_signature, "Ljava/lang/invoke/LambdaForm$Hidden;") \
|
||||
template(java_lang_invoke_MagicLambdaImpl, "java/lang/invoke/MagicLambdaImpl") \
|
||||
/* internal up-calls made only by the JVM, via class sun.invoke.MethodHandleNatives: */ \
|
||||
template(findMethodHandleType_name, "findMethodHandleType") \
|
||||
template(findMethodHandleType_signature, "(Ljava/lang/Class;[Ljava/lang/Class;)Ljava/lang/invoke/MethodType;") \
|
||||
|
||||
@ -191,8 +191,8 @@ void CompiledIC::set_to_megamorphic(CallInfo* call_info, Bytecodes::Code bytecod
|
||||
int index = klassItable::compute_itable_index(call_info->resolved_method()());
|
||||
entry = VtableStubs::create_stub(false, index, method());
|
||||
assert(entry != NULL, "entry not computed");
|
||||
Klass* k = call_info->resolved_method()->method_holder();
|
||||
assert(Klass::cast(k)->is_interface(), "sanity check");
|
||||
InstanceKlass* k = call_info->resolved_method()->method_holder();
|
||||
assert(k->is_interface(), "sanity check");
|
||||
InlineCacheBuffer::create_transition_stub(this, k, entry);
|
||||
} else {
|
||||
// Can be different than method->vtable_index(), due to package-private etc.
|
||||
|
||||
@ -552,7 +552,7 @@ void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
|
||||
}
|
||||
tty->print(" %s = %s", what, (put_star? "*": ""));
|
||||
if (arg.is_klass())
|
||||
tty->print("%s", Klass::cast((Klass*)arg.metadata_value())->external_name());
|
||||
tty->print("%s", ((Klass*)arg.metadata_value())->external_name());
|
||||
else if (arg.is_method())
|
||||
((Method*)arg.metadata_value())->print_value();
|
||||
else
|
||||
@ -563,12 +563,13 @@ void Dependencies::print_dependency(DepType dept, int nargs, DepArgument args[],
|
||||
bool put_star = !Dependencies::is_concrete_klass(witness);
|
||||
tty->print_cr(" witness = %s%s",
|
||||
(put_star? "*": ""),
|
||||
Klass::cast(witness)->external_name());
|
||||
witness->external_name());
|
||||
}
|
||||
}
|
||||
|
||||
void Dependencies::DepStream::log_dependency(Klass* witness) {
|
||||
if (_deps == NULL && xtty == NULL) return; // fast cutout for runtime
|
||||
ResourceMark rm;
|
||||
int nargs = argument_count();
|
||||
DepArgument args[max_arg_count];
|
||||
for (int j = 0; j < nargs; j++) {
|
||||
@ -808,7 +809,7 @@ class ClassHierarchyWalker {
|
||||
if (!(m->is_public() || m->is_protected()))
|
||||
// The override story is complex when packages get involved.
|
||||
return true; // Must punt the assertion to true.
|
||||
Klass* k = Klass::cast(ctxk);
|
||||
Klass* k = ctxk;
|
||||
Method* lm = k->lookup_method(m->name(), m->signature());
|
||||
if (lm == NULL && k->oop_is_instance()) {
|
||||
// It might be an abstract interface method, devoid of mirandas.
|
||||
@ -829,13 +830,13 @@ class ClassHierarchyWalker {
|
||||
}
|
||||
if ( !Dependencies::is_concrete_method(lm)
|
||||
&& !Dependencies::is_concrete_method(m)
|
||||
&& Klass::cast(lm->method_holder())->is_subtype_of(m->method_holder()))
|
||||
&& lm->method_holder()->is_subtype_of(m->method_holder()))
|
||||
// Method m is overridden by lm, but both are non-concrete.
|
||||
return true;
|
||||
}
|
||||
ResourceMark rm;
|
||||
tty->print_cr("Dependency method not found in the associated context:");
|
||||
tty->print_cr(" context = %s", Klass::cast(ctxk)->external_name());
|
||||
tty->print_cr(" context = %s", ctxk->external_name());
|
||||
tty->print( " method = "); m->print_short_name(tty); tty->cr();
|
||||
if (lm != NULL) {
|
||||
tty->print( " found = "); lm->print_short_name(tty); tty->cr();
|
||||
@ -1010,7 +1011,7 @@ Klass* ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
|
||||
for (int i = 0; i < num_participants(); i++) {
|
||||
Klass* part = participant(i);
|
||||
if (part == NULL) continue;
|
||||
assert(changes.involves_context(part) == Klass::cast(new_type)->is_subtype_of(part),
|
||||
assert(changes.involves_context(part) == new_type->is_subtype_of(part),
|
||||
"correct marking of participants, b/c new_type is unique");
|
||||
if (changes.involves_context(part)) {
|
||||
// new guy is protected from this check by previous participant
|
||||
@ -1146,7 +1147,7 @@ Klass* ClassHierarchyWalker::find_witness_anywhere(Klass* context_type,
|
||||
|
||||
|
||||
bool Dependencies::is_concrete_klass(Klass* k) {
|
||||
if (Klass::cast(k)->is_abstract()) return false;
|
||||
if (k->is_abstract()) return false;
|
||||
// %%% We could treat classes which are concrete but
|
||||
// have not yet been instantiated as virtually abstract.
|
||||
// This would require a deoptimization barrier on first instantiation.
|
||||
@ -1160,7 +1161,11 @@ bool Dependencies::is_concrete_method(Method* m) {
|
||||
|
||||
// We could also return false if m does not yet appear to be
|
||||
// executed, if the VM version supports this distinction also.
|
||||
return !m->is_abstract();
|
||||
return !m->is_abstract() &&
|
||||
!InstanceKlass::cast(m->method_holder())->is_interface();
|
||||
// TODO: investigate whether default methods should be
|
||||
// considered as "concrete" in this situation. For now they
|
||||
// are not.
|
||||
}
|
||||
|
||||
|
||||
@ -1701,12 +1706,12 @@ KlassDepChange::~KlassDepChange() {
|
||||
}
|
||||
|
||||
bool KlassDepChange::involves_context(Klass* k) {
|
||||
if (k == NULL || !Klass::cast(k)->oop_is_instance()) {
|
||||
if (k == NULL || !k->oop_is_instance()) {
|
||||
return false;
|
||||
}
|
||||
InstanceKlass* ik = InstanceKlass::cast(k);
|
||||
bool is_contained = ik->is_marked_dependent();
|
||||
assert(is_contained == Klass::cast(new_type())->is_subtype_of(k),
|
||||
assert(is_contained == new_type()->is_subtype_of(k),
|
||||
"correct marking of potential context types");
|
||||
return is_contained;
|
||||
}
|
||||
|
||||
@ -1263,7 +1263,7 @@ void nmethod::invalidate_osr_method() {
|
||||
assert(_entry_bci != InvocationEntryBci, "wrong kind of nmethod");
|
||||
// Remove from list of active nmethods
|
||||
if (method() != NULL)
|
||||
InstanceKlass::cast(method()->method_holder())->remove_osr_nmethod(this);
|
||||
method()->method_holder()->remove_osr_nmethod(this);
|
||||
// Set entry as invalid
|
||||
_entry_bci = InvalidOSREntryBci;
|
||||
}
|
||||
@ -2568,9 +2568,8 @@ void nmethod::print_dependencies() {
|
||||
deps.print_dependency();
|
||||
Klass* ctxk = deps.context_type();
|
||||
if (ctxk != NULL) {
|
||||
Klass* k = Klass::cast(ctxk);
|
||||
if (k->oop_is_instance() && ((InstanceKlass*)k)->is_dependent_nmethod(this)) {
|
||||
tty->print_cr(" [nmethod<=klass]%s", k->external_name());
|
||||
if (ctxk->oop_is_instance() && ((InstanceKlass*)ctxk)->is_dependent_nmethod(this)) {
|
||||
tty->print_cr(" [nmethod<=klass]%s", ctxk->external_name());
|
||||
}
|
||||
}
|
||||
deps.log_dependency(); // put it into the xml log also
|
||||
|
||||
@ -1051,7 +1051,7 @@ void CompileBroker::compile_method_base(methodHandle method,
|
||||
guarantee(!method->is_abstract(), "cannot compile abstract methods");
|
||||
assert(method->method_holder()->oop_is_instance(),
|
||||
"sanity check");
|
||||
assert(!InstanceKlass::cast(method->method_holder())->is_not_initialized(),
|
||||
assert(!method->method_holder()->is_not_initialized(),
|
||||
"method holder must be initialized");
|
||||
assert(!method->is_method_handle_intrinsic(), "do not enqueue these guys");
|
||||
|
||||
@ -1206,7 +1206,7 @@ nmethod* CompileBroker::compile_method(methodHandle method, int osr_bci,
|
||||
assert(method->method_holder()->oop_is_instance(), "not an instance method");
|
||||
assert(osr_bci == InvocationEntryBci || (0 <= osr_bci && osr_bci < method->code_size()), "bci out of range");
|
||||
assert(!method->is_abstract() && (osr_bci == InvocationEntryBci || !method->is_native()), "cannot compile abstract/native methods");
|
||||
assert(!InstanceKlass::cast(method->method_holder())->is_not_initialized(), "method holder must be initialized");
|
||||
assert(!method->method_holder()->is_not_initialized(), "method holder must be initialized");
|
||||
|
||||
if (!TieredCompilation) {
|
||||
comp_level = CompLevel_highest_tier;
|
||||
|
||||
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