mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-28 15:24:43 +02:00
Merge
This commit is contained in:
commit
8e6c71d7c2
1098 changed files with 42544 additions and 11465 deletions
3
.hgtags
3
.hgtags
|
@ -331,3 +331,6 @@ f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83
|
||||||
7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86
|
7db0663a5e968059fa7c772172187ebd60b6492d jdk9-b86
|
||||||
1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87
|
1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87
|
||||||
16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88
|
16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88
|
||||||
|
4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89
|
||||||
|
d131f4b8433a79408f935eff9bf92a0664229b60 jdk9-b90
|
||||||
|
8077fd2f055d31e50b46fcf62d9c035bc385a215 jdk9-b91
|
||||||
|
|
|
@ -331,3 +331,6 @@ ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
|
||||||
2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86
|
2aa1daf98d3e2ee37f20f6858c53cc37020f6937 jdk9-b86
|
||||||
fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87
|
fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87
|
||||||
0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88
|
0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88
|
||||||
|
895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89
|
||||||
|
cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90
|
||||||
|
122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91
|
||||||
|
|
|
@ -283,6 +283,7 @@ AC_DEFUN([BASIC_CHECK_LEFTOVER_OVERRIDDEN],
|
||||||
# use that value, otherwise search for the tool using the supplied code snippet.
|
# use that value, otherwise search for the tool using the supplied code snippet.
|
||||||
# $1: variable to set
|
# $1: variable to set
|
||||||
# $2: code snippet to call to look for the tool
|
# $2: code snippet to call to look for the tool
|
||||||
|
# $3: code snippet to call if variable was used to find tool
|
||||||
AC_DEFUN([BASIC_SETUP_TOOL],
|
AC_DEFUN([BASIC_SETUP_TOOL],
|
||||||
[
|
[
|
||||||
# Publish this variable in the help.
|
# Publish this variable in the help.
|
||||||
|
@ -340,6 +341,7 @@ AC_DEFUN([BASIC_SETUP_TOOL],
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
$3
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
@ -848,17 +850,8 @@ AC_DEFUN([BASIC_CHECK_MAKE_OUTPUT_SYNC],
|
||||||
# Goes looking for a usable version of GNU make.
|
# Goes looking for a usable version of GNU make.
|
||||||
AC_DEFUN([BASIC_CHECK_GNU_MAKE],
|
AC_DEFUN([BASIC_CHECK_GNU_MAKE],
|
||||||
[
|
[
|
||||||
# We need to find a recent version of GNU make. Especially on Solaris, this can be tricky.
|
BASIC_SETUP_TOOL([MAKE],
|
||||||
if test "x$MAKE" != x; then
|
[
|
||||||
# User has supplied a make, test it.
|
|
||||||
if test ! -f "$MAKE"; then
|
|
||||||
AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not found.])
|
|
||||||
fi
|
|
||||||
BASIC_CHECK_MAKE_VERSION("$MAKE", [user supplied MAKE=$MAKE])
|
|
||||||
if test "x$FOUND_MAKE" = x; then
|
|
||||||
AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not GNU make $MAKE_REQUIRED_VERSION or newer.])
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
# Try our hardest to locate a correct version of GNU make
|
# Try our hardest to locate a correct version of GNU make
|
||||||
AC_PATH_PROGS(CHECK_GMAKE, gmake)
|
AC_PATH_PROGS(CHECK_GMAKE, gmake)
|
||||||
BASIC_CHECK_MAKE_VERSION("$CHECK_GMAKE", [gmake in PATH])
|
BASIC_CHECK_MAKE_VERSION("$CHECK_GMAKE", [gmake in PATH])
|
||||||
|
@ -886,7 +879,13 @@ AC_DEFUN([BASIC_CHECK_GNU_MAKE],
|
||||||
if test "x$FOUND_MAKE" = x; then
|
if test "x$FOUND_MAKE" = x; then
|
||||||
AC_MSG_ERROR([Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.])
|
AC_MSG_ERROR([Cannot find GNU make $MAKE_REQUIRED_VERSION or newer! Please put it in the path, or add e.g. MAKE=/opt/gmake3.81/make as argument to configure.])
|
||||||
fi
|
fi
|
||||||
fi
|
],[
|
||||||
|
# If MAKE was set by user, verify the version
|
||||||
|
BASIC_CHECK_MAKE_VERSION("$MAKE", [user supplied MAKE=$MAKE])
|
||||||
|
if test "x$FOUND_MAKE" = x; then
|
||||||
|
AC_MSG_ERROR([The specified make (by MAKE=$MAKE) is not GNU make $MAKE_REQUIRED_VERSION or newer.])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
|
||||||
MAKE=$FOUND_MAKE
|
MAKE=$FOUND_MAKE
|
||||||
AC_SUBST(MAKE)
|
AC_SUBST(MAKE)
|
||||||
|
|
|
@ -86,4 +86,6 @@ fi
|
||||||
$RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
|
$RM $OUTPUT_ROOT/compare.log.old 2> /dev/null
|
||||||
$MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
|
$MV $OUTPUT_ROOT/compare.log $OUTPUT_ROOT/compare.log.old 2> /dev/null
|
||||||
|
|
||||||
|
export SCRIPT_DIR="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
|
||||||
|
|
||||||
$BASH $SRC_ROOT/common/bin/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
|
$BASH $SRC_ROOT/common/bin/logger.sh $OUTPUT_ROOT/compare.log $BASH "$REAL_COMPARE_SCRIPT" "$@"
|
||||||
|
|
|
@ -72,49 +72,50 @@ AC_DEFUN_ONCE([FLAGS_SETUP_USER_SUPPLIED_FLAGS],
|
||||||
# Setup the sysroot flags and add them to global CFLAGS and LDFLAGS so
|
# Setup the sysroot flags and add them to global CFLAGS and LDFLAGS so
|
||||||
# that configure can use them while detecting compilers.
|
# that configure can use them while detecting compilers.
|
||||||
# TOOLCHAIN_TYPE is available here.
|
# TOOLCHAIN_TYPE is available here.
|
||||||
AC_DEFUN_ONCE([FLAGS_SETUP_SYSROOT_FLAGS],
|
# Param 1 - Optional prefix to all variables. (e.g BUILD_)
|
||||||
|
AC_DEFUN([FLAGS_SETUP_SYSROOT_FLAGS],
|
||||||
[
|
[
|
||||||
if test "x$SYSROOT" != "x"; then
|
if test "x[$]$1SYSROOT" != "x"; then
|
||||||
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
||||||
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
|
if test "x$OPENJDK_TARGET_OS" = xsolaris; then
|
||||||
# Solaris Studio does not have a concept of sysroot. Instead we must
|
# Solaris Studio does not have a concept of sysroot. Instead we must
|
||||||
# make sure the default include and lib dirs are appended to each
|
# make sure the default include and lib dirs are appended to each
|
||||||
# compile and link command line.
|
# compile and link command line.
|
||||||
SYSROOT_CFLAGS="-I$SYSROOT/usr/include"
|
$1SYSROOT_CFLAGS="-I[$]$1SYSROOT/usr/include"
|
||||||
SYSROOT_LDFLAGS="-L$SYSROOT/usr/lib$OPENJDK_TARGET_CPU_ISADIR \
|
$1SYSROOT_LDFLAGS="-L[$]$1SYSROOT/usr/lib$OPENJDK_TARGET_CPU_ISADIR \
|
||||||
-L$SYSROOT/lib$OPENJDK_TARGET_CPU_ISADIR \
|
-L[$]$1SYSROOT/lib$OPENJDK_TARGET_CPU_ISADIR \
|
||||||
-L$SYSROOT/usr/ccs/lib$OPENJDK_TARGET_CPU_ISADIR"
|
-L[$]$1SYSROOT/usr/ccs/lib$OPENJDK_TARGET_CPU_ISADIR"
|
||||||
fi
|
fi
|
||||||
elif test "x$TOOLCHAIN_TYPE" = xgcc; then
|
elif test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||||
SYSROOT_CFLAGS="--sysroot=$SYSROOT"
|
$1SYSROOT_CFLAGS="--sysroot=[$]$1SYSROOT"
|
||||||
SYSROOT_LDFLAGS="--sysroot=$SYSROOT"
|
$1SYSROOT_LDFLAGS="--sysroot=[$]$1SYSROOT"
|
||||||
elif test "x$TOOLCHAIN_TYPE" = xclang; then
|
elif test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||||
SYSROOT_CFLAGS="-isysroot $SYSROOT"
|
$1SYSROOT_CFLAGS="-isysroot [$]$1SYSROOT"
|
||||||
SYSROOT_LDFLAGS="-isysroot $SYSROOT"
|
$1SYSROOT_LDFLAGS="-isysroot [$]$1SYSROOT"
|
||||||
fi
|
fi
|
||||||
# Propagate the sysroot args to hotspot
|
# Propagate the sysroot args to hotspot
|
||||||
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $SYSROOT_CFLAGS"
|
$1LEGACY_EXTRA_CFLAGS="[$]$1LEGACY_EXTRA_CFLAGS [$]$1SYSROOT_CFLAGS"
|
||||||
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $SYSROOT_CFLAGS"
|
$1LEGACY_EXTRA_CXXFLAGS="[$]$1LEGACY_EXTRA_CXXFLAGS [$]$1SYSROOT_CFLAGS"
|
||||||
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $SYSROOT_LDFLAGS"
|
$1LEGACY_EXTRA_LDFLAGS="[$]$1LEGACY_EXTRA_LDFLAGS [$]$1SYSROOT_LDFLAGS"
|
||||||
# The global CFLAGS and LDFLAGS variables need these for configure to function
|
# The global CFLAGS and LDFLAGS variables need these for configure to function
|
||||||
CFLAGS="$CFLAGS $SYSROOT_CFLAGS"
|
$1CFLAGS="[$]$1CFLAGS [$]$1SYSROOT_CFLAGS"
|
||||||
CPPFLAGS="$CPPFLAGS $SYSROOT_CFLAGS"
|
$1CPPFLAGS="[$]$1CPPFLAGS [$]$1SYSROOT_CFLAGS"
|
||||||
CXXFLAGS="$CXXFLAGS $SYSROOT_CFLAGS"
|
$1CXXFLAGS="[$]$1CXXFLAGS [$]$1SYSROOT_CFLAGS"
|
||||||
LDFLAGS="$LDFLAGS $SYSROOT_LDFLAGS"
|
$1LDFLAGS="[$]$1LDFLAGS [$]$1SYSROOT_LDFLAGS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||||
# We also need -iframework<path>/System/Library/Frameworks
|
# We also need -iframework<path>/System/Library/Frameworks
|
||||||
SYSROOT_CFLAGS="$SYSROOT_CFLAGS -iframework $SYSROOT/System/Library/Frameworks"
|
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -iframework [$]$1SYSROOT/System/Library/Frameworks"
|
||||||
SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS -iframework $SYSROOT/System/Library/Frameworks"
|
$1SYSROOT_LDFLAGS="[$]$1SYSROOT_LDFLAGS -iframework [$]$1SYSROOT/System/Library/Frameworks"
|
||||||
# These always need to be set, or we can't find the frameworks embedded in JavaVM.framework
|
# These always need to be set, or we can't find the frameworks embedded in JavaVM.framework
|
||||||
# set this here so it doesn't have to be peppered throughout the forest
|
# set this here so it doesn't have to be peppered throughout the forest
|
||||||
SYSROOT_CFLAGS="$SYSROOT_CFLAGS -F $SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||||
SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS -F $SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
$1SYSROOT_LDFLAGS="[$]$1SYSROOT_LDFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(SYSROOT_CFLAGS)
|
AC_SUBST($1SYSROOT_CFLAGS)
|
||||||
AC_SUBST(SYSROOT_LDFLAGS)
|
AC_SUBST($1SYSROOT_LDFLAGS)
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS],
|
AC_DEFUN_ONCE([FLAGS_SETUP_INIT_FLAGS],
|
||||||
|
@ -785,7 +786,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
|
||||||
LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext"
|
LDFLAGS_JDK="$LDFLAGS_JDK -z defs -xildoff -ztext"
|
||||||
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib"
|
LDFLAGS_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib"
|
||||||
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
|
elif test "x$TOOLCHAIN_TYPE" = xxlc; then
|
||||||
LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -liconv -bexpall -bernotok"
|
LDFLAGS_JDK="${LDFLAGS_JDK} -brtl -bnolibpath -bexpall -bernotok"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Customize LDFLAGS for executables
|
# Customize LDFLAGS for executables
|
||||||
|
@ -808,7 +809,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
|
||||||
|
|
||||||
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -dll -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
|
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -dll -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
|
||||||
LDFLAGS_JDKLIB_SUFFIX=""
|
JDKLIB_LIBS=""
|
||||||
else
|
else
|
||||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS} \
|
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS} \
|
||||||
-L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
|
-L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}"
|
||||||
|
@ -827,27 +828,23 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
|
||||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
|
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -L${OUTPUT_ROOT}/support/modules_libs/java.base${OPENJDK_TARGET_CPU_LIBDIR}/server"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
LDFLAGS_JDKLIB_SUFFIX="-ljava -ljvm"
|
JDKLIB_LIBS="-ljava -ljvm"
|
||||||
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
||||||
LDFLAGS_JDKLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX -lc"
|
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_SUBST(LDFLAGS_JDKLIB)
|
AC_SUBST(LDFLAGS_JDKLIB)
|
||||||
AC_SUBST(LDFLAGS_JDKEXE)
|
AC_SUBST(LDFLAGS_JDKEXE)
|
||||||
AC_SUBST(LDFLAGS_JDKLIB_SUFFIX)
|
AC_SUBST(JDKLIB_LIBS)
|
||||||
AC_SUBST(LDFLAGS_JDKEXE_SUFFIX)
|
AC_SUBST(JDKEXE_LIBS)
|
||||||
AC_SUBST(LDFLAGS_CXX_JDK)
|
AC_SUBST(LDFLAGS_CXX_JDK)
|
||||||
|
|
||||||
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
|
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
|
||||||
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
|
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
|
||||||
LDFLAGS_TESTLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX"
|
|
||||||
LDFLAGS_TESTEXE_SUFFIX="$LDFLAGS_JDKEXE_SUFFIX"
|
|
||||||
|
|
||||||
AC_SUBST(LDFLAGS_TESTLIB)
|
AC_SUBST(LDFLAGS_TESTLIB)
|
||||||
AC_SUBST(LDFLAGS_TESTEXE)
|
AC_SUBST(LDFLAGS_TESTEXE)
|
||||||
AC_SUBST(LDFLAGS_TESTLIB_SUFFIX)
|
|
||||||
AC_SUBST(LDFLAGS_TESTEXE_SUFFIX)
|
|
||||||
])
|
])
|
||||||
|
|
||||||
# FLAGS_COMPILER_CHECK_ARGUMENTS([ARGUMENT], [RUN-IF-TRUE],
|
# FLAGS_COMPILER_CHECK_ARGUMENTS([ARGUMENT], [RUN-IF-TRUE],
|
||||||
|
@ -945,7 +942,16 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
|
||||||
else
|
else
|
||||||
AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
|
AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if test "x$WARNINGS_AS_ERRORS" = "xfalse"; then
|
||||||
|
# Set legacy hotspot variable
|
||||||
|
HOTSPOT_SET_WARNINGS_AS_ERRORS="WARNINGS_ARE_ERRORS="
|
||||||
|
else
|
||||||
|
HOTSPOT_SET_WARNINGS_AS_ERRORS=""
|
||||||
|
fi
|
||||||
|
|
||||||
AC_SUBST(WARNINGS_AS_ERRORS)
|
AC_SUBST(WARNINGS_AS_ERRORS)
|
||||||
|
AC_SUBST(HOTSPOT_SET_WARNINGS_AS_ERRORS)
|
||||||
|
|
||||||
case "${TOOLCHAIN_TYPE}" in
|
case "${TOOLCHAIN_TYPE}" in
|
||||||
microsoft)
|
microsoft)
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -33,6 +33,7 @@ include $(BASE_SPEC)
|
||||||
# Additional legacy variables defined for Hotspot
|
# Additional legacy variables defined for Hotspot
|
||||||
|
|
||||||
@SET_OPENJDK@
|
@SET_OPENJDK@
|
||||||
|
@HOTSPOT_SET_WARNINGS_AS_ERRORS@
|
||||||
|
|
||||||
# Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options.
|
# Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options.
|
||||||
@BUILD_HEADLESS@
|
@BUILD_HEADLESS@
|
||||||
|
|
|
@ -37,8 +37,10 @@ AC_DEFUN_ONCE([LIB_SETUP_ALSA],
|
||||||
[specify directory for the alsa library])])
|
[specify directory for the alsa library])])
|
||||||
|
|
||||||
if test "x$NEEDS_LIB_ALSA" = xfalse; then
|
if test "x$NEEDS_LIB_ALSA" = xfalse; then
|
||||||
if test "x${with_alsa}" != x || test "x${with_alsa_include}" != x || test "x${with_alsa_lib}" != x; then
|
if (test "x${with_alsa}" != x && test "x${with_alsa}" != xno) || \
|
||||||
AC_MSG_WARN([alsa not used, so --with-alsa is ignored])
|
(test "x${with_alsa_include}" != x && test "x${with_alsa_include}" != xno) || \
|
||||||
|
(test "x${with_alsa_lib}" != x && test "x${with_alsa_lib}" != xno); then
|
||||||
|
AC_MSG_WARN([[alsa not used, so --with-alsa[-*] is ignored]])
|
||||||
fi
|
fi
|
||||||
ALSA_CFLAGS=
|
ALSA_CFLAGS=
|
||||||
ALSA_LIBS=
|
ALSA_LIBS=
|
||||||
|
|
|
@ -35,8 +35,9 @@ AC_DEFUN_ONCE([LIB_SETUP_CUPS],
|
||||||
[specify directory for the cups include files])])
|
[specify directory for the cups include files])])
|
||||||
|
|
||||||
if test "x$NEEDS_LIB_CUPS" = xfalse; then
|
if test "x$NEEDS_LIB_CUPS" = xfalse; then
|
||||||
if test "x${with_cups}" != x || test "x${with_cups_include}" != x; then
|
if (test "x${with_cups}" != x && test "x${with_cups}" != xno) || \
|
||||||
AC_MSG_WARN([cups not used, so --with-cups is ignored])
|
(test "x${with_cups_include}" != x && test "x${with_cups_include}" != xno); then
|
||||||
|
AC_MSG_WARN([[cups not used, so --with-cups[-*] is ignored]])
|
||||||
fi
|
fi
|
||||||
CUPS_CFLAGS=
|
CUPS_CFLAGS=
|
||||||
else
|
else
|
||||||
|
|
|
@ -37,8 +37,10 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
|
||||||
[specify directory for the libffi library])])
|
[specify directory for the libffi library])])
|
||||||
|
|
||||||
if test "x$NEEDS_LIB_FFI" = xfalse; then
|
if test "x$NEEDS_LIB_FFI" = xfalse; then
|
||||||
if test "x${with_libffi}" != x || test "x${with_libffi_include}" != x || test "x${with_libffi_lib}" != x; then
|
if (test "x${with_libffi}" != x && test "x${with_libffi}" != xno) || \
|
||||||
AC_MSG_WARN([libffi not used, so --with-libffi is ignored])
|
(test "x${with_libffi_include}" != x && test "x${with_libffi_include}" != xno) || \
|
||||||
|
(test "x${with_libffi_lib}" != x && test "x${with_libffi_lib}" != xno); then
|
||||||
|
AC_MSG_WARN([[libffi not used, so --with-libffi[-*] is ignored]])
|
||||||
fi
|
fi
|
||||||
LIBFFI_CFLAGS=
|
LIBFFI_CFLAGS=
|
||||||
LIBFFI_LIBS=
|
LIBFFI_LIBS=
|
||||||
|
|
|
@ -202,10 +202,13 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
|
||||||
FREETYPE_BUNDLE_LIB_PATH=
|
FREETYPE_BUNDLE_LIB_PATH=
|
||||||
|
|
||||||
if test "x$NEEDS_LIB_FREETYPE" = xfalse; then
|
if test "x$NEEDS_LIB_FREETYPE" = xfalse; then
|
||||||
if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x || test "x$with_freetype_src" != x; then
|
if (test "x$with_freetype" != x && test "x$with_freetype" != xno) || \
|
||||||
AC_MSG_WARN([freetype not used, so --with-freetype is ignored])
|
(test "x$with_freetype_include" != x && test "x$with_freetype_include" != xno) || \
|
||||||
|
(test "x$with_freetype_lib" != x && test "x$with_freetype_lib" != xno) || \
|
||||||
|
(test "x$with_freetype_src" != x && test "x$with_freetype_src" != xno); then
|
||||||
|
AC_MSG_WARN([[freetype not used, so --with-freetype[-*] is ignored]])
|
||||||
fi
|
fi
|
||||||
if test "x$enable_freetype_bundling" != x; then
|
if (test "x$enable_freetype_bundling" != x && test "x$enable_freetype_bundling" != xno); then
|
||||||
AC_MSG_WARN([freetype not used, so --enable-freetype-bundling is ignored])
|
AC_MSG_WARN([freetype not used, so --enable-freetype-bundling is ignored])
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
AC_DEFUN_ONCE([LIB_SETUP_X11],
|
AC_DEFUN_ONCE([LIB_SETUP_X11],
|
||||||
[
|
[
|
||||||
if test "x$NEEDS_LIB_X11" = xfalse; then
|
if test "x$NEEDS_LIB_X11" = xfalse; then
|
||||||
if test "x${with_x}" != x; then
|
if (test "x${with_x}" != x && test "x${with_x}" != xno); then
|
||||||
AC_MSG_WARN([X11 is not used, so --with-x is ignored])
|
AC_MSG_WARN([X11 is not used, so --with-x is ignored])
|
||||||
fi
|
fi
|
||||||
X_CFLAGS=
|
X_CFLAGS=
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
#
|
#
|
||||||
# This code is free software; you can redistribute it and/or modify it
|
# This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -25,8 +25,7 @@
|
||||||
|
|
||||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
||||||
[
|
[
|
||||||
# Where are the sources. Any of these can be overridden
|
# Where are the sources.
|
||||||
# using --with-override-corba and the likes.
|
|
||||||
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
||||||
CORBA_TOPDIR="$SRC_ROOT/corba"
|
CORBA_TOPDIR="$SRC_ROOT/corba"
|
||||||
JAXP_TOPDIR="$SRC_ROOT/jaxp"
|
JAXP_TOPDIR="$SRC_ROOT/jaxp"
|
||||||
|
@ -43,216 +42,20 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
||||||
AC_SUBST(JDK_TOPDIR)
|
AC_SUBST(JDK_TOPDIR)
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS],
|
AC_DEFUN_ONCE([SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS],
|
||||||
[
|
[
|
||||||
|
# This feature is no longer supported.
|
||||||
|
|
||||||
###############################################################################
|
BASIC_DEPRECATED_ARG_WITH(add-source-root)
|
||||||
#
|
BASIC_DEPRECATED_ARG_WITH(override-source-root)
|
||||||
# Pickup additional source for a component from outside of the source root
|
BASIC_DEPRECATED_ARG_WITH(adds-and-overrides)
|
||||||
# or override source for a component.
|
BASIC_DEPRECATED_ARG_WITH(override-langtools)
|
||||||
#
|
BASIC_DEPRECATED_ARG_WITH(override-corba)
|
||||||
AC_ARG_WITH(add-source-root, [AS_HELP_STRING([--with-add-source-root],
|
BASIC_DEPRECATED_ARG_WITH(override-jaxp)
|
||||||
[for each and every source directory, look in this additional source root for
|
BASIC_DEPRECATED_ARG_WITH(override-jaxws)
|
||||||
the same directory; if it exists and have files in it, include it in the build])])
|
BASIC_DEPRECATED_ARG_WITH(override-hotspot)
|
||||||
|
BASIC_DEPRECATED_ARG_WITH(override-nashorn)
|
||||||
AC_ARG_WITH(override-source-root, [AS_HELP_STRING([--with-override-source-root],
|
BASIC_DEPRECATED_ARG_WITH(override-jdk)
|
||||||
[for each and every source directory, look in this override source root for
|
|
||||||
the same directory; if it exists, use that directory instead and
|
|
||||||
ignore the directory in the original source root])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(adds-and-overrides, [AS_HELP_STRING([--with-adds-and-overrides],
|
|
||||||
[use the subdirs 'adds' and 'overrides' in the specified directory as
|
|
||||||
add-source-root and override-source-root])])
|
|
||||||
|
|
||||||
if test "x$with_adds_and_overrides" != x; then
|
|
||||||
with_add_source_root="$with_adds_and_overrides/adds"
|
|
||||||
with_override_source_root="$with_adds_and_overrides/overrides"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$with_add_source_root" != x; then
|
|
||||||
if ! test -d $with_add_source_root; then
|
|
||||||
AC_MSG_ERROR([Trying to use a non-existant add-source-root $with_add_source_root])
|
|
||||||
fi
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_add_source_root"
|
|
||||||
ADD_SRC_ROOT="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
# Verify that the addon source root does not have any root makefiles.
|
|
||||||
# If it does, then it is usually an error, prevent this.
|
|
||||||
if test -f $with_add_source_root/langtools/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full langtools repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
if test -f $with_add_source_root/corba/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full corba repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
if test -f $with_add_source_root/jaxp/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full jaxp repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
if test -f $with_add_source_root/jaxws/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full jaxws repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
if test -f $with_add_source_root/hotspot/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full hotspot repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
if test -f $with_add_source_root/nashorn/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full nashorn repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
if test -f $with_add_source_root/jdk/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your add source root seems to contain a full JDK repo! An add source root should only contain additional sources.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(ADD_SRC_ROOT)
|
|
||||||
|
|
||||||
if test "x$with_override_source_root" != x; then
|
|
||||||
if ! test -d $with_override_source_root; then
|
|
||||||
AC_MSG_ERROR([Trying to use a non-existant override-source-root $with_override_source_root])
|
|
||||||
fi
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_source_root"
|
|
||||||
OVERRIDE_SRC_ROOT="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if test -f $with_override_source_root/langtools/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full langtools repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
if test -f $with_override_source_root/corba/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full corba repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
if test -f $with_override_source_root/jaxp/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full jaxp repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
if test -f $with_override_source_root/jaxws/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full jaxws repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
if test -f $with_override_source_root/hotspot/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full hotspot repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
if test -f $with_override_source_root/nashorn/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full nashorn repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
if test -f $with_override_source_root/jdk/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([Your override source root seems to contain a full JDK repo! An override source root should only contain sources that override.])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
AC_SUBST(OVERRIDE_SRC_ROOT)
|
|
||||||
|
|
||||||
###############################################################################
|
|
||||||
#
|
|
||||||
# Override a repo completely, this is used for example when you have 3 small
|
|
||||||
# development sandboxes of the langtools sources and want to avoid having 3 full
|
|
||||||
# OpenJDK sources checked out on disk.
|
|
||||||
#
|
|
||||||
# Assuming that the 3 langtools sandboxes are located here:
|
|
||||||
# /home/fredrik/sandbox1/langtools
|
|
||||||
# /home/fredrik/sandbox2/langtools
|
|
||||||
# /home/fredrik/sandbox3/langtools
|
|
||||||
#
|
|
||||||
# From the source root you create build subdirs manually:
|
|
||||||
# mkdir -p build1 build2 build3
|
|
||||||
# in each build directory run:
|
|
||||||
# (cd build1 && ../configure --with-override-langtools=/home/fredrik/sandbox1 && make)
|
|
||||||
# (cd build2 && ../configure --with-override-langtools=/home/fredrik/sandbox2 && make)
|
|
||||||
# (cd build3 && ../configure --with-override-langtools=/home/fredrik/sandbox3 && make)
|
|
||||||
#
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-langtools, [AS_HELP_STRING([--with-override-langtools],
|
|
||||||
[use this langtools dir for the build])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-corba, [AS_HELP_STRING([--with-override-corba],
|
|
||||||
[use this corba dir for the build])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-jaxp, [AS_HELP_STRING([--with-override-jaxp],
|
|
||||||
[use this jaxp dir for the build])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-jaxws, [AS_HELP_STRING([--with-override-jaxws],
|
|
||||||
[use this jaxws dir for the build])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-hotspot, [AS_HELP_STRING([--with-override-hotspot],
|
|
||||||
[use this hotspot dir for the build])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-nashorn, [AS_HELP_STRING([--with-override-nashorn],
|
|
||||||
[use this nashorn dir for the build])])
|
|
||||||
|
|
||||||
AC_ARG_WITH(override-jdk, [AS_HELP_STRING([--with-override-jdk],
|
|
||||||
[use this jdk dir for the build])])
|
|
||||||
|
|
||||||
if test "x$with_override_langtools" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_langtools"
|
|
||||||
LANGTOOLS_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $LANGTOOLS_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override langtools with a full langtools repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if langtools should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $LANGTOOLS_TOPDIR])
|
|
||||||
fi
|
|
||||||
if test "x$with_override_corba" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_corba"
|
|
||||||
CORBA_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $CORBA_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override corba with a full corba repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if corba should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $CORBA_TOPDIR])
|
|
||||||
fi
|
|
||||||
if test "x$with_override_jaxp" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_jaxp"
|
|
||||||
JAXP_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $JAXP_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override jaxp with a full jaxp repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if jaxp should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $JAXP_TOPDIR])
|
|
||||||
fi
|
|
||||||
if test "x$with_override_jaxws" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_jaxws"
|
|
||||||
JAXWS_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $JAXWS_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override jaxws with a full jaxws repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if jaxws should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $JAXWS_TOPDIR])
|
|
||||||
fi
|
|
||||||
if test "x$with_override_hotspot" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_hotspot"
|
|
||||||
HOTSPOT_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $HOTSPOT_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override hotspot with a full hotspot repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if hotspot should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $HOTSPOT_TOPDIR])
|
|
||||||
fi
|
|
||||||
if test "x$with_override_nashorn" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_nashorn"
|
|
||||||
NASHORN_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $NASHORN_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override nashorn with a full nashorn repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if nashorn should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $NASHORN_TOPDIR])
|
|
||||||
fi
|
|
||||||
if test "x$with_override_jdk" != x; then
|
|
||||||
CURDIR="$PWD"
|
|
||||||
cd "$with_override_jdk"
|
|
||||||
JDK_TOPDIR="`pwd`"
|
|
||||||
cd "$CURDIR"
|
|
||||||
if ! test -f $JDK_TOPDIR/make/Makefile; then
|
|
||||||
AC_MSG_ERROR([You have to override JDK with a full JDK repo!])
|
|
||||||
fi
|
|
||||||
AC_MSG_CHECKING([if JDK should be overridden])
|
|
||||||
AC_MSG_RESULT([yes with $JDK_TOPDIR])
|
|
||||||
fi
|
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
||||||
|
|
|
@ -113,10 +113,6 @@ endif
|
||||||
SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
|
SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
|
||||||
SYSROOT_LDFLAGS := @SYSROOT_LDFLAGS@
|
SYSROOT_LDFLAGS := @SYSROOT_LDFLAGS@
|
||||||
|
|
||||||
# Paths to the source code
|
|
||||||
ADD_SRC_ROOT:=@ADD_SRC_ROOT@
|
|
||||||
OVERRIDE_SRC_ROOT:=@OVERRIDE_SRC_ROOT@
|
|
||||||
|
|
||||||
# The top-level directory of the forest (SRC_ROOT is a traditional alias)
|
# The top-level directory of the forest (SRC_ROOT is a traditional alias)
|
||||||
TOPDIR:=@TOPDIR@
|
TOPDIR:=@TOPDIR@
|
||||||
# These two versions of TOPDIR are used in string comparisons
|
# These two versions of TOPDIR are used in string comparisons
|
||||||
|
@ -340,11 +336,11 @@ USING_BROKEN_SUSE_LD:=@USING_BROKEN_SUSE_LD@
|
||||||
|
|
||||||
# LDFLAGS used to link the jdk native libraries (C-code)
|
# LDFLAGS used to link the jdk native libraries (C-code)
|
||||||
LDFLAGS_JDKLIB:=@LDFLAGS_JDKLIB@
|
LDFLAGS_JDKLIB:=@LDFLAGS_JDKLIB@
|
||||||
LDFLAGS_JDKLIB_SUFFIX:=@LDFLAGS_JDKLIB_SUFFIX@
|
JDKLIB_LIBS:=@JDKLIB_LIBS@
|
||||||
|
|
||||||
# LDFLAGS used to link the jdk native launchers (C-code)
|
# LDFLAGS used to link the jdk native launchers (C-code)
|
||||||
LDFLAGS_JDKEXE:=@LDFLAGS_JDKEXE@
|
LDFLAGS_JDKEXE:=@LDFLAGS_JDKEXE@
|
||||||
LDFLAGS_JDKEXE_SUFFIX:=@LDFLAGS_JDKEXE_SUFFIX@
|
JDKEXE_LIBS:=@JDKEXE_LIBS@
|
||||||
|
|
||||||
# LDFLAGS specific to C++ linking.
|
# LDFLAGS specific to C++ linking.
|
||||||
LDFLAGS_CXX_JDK:=@LDFLAGS_CXX_JDK@
|
LDFLAGS_CXX_JDK:=@LDFLAGS_CXX_JDK@
|
||||||
|
@ -360,9 +356,7 @@ CXXFLAGS_TESTLIB:=@CXXFLAGS_TESTLIB@
|
||||||
CFLAGS_TESTEXE:=@CFLAGS_TESTEXE@
|
CFLAGS_TESTEXE:=@CFLAGS_TESTEXE@
|
||||||
CXXFLAGS_TESTEXE:=@CXXFLAGS_TESTEXE@
|
CXXFLAGS_TESTEXE:=@CXXFLAGS_TESTEXE@
|
||||||
LDFLAGS_TESTLIB:=@LDFLAGS_TESTLIB@
|
LDFLAGS_TESTLIB:=@LDFLAGS_TESTLIB@
|
||||||
LDFLAGS_TESTLIB_SUFFIX:=@LDFLAGS_TESTLIB_SUFFIX@
|
|
||||||
LDFLAGS_TESTEXE:=@LDFLAGS_TESTEXE@
|
LDFLAGS_TESTEXE:=@LDFLAGS_TESTEXE@
|
||||||
LDFLAGS_TESTEXE_SUFFIX:=@LDFLAGS_TESTEXE_SUFFIX@
|
|
||||||
|
|
||||||
# BUILD_CC/BUILD_LD is a compiler/linker that generates code that is runnable on the
|
# BUILD_CC/BUILD_LD is a compiler/linker that generates code that is runnable on the
|
||||||
# build platform.
|
# build platform.
|
||||||
|
@ -550,34 +544,6 @@ LIBZIP_CAN_USE_MMAP:=@LIBZIP_CAN_USE_MMAP@
|
||||||
MSVCR_DLL:=@MSVCR_DLL@
|
MSVCR_DLL:=@MSVCR_DLL@
|
||||||
MSVCP_DLL:=@MSVCP_DLL@
|
MSVCP_DLL:=@MSVCP_DLL@
|
||||||
|
|
||||||
|
|
||||||
# ADD_SRCS takes a single argument with source roots
|
|
||||||
# and appends any corresponding source roots found
|
|
||||||
# below --with-add-source-root and below
|
|
||||||
# --with-override-source-root. It is the responsibility
|
|
||||||
# of the next macro to get rid of superfluous files.
|
|
||||||
ADD_SRCS=$1
|
|
||||||
ifneq (,$(ADD_SRC_ROOT))
|
|
||||||
# Append wildcard rule to pickup any matching source roots found below ADD_SRC_ROOT
|
|
||||||
ADD_SRCS+=$(wildcard $(subst $(SRC_ROOT),$(ADD_SRC_ROOT),$1))
|
|
||||||
endif
|
|
||||||
ifneq (,$(OVERRIDE_SRC_ROOT))
|
|
||||||
# Append wildcard rule to pickup any matching source roots found below OVERRIDE_SRC_ROOT
|
|
||||||
ADD_SRCS+=$(wildcard $(subst $(SRC_ROOT),$(OVERRIDE_SRC_ROOT),$1))
|
|
||||||
endif
|
|
||||||
|
|
||||||
# OVR_SRCS creates a filter expression to filter out sources in
|
|
||||||
# the original source directory that lie inside directories below
|
|
||||||
# --with-override-source-root.
|
|
||||||
# Use := here since we want to scan for these files here. To avoid recomputation later.
|
|
||||||
# We cannot do the scan in configure, since that would force us to rerun configure when
|
|
||||||
# we add overridden sources.
|
|
||||||
ifneq (,$(OVERRIDE_SRC_ROOT))
|
|
||||||
OVR_SRCS:=$(addsuffix %,$(subst $(OVERRIDE_SRC_ROOT),$(SRC_ROOT),$(sort $(dir $(shell $(FIND) $(OVERRIDE_SRC_ROOT) -type f)))))
|
|
||||||
else
|
|
||||||
OVR_SRCS:=
|
|
||||||
endif
|
|
||||||
|
|
||||||
####################################################
|
####################################################
|
||||||
#
|
#
|
||||||
# INSTALLATION
|
# INSTALLATION
|
||||||
|
|
|
@ -647,17 +647,68 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
|
||||||
# path, otherwise we might pick up cross-compilers which don't use standard
|
# path, otherwise we might pick up cross-compilers which don't use standard
|
||||||
# naming.
|
# naming.
|
||||||
|
|
||||||
|
OLDPATH="$PATH"
|
||||||
|
|
||||||
|
AC_ARG_WITH(build-devkit, [AS_HELP_STRING([--with-build-devkit],
|
||||||
|
[Devkit to use for the build platform toolchain])])
|
||||||
|
if test "x$with_build_devkit" = "xyes"; then
|
||||||
|
AC_MSG_ERROR([--with-build-devkit must have a value])
|
||||||
|
elif test -n "$with_build_devkit"; then
|
||||||
|
if test ! -d "$with_build_devkit"; then
|
||||||
|
AC_MSG_ERROR([--with-build-devkit points to non existing dir: $with_build_devkit])
|
||||||
|
else
|
||||||
|
BASIC_FIXUP_PATH([with_build_devkit])
|
||||||
|
BUILD_DEVKIT_ROOT="$with_build_devkit"
|
||||||
|
# Check for a meta data info file in the root of the devkit
|
||||||
|
if test -f "$BUILD_DEVKIT_ROOT/devkit.info"; then
|
||||||
|
# Process devkit.info so that existing devkit variables are not
|
||||||
|
# modified by this
|
||||||
|
$SED -e "s/^DEVKIT_/BUILD_DEVKIT_/g" \
|
||||||
|
-e "s/\$DEVKIT_ROOT/\$BUILD_DEVKIT_ROOT/g" \
|
||||||
|
-e "s/\$host/\$build/g" \
|
||||||
|
$BUILD_DEVKIT_ROOT/devkit.info \
|
||||||
|
> $CONFIGURESUPPORT_OUTPUTDIR/build-devkit.info
|
||||||
|
. $CONFIGURESUPPORT_OUTPUTDIR/build-devkit.info
|
||||||
|
# This potentially sets the following:
|
||||||
|
# A descriptive name of the devkit
|
||||||
|
BASIC_EVAL_DEVKIT_VARIABLE([BUILD_DEVKIT_NAME])
|
||||||
|
# Corresponds to --with-extra-path
|
||||||
|
BASIC_EVAL_DEVKIT_VARIABLE([BUILD_DEVKIT_EXTRA_PATH])
|
||||||
|
# Corresponds to --with-toolchain-path
|
||||||
|
BASIC_EVAL_DEVKIT_VARIABLE([BUILD_DEVKIT_TOOLCHAIN_PATH])
|
||||||
|
# Corresponds to --with-sysroot
|
||||||
|
BASIC_EVAL_DEVKIT_VARIABLE([BUILD_DEVKIT_SYSROOT])
|
||||||
|
# Skip the Window specific parts
|
||||||
|
fi
|
||||||
|
|
||||||
|
AC_MSG_CHECKING([for build platform devkit])
|
||||||
|
if test "x$BUILD_DEVKIT_NAME" != x; then
|
||||||
|
AC_MSG_RESULT([$BUILD_DEVKIT_NAME in $BUILD_DEVKIT_ROOT])
|
||||||
|
else
|
||||||
|
AC_MSG_RESULT([$BUILD_DEVKIT_ROOT])
|
||||||
|
fi
|
||||||
|
|
||||||
|
BUILD_SYSROOT="$BUILD_DEVKIT_SYSROOT"
|
||||||
|
FLAGS_SETUP_SYSROOT_FLAGS([BUILD_])
|
||||||
|
|
||||||
|
# Fallback default of just /bin if DEVKIT_PATH is not defined
|
||||||
|
if test "x$BUILD_DEVKIT_TOOLCHAIN_PATH" = x; then
|
||||||
|
BUILD_DEVKIT_TOOLCHAIN_PATH="$BUILD_DEVKIT_ROOT/bin"
|
||||||
|
fi
|
||||||
|
PATH="$BUILD_DEVKIT_TOOLCHAIN_PATH:$BUILD_DEVKIT_EXTRA_PATH"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
# FIXME: we should list the discovered compilers as an exclude pattern!
|
# FIXME: we should list the discovered compilers as an exclude pattern!
|
||||||
# If we do that, we can do this detection before POST_DETECTION, and still
|
# If we do that, we can do this detection before POST_DETECTION, and still
|
||||||
# find the build compilers in the tools dir, if needed.
|
# find the build compilers in the tools dir, if needed.
|
||||||
BASIC_PATH_PROGS(BUILD_CC, [cl cc gcc])
|
BASIC_REQUIRE_PROGS(BUILD_CC, [cl cc gcc])
|
||||||
BASIC_FIXUP_EXECUTABLE(BUILD_CC)
|
BASIC_FIXUP_EXECUTABLE(BUILD_CC)
|
||||||
BASIC_PATH_PROGS(BUILD_CXX, [cl CC g++])
|
BASIC_REQUIRE_PROGS(BUILD_CXX, [cl CC g++])
|
||||||
BASIC_FIXUP_EXECUTABLE(BUILD_CXX)
|
BASIC_FIXUP_EXECUTABLE(BUILD_CXX)
|
||||||
BASIC_PATH_PROGS(BUILD_LD, ld)
|
BUILD_LD="$BUILD_CC"
|
||||||
BASIC_FIXUP_EXECUTABLE(BUILD_LD)
|
|
||||||
BUILD_SYSROOT_CFLAGS=""
|
PATH="$OLDPATH"
|
||||||
BUILD_SYSROOT_LDFLAGS=""
|
|
||||||
else
|
else
|
||||||
# If we are not cross compiling, use the normal target compilers for
|
# If we are not cross compiling, use the normal target compilers for
|
||||||
# building the build platform executables.
|
# building the build platform executables.
|
||||||
|
|
|
@ -989,7 +989,7 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
THIS="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
|
THIS="$SCRIPT_DIR"
|
||||||
echo "$THIS"
|
echo "$THIS"
|
||||||
THIS_SCRIPT="$0"
|
THIS_SCRIPT="$0"
|
||||||
|
|
||||||
|
|
|
@ -331,3 +331,6 @@ df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
|
||||||
0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
|
0a3f0d25c201b40575a7c3920fce4d6f4d3ae310 jdk9-b86
|
||||||
a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
|
a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
|
||||||
00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88
|
00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88
|
||||||
|
c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89
|
||||||
|
29cc8228d62319af21cad7c90817671e0813b6bd jdk9-b90
|
||||||
|
75843e0a9371d445a3c9b440bab85e50b5dc287c jdk9-b91
|
||||||
|
|
|
@ -11,3 +11,12 @@
|
||||||
^.hgtip
|
^.hgtip
|
||||||
.DS_Store
|
.DS_Store
|
||||||
\.class$
|
\.class$
|
||||||
|
^\.?mx.jvmci/
|
||||||
|
^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.xml
|
||||||
|
^src/jdk.vm.ci/share/classes/\w[\w\.]*/.*\.iml
|
||||||
|
^src/jdk.vm.ci/share/classes/\w[\w\.]*/nbproject
|
||||||
|
^src/jdk.vm.ci/share/classes/\w[\w\.]*/\..*
|
||||||
|
^test/compiler/jvmci/\w[\w\.]*/.*\.xml
|
||||||
|
^test/compiler/jvmci/\w[\w\.]*/.*\.iml
|
||||||
|
^test/compiler/jvmci/\w[\w\.]*/nbproject
|
||||||
|
^test/compiler/jvmci/\w[\w\.]*/\..*
|
||||||
|
|
|
@ -491,3 +491,6 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
|
||||||
1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
|
1ae4191359d811a51512f17dca80ffe79837a5ff jdk9-b86
|
||||||
d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
|
d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
|
||||||
bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
|
bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
|
||||||
|
20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89
|
||||||
|
7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90
|
||||||
|
3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91
|
||||||
|
|
|
@ -40,8 +40,7 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
|
||||||
// FIXME: access should be synchronized and cleared when VM is
|
// FIXME: access should be synchronized and cleared when VM is
|
||||||
// resumed
|
// resumed
|
||||||
// String fields
|
// String fields
|
||||||
private static IntField offsetField;
|
private static ByteField coderField;
|
||||||
private static IntField countField;
|
|
||||||
private static OopField valueField;
|
private static OopField valueField;
|
||||||
// ThreadGroup fields
|
// ThreadGroup fields
|
||||||
private static OopField threadGroupParentField;
|
private static OopField threadGroupParentField;
|
||||||
|
@ -96,20 +95,30 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
|
||||||
if (charArray == null) {
|
if (charArray == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return charArrayToString(charArray, 0, (int) charArray.getLength());
|
int length = (int)charArray.getLength();
|
||||||
|
StringBuffer buf = new StringBuffer(length);
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
buf.append(charArray.getCharAt(i));
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String charArrayToString(TypeArray charArray, int offset, int length) {
|
public static String byteArrayToString(TypeArray byteArray, byte coder) {
|
||||||
if (charArray == null) {
|
if (byteArray == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final int limit = offset + length;
|
int length = (int)byteArray.getLength() >> coder;
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
|
||||||
Assert.that(offset >= 0 && limit <= charArray.getLength(), "out of bounds");
|
|
||||||
}
|
|
||||||
StringBuffer buf = new StringBuffer(length);
|
StringBuffer buf = new StringBuffer(length);
|
||||||
for (int i = offset; i < limit; i++) {
|
if (coder == 0) {
|
||||||
buf.append(charArray.getCharAt(i));
|
// Latin1 encoded
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
buf.append((char)(byteArray.getByteAt(i) & 0xff));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// UTF16 encoded
|
||||||
|
for (int i = 0; i < length; i++) {
|
||||||
|
buf.append(byteArray.getCharAt(i));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return buf.toString();
|
return buf.toString();
|
||||||
}
|
}
|
||||||
|
@ -141,21 +150,14 @@ public class OopUtilities implements /* imports */ JVMTIThreadState {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String stringOopToString(Oop stringOop) {
|
public static String stringOopToString(Oop stringOop) {
|
||||||
if (offsetField == null) {
|
InstanceKlass k = (InstanceKlass) stringOop.getKlass();
|
||||||
InstanceKlass k = (InstanceKlass) stringOop.getKlass();
|
coderField = (ByteField) k.findField("coder", "B");
|
||||||
offsetField = (IntField) k.findField("offset", "I"); // optional
|
valueField = (OopField) k.findField("value", "[B");
|
||||||
countField = (IntField) k.findField("count", "I"); // optional
|
if (Assert.ASSERTS_ENABLED) {
|
||||||
valueField = (OopField) k.findField("value", "[C");
|
Assert.that(coderField != null, "Field \'coder\' of java.lang.String not found");
|
||||||
if (Assert.ASSERTS_ENABLED) {
|
Assert.that(valueField != null, "Field \'value\' of java.lang.String not found");
|
||||||
Assert.that(valueField != null, "Field \'value\' of java.lang.String not found");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (offsetField != null && countField != null) {
|
return byteArrayToString((TypeArray) valueField.getValue(stringOop), coderField.getValue(stringOop));
|
||||||
return charArrayToString((TypeArray) valueField.getValue(stringOop),
|
|
||||||
offsetField.getValue(stringOop),
|
|
||||||
countField.getValue(stringOop));
|
|
||||||
}
|
|
||||||
return charArrayToString((TypeArray) valueField.getValue(stringOop));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String stringOopToEscapedString(Oop stringOop) {
|
public static String stringOopToEscapedString(Oop stringOop) {
|
||||||
|
|
|
@ -268,8 +268,8 @@ public class HeapSummary extends Tool {
|
||||||
VM vm = VM.getVM();
|
VM vm = VM.getVM();
|
||||||
SystemDictionary sysDict = vm.getSystemDictionary();
|
SystemDictionary sysDict = vm.getSystemDictionary();
|
||||||
InstanceKlass strKlass = sysDict.getStringKlass();
|
InstanceKlass strKlass = sysDict.getStringKlass();
|
||||||
// String has a field named 'value' of type 'char[]'.
|
// String has a field named 'value' of type 'byte[]'.
|
||||||
stringValueField = (OopField) strKlass.findField("value", "[C");
|
stringValueField = (OopField) strKlass.findField("value", "[B");
|
||||||
}
|
}
|
||||||
|
|
||||||
private long stringSize(Instance instance) {
|
private long stringSize(Instance instance) {
|
||||||
|
|
|
@ -61,9 +61,8 @@ public class Hashtable extends BasicHashtable {
|
||||||
long h = 0;
|
long h = 0;
|
||||||
int s = 0;
|
int s = 0;
|
||||||
int len = buf.length;
|
int len = buf.length;
|
||||||
// Emulate the unsigned int in java_lang_String::hash_code
|
|
||||||
while (len-- > 0) {
|
while (len-- > 0) {
|
||||||
h = 31*h + (0xFFFFFFFFL & buf[s]);
|
h = 31*h + (0xFFL & buf[s]);
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
return h & 0xFFFFFFFFL;
|
return h & 0xFFFFFFFFL;
|
||||||
|
|
|
@ -97,6 +97,7 @@ else
|
||||||
# prints the numbers (e.g. "2.95", "3.2.1")
|
# prints the numbers (e.g. "2.95", "3.2.1")
|
||||||
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
|
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
|
||||||
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
||||||
|
CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_CLANG), true)
|
ifeq ($(USE_CLANG), true)
|
||||||
|
@ -333,6 +334,10 @@ ifeq ($(USE_CLANG), true)
|
||||||
$(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
|
$(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
|
# Do not allow GCC 4.1.1
|
||||||
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
|
||||||
|
$(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
|
||||||
|
endif
|
||||||
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
||||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||||
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||||
|
|
|
@ -56,10 +56,10 @@ $(eval $(call SetupJavaCompilation, BUILD_JVMCI_SERVICE, \
|
||||||
################################################################################
|
################################################################################
|
||||||
|
|
||||||
PROC_SRC_SUBDIRS := \
|
PROC_SRC_SUBDIRS := \
|
||||||
jdk.vm.ci.compiler \
|
|
||||||
jdk.vm.ci.hotspot \
|
jdk.vm.ci.hotspot \
|
||||||
jdk.vm.ci.hotspot.amd64 \
|
jdk.vm.ci.hotspot.amd64 \
|
||||||
jdk.vm.ci.hotspot.sparc \
|
jdk.vm.ci.hotspot.sparc \
|
||||||
|
jdk.vm.ci.runtime \
|
||||||
#
|
#
|
||||||
|
|
||||||
PROC_SRC_DIRS := $(patsubst %, $(SRC_DIR)/%/src, $(PROC_SRC_SUBDIRS))
|
PROC_SRC_DIRS := $(patsubst %, $(SRC_DIR)/%/src, $(PROC_SRC_SUBDIRS))
|
||||||
|
@ -94,11 +94,7 @@ TARGETS += $(GENSRC_DIR)/_gensrc_proc_done
|
||||||
$(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \
|
$(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors: \
|
||||||
$(GENSRC_DIR)/_gensrc_proc_done
|
$(GENSRC_DIR)/_gensrc_proc_done
|
||||||
$(MKDIR) -p $(@D)
|
$(MKDIR) -p $(@D)
|
||||||
($(CD) $(GENSRC_DIR)/META-INF/jvmci.options && \
|
$(FIND) $(GENSRC_DIR) -name '*_OptionDescriptors.java' | $(SED) 's:.*/jdk\.vm\.ci/\(.*\)\.java:\1:' | $(TR) '/' '.' > $@
|
||||||
$(RM) -f $@; \
|
|
||||||
for i in $$(ls); do \
|
|
||||||
echo $${i}_OptionDescriptors >> $@; \
|
|
||||||
done)
|
|
||||||
|
|
||||||
TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors
|
TARGETS += $(GENSRC_DIR)/META-INF/services/jdk.vm.ci.options.OptionDescriptors
|
||||||
|
|
||||||
|
@ -109,7 +105,11 @@ $(GENSRC_DIR)/_providers_converted: $(GENSRC_DIR)/_gensrc_proc_done
|
||||||
($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
|
($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
|
||||||
for i in $$($(LS)); do \
|
for i in $$($(LS)); do \
|
||||||
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
|
c=$$($(CAT) $$i | $(TR) -d '\n\r'); \
|
||||||
$(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c; \
|
$(ECHO) $$i >> $(GENSRC_DIR)/META-INF/services/$$c.tmp; \
|
||||||
|
done)
|
||||||
|
($(CD) $(GENSRC_DIR)/META-INF/services && \
|
||||||
|
for i in $$($(LS) *.tmp); do \
|
||||||
|
$(MV) $$i $${i%.tmp}; \
|
||||||
done)
|
done)
|
||||||
$(TOUCH) $@
|
$(TOUCH) $@
|
||||||
|
|
||||||
|
|
|
@ -60,6 +60,12 @@ else
|
||||||
# prints the numbers (e.g. "2.95", "3.2.1")
|
# prints the numbers (e.g. "2.95", "3.2.1")
|
||||||
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
|
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
|
||||||
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
||||||
|
CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
|
||||||
|
# Workaround Ubuntu bug where -dumpversion doesn't print a micro version
|
||||||
|
# https://bugs.launchpad.net/ubuntu/+source/gcc-4.8/+bug/1360404
|
||||||
|
ifeq ($(CC_VER_MICRO),)
|
||||||
|
CC_VER_MICRO := "0"
|
||||||
|
endif
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(USE_CLANG), true)
|
ifeq ($(USE_CLANG), true)
|
||||||
|
@ -266,6 +272,10 @@ ifeq ($(USE_CLANG), true)
|
||||||
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
|
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
|
# Do not allow GCC 4.1.1
|
||||||
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
|
||||||
|
$(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
|
||||||
|
endif
|
||||||
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
||||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||||
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||||
|
|
|
@ -39,6 +39,7 @@ Compiler = gcc
|
||||||
# prints the numbers (e.g. "2.95", "3.2.1")
|
# prints the numbers (e.g. "2.95", "3.2.1")
|
||||||
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
|
CC_VER_MAJOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f1)
|
||||||
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
CC_VER_MINOR := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f2)
|
||||||
|
CC_VER_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
|
||||||
|
|
||||||
# Check for the versions of C++ and C compilers ($CXX and $CC) used.
|
# Check for the versions of C++ and C compilers ($CXX and $CC) used.
|
||||||
|
|
||||||
|
@ -160,6 +161,10 @@ ifeq ($(USE_CLANG), true)
|
||||||
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
|
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
|
||||||
endif
|
endif
|
||||||
else
|
else
|
||||||
|
# Do not allow GCC 4.1.1
|
||||||
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 1 \& $(CC_VER_MICRO) = 1), 1)
|
||||||
|
$(error "GCC $(CC_VER_MAJOR).$(CC_VER_MINOR).$(CC_VER_MICRO) not supported because of https://gcc.gnu.org/bugzilla/show_bug.cgi?id=27724")
|
||||||
|
endif
|
||||||
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
# 6835796. Problem in GCC 4.3.0 with mulnode.o optimized compilation.
|
||||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||||
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||||
|
|
|
@ -14150,6 +14150,7 @@ instruct partialSubtypeCheckVsZero(iRegP_R4 sub, iRegP_R0 super, iRegP_R2 temp,
|
||||||
instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
|
instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cnt2,
|
||||||
iRegI_R0 result, iRegP_R10 tmp1, rFlagsReg cr)
|
iRegI_R0 result, iRegP_R10 tmp1, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(!CompactStrings);
|
||||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
effect(KILL tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
@ -14165,6 +14166,7 @@ instruct string_compare(iRegP_R1 str1, iRegI_R2 cnt1, iRegP_R3 str2, iRegI_R4 cn
|
||||||
instruct string_indexof(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
|
instruct string_indexof(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2, iRegI_R2 cnt2,
|
||||||
iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
|
iRegI_R0 result, iRegI tmp1, iRegI tmp2, iRegI tmp3, iRegI tmp4, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(!CompactStrings);
|
||||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2,
|
||||||
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
|
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
|
||||||
|
@ -14184,6 +14186,7 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
|
||||||
immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
|
immI_le_4 int_cnt2, iRegI_R0 result, iRegI tmp1, iRegI tmp2,
|
||||||
iRegI tmp3, iRegI tmp4, rFlagsReg cr)
|
iRegI tmp3, iRegI tmp4, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(!CompactStrings);
|
||||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1,
|
||||||
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
|
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr);
|
||||||
|
@ -14203,6 +14206,7 @@ instruct string_indexof_con(iRegP_R1 str1, iRegI_R4 cnt1, iRegP_R3 str2,
|
||||||
instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
|
instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
|
||||||
iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr)
|
iRegI_R0 result, iRegP_R10 tmp, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(!CompactStrings);
|
||||||
match(Set result (StrEquals (Binary str1 str2) cnt));
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
|
effect(KILL tmp, USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL cr);
|
||||||
|
|
||||||
|
@ -14218,6 +14222,7 @@ instruct string_equals(iRegP_R1 str1, iRegP_R3 str2, iRegI_R4 cnt,
|
||||||
instruct array_equals(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
|
instruct array_equals(iRegP_R1 ary1, iRegP_R2 ary2, iRegI_R0 result,
|
||||||
iRegP_R10 tmp, rFlagsReg cr)
|
iRegP_R10 tmp, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr);
|
effect(KILL tmp, USE_KILL ary1, USE_KILL ary2, KILL cr);
|
||||||
|
|
||||||
|
|
|
@ -483,15 +483,6 @@ int LIR_Assembler::emit_deopt_handler() {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is the fast version of java.lang.String.compare; it has not
|
|
||||||
// OSR-entry and therefore, we generate a slow version for OSR's
|
|
||||||
void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) {
|
|
||||||
__ mov(r2, (address)__FUNCTION__);
|
|
||||||
__ call_Unimplemented();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) {
|
void LIR_Assembler::add_debug_info_for_branch(address adr, CodeEmitInfo* info) {
|
||||||
_masm->code_section()->relocate(adr, relocInfo::poll_type);
|
_masm->code_section()->relocate(adr, relocInfo::poll_type);
|
||||||
int pc_offset = code_offset();
|
int pc_offset = code_offset();
|
||||||
|
|
|
@ -59,9 +59,9 @@ define_pd_global(intx, InlineFrequencyCount, 100);
|
||||||
#define DEFAULT_STACK_RED_PAGES (1)
|
#define DEFAULT_STACK_RED_PAGES (1)
|
||||||
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
|
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
|
||||||
|
|
||||||
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
|
#define MIN_STACK_YELLOW_PAGES 1
|
||||||
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
|
#define MIN_STACK_RED_PAGES 1
|
||||||
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
|
#define MIN_STACK_SHADOW_PAGES 1
|
||||||
|
|
||||||
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
|
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
|
||||||
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
||||||
|
@ -79,6 +79,9 @@ define_pd_global(uintx, CMSYoungGenPerWorker, 64*M); // default max size of CMS
|
||||||
|
|
||||||
define_pd_global(uintx, TypeProfileLevel, 111);
|
define_pd_global(uintx, TypeProfileLevel, 111);
|
||||||
|
|
||||||
|
// No performance work done here yet.
|
||||||
|
define_pd_global(bool, CompactStrings, false);
|
||||||
|
|
||||||
// avoid biased locking while we are bootstrapping the aarch64 build
|
// avoid biased locking while we are bootstrapping the aarch64 build
|
||||||
define_pd_global(bool, UseBiasedLocking, false);
|
define_pd_global(bool, UseBiasedLocking, false);
|
||||||
|
|
||||||
|
|
|
@ -38,11 +38,11 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
|
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1777,7 +1777,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||||
const Register obj_reg = r19; // Will contain the oop
|
const Register obj_reg = r19; // Will contain the oop
|
||||||
const Register lock_reg = r13; // Address of compiler lock object (BasicLock)
|
const Register lock_reg = r13; // Address of compiler lock object (BasicLock)
|
||||||
const Register old_hdr = r13; // value of old header at unlock time
|
const Register old_hdr = r13; // value of old header at unlock time
|
||||||
const Register tmp = c_rarg3;
|
const Register tmp = lr;
|
||||||
|
|
||||||
Label slow_path_lock;
|
Label slow_path_lock;
|
||||||
Label lock_done;
|
Label lock_done;
|
||||||
|
|
|
@ -72,6 +72,9 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 16*M); // Default max size of CM
|
||||||
|
|
||||||
define_pd_global(uintx, TypeProfileLevel, 111);
|
define_pd_global(uintx, TypeProfileLevel, 111);
|
||||||
|
|
||||||
|
// No performance work done here yet.
|
||||||
|
define_pd_global(bool, CompactStrings, false);
|
||||||
|
|
||||||
// Platform dependent flag handling: flags only defined on this platform.
|
// Platform dependent flag handling: flags only defined on this platform.
|
||||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||||
\
|
\
|
||||||
|
|
|
@ -38,11 +38,11 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
|
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
||||||
Unimplemented();
|
Unimplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2054,11 +2054,11 @@ const bool Matcher::match_rule_supported(int opcode) {
|
||||||
return (UsePopCountInstruction && VM_Version::has_popcntw());
|
return (UsePopCountInstruction && VM_Version::has_popcntw());
|
||||||
|
|
||||||
case Op_StrComp:
|
case Op_StrComp:
|
||||||
return SpecialStringCompareTo;
|
return SpecialStringCompareTo && !CompactStrings;
|
||||||
case Op_StrEquals:
|
case Op_StrEquals:
|
||||||
return SpecialStringEquals;
|
return SpecialStringEquals && !CompactStrings;
|
||||||
case Op_StrIndexOf:
|
case Op_StrIndexOf:
|
||||||
return SpecialStringIndexOf;
|
return SpecialStringIndexOf && !CompactStrings;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true; // Per default match rules are supported.
|
return true; // Per default match rules are supported.
|
||||||
|
@ -11076,7 +11076,7 @@ instruct string_indexOf_imm1_char(iRegIdst result, iRegPsrc haystack, iRegIsrc h
|
||||||
immP needleImm, immL offsetImm, immI_1 needlecntImm,
|
immP needleImm, immL offsetImm, immI_1 needlecntImm,
|
||||||
iRegIdst tmp1, iRegIdst tmp2,
|
iRegIdst tmp1, iRegIdst tmp2,
|
||||||
flagsRegCR0 cr0, flagsRegCR1 cr1) %{
|
flagsRegCR0 cr0, flagsRegCR1 cr1) %{
|
||||||
predicate(SpecialStringIndexOf); // type check implicit by parameter type, See Matcher::match_rule_supported
|
predicate(SpecialStringIndexOf && !CompactStrings); // type check implicit by parameter type, See Matcher::match_rule_supported
|
||||||
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
|
match(Set result (StrIndexOf (Binary haystack haycnt) (Binary (AddP needleImm offsetImm) needlecntImm)));
|
||||||
|
|
||||||
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
|
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, KILL cr0, KILL cr1);
|
||||||
|
@ -11119,7 +11119,7 @@ instruct string_indexOf_imm1(iRegIdst result, iRegPsrc haystack, iRegIsrc haycnt
|
||||||
effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
|
effect(USE_KILL needle, /* TDEF needle, */ TEMP_DEF result,
|
||||||
TEMP tmp1, TEMP tmp2);
|
TEMP tmp1, TEMP tmp2);
|
||||||
// Required for EA: check if it is still a type_array.
|
// Required for EA: check if it is still a type_array.
|
||||||
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
|
predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
|
||||||
n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
|
n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
|
||||||
ins_cost(180);
|
ins_cost(180);
|
||||||
|
|
||||||
|
@ -11166,7 +11166,7 @@ instruct string_indexOf_imm(iRegIdst result, iRegPsrc haystack, rscratch1RegI ha
|
||||||
effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
|
effect(USE_KILL haycnt, /* better: TDEF haycnt, */ TEMP_DEF result,
|
||||||
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
|
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5, KILL cr0, KILL cr1, KILL cr6);
|
||||||
// Required for EA: check if it is still a type_array.
|
// Required for EA: check if it is still a type_array.
|
||||||
predicate(SpecialStringIndexOf && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
|
predicate(SpecialStringIndexOf && !CompactStrings && n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop() &&
|
||||||
n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
|
n->in(3)->in(1)->bottom_type()->is_aryptr()->const_oop()->is_type_array());
|
||||||
ins_cost(250);
|
ins_cost(250);
|
||||||
|
|
||||||
|
@ -11199,7 +11199,7 @@ instruct string_indexOf(iRegIdst result, iRegPsrc haystack, rscratch1RegI haycnt
|
||||||
effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
|
effect(USE_KILL haycnt, USE_KILL needlecnt, /*better: TDEF haycnt, TDEF needlecnt,*/
|
||||||
TEMP_DEF result,
|
TEMP_DEF result,
|
||||||
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
|
TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, KILL cr0, KILL cr1, KILL cr6);
|
||||||
predicate(SpecialStringIndexOf); // See Matcher::match_rule_supported.
|
predicate(SpecialStringIndexOf && !CompactStrings); // See Matcher::match_rule_supported.
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
|
|
||||||
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
|
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
|
||||||
|
@ -11223,7 +11223,7 @@ instruct string_equals_imm(iRegPsrc str1, iRegPsrc str2, uimmI15 cntImm, iRegIds
|
||||||
match(Set result (StrEquals (Binary str1 str2) cntImm));
|
match(Set result (StrEquals (Binary str1 str2) cntImm));
|
||||||
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
|
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2,
|
||||||
KILL cr0, KILL cr6, KILL ctr);
|
KILL cr0, KILL cr6, KILL ctr);
|
||||||
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
|
predicate(SpecialStringEquals && !CompactStrings); // See Matcher::match_rule_supported.
|
||||||
ins_cost(250);
|
ins_cost(250);
|
||||||
|
|
||||||
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
|
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
|
||||||
|
@ -11246,7 +11246,7 @@ instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst resu
|
||||||
match(Set result (StrEquals (Binary str1 str2) cnt));
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
|
effect(TEMP_DEF result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP tmp5,
|
||||||
KILL cr0, KILL cr1, KILL cr6, KILL ctr);
|
KILL cr0, KILL cr1, KILL cr6, KILL ctr);
|
||||||
predicate(SpecialStringEquals); // See Matcher::match_rule_supported.
|
predicate(SpecialStringEquals && !CompactStrings); // See Matcher::match_rule_supported.
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
|
|
||||||
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
|
ins_alignment(8); // 'compute_padding()' gets called, up to this number-1 nops will get inserted.
|
||||||
|
@ -11266,6 +11266,7 @@ instruct string_equals(iRegPsrc str1, iRegPsrc str2, iRegIsrc cnt, iRegIdst resu
|
||||||
// Use dst register classes if register gets killed, as it is the case for TEMP operands!
|
// Use dst register classes if register gets killed, as it is the case for TEMP operands!
|
||||||
instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
|
instruct string_compare(rarg1RegP str1, rarg2RegP str2, rarg3RegI cnt1, rarg4RegI cnt2, iRegIdst result,
|
||||||
iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
|
iRegPdst tmp, flagsRegCR0 cr0, regCTR ctr) %{
|
||||||
|
predicate(!CompactStrings);
|
||||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
|
effect(USE_KILL cnt1, USE_KILL cnt2, USE_KILL str1, USE_KILL str2, TEMP_DEF result, TEMP tmp, KILL cr0, KILL ctr);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
|
|
|
@ -124,6 +124,8 @@ class Assembler : public AbstractAssembler {
|
||||||
impdep1_op3 = 0x36,
|
impdep1_op3 = 0x36,
|
||||||
aes3_op3 = 0x36,
|
aes3_op3 = 0x36,
|
||||||
sha_op3 = 0x36,
|
sha_op3 = 0x36,
|
||||||
|
bmask_op3 = 0x36,
|
||||||
|
bshuffle_op3 = 0x36,
|
||||||
alignaddr_op3 = 0x36,
|
alignaddr_op3 = 0x36,
|
||||||
faligndata_op3 = 0x36,
|
faligndata_op3 = 0x36,
|
||||||
flog3_op3 = 0x36,
|
flog3_op3 = 0x36,
|
||||||
|
@ -194,6 +196,7 @@ class Assembler : public AbstractAssembler {
|
||||||
fnegd_opf = 0x06,
|
fnegd_opf = 0x06,
|
||||||
|
|
||||||
alignaddr_opf = 0x18,
|
alignaddr_opf = 0x18,
|
||||||
|
bmask_opf = 0x19,
|
||||||
|
|
||||||
fadds_opf = 0x41,
|
fadds_opf = 0x41,
|
||||||
faddd_opf = 0x42,
|
faddd_opf = 0x42,
|
||||||
|
@ -204,6 +207,7 @@ class Assembler : public AbstractAssembler {
|
||||||
|
|
||||||
fmuls_opf = 0x49,
|
fmuls_opf = 0x49,
|
||||||
fmuld_opf = 0x4a,
|
fmuld_opf = 0x4a,
|
||||||
|
bshuffle_opf = 0x4c,
|
||||||
fdivs_opf = 0x4d,
|
fdivs_opf = 0x4d,
|
||||||
fdivd_opf = 0x4e,
|
fdivd_opf = 0x4e,
|
||||||
|
|
||||||
|
@ -1226,6 +1230,9 @@ public:
|
||||||
|
|
||||||
void edge8n( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(edge_op3) | rs1(s1) | opf(edge8n_opf) | rs2(s2)); }
|
void edge8n( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(edge_op3) | rs1(s1) | opf(edge8n_opf) | rs2(s2)); }
|
||||||
|
|
||||||
|
void bmask( Register s1, Register s2, Register d ) { vis2_only(); emit_int32( op(arith_op) | rd(d) | op3(bmask_op3) | rs1(s1) | opf(bmask_opf) | rs2(s2)); }
|
||||||
|
void bshuffle( FloatRegister s1, FloatRegister s2, FloatRegister d ) { vis2_only(); emit_int32( op(arith_op) | fd(d, FloatRegisterImpl::D) | op3(bshuffle_op3) | fs1(s1, FloatRegisterImpl::D) | opf(bshuffle_opf) | fs2(s2, FloatRegisterImpl::D)); }
|
||||||
|
|
||||||
// VIS3 instructions
|
// VIS3 instructions
|
||||||
|
|
||||||
void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); }
|
void movstosw( FloatRegister s, Register d ) { vis3_only(); emit_int32( op(arith_op) | rd(d) | op3(mftoi_op3) | opf(mstosw_opf) | fs2(s, FloatRegisterImpl::S)); }
|
||||||
|
|
|
@ -232,118 +232,6 @@ void LIR_Assembler::osr_entry() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Optimized Library calls
|
|
||||||
// This is the fast version of java.lang.String.compare; it has not
|
|
||||||
// OSR-entry and therefore, we generate a slow version for OSR's
|
|
||||||
void LIR_Assembler::emit_string_compare(LIR_Opr left, LIR_Opr right, LIR_Opr dst, CodeEmitInfo* info) {
|
|
||||||
Register str0 = left->as_register();
|
|
||||||
Register str1 = right->as_register();
|
|
||||||
|
|
||||||
Label Ldone;
|
|
||||||
|
|
||||||
Register result = dst->as_register();
|
|
||||||
{
|
|
||||||
// Get a pointer to the first character of string0 in tmp0
|
|
||||||
// and get string0.length() in str0
|
|
||||||
// Get a pointer to the first character of string1 in tmp1
|
|
||||||
// and get string1.length() in str1
|
|
||||||
// Also, get string0.length()-string1.length() in
|
|
||||||
// o7 and get the condition code set
|
|
||||||
// Note: some instructions have been hoisted for better instruction scheduling
|
|
||||||
|
|
||||||
Register tmp0 = L0;
|
|
||||||
Register tmp1 = L1;
|
|
||||||
Register tmp2 = L2;
|
|
||||||
|
|
||||||
int value_offset = java_lang_String:: value_offset_in_bytes(); // char array
|
|
||||||
if (java_lang_String::has_offset_field()) {
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
|
||||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
|
||||||
__ load_heap_oop(str0, value_offset, tmp0);
|
|
||||||
__ ld(str0, offset_offset, tmp2);
|
|
||||||
__ add(tmp0, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
|
||||||
__ ld(str0, count_offset, str0);
|
|
||||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
|
||||||
} else {
|
|
||||||
__ load_heap_oop(str0, value_offset, tmp1);
|
|
||||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp0);
|
|
||||||
__ ld(tmp1, arrayOopDesc::length_offset_in_bytes(), str0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// str1 may be null
|
|
||||||
add_debug_info_for_null_check_here(info);
|
|
||||||
|
|
||||||
if (java_lang_String::has_offset_field()) {
|
|
||||||
int offset_offset = java_lang_String::offset_offset_in_bytes(); // first character position
|
|
||||||
int count_offset = java_lang_String:: count_offset_in_bytes();
|
|
||||||
__ load_heap_oop(str1, value_offset, tmp1);
|
|
||||||
__ add(tmp0, tmp2, tmp0);
|
|
||||||
|
|
||||||
__ ld(str1, offset_offset, tmp2);
|
|
||||||
__ add(tmp1, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
|
||||||
__ ld(str1, count_offset, str1);
|
|
||||||
__ sll(tmp2, exact_log2(sizeof(jchar)), tmp2);
|
|
||||||
__ add(tmp1, tmp2, tmp1);
|
|
||||||
} else {
|
|
||||||
__ load_heap_oop(str1, value_offset, tmp2);
|
|
||||||
__ add(tmp2, arrayOopDesc::base_offset_in_bytes(T_CHAR), tmp1);
|
|
||||||
__ ld(tmp2, arrayOopDesc::length_offset_in_bytes(), str1);
|
|
||||||
}
|
|
||||||
__ subcc(str0, str1, O7);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Compute the minimum of the string lengths, scale it and store it in limit
|
|
||||||
Register count0 = I0;
|
|
||||||
Register count1 = I1;
|
|
||||||
Register limit = L3;
|
|
||||||
|
|
||||||
Label Lskip;
|
|
||||||
__ sll(count0, exact_log2(sizeof(jchar)), limit); // string0 is shorter
|
|
||||||
__ br(Assembler::greater, true, Assembler::pt, Lskip);
|
|
||||||
__ delayed()->sll(count1, exact_log2(sizeof(jchar)), limit); // string1 is shorter
|
|
||||||
__ bind(Lskip);
|
|
||||||
|
|
||||||
// If either string is empty (or both of them) the result is the difference in lengths
|
|
||||||
__ cmp(limit, 0);
|
|
||||||
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(O7, result); // result is difference in lengths
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
// Neither string is empty
|
|
||||||
Label Lloop;
|
|
||||||
|
|
||||||
Register base0 = L0;
|
|
||||||
Register base1 = L1;
|
|
||||||
Register chr0 = I0;
|
|
||||||
Register chr1 = I1;
|
|
||||||
Register limit = L3;
|
|
||||||
|
|
||||||
// Shift base0 and base1 to the end of the arrays, negate limit
|
|
||||||
__ add(base0, limit, base0);
|
|
||||||
__ add(base1, limit, base1);
|
|
||||||
__ neg(limit); // limit = -min{string0.length(), string1.length()}
|
|
||||||
|
|
||||||
__ lduh(base0, limit, chr0);
|
|
||||||
__ bind(Lloop);
|
|
||||||
__ lduh(base1, limit, chr1);
|
|
||||||
__ subcc(chr0, chr1, chr0);
|
|
||||||
__ br(Assembler::notZero, false, Assembler::pn, Ldone);
|
|
||||||
assert(chr0 == result, "result must be pre-placed");
|
|
||||||
__ delayed()->inccc(limit, sizeof(jchar));
|
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lloop);
|
|
||||||
__ delayed()->lduh(base0, limit, chr0);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If strings are equal up to min length, return the length difference.
|
|
||||||
__ mov(O7, result);
|
|
||||||
|
|
||||||
// Otherwise, return the difference between the first mismatched chars.
|
|
||||||
__ bind(Ldone);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// --------------------------------------------------------------------------------------------
|
// --------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no) {
|
void LIR_Assembler::monitorexit(LIR_Opr obj_opr, LIR_Opr lock_opr, Register hdr, int monitor_no) {
|
||||||
|
|
|
@ -86,6 +86,8 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 16*M); // default max size of CM
|
||||||
|
|
||||||
define_pd_global(uintx, TypeProfileLevel, 111);
|
define_pd_global(uintx, TypeProfileLevel, 111);
|
||||||
|
|
||||||
|
define_pd_global(bool, CompactStrings, true);
|
||||||
|
|
||||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||||
\
|
\
|
||||||
product(intx, UseVIS, 99, \
|
product(intx, UseVIS, 99, \
|
||||||
|
|
|
@ -66,6 +66,25 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
|
||||||
|
address pc = _instructions->start() + pc_offset;
|
||||||
|
if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
|
||||||
|
#ifdef _LP64
|
||||||
|
NativeMovConstReg32* move = nativeMovConstReg32_at(pc);
|
||||||
|
narrowKlass narrowOop = record_narrow_metadata_reference(constant);
|
||||||
|
move->set_data((intptr_t)narrowOop);
|
||||||
|
TRACE_jvmci_3("relocating (narrow metaspace constant) at %p/%p", pc, narrowOop);
|
||||||
|
#else
|
||||||
|
fatal("compressed Klass* on 32bit");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
NativeMovConstReg* move = nativeMovConstReg_at(pc);
|
||||||
|
Metadata* reference = record_metadata_reference(constant);
|
||||||
|
move->set_data((intptr_t)reference);
|
||||||
|
TRACE_jvmci_3("relocating (metaspace constant) at %p/%p", pc, reference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
||||||
address pc = _instructions->start() + pc_offset;
|
address pc = _instructions->start() + pc_offset;
|
||||||
NativeInstruction* inst = nativeInstruction_at(pc);
|
NativeInstruction* inst = nativeInstruction_at(pc);
|
||||||
|
@ -87,10 +106,6 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
|
|
||||||
fatal("CodeInstaller::pd_relocate_CodeBlob - sparc unimp");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
|
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
|
||||||
address pc = (address) inst;
|
address pc = (address) inst;
|
||||||
if (inst->is_call()) {
|
if (inst->is_call()) {
|
||||||
|
@ -168,16 +183,25 @@ void CodeInstaller::pd_relocate_poll(address pc, jint mark) {
|
||||||
|
|
||||||
// convert JVMCI register indices (as used in oop maps) to HotSpot registers
|
// convert JVMCI register indices (as used in oop maps) to HotSpot registers
|
||||||
VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
|
VMReg CodeInstaller::get_hotspot_reg(jint jvmci_reg) {
|
||||||
if (jvmci_reg < RegisterImpl::number_of_registers) {
|
// JVMCI Registers are numbered as follows:
|
||||||
|
// 0..31: Thirty-two General Purpose registers (CPU Registers)
|
||||||
|
// 32..63: Thirty-two single precision float registers
|
||||||
|
// 64..95: Thirty-two double precision float registers
|
||||||
|
// 96..111: Sixteen quad precision float registers
|
||||||
|
if (jvmci_reg < 32) {
|
||||||
return as_Register(jvmci_reg)->as_VMReg();
|
return as_Register(jvmci_reg)->as_VMReg();
|
||||||
} else {
|
} else {
|
||||||
jint floatRegisterNumber = jvmci_reg - RegisterImpl::number_of_registers;
|
jint floatRegisterNumber;
|
||||||
floatRegisterNumber += MAX2(0, floatRegisterNumber-32); // Beginning with f32, only every second register is going to be addressed
|
if(jvmci_reg < 64) { // Single precision
|
||||||
if (floatRegisterNumber < FloatRegisterImpl::number_of_registers) {
|
floatRegisterNumber = jvmci_reg - 32;
|
||||||
return as_FloatRegister(floatRegisterNumber)->as_VMReg();
|
} else if(jvmci_reg < 96) {
|
||||||
|
floatRegisterNumber = 2 * (jvmci_reg - 64);
|
||||||
|
} else if(jvmci_reg < 112) {
|
||||||
|
floatRegisterNumber = 4 * (jvmci_reg - 96);
|
||||||
|
} else {
|
||||||
|
fatal("Unknown jvmci register");
|
||||||
}
|
}
|
||||||
ShouldNotReachHere();
|
return as_FloatRegister(floatRegisterNumber)->as_VMReg();
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,9 @@
|
||||||
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
#include "gc/g1/g1SATBCardTableModRefBS.hpp"
|
||||||
#include "gc/g1/heapRegion.hpp"
|
#include "gc/g1/heapRegion.hpp"
|
||||||
#endif // INCLUDE_ALL_GCS
|
#endif // INCLUDE_ALL_GCS
|
||||||
|
#ifdef COMPILER2
|
||||||
|
#include "opto/intrinsicnode.hpp"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef PRODUCT
|
#ifdef PRODUCT
|
||||||
#define BLOCK_COMMENT(str) /* nothing */
|
#define BLOCK_COMMENT(str) /* nothing */
|
||||||
|
@ -4253,27 +4256,385 @@ void MacroAssembler::reinit_heapbase() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Compare char[] arrays aligned to 4 bytes.
|
#ifdef COMPILER2
|
||||||
void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
|
|
||||||
Register limit, Register result,
|
|
||||||
Register chr1, Register chr2, Label& Ldone) {
|
|
||||||
Label Lvector, Lloop;
|
|
||||||
assert(chr1 == result, "should be the same");
|
|
||||||
|
|
||||||
// Note: limit contains number of bytes (2*char_elements) != 0.
|
// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
|
||||||
andcc(limit, 0x2, chr1); // trailing character ?
|
void MacroAssembler::string_compress_16(Register src, Register dst, Register cnt, Register result,
|
||||||
|
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
|
||||||
|
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone) {
|
||||||
|
Label Lloop, Lslow;
|
||||||
|
assert(UseVIS >= 3, "VIS3 is required");
|
||||||
|
assert_different_registers(src, dst, cnt, tmp1, tmp2, tmp3, tmp4, result);
|
||||||
|
assert_different_registers(ftmp1, ftmp2, ftmp3);
|
||||||
|
|
||||||
|
// Check if cnt >= 8 (= 16 bytes)
|
||||||
|
cmp(cnt, 8);
|
||||||
|
br(Assembler::less, false, Assembler::pn, Lslow);
|
||||||
|
delayed()->mov(cnt, result); // copy count
|
||||||
|
|
||||||
|
// Check for 8-byte alignment of src and dst
|
||||||
|
or3(src, dst, tmp1);
|
||||||
|
andcc(tmp1, 7, G0);
|
||||||
|
br(Assembler::notZero, false, Assembler::pn, Lslow);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
// Set mask for bshuffle instruction
|
||||||
|
Register mask = tmp4;
|
||||||
|
set(0x13579bdf, mask);
|
||||||
|
bmask(mask, G0, G0);
|
||||||
|
|
||||||
|
// Set mask to 0xff00 ff00 ff00 ff00 to check for non-latin1 characters
|
||||||
|
Assembler::sethi(0xff00fc00, mask); // mask = 0x0000 0000 ff00 fc00
|
||||||
|
add(mask, 0x300, mask); // mask = 0x0000 0000 ff00 ff00
|
||||||
|
sllx(mask, 32, tmp1); // tmp1 = 0xff00 ff00 0000 0000
|
||||||
|
or3(mask, tmp1, mask); // mask = 0xff00 ff00 ff00 ff00
|
||||||
|
|
||||||
|
// Load first 8 bytes
|
||||||
|
ldx(src, 0, tmp1);
|
||||||
|
|
||||||
|
bind(Lloop);
|
||||||
|
// Load next 8 bytes
|
||||||
|
ldx(src, 8, tmp2);
|
||||||
|
|
||||||
|
// Check for non-latin1 character by testing if the most significant byte of a char is set.
|
||||||
|
// Although we have to move the data between integer and floating point registers, this is
|
||||||
|
// still faster than the corresponding VIS instructions (ford/fand/fcmpd).
|
||||||
|
or3(tmp1, tmp2, tmp3);
|
||||||
|
btst(tmp3, mask);
|
||||||
|
// annul zeroing if branch is not taken to preserve original count
|
||||||
|
brx(Assembler::notZero, true, Assembler::pn, Ldone);
|
||||||
|
delayed()->mov(G0, result); // 0 - failed
|
||||||
|
|
||||||
|
// Move bytes into float register
|
||||||
|
movxtod(tmp1, ftmp1);
|
||||||
|
movxtod(tmp2, ftmp2);
|
||||||
|
|
||||||
|
// Compress by copying one byte per char from ftmp1 and ftmp2 to ftmp3
|
||||||
|
bshuffle(ftmp1, ftmp2, ftmp3);
|
||||||
|
stf(FloatRegisterImpl::D, ftmp3, dst, 0);
|
||||||
|
|
||||||
|
// Increment addresses and decrement count
|
||||||
|
inc(src, 16);
|
||||||
|
inc(dst, 8);
|
||||||
|
dec(cnt, 8);
|
||||||
|
|
||||||
|
cmp(cnt, 8);
|
||||||
|
// annul LDX if branch is not taken to prevent access past end of string
|
||||||
|
br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
|
||||||
|
delayed()->ldx(src, 0, tmp1);
|
||||||
|
|
||||||
|
// Fallback to slow version
|
||||||
|
bind(Lslow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compress char[] to byte[]. Return 0 on failure.
|
||||||
|
void MacroAssembler::string_compress(Register src, Register dst, Register cnt, Register result, Register tmp, Label& Ldone) {
|
||||||
|
Label Lloop;
|
||||||
|
assert_different_registers(src, dst, cnt, tmp, result);
|
||||||
|
|
||||||
|
lduh(src, 0, tmp);
|
||||||
|
|
||||||
|
bind(Lloop);
|
||||||
|
inc(src, sizeof(jchar));
|
||||||
|
cmp(tmp, 0xff);
|
||||||
|
// annul zeroing if branch is not taken to preserve original count
|
||||||
|
br(Assembler::greater, true, Assembler::pn, Ldone); // don't check xcc
|
||||||
|
delayed()->mov(G0, result); // 0 - failed
|
||||||
|
deccc(cnt);
|
||||||
|
stb(tmp, dst, 0);
|
||||||
|
inc(dst);
|
||||||
|
// annul LDUH if branch is not taken to prevent access past end of string
|
||||||
|
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||||
|
delayed()->lduh(src, 0, tmp); // hoisted
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||||
|
void MacroAssembler::string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
|
||||||
|
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone) {
|
||||||
|
Label Lloop, Lslow;
|
||||||
|
assert(UseVIS >= 3, "VIS3 is required");
|
||||||
|
assert_different_registers(src, dst, cnt, tmp);
|
||||||
|
assert_different_registers(ftmp1, ftmp2, ftmp3, ftmp4);
|
||||||
|
|
||||||
|
// Check if cnt >= 8 (= 16 bytes)
|
||||||
|
cmp(cnt, 8);
|
||||||
|
br(Assembler::less, false, Assembler::pn, Lslow);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
// Check for 8-byte alignment of src and dst
|
||||||
|
or3(src, dst, tmp);
|
||||||
|
andcc(tmp, 7, G0);
|
||||||
|
br(Assembler::notZero, false, Assembler::pn, Lslow);
|
||||||
|
// Initialize float register to zero
|
||||||
|
FloatRegister zerof = ftmp4;
|
||||||
|
delayed()->fzero(FloatRegisterImpl::D, zerof);
|
||||||
|
|
||||||
|
// Load first 8 bytes
|
||||||
|
ldf(FloatRegisterImpl::D, src, 0, ftmp1);
|
||||||
|
|
||||||
|
bind(Lloop);
|
||||||
|
inc(src, 8);
|
||||||
|
dec(cnt, 8);
|
||||||
|
|
||||||
|
// Inflate the string by interleaving each byte from the source array
|
||||||
|
// with a zero byte and storing the result in the destination array.
|
||||||
|
fpmerge(zerof, ftmp1->successor(), ftmp2);
|
||||||
|
stf(FloatRegisterImpl::D, ftmp2, dst, 8);
|
||||||
|
fpmerge(zerof, ftmp1, ftmp3);
|
||||||
|
stf(FloatRegisterImpl::D, ftmp3, dst, 0);
|
||||||
|
|
||||||
|
inc(dst, 16);
|
||||||
|
|
||||||
|
cmp(cnt, 8);
|
||||||
|
// annul LDX if branch is not taken to prevent access past end of string
|
||||||
|
br(Assembler::greaterEqual, true, Assembler::pt, Lloop);
|
||||||
|
delayed()->ldf(FloatRegisterImpl::D, src, 0, ftmp1);
|
||||||
|
|
||||||
|
// Fallback to slow version
|
||||||
|
bind(Lslow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Inflate byte[] to char[].
|
||||||
|
void MacroAssembler::string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone) {
|
||||||
|
Label Loop;
|
||||||
|
assert_different_registers(src, dst, cnt, tmp);
|
||||||
|
|
||||||
|
ldub(src, 0, tmp);
|
||||||
|
bind(Loop);
|
||||||
|
inc(src);
|
||||||
|
deccc(cnt);
|
||||||
|
sth(tmp, dst, 0);
|
||||||
|
inc(dst, sizeof(jchar));
|
||||||
|
// annul LDUB if branch is not taken to prevent access past end of string
|
||||||
|
br(Assembler::notZero, true, Assembler::pt, Loop);
|
||||||
|
delayed()->ldub(src, 0, tmp); // hoisted
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::string_compare(Register str1, Register str2,
|
||||||
|
Register cnt1, Register cnt2,
|
||||||
|
Register tmp1, Register tmp2,
|
||||||
|
Register result, int ae) {
|
||||||
|
Label Ldone, Lloop;
|
||||||
|
assert_different_registers(str1, str2, cnt1, cnt2, tmp1, result);
|
||||||
|
int stride1, stride2;
|
||||||
|
|
||||||
|
// Note: Making use of the fact that compareTo(a, b) == -compareTo(b, a)
|
||||||
|
// we interchange str1 and str2 in the UL case and negate the result.
|
||||||
|
// Like this, str1 is always latin1 encoded, expect for the UU case.
|
||||||
|
|
||||||
|
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||||
|
srl(cnt2, 1, cnt2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// See if the lengths are different, and calculate min in cnt1.
|
||||||
|
// Save diff in case we need it for a tie-breaker.
|
||||||
|
Label Lskip;
|
||||||
|
Register diff = tmp1;
|
||||||
|
subcc(cnt1, cnt2, diff);
|
||||||
|
br(Assembler::greater, true, Assembler::pt, Lskip);
|
||||||
|
// cnt2 is shorter, so use its count:
|
||||||
|
delayed()->mov(cnt2, cnt1);
|
||||||
|
bind(Lskip);
|
||||||
|
|
||||||
|
// Rename registers
|
||||||
|
Register limit1 = cnt1;
|
||||||
|
Register limit2 = limit1;
|
||||||
|
Register chr1 = result;
|
||||||
|
Register chr2 = cnt2;
|
||||||
|
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||||
|
// We need an additional register to keep track of two limits
|
||||||
|
assert_different_registers(str1, str2, cnt1, cnt2, tmp1, tmp2, result);
|
||||||
|
limit2 = tmp2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is the minimum length zero?
|
||||||
|
cmp(limit1, (int)0); // use cast to resolve overloading ambiguity
|
||||||
|
br(Assembler::equal, true, Assembler::pn, Ldone);
|
||||||
|
// result is difference in lengths
|
||||||
|
if (ae == StrIntrinsicNode::UU) {
|
||||||
|
delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars
|
||||||
|
} else {
|
||||||
|
delayed()->mov(diff, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load first characters
|
||||||
|
if (ae == StrIntrinsicNode::LL) {
|
||||||
|
stride1 = stride2 = sizeof(jbyte);
|
||||||
|
ldub(str1, 0, chr1);
|
||||||
|
ldub(str2, 0, chr2);
|
||||||
|
} else if (ae == StrIntrinsicNode::UU) {
|
||||||
|
stride1 = stride2 = sizeof(jchar);
|
||||||
|
lduh(str1, 0, chr1);
|
||||||
|
lduh(str2, 0, chr2);
|
||||||
|
} else {
|
||||||
|
stride1 = sizeof(jbyte);
|
||||||
|
stride2 = sizeof(jchar);
|
||||||
|
ldub(str1, 0, chr1);
|
||||||
|
lduh(str2, 0, chr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare first characters
|
||||||
|
subcc(chr1, chr2, chr1);
|
||||||
|
br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||||
|
assert(chr1 == result, "result must be pre-placed");
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
// Check if the strings start at same location
|
||||||
|
cmp(str1, str2);
|
||||||
|
brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||||
|
delayed()->mov(G0, result); // result is zero
|
||||||
|
|
||||||
|
// We have no guarantee that on 64 bit the higher half of limit is 0
|
||||||
|
signx(limit1);
|
||||||
|
|
||||||
|
// Get limit
|
||||||
|
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||||
|
sll(limit1, 1, limit2);
|
||||||
|
subcc(limit2, stride2, chr2);
|
||||||
|
}
|
||||||
|
subcc(limit1, stride1, chr1);
|
||||||
|
br(Assembler::zero, true, Assembler::pn, Ldone);
|
||||||
|
// result is difference in lengths
|
||||||
|
if (ae == StrIntrinsicNode::UU) {
|
||||||
|
delayed()->sra(diff, 1, result); // Divide by 2 to get number of chars
|
||||||
|
} else {
|
||||||
|
delayed()->mov(diff, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shift str1 and str2 to the end of the arrays, negate limit
|
||||||
|
add(str1, limit1, str1);
|
||||||
|
add(str2, limit2, str2);
|
||||||
|
neg(chr1, limit1); // limit1 = -(limit1-stride1)
|
||||||
|
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||||
|
neg(chr2, limit2); // limit2 = -(limit2-stride2)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compare the rest of the characters
|
||||||
|
if (ae == StrIntrinsicNode::UU) {
|
||||||
|
lduh(str1, limit1, chr1);
|
||||||
|
} else {
|
||||||
|
ldub(str1, limit1, chr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bind(Lloop);
|
||||||
|
if (ae == StrIntrinsicNode::LL) {
|
||||||
|
ldub(str2, limit2, chr2);
|
||||||
|
} else {
|
||||||
|
lduh(str2, limit2, chr2);
|
||||||
|
}
|
||||||
|
|
||||||
|
subcc(chr1, chr2, chr1);
|
||||||
|
br(Assembler::notZero, false, Assembler::pt, Ldone);
|
||||||
|
assert(chr1 == result, "result must be pre-placed");
|
||||||
|
delayed()->inccc(limit1, stride1);
|
||||||
|
if (ae == StrIntrinsicNode::LU || ae == StrIntrinsicNode::UL) {
|
||||||
|
inccc(limit2, stride2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// annul LDUB if branch is not taken to prevent access past end of string
|
||||||
|
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||||
|
if (ae == StrIntrinsicNode::UU) {
|
||||||
|
delayed()->lduh(str1, limit2, chr1);
|
||||||
|
} else {
|
||||||
|
delayed()->ldub(str1, limit1, chr1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If strings are equal up to min length, return the length difference.
|
||||||
|
if (ae == StrIntrinsicNode::UU) {
|
||||||
|
// Divide by 2 to get number of chars
|
||||||
|
sra(diff, 1, result);
|
||||||
|
} else {
|
||||||
|
mov(diff, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, return the difference between the first mismatched chars.
|
||||||
|
bind(Ldone);
|
||||||
|
if(ae == StrIntrinsicNode::UL) {
|
||||||
|
// Negate result (see note above)
|
||||||
|
neg(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroAssembler::array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||||
|
Register limit, Register tmp, Register result, bool is_byte) {
|
||||||
|
Label Ldone, Lvector, Lloop;
|
||||||
|
assert_different_registers(ary1, ary2, limit, tmp, result);
|
||||||
|
|
||||||
|
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
||||||
|
int base_offset = arrayOopDesc::base_offset_in_bytes(is_byte ? T_BYTE : T_CHAR);
|
||||||
|
|
||||||
|
if (is_array_equ) {
|
||||||
|
// return true if the same array
|
||||||
|
cmp(ary1, ary2);
|
||||||
|
brx(Assembler::equal, true, Assembler::pn, Ldone);
|
||||||
|
delayed()->add(G0, 1, result); // equal
|
||||||
|
|
||||||
|
br_null(ary1, true, Assembler::pn, Ldone);
|
||||||
|
delayed()->mov(G0, result); // not equal
|
||||||
|
|
||||||
|
br_null(ary2, true, Assembler::pn, Ldone);
|
||||||
|
delayed()->mov(G0, result); // not equal
|
||||||
|
|
||||||
|
// load the lengths of arrays
|
||||||
|
ld(Address(ary1, length_offset), limit);
|
||||||
|
ld(Address(ary2, length_offset), tmp);
|
||||||
|
|
||||||
|
// return false if the two arrays are not equal length
|
||||||
|
cmp(limit, tmp);
|
||||||
|
br(Assembler::notEqual, true, Assembler::pn, Ldone);
|
||||||
|
delayed()->mov(G0, result); // not equal
|
||||||
|
}
|
||||||
|
|
||||||
|
cmp_zero_and_br(Assembler::zero, limit, Ldone, true, Assembler::pn);
|
||||||
|
delayed()->add(G0, 1, result); // zero-length arrays are equal
|
||||||
|
|
||||||
|
if (is_array_equ) {
|
||||||
|
// load array addresses
|
||||||
|
add(ary1, base_offset, ary1);
|
||||||
|
add(ary2, base_offset, ary2);
|
||||||
|
} else {
|
||||||
|
// We have no guarantee that on 64 bit the higher half of limit is 0
|
||||||
|
signx(limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_byte) {
|
||||||
|
Label Lskip;
|
||||||
|
// check for trailing byte
|
||||||
|
andcc(limit, 0x1, tmp);
|
||||||
|
br(Assembler::zero, false, Assembler::pt, Lskip);
|
||||||
|
delayed()->nop();
|
||||||
|
|
||||||
|
// compare the trailing byte
|
||||||
|
sub(limit, sizeof(jbyte), limit);
|
||||||
|
ldub(ary1, limit, result);
|
||||||
|
ldub(ary2, limit, tmp);
|
||||||
|
cmp(result, tmp);
|
||||||
|
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
||||||
|
delayed()->mov(G0, result); // not equal
|
||||||
|
|
||||||
|
// only one byte?
|
||||||
|
cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
|
||||||
|
delayed()->add(G0, 1, result); // zero-length arrays are equal
|
||||||
|
bind(Lskip);
|
||||||
|
} else if (is_array_equ) {
|
||||||
|
// set byte count
|
||||||
|
sll(limit, exact_log2(sizeof(jchar)), limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check for trailing character
|
||||||
|
andcc(limit, 0x2, tmp);
|
||||||
br(Assembler::zero, false, Assembler::pt, Lvector);
|
br(Assembler::zero, false, Assembler::pt, Lvector);
|
||||||
delayed()->nop();
|
delayed()->nop();
|
||||||
|
|
||||||
// compare the trailing char
|
// compare the trailing char
|
||||||
sub(limit, sizeof(jchar), limit);
|
sub(limit, sizeof(jchar), limit);
|
||||||
lduh(ary1, limit, chr1);
|
lduh(ary1, limit, result);
|
||||||
lduh(ary2, limit, chr2);
|
lduh(ary2, limit, tmp);
|
||||||
cmp(chr1, chr2);
|
cmp(result, tmp);
|
||||||
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
||||||
delayed()->mov(G0, result); // not equal
|
delayed()->mov(G0, result); // not equal
|
||||||
|
|
||||||
// only one char ?
|
// only one char?
|
||||||
cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
|
cmp_zero_and_br(zero, limit, Ldone, true, Assembler::pn);
|
||||||
delayed()->add(G0, 1, result); // zero-length arrays are equal
|
delayed()->add(G0, 1, result); // zero-length arrays are equal
|
||||||
|
|
||||||
|
@ -4284,21 +4645,23 @@ void MacroAssembler::char_arrays_equals(Register ary1, Register ary2,
|
||||||
add(ary2, limit, ary2);
|
add(ary2, limit, ary2);
|
||||||
neg(limit, limit);
|
neg(limit, limit);
|
||||||
|
|
||||||
lduw(ary1, limit, chr1);
|
lduw(ary1, limit, result);
|
||||||
bind(Lloop);
|
bind(Lloop);
|
||||||
lduw(ary2, limit, chr2);
|
lduw(ary2, limit, tmp);
|
||||||
cmp(chr1, chr2);
|
cmp(result, tmp);
|
||||||
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
||||||
delayed()->mov(G0, result); // not equal
|
delayed()->mov(G0, result); // not equal
|
||||||
inccc(limit, 2*sizeof(jchar));
|
inccc(limit, 2*sizeof(jchar));
|
||||||
// annul LDUW if branch is not taken to prevent access past end of array
|
// annul LDUW if branch is not taken to prevent access past end of array
|
||||||
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
br(Assembler::notZero, true, Assembler::pt, Lloop);
|
||||||
delayed()->lduw(ary1, limit, chr1); // hoisted
|
delayed()->lduw(ary1, limit, result); // hoisted
|
||||||
|
|
||||||
// Caller should set it:
|
add(G0, 1, result); // equals
|
||||||
// add(G0, 1, result); // equals
|
bind(Ldone);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// Use BIS for zeroing (count is in bytes).
|
// Use BIS for zeroing (count is in bytes).
|
||||||
void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) {
|
void MacroAssembler::bis_zeroing(Register to, Register count, Register temp, Label& Ldone) {
|
||||||
assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing");
|
assert(UseBlockZeroing && VM_Version::has_block_zeroing(), "only works with BIS zeroing");
|
||||||
|
|
|
@ -1433,10 +1433,31 @@ public:
|
||||||
void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
|
void inc_counter(address counter_addr, Register Rtmp1, Register Rtmp2);
|
||||||
void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2);
|
void inc_counter(int* counter_addr, Register Rtmp1, Register Rtmp2);
|
||||||
|
|
||||||
// Compare char[] arrays aligned to 4 bytes.
|
#ifdef COMPILER2
|
||||||
void char_arrays_equals(Register ary1, Register ary2,
|
// Compress char[] to byte[] by compressing 16 bytes at once. Return 0 on failure.
|
||||||
Register limit, Register result,
|
void string_compress_16(Register src, Register dst, Register cnt, Register result,
|
||||||
Register chr1, Register chr2, Label& Ldone);
|
Register tmp1, Register tmp2, Register tmp3, Register tmp4,
|
||||||
|
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, Label& Ldone);
|
||||||
|
|
||||||
|
// Compress char[] to byte[]. Return 0 on failure.
|
||||||
|
void string_compress(Register src, Register dst, Register cnt, Register tmp, Register result, Label& Ldone);
|
||||||
|
|
||||||
|
// Inflate byte[] to char[] by inflating 16 bytes at once.
|
||||||
|
void string_inflate_16(Register src, Register dst, Register cnt, Register tmp,
|
||||||
|
FloatRegister ftmp1, FloatRegister ftmp2, FloatRegister ftmp3, FloatRegister ftmp4, Label& Ldone);
|
||||||
|
|
||||||
|
// Inflate byte[] to char[].
|
||||||
|
void string_inflate(Register src, Register dst, Register cnt, Register tmp, Label& Ldone);
|
||||||
|
|
||||||
|
void string_compare(Register str1, Register str2,
|
||||||
|
Register cnt1, Register cnt2,
|
||||||
|
Register tmp1, Register tmp2,
|
||||||
|
Register result, int ae);
|
||||||
|
|
||||||
|
void array_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||||
|
Register limit, Register tmp, Register result, bool is_byte);
|
||||||
|
#endif
|
||||||
|
|
||||||
// Use BIS for zeroing
|
// Use BIS for zeroing
|
||||||
void bis_zeroing(Register to, Register count, Register temp, Label& Ldone);
|
void bis_zeroing(Register to, Register count, Register temp, Label& Ldone);
|
||||||
|
|
||||||
|
|
|
@ -417,6 +417,67 @@ void NativeMovConstReg::test() {
|
||||||
|
|
||||||
//-------------------------------------------------------------------
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
|
void NativeMovConstReg32::verify() {
|
||||||
|
NativeInstruction::verify();
|
||||||
|
// make sure code pattern is actually a "set_metadata" synthetic instruction
|
||||||
|
// see MacroAssembler::set_oop()
|
||||||
|
int i0 = long_at(sethi_offset);
|
||||||
|
int i1 = long_at(add_offset);
|
||||||
|
|
||||||
|
// verify the pattern "sethi %hi22(imm), reg ; add reg, %lo10(imm), reg"
|
||||||
|
Register rd = inv_rd(i0);
|
||||||
|
if (!is_op2(i0, Assembler::sethi_op2) && rd != G0 ) {
|
||||||
|
fatal("not a set_metadata");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NativeMovConstReg32::print() {
|
||||||
|
tty->print_cr(INTPTR_FORMAT ": mov reg, " INTPTR_FORMAT, instruction_address(), data());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
intptr_t NativeMovConstReg32::data() const {
|
||||||
|
return data32(long_at(sethi_offset), long_at(add_offset));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NativeMovConstReg32::set_data(intptr_t x) {
|
||||||
|
set_long_at(sethi_offset, set_data32_sethi( long_at(sethi_offset), x));
|
||||||
|
set_long_at(add_offset, set_data32_simm13( long_at(add_offset), x));
|
||||||
|
|
||||||
|
// also store the value into an oop_Relocation cell, if any
|
||||||
|
CodeBlob* cb = CodeCache::find_blob(instruction_address());
|
||||||
|
nmethod* nm = cb ? cb->as_nmethod_or_null() : NULL;
|
||||||
|
if (nm != NULL) {
|
||||||
|
RelocIterator iter(nm, instruction_address(), next_instruction_address());
|
||||||
|
oop* oop_addr = NULL;
|
||||||
|
Metadata** metadata_addr = NULL;
|
||||||
|
while (iter.next()) {
|
||||||
|
if (iter.type() == relocInfo::oop_type) {
|
||||||
|
oop_Relocation *r = iter.oop_reloc();
|
||||||
|
if (oop_addr == NULL) {
|
||||||
|
oop_addr = r->oop_addr();
|
||||||
|
*oop_addr = cast_to_oop(x);
|
||||||
|
} else {
|
||||||
|
assert(oop_addr == r->oop_addr(), "must be only one set-oop here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (iter.type() == relocInfo::metadata_type) {
|
||||||
|
metadata_Relocation *r = iter.metadata_reloc();
|
||||||
|
if (metadata_addr == NULL) {
|
||||||
|
metadata_addr = r->metadata_addr();
|
||||||
|
*metadata_addr = (Metadata*)x;
|
||||||
|
} else {
|
||||||
|
assert(metadata_addr == r->metadata_addr(), "must be only one set-metadata here");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------
|
||||||
|
|
||||||
void NativeMovConstRegPatching::verify() {
|
void NativeMovConstRegPatching::verify() {
|
||||||
NativeInstruction::verify();
|
NativeInstruction::verify();
|
||||||
// Make sure code pattern is sethi/nop/add.
|
// Make sure code pattern is sethi/nop/add.
|
||||||
|
|
|
@ -518,6 +518,46 @@ class NativeFarCall: public NativeInstruction {
|
||||||
|
|
||||||
#endif // _LP64
|
#endif // _LP64
|
||||||
|
|
||||||
|
// An interface for accessing/manipulating 32 bit native set_metadata imm, reg instructions
|
||||||
|
// (used to manipulate inlined data references, etc.)
|
||||||
|
// set_metadata imm, reg
|
||||||
|
// == sethi %hi22(imm), reg ; add reg, %lo10(imm), reg
|
||||||
|
class NativeMovConstReg32;
|
||||||
|
inline NativeMovConstReg32* nativeMovConstReg32_at(address address);
|
||||||
|
class NativeMovConstReg32: public NativeInstruction {
|
||||||
|
public:
|
||||||
|
enum Sparc_specific_constants {
|
||||||
|
sethi_offset = 0,
|
||||||
|
add_offset = 4,
|
||||||
|
instruction_size = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
address instruction_address() const { return addr_at(0); }
|
||||||
|
address next_instruction_address() const { return addr_at(instruction_size); }
|
||||||
|
|
||||||
|
// (The [set_]data accessor respects oop_type relocs also.)
|
||||||
|
intptr_t data() const;
|
||||||
|
void set_data(intptr_t x);
|
||||||
|
|
||||||
|
// report the destination register
|
||||||
|
Register destination() { return inv_rd(long_at(sethi_offset)); }
|
||||||
|
|
||||||
|
void verify();
|
||||||
|
void print();
|
||||||
|
|
||||||
|
// unit test stuff
|
||||||
|
static void test();
|
||||||
|
|
||||||
|
// Creation
|
||||||
|
friend inline NativeMovConstReg32* nativeMovConstReg32_at(address address) {
|
||||||
|
NativeMovConstReg32* test = (NativeMovConstReg32*)address;
|
||||||
|
#ifdef ASSERT
|
||||||
|
test->verify();
|
||||||
|
#endif
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// An interface for accessing/manipulating native set_metadata imm, reg instructions.
|
// An interface for accessing/manipulating native set_metadata imm, reg instructions.
|
||||||
// (used to manipulate inlined data references, etc.)
|
// (used to manipulate inlined data references, etc.)
|
||||||
// set_metadata imm, reg
|
// set_metadata imm, reg
|
||||||
|
|
|
@ -2905,232 +2905,6 @@ enc_class Fast_Unlock(iRegP oop, iRegP box, o7RegP scratch, iRegP scratch2) %{
|
||||||
__ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst);
|
__ float_cmp( $primary, -1, Fsrc1, Fsrc2, Rdst);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
||||||
enc_class enc_String_Compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result) %{
|
|
||||||
Label Ldone, Lloop;
|
|
||||||
MacroAssembler _masm(&cbuf);
|
|
||||||
|
|
||||||
Register str1_reg = reg_to_register_object($str1$$reg);
|
|
||||||
Register str2_reg = reg_to_register_object($str2$$reg);
|
|
||||||
Register cnt1_reg = reg_to_register_object($cnt1$$reg);
|
|
||||||
Register cnt2_reg = reg_to_register_object($cnt2$$reg);
|
|
||||||
Register result_reg = reg_to_register_object($result$$reg);
|
|
||||||
|
|
||||||
assert(result_reg != str1_reg &&
|
|
||||||
result_reg != str2_reg &&
|
|
||||||
result_reg != cnt1_reg &&
|
|
||||||
result_reg != cnt2_reg ,
|
|
||||||
"need different registers");
|
|
||||||
|
|
||||||
// Compute the minimum of the string lengths(str1_reg) and the
|
|
||||||
// difference of the string lengths (stack)
|
|
||||||
|
|
||||||
// See if the lengths are different, and calculate min in str1_reg.
|
|
||||||
// Stash diff in O7 in case we need it for a tie-breaker.
|
|
||||||
Label Lskip;
|
|
||||||
__ subcc(cnt1_reg, cnt2_reg, O7);
|
|
||||||
__ sll(cnt1_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
|
|
||||||
__ br(Assembler::greater, true, Assembler::pt, Lskip);
|
|
||||||
// cnt2 is shorter, so use its count:
|
|
||||||
__ delayed()->sll(cnt2_reg, exact_log2(sizeof(jchar)), cnt1_reg); // scale the limit
|
|
||||||
__ bind(Lskip);
|
|
||||||
|
|
||||||
// reallocate cnt1_reg, cnt2_reg, result_reg
|
|
||||||
// Note: limit_reg holds the string length pre-scaled by 2
|
|
||||||
Register limit_reg = cnt1_reg;
|
|
||||||
Register chr2_reg = cnt2_reg;
|
|
||||||
Register chr1_reg = result_reg;
|
|
||||||
// str{12} are the base pointers
|
|
||||||
|
|
||||||
// Is the minimum length zero?
|
|
||||||
__ cmp(limit_reg, (int)(0 * sizeof(jchar))); // use cast to resolve overloading ambiguity
|
|
||||||
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(O7, result_reg); // result is difference in lengths
|
|
||||||
|
|
||||||
// Load first characters
|
|
||||||
__ lduh(str1_reg, 0, chr1_reg);
|
|
||||||
__ lduh(str2_reg, 0, chr2_reg);
|
|
||||||
|
|
||||||
// Compare first characters
|
|
||||||
__ subcc(chr1_reg, chr2_reg, chr1_reg);
|
|
||||||
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
|
|
||||||
assert(chr1_reg == result_reg, "result must be pre-placed");
|
|
||||||
__ delayed()->nop();
|
|
||||||
|
|
||||||
{
|
|
||||||
// Check after comparing first character to see if strings are equivalent
|
|
||||||
Label LSkip2;
|
|
||||||
// Check if the strings start at same location
|
|
||||||
__ cmp(str1_reg, str2_reg);
|
|
||||||
__ brx(Assembler::notEqual, true, Assembler::pt, LSkip2);
|
|
||||||
__ delayed()->nop();
|
|
||||||
|
|
||||||
// Check if the length difference is zero (in O7)
|
|
||||||
__ cmp(G0, O7);
|
|
||||||
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // result is zero
|
|
||||||
|
|
||||||
// Strings might not be equal
|
|
||||||
__ bind(LSkip2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// We have no guarantee that on 64 bit the higher half of limit_reg is 0
|
|
||||||
__ signx(limit_reg);
|
|
||||||
|
|
||||||
__ subcc(limit_reg, 1 * sizeof(jchar), chr1_reg);
|
|
||||||
__ br(Assembler::equal, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(O7, result_reg); // result is difference in lengths
|
|
||||||
|
|
||||||
// Shift str1_reg and str2_reg to the end of the arrays, negate limit
|
|
||||||
__ add(str1_reg, limit_reg, str1_reg);
|
|
||||||
__ add(str2_reg, limit_reg, str2_reg);
|
|
||||||
__ neg(chr1_reg, limit_reg); // limit = -(limit-2)
|
|
||||||
|
|
||||||
// Compare the rest of the characters
|
|
||||||
__ lduh(str1_reg, limit_reg, chr1_reg);
|
|
||||||
__ bind(Lloop);
|
|
||||||
// __ lduh(str1_reg, limit_reg, chr1_reg); // hoisted
|
|
||||||
__ lduh(str2_reg, limit_reg, chr2_reg);
|
|
||||||
__ subcc(chr1_reg, chr2_reg, chr1_reg);
|
|
||||||
__ br(Assembler::notZero, false, Assembler::pt, Ldone);
|
|
||||||
assert(chr1_reg == result_reg, "result must be pre-placed");
|
|
||||||
__ delayed()->inccc(limit_reg, sizeof(jchar));
|
|
||||||
// annul LDUH if branch is not taken to prevent access past end of string
|
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lloop);
|
|
||||||
__ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
|
|
||||||
|
|
||||||
// If strings are equal up to min length, return the length difference.
|
|
||||||
__ mov(O7, result_reg);
|
|
||||||
|
|
||||||
// Otherwise, return the difference between the first mismatched chars.
|
|
||||||
__ bind(Ldone);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_String_Equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result) %{
|
|
||||||
Label Lchar, Lchar_loop, Ldone;
|
|
||||||
MacroAssembler _masm(&cbuf);
|
|
||||||
|
|
||||||
Register str1_reg = reg_to_register_object($str1$$reg);
|
|
||||||
Register str2_reg = reg_to_register_object($str2$$reg);
|
|
||||||
Register cnt_reg = reg_to_register_object($cnt$$reg);
|
|
||||||
Register tmp1_reg = O7;
|
|
||||||
Register result_reg = reg_to_register_object($result$$reg);
|
|
||||||
|
|
||||||
assert(result_reg != str1_reg &&
|
|
||||||
result_reg != str2_reg &&
|
|
||||||
result_reg != cnt_reg &&
|
|
||||||
result_reg != tmp1_reg ,
|
|
||||||
"need different registers");
|
|
||||||
|
|
||||||
__ cmp(str1_reg, str2_reg); //same char[] ?
|
|
||||||
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->add(G0, 1, result_reg);
|
|
||||||
|
|
||||||
__ cmp_zero_and_br(Assembler::zero, cnt_reg, Ldone, true, Assembler::pn);
|
|
||||||
__ delayed()->add(G0, 1, result_reg); // count == 0
|
|
||||||
|
|
||||||
//rename registers
|
|
||||||
Register limit_reg = cnt_reg;
|
|
||||||
Register chr1_reg = result_reg;
|
|
||||||
Register chr2_reg = tmp1_reg;
|
|
||||||
|
|
||||||
// We have no guarantee that on 64 bit the higher half of limit_reg is 0
|
|
||||||
__ signx(limit_reg);
|
|
||||||
|
|
||||||
//check for alignment and position the pointers to the ends
|
|
||||||
__ or3(str1_reg, str2_reg, chr1_reg);
|
|
||||||
__ andcc(chr1_reg, 0x3, chr1_reg);
|
|
||||||
// notZero means at least one not 4-byte aligned.
|
|
||||||
// We could optimize the case when both arrays are not aligned
|
|
||||||
// but it is not frequent case and it requires additional checks.
|
|
||||||
__ br(Assembler::notZero, false, Assembler::pn, Lchar); // char by char compare
|
|
||||||
__ delayed()->sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg); // set byte count
|
|
||||||
|
|
||||||
// Compare char[] arrays aligned to 4 bytes.
|
|
||||||
__ char_arrays_equals(str1_reg, str2_reg, limit_reg, result_reg,
|
|
||||||
chr1_reg, chr2_reg, Ldone);
|
|
||||||
__ ba(Ldone);
|
|
||||||
__ delayed()->add(G0, 1, result_reg);
|
|
||||||
|
|
||||||
// char by char compare
|
|
||||||
__ bind(Lchar);
|
|
||||||
__ add(str1_reg, limit_reg, str1_reg);
|
|
||||||
__ add(str2_reg, limit_reg, str2_reg);
|
|
||||||
__ neg(limit_reg); //negate count
|
|
||||||
|
|
||||||
__ lduh(str1_reg, limit_reg, chr1_reg);
|
|
||||||
// Lchar_loop
|
|
||||||
__ bind(Lchar_loop);
|
|
||||||
__ lduh(str2_reg, limit_reg, chr2_reg);
|
|
||||||
__ cmp(chr1_reg, chr2_reg);
|
|
||||||
__ br(Assembler::notEqual, true, Assembler::pt, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); //not equal
|
|
||||||
__ inccc(limit_reg, sizeof(jchar));
|
|
||||||
// annul LDUH if branch is not taken to prevent access past end of string
|
|
||||||
__ br(Assembler::notZero, true, Assembler::pt, Lchar_loop);
|
|
||||||
__ delayed()->lduh(str1_reg, limit_reg, chr1_reg); // hoisted
|
|
||||||
|
|
||||||
__ add(G0, 1, result_reg); //equal
|
|
||||||
|
|
||||||
__ bind(Ldone);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_Array_Equals(o0RegP ary1, o1RegP ary2, g3RegP tmp1, notemp_iRegI result) %{
|
|
||||||
Label Lvector, Ldone, Lloop;
|
|
||||||
MacroAssembler _masm(&cbuf);
|
|
||||||
|
|
||||||
Register ary1_reg = reg_to_register_object($ary1$$reg);
|
|
||||||
Register ary2_reg = reg_to_register_object($ary2$$reg);
|
|
||||||
Register tmp1_reg = reg_to_register_object($tmp1$$reg);
|
|
||||||
Register tmp2_reg = O7;
|
|
||||||
Register result_reg = reg_to_register_object($result$$reg);
|
|
||||||
|
|
||||||
int length_offset = arrayOopDesc::length_offset_in_bytes();
|
|
||||||
int base_offset = arrayOopDesc::base_offset_in_bytes(T_CHAR);
|
|
||||||
|
|
||||||
// return true if the same array
|
|
||||||
__ cmp(ary1_reg, ary2_reg);
|
|
||||||
__ brx(Assembler::equal, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->add(G0, 1, result_reg); // equal
|
|
||||||
|
|
||||||
__ br_null(ary1_reg, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
|
||||||
|
|
||||||
__ br_null(ary2_reg, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
|
||||||
|
|
||||||
//load the lengths of arrays
|
|
||||||
__ ld(Address(ary1_reg, length_offset), tmp1_reg);
|
|
||||||
__ ld(Address(ary2_reg, length_offset), tmp2_reg);
|
|
||||||
|
|
||||||
// return false if the two arrays are not equal length
|
|
||||||
__ cmp(tmp1_reg, tmp2_reg);
|
|
||||||
__ br(Assembler::notEqual, true, Assembler::pn, Ldone);
|
|
||||||
__ delayed()->mov(G0, result_reg); // not equal
|
|
||||||
|
|
||||||
__ cmp_zero_and_br(Assembler::zero, tmp1_reg, Ldone, true, Assembler::pn);
|
|
||||||
__ delayed()->add(G0, 1, result_reg); // zero-length arrays are equal
|
|
||||||
|
|
||||||
// load array addresses
|
|
||||||
__ add(ary1_reg, base_offset, ary1_reg);
|
|
||||||
__ add(ary2_reg, base_offset, ary2_reg);
|
|
||||||
|
|
||||||
// renaming registers
|
|
||||||
Register chr1_reg = result_reg; // for characters in ary1
|
|
||||||
Register chr2_reg = tmp2_reg; // for characters in ary2
|
|
||||||
Register limit_reg = tmp1_reg; // length
|
|
||||||
|
|
||||||
// set byte count
|
|
||||||
__ sll(limit_reg, exact_log2(sizeof(jchar)), limit_reg);
|
|
||||||
|
|
||||||
// Compare char[] arrays aligned to 4 bytes.
|
|
||||||
__ char_arrays_equals(ary1_reg, ary2_reg, limit_reg, result_reg,
|
|
||||||
chr1_reg, chr2_reg, Ldone);
|
|
||||||
__ add(G0, 1, result_reg); // equals
|
|
||||||
|
|
||||||
__ bind(Ldone);
|
|
||||||
%}
|
|
||||||
|
|
||||||
enc_class enc_rethrow() %{
|
enc_class enc_rethrow() %{
|
||||||
cbuf.set_insts_mark();
|
cbuf.set_insts_mark();
|
||||||
Register temp_reg = G3;
|
Register temp_reg = G3;
|
||||||
|
@ -10275,33 +10049,204 @@ instruct clear_array_bis_2(g1RegX cnt, o0RegP base, iRegX tmp, Universe dummy, f
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_compare(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
|
instruct string_compareL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
|
||||||
o7RegI tmp, flagsReg ccr) %{
|
o7RegI tmp, flagsReg ccr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %}
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %}
|
||||||
ins_encode( enc_String_Compare(str1, str2, cnt1, cnt2, result) );
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
$tmp$$Register, $tmp$$Register,
|
||||||
|
$result$$Register, StrIntrinsicNode::LL);
|
||||||
|
%}
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_equals(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
|
instruct string_compareU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
|
||||||
o7RegI tmp, flagsReg ccr) %{
|
o7RegI tmp, flagsReg ccr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
$tmp$$Register, $tmp$$Register,
|
||||||
|
$result$$Register, StrIntrinsicNode::UU);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareLU(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
|
||||||
|
o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1,$tmp2" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
$tmp1$$Register, $tmp2$$Register,
|
||||||
|
$result$$Register, StrIntrinsicNode::LU);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareUL(o0RegP str1, o1RegP str2, g3RegI cnt1, g4RegI cnt2, notemp_iRegI result,
|
||||||
|
o7RegI tmp1, g1RegI tmp2, flagsReg ccr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL ccr, KILL tmp1, KILL tmp2);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1,$tmp2" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str2$$Register, $str1$$Register,
|
||||||
|
$cnt2$$Register, $cnt1$$Register,
|
||||||
|
$tmp1$$Register, $tmp2$$Register,
|
||||||
|
$result$$Register, StrIntrinsicNode::UL);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_equalsL(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
|
||||||
|
o7RegI tmp, flagsReg ccr) %{
|
||||||
|
predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (StrEquals (Binary str1 str2) cnt));
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp" %}
|
format %{ "String Equals byte[] $str1,$str2,$cnt -> $result // KILL $tmp" %}
|
||||||
ins_encode( enc_String_Equals(str1, str2, cnt, result) );
|
ins_encode %{
|
||||||
|
__ array_equals(false, $str1$$Register, $str2$$Register,
|
||||||
|
$cnt$$Register, $tmp$$Register,
|
||||||
|
$result$$Register, true /* byte */);
|
||||||
|
%}
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct array_equals(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
|
instruct string_equalsU(o0RegP str1, o1RegP str2, g3RegI cnt, notemp_iRegI result,
|
||||||
o7RegI tmp2, flagsReg ccr) %{
|
o7RegI tmp, flagsReg ccr) %{
|
||||||
|
predicate(((StrEqualsNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (StrEquals (Binary str1 str2) cnt));
|
||||||
|
effect(USE_KILL str1, USE_KILL str2, USE_KILL cnt, KILL tmp, KILL ccr);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Equals char[] $str1,$str2,$cnt -> $result // KILL $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ array_equals(false, $str1$$Register, $str2$$Register,
|
||||||
|
$cnt$$Register, $tmp$$Register,
|
||||||
|
$result$$Register, false /* byte */);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct array_equalsB(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
|
||||||
|
o7RegI tmp2, flagsReg ccr) %{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
|
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
|
||||||
ins_cost(300);
|
ins_cost(300);
|
||||||
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %}
|
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %}
|
||||||
ins_encode( enc_Array_Equals(ary1, ary2, tmp1, result));
|
ins_encode %{
|
||||||
|
__ array_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
|
$tmp1$$Register, $tmp2$$Register,
|
||||||
|
$result$$Register, true /* byte */);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct array_equalsC(o0RegP ary1, o1RegP ary2, g3RegI tmp1, notemp_iRegI result,
|
||||||
|
o7RegI tmp2, flagsReg ccr) %{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (AryEq ary1 ary2));
|
||||||
|
effect(USE_KILL ary1, USE_KILL ary2, KILL tmp1, KILL tmp2, KILL ccr);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1,$tmp2" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ array_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
|
$tmp1$$Register, $tmp2$$Register,
|
||||||
|
$result$$Register, false /* byte */);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
// char[] to byte[] compression
|
||||||
|
instruct string_compress(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result, iRegL tmp, flagsReg ccr) %{
|
||||||
|
predicate(UseVIS < 3);
|
||||||
|
match(Set result (StrCompressedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP result, TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Compress $src,$dst,$len -> $result // KILL $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label Ldone;
|
||||||
|
__ signx($len$$Register);
|
||||||
|
__ cmp_zero_and_br(Assembler::zero, $len$$Register, Ldone, false, Assembler::pn);
|
||||||
|
__ delayed()->mov($len$$Register, $result$$Register); // copy count
|
||||||
|
__ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp$$Register, Ldone);
|
||||||
|
__ bind(Ldone);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast char[] to byte[] compression using VIS instructions
|
||||||
|
instruct string_compress_fast(o0RegP src, o1RegP dst, g3RegI len, notemp_iRegI result,
|
||||||
|
iRegL tmp1, iRegL tmp2, iRegL tmp3, iRegL tmp4,
|
||||||
|
regD ftmp1, regD ftmp2, regD ftmp3, flagsReg ccr) %{
|
||||||
|
predicate(UseVIS >= 3);
|
||||||
|
match(Set result (StrCompressedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP result, TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Compress Fast $src,$dst,$len -> $result // KILL $tmp1,$tmp2,$tmp3,$tmp4,$ftmp1,$ftmp2,$ftmp3" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label Ldone;
|
||||||
|
__ signx($len$$Register);
|
||||||
|
__ string_compress_16($src$$Register, $dst$$Register, $len$$Register, $result$$Register,
|
||||||
|
$tmp1$$Register, $tmp2$$Register, $tmp3$$Register, $tmp4$$Register,
|
||||||
|
$ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, Ldone);
|
||||||
|
__ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone);
|
||||||
|
__ string_compress($src$$Register, $dst$$Register, $len$$Register, $result$$Register, $tmp1$$Register, Ldone);
|
||||||
|
__ bind(Ldone);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
// byte[] to char[] inflation
|
||||||
|
instruct string_inflate(Universe dummy, o0RegP src, o1RegP dst, g3RegI len,
|
||||||
|
iRegL tmp, flagsReg ccr) %{
|
||||||
|
match(Set dummy (StrInflatedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP tmp, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Inflate $src,$dst,$len // KILL $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label Ldone;
|
||||||
|
__ signx($len$$Register);
|
||||||
|
__ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone);
|
||||||
|
__ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone);
|
||||||
|
__ bind(Ldone);
|
||||||
|
%}
|
||||||
|
ins_pipe(long_memory_op);
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast byte[] to char[] inflation using VIS instructions
|
||||||
|
instruct string_inflate_fast(Universe dummy, o0RegP src, o1RegP dst, g3RegI len,
|
||||||
|
iRegL tmp, regD ftmp1, regD ftmp2, regD ftmp3, regD ftmp4, flagsReg ccr) %{
|
||||||
|
predicate(UseVIS >= 3);
|
||||||
|
match(Set dummy (StrInflatedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP tmp, TEMP ftmp1, TEMP ftmp2, TEMP ftmp3, TEMP ftmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL ccr);
|
||||||
|
ins_cost(300);
|
||||||
|
format %{ "String Inflate Fast $src,$dst,$len // KILL $tmp,$ftmp1,$ftmp2,$ftmp3,$ftmp4" %}
|
||||||
|
ins_encode %{
|
||||||
|
Label Ldone;
|
||||||
|
__ signx($len$$Register);
|
||||||
|
__ string_inflate_16($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register,
|
||||||
|
$ftmp1$$FloatRegister, $ftmp2$$FloatRegister, $ftmp3$$FloatRegister, $ftmp4$$FloatRegister, Ldone);
|
||||||
|
__ cmp_and_brx_short($len$$Register, 0, Assembler::equal, Assembler::pn, Ldone);
|
||||||
|
__ string_inflate($src$$Register, $dst$$Register, $len$$Register, $tmp$$Register, Ldone);
|
||||||
|
__ bind(Ldone);
|
||||||
|
%}
|
||||||
ins_pipe(long_memory_op);
|
ins_pipe(long_memory_op);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,26 @@
|
||||||
declare_constant(VM_Version::vis1_instructions_m) \
|
declare_constant(VM_Version::vis1_instructions_m) \
|
||||||
declare_constant(VM_Version::vis2_instructions_m) \
|
declare_constant(VM_Version::vis2_instructions_m) \
|
||||||
declare_constant(VM_Version::vis3_instructions_m) \
|
declare_constant(VM_Version::vis3_instructions_m) \
|
||||||
declare_constant(VM_Version::cbcond_instructions_m)
|
declare_constant(VM_Version::cbcond_instructions_m) \
|
||||||
|
declare_constant(VM_Version::v8_instructions_m) \
|
||||||
|
declare_constant(VM_Version::hardware_mul32_m) \
|
||||||
|
declare_constant(VM_Version::hardware_div32_m) \
|
||||||
|
declare_constant(VM_Version::hardware_fsmuld_m) \
|
||||||
|
declare_constant(VM_Version::hardware_popc_m) \
|
||||||
|
declare_constant(VM_Version::v9_instructions_m) \
|
||||||
|
declare_constant(VM_Version::sun4v_m) \
|
||||||
|
declare_constant(VM_Version::blk_init_instructions_m) \
|
||||||
|
declare_constant(VM_Version::fmaf_instructions_m) \
|
||||||
|
declare_constant(VM_Version::fmau_instructions_m) \
|
||||||
|
declare_constant(VM_Version::sparc64_family_m) \
|
||||||
|
declare_constant(VM_Version::M_family_m) \
|
||||||
|
declare_constant(VM_Version::T_family_m) \
|
||||||
|
declare_constant(VM_Version::T1_model_m) \
|
||||||
|
declare_constant(VM_Version::sparc5_instructions_m) \
|
||||||
|
declare_constant(VM_Version::aes_instructions_m) \
|
||||||
|
declare_constant(VM_Version::sha1_instruction_m) \
|
||||||
|
declare_constant(VM_Version::sha256_instruction_m) \
|
||||||
|
declare_constant(VM_Version::sha512_instruction_m)
|
||||||
|
|
||||||
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
|
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
|
||||||
|
|
||||||
|
|
|
@ -1539,7 +1539,6 @@ void Assembler::cmpl(Register dst, Register src) {
|
||||||
emit_arith(0x3B, 0xC0, dst, src);
|
emit_arith(0x3B, 0xC0, dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Assembler::cmpl(Register dst, Address src) {
|
void Assembler::cmpl(Register dst, Address src) {
|
||||||
InstructionMark im(this);
|
InstructionMark im(this);
|
||||||
prefix(src, dst);
|
prefix(src, dst);
|
||||||
|
@ -2125,6 +2124,16 @@ void Assembler::movb(Register dst, Address src) {
|
||||||
emit_operand(dst, src);
|
emit_operand(dst, src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembler::movddup(XMMRegister dst, XMMRegister src) {
|
||||||
|
_instruction_uses_vl = true;
|
||||||
|
NOT_LP64(assert(VM_Version::supports_sse3(), ""));
|
||||||
|
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_F2, /* no_mask_reg */ false, VEX_OPCODE_0F,
|
||||||
|
/* rex_w */ VM_Version::supports_evex(), AVX_128bit, /* legacy_mode */ false);
|
||||||
|
emit_int8(0x12);
|
||||||
|
emit_int8(0xC0 | encode);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void Assembler::kmovql(KRegister dst, KRegister src) {
|
void Assembler::kmovql(KRegister dst, KRegister src) {
|
||||||
NOT_LP64(assert(VM_Version::supports_evex(), ""));
|
NOT_LP64(assert(VM_Version::supports_evex(), ""));
|
||||||
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
|
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
|
||||||
|
@ -3027,6 +3036,35 @@ void Assembler::pcmpestri(XMMRegister dst, XMMRegister src, int imm8) {
|
||||||
emit_int8(imm8);
|
emit_int8(imm8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembler::pcmpeqw(XMMRegister dst, XMMRegister src) {
|
||||||
|
NOT_LP64(assert(VM_Version::supports_sse2(), ""));
|
||||||
|
emit_simd_arith(0x75, dst, src, VEX_SIMD_66,
|
||||||
|
false, (VM_Version::supports_avx512dq() == false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assembler::vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len) {
|
||||||
|
assert(UseAVX > 0, "some form of AVX must be enabled");
|
||||||
|
emit_vex_arith(0x75, dst, nds, src, VEX_SIMD_66, vector_len,
|
||||||
|
false, (VM_Version::supports_avx512dq() == false));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assembler::pmovmskb(Register dst, XMMRegister src) {
|
||||||
|
assert(VM_Version::supports_sse2(), "");
|
||||||
|
int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, true, VEX_OPCODE_0F,
|
||||||
|
false, AVX_128bit, (VM_Version::supports_avx512dq() == false));
|
||||||
|
emit_int8((unsigned char)0xD7);
|
||||||
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assembler::vpmovmskb(Register dst, XMMRegister src) {
|
||||||
|
assert(VM_Version::supports_avx2(), "");
|
||||||
|
int vector_len = AVX_256bit;
|
||||||
|
int encode = vex_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66,
|
||||||
|
vector_len, VEX_OPCODE_0F, true, false);
|
||||||
|
emit_int8((unsigned char)0xD7);
|
||||||
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
|
}
|
||||||
|
|
||||||
void Assembler::pextrd(Register dst, XMMRegister src, int imm8) {
|
void Assembler::pextrd(Register dst, XMMRegister src, int imm8) {
|
||||||
assert(VM_Version::supports_sse4_1(), "");
|
assert(VM_Version::supports_sse4_1(), "");
|
||||||
int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
|
int encode = simd_prefix_and_encode(as_XMMRegister(dst->encoding()), xnoreg, src, VEX_SIMD_66, /* no_mask_reg */ true,
|
||||||
|
@ -3099,6 +3137,17 @@ void Assembler::pmovzxbw(XMMRegister dst, XMMRegister src) {
|
||||||
emit_int8((unsigned char)(0xC0 | encode));
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembler::vpmovzxbw(XMMRegister dst, Address src) {
|
||||||
|
assert(VM_Version::supports_avx(), "");
|
||||||
|
InstructionMark im(this);
|
||||||
|
bool vector256 = true;
|
||||||
|
assert(dst != xnoreg, "sanity");
|
||||||
|
int dst_enc = dst->encoding();
|
||||||
|
vex_prefix(src, 0, dst_enc, VEX_SIMD_66, VEX_OPCODE_0F_38, false, vector256);
|
||||||
|
emit_int8(0x30);
|
||||||
|
emit_operand(dst, src);
|
||||||
|
}
|
||||||
|
|
||||||
// generic
|
// generic
|
||||||
void Assembler::pop(Register dst) {
|
void Assembler::pop(Register dst) {
|
||||||
int encode = prefix_and_encode(dst->encoding());
|
int encode = prefix_and_encode(dst->encoding());
|
||||||
|
@ -3403,6 +3452,20 @@ void Assembler::rcll(Register dst, int imm8) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembler::rcpps(XMMRegister dst, XMMRegister src) {
|
||||||
|
NOT_LP64(assert(VM_Version::supports_sse(), ""));
|
||||||
|
int encode = simd_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_NONE, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
|
||||||
|
emit_int8(0x53);
|
||||||
|
emit_int8(0xC0 | encode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assembler::rcpss(XMMRegister dst, XMMRegister src) {
|
||||||
|
NOT_LP64(assert(VM_Version::supports_sse(), ""));
|
||||||
|
int encode = simd_prefix_and_encode(dst, dst, src, VEX_SIMD_F3, /* no_mask_reg */ false, VEX_OPCODE_0F, /* rex_w */ false, AVX_128bit, /* legacy_mode */ true);
|
||||||
|
emit_int8(0x53);
|
||||||
|
emit_int8(0xC0 | encode);
|
||||||
|
}
|
||||||
|
|
||||||
void Assembler::rdtsc() {
|
void Assembler::rdtsc() {
|
||||||
emit_int8((unsigned char)0x0F);
|
emit_int8((unsigned char)0x0F);
|
||||||
emit_int8((unsigned char)0x31);
|
emit_int8((unsigned char)0x31);
|
||||||
|
@ -5347,6 +5410,16 @@ void Assembler::vpbroadcastd(XMMRegister dst, XMMRegister src) {
|
||||||
emit_int8((unsigned char)(0xC0 | encode));
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// duplicate 2-bytes integer data from src into 16 locations in dest
|
||||||
|
void Assembler::vpbroadcastw(XMMRegister dst, XMMRegister src) {
|
||||||
|
assert(VM_Version::supports_avx2(), "");
|
||||||
|
bool vector_len = AVX_256bit;
|
||||||
|
int encode = vex_prefix_and_encode(dst, xnoreg, src, VEX_SIMD_66,
|
||||||
|
vector_len, VEX_OPCODE_0F_38, false);
|
||||||
|
emit_int8(0x79);
|
||||||
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
|
}
|
||||||
|
|
||||||
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
|
// duplicate 1-byte integer data from src into 16||32|64 locations in dest : requires AVX512BW and AVX512VL
|
||||||
void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
|
void Assembler::evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len) {
|
||||||
_instruction_uses_vl = true;
|
_instruction_uses_vl = true;
|
||||||
|
@ -6326,6 +6399,26 @@ void Assembler::emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds, X
|
||||||
emit_int8((unsigned char)(0xC0 | encode));
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Assembler::cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len) {
|
||||||
|
assert(VM_Version::supports_avx(), "");
|
||||||
|
assert(!VM_Version::supports_evex(), "");
|
||||||
|
int encode = vex_prefix_and_encode(dst, nds, src, VEX_SIMD_66, vector_len, VEX_OPCODE_0F, /* no_mask_reg */ false);
|
||||||
|
emit_int8((unsigned char)0xC2);
|
||||||
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
|
emit_int8((unsigned char)(0xF & cop));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Assembler::vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len) {
|
||||||
|
assert(VM_Version::supports_avx(), "");
|
||||||
|
assert(!VM_Version::supports_evex(), "");
|
||||||
|
int encode = vex_prefix_and_encode(dst, nds, src1, VEX_SIMD_66, vector_len, VEX_OPCODE_0F_3A, /* no_mask_reg */ false);
|
||||||
|
emit_int8((unsigned char)0x4B);
|
||||||
|
emit_int8((unsigned char)(0xC0 | encode));
|
||||||
|
int src2_enc = src2->encoding();
|
||||||
|
emit_int8((unsigned char)(0xF0 & src2_enc<<4));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
|
|
||||||
void Assembler::incl(Register dst) {
|
void Assembler::incl(Register dst) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -1504,6 +1504,8 @@ private:
|
||||||
void movb(Address dst, int imm8);
|
void movb(Address dst, int imm8);
|
||||||
void movb(Register dst, Address src);
|
void movb(Register dst, Address src);
|
||||||
|
|
||||||
|
void movddup(XMMRegister dst, XMMRegister src);
|
||||||
|
|
||||||
void kmovql(KRegister dst, KRegister src);
|
void kmovql(KRegister dst, KRegister src);
|
||||||
void kmovql(KRegister dst, Register src);
|
void kmovql(KRegister dst, Register src);
|
||||||
void kmovdl(KRegister dst, Register src);
|
void kmovdl(KRegister dst, Register src);
|
||||||
|
@ -1680,6 +1682,12 @@ private:
|
||||||
void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
|
void pcmpestri(XMMRegister xmm1, XMMRegister xmm2, int imm8);
|
||||||
void pcmpestri(XMMRegister xmm1, Address src, int imm8);
|
void pcmpestri(XMMRegister xmm1, Address src, int imm8);
|
||||||
|
|
||||||
|
void pcmpeqw(XMMRegister dst, XMMRegister src);
|
||||||
|
void vpcmpeqw(XMMRegister dst, XMMRegister nds, XMMRegister src, int vector_len);
|
||||||
|
|
||||||
|
void pmovmskb(Register dst, XMMRegister src);
|
||||||
|
void vpmovmskb(Register dst, XMMRegister src);
|
||||||
|
|
||||||
// SSE 4.1 extract
|
// SSE 4.1 extract
|
||||||
void pextrd(Register dst, XMMRegister src, int imm8);
|
void pextrd(Register dst, XMMRegister src, int imm8);
|
||||||
void pextrq(Register dst, XMMRegister src, int imm8);
|
void pextrq(Register dst, XMMRegister src, int imm8);
|
||||||
|
@ -1696,6 +1704,8 @@ private:
|
||||||
void pmovzxbw(XMMRegister dst, XMMRegister src);
|
void pmovzxbw(XMMRegister dst, XMMRegister src);
|
||||||
void pmovzxbw(XMMRegister dst, Address src);
|
void pmovzxbw(XMMRegister dst, Address src);
|
||||||
|
|
||||||
|
void vpmovzxbw(XMMRegister dst, Address src);
|
||||||
|
|
||||||
#ifndef _LP64 // no 32bit push/pop on amd64
|
#ifndef _LP64 // no 32bit push/pop on amd64
|
||||||
void popl(Address dst);
|
void popl(Address dst);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1768,6 +1778,10 @@ private:
|
||||||
|
|
||||||
void rcrq(Register dst, int imm8);
|
void rcrq(Register dst, int imm8);
|
||||||
|
|
||||||
|
void rcpps(XMMRegister dst, XMMRegister src);
|
||||||
|
|
||||||
|
void rcpss(XMMRegister dst, XMMRegister src);
|
||||||
|
|
||||||
void rdtsc();
|
void rdtsc();
|
||||||
|
|
||||||
void ret(int imm16);
|
void ret(int imm16);
|
||||||
|
@ -2110,6 +2124,9 @@ private:
|
||||||
// duplicate 4-bytes integer data from src into 8 locations in dest
|
// duplicate 4-bytes integer data from src into 8 locations in dest
|
||||||
void vpbroadcastd(XMMRegister dst, XMMRegister src);
|
void vpbroadcastd(XMMRegister dst, XMMRegister src);
|
||||||
|
|
||||||
|
// duplicate 2-bytes integer data from src into 16 locations in dest
|
||||||
|
void vpbroadcastw(XMMRegister dst, XMMRegister src);
|
||||||
|
|
||||||
// duplicate n-bytes integer data from src into vector_len locations in dest
|
// duplicate n-bytes integer data from src into vector_len locations in dest
|
||||||
void evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len);
|
void evpbroadcastb(XMMRegister dst, XMMRegister src, int vector_len);
|
||||||
void evpbroadcastb(XMMRegister dst, Address src, int vector_len);
|
void evpbroadcastb(XMMRegister dst, Address src, int vector_len);
|
||||||
|
@ -2141,6 +2158,11 @@ private:
|
||||||
// runtime code and native libraries.
|
// runtime code and native libraries.
|
||||||
void vzeroupper();
|
void vzeroupper();
|
||||||
|
|
||||||
|
// AVX support for vectorized conditional move (double). The following two instructions used only coupled.
|
||||||
|
void cmppd(XMMRegister dst, XMMRegister nds, XMMRegister src, int cop, int vector_len);
|
||||||
|
void vpblendd(XMMRegister dst, XMMRegister nds, XMMRegister src1, XMMRegister src2, int vector_len);
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Next instructions require address alignment 16 bytes SSE mode.
|
// Next instructions require address alignment 16 bytes SSE mode.
|
||||||
// They should be called only from corresponding MacroAssembler instructions.
|
// They should be called only from corresponding MacroAssembler instructions.
|
||||||
|
|
|
@ -509,86 +509,6 @@ int LIR_Assembler::emit_deopt_handler() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This is the fast version of java.lang.String.compare; it has not
|
|
||||||
// OSR-entry and therefore, we generate a slow version for OSR's
|
|
||||||
void LIR_Assembler::emit_string_compare(LIR_Opr arg0, LIR_Opr arg1, LIR_Opr dst, CodeEmitInfo* info) {
|
|
||||||
__ movptr (rbx, rcx); // receiver is in rcx
|
|
||||||
__ movptr (rax, arg1->as_register());
|
|
||||||
|
|
||||||
// Get addresses of first characters from both Strings
|
|
||||||
__ load_heap_oop(rsi, Address(rax, java_lang_String::value_offset_in_bytes()));
|
|
||||||
if (java_lang_String::has_offset_field()) {
|
|
||||||
__ movptr (rcx, Address(rax, java_lang_String::offset_offset_in_bytes()));
|
|
||||||
__ movl (rax, Address(rax, java_lang_String::count_offset_in_bytes()));
|
|
||||||
__ lea (rsi, Address(rsi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
|
||||||
} else {
|
|
||||||
__ movl (rax, Address(rsi, arrayOopDesc::length_offset_in_bytes()));
|
|
||||||
__ lea (rsi, Address(rsi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// rbx, may be NULL
|
|
||||||
add_debug_info_for_null_check_here(info);
|
|
||||||
__ load_heap_oop(rdi, Address(rbx, java_lang_String::value_offset_in_bytes()));
|
|
||||||
if (java_lang_String::has_offset_field()) {
|
|
||||||
__ movptr (rcx, Address(rbx, java_lang_String::offset_offset_in_bytes()));
|
|
||||||
__ movl (rbx, Address(rbx, java_lang_String::count_offset_in_bytes()));
|
|
||||||
__ lea (rdi, Address(rdi, rcx, Address::times_2, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
|
||||||
} else {
|
|
||||||
__ movl (rbx, Address(rdi, arrayOopDesc::length_offset_in_bytes()));
|
|
||||||
__ lea (rdi, Address(rdi, arrayOopDesc::base_offset_in_bytes(T_CHAR)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// compute minimum length (in rax) and difference of lengths (on top of stack)
|
|
||||||
__ mov (rcx, rbx);
|
|
||||||
__ subptr(rbx, rax); // subtract lengths
|
|
||||||
__ push (rbx); // result
|
|
||||||
__ cmov (Assembler::lessEqual, rax, rcx);
|
|
||||||
|
|
||||||
// is minimum length 0?
|
|
||||||
Label noLoop, haveResult;
|
|
||||||
__ testptr (rax, rax);
|
|
||||||
__ jcc (Assembler::zero, noLoop);
|
|
||||||
|
|
||||||
// compare first characters
|
|
||||||
__ load_unsigned_short(rcx, Address(rdi, 0));
|
|
||||||
__ load_unsigned_short(rbx, Address(rsi, 0));
|
|
||||||
__ subl(rcx, rbx);
|
|
||||||
__ jcc(Assembler::notZero, haveResult);
|
|
||||||
// starting loop
|
|
||||||
__ decrement(rax); // we already tested index: skip one
|
|
||||||
__ jcc(Assembler::zero, noLoop);
|
|
||||||
|
|
||||||
// set rsi.edi to the end of the arrays (arrays have same length)
|
|
||||||
// negate the index
|
|
||||||
|
|
||||||
__ lea(rsi, Address(rsi, rax, Address::times_2, type2aelembytes(T_CHAR)));
|
|
||||||
__ lea(rdi, Address(rdi, rax, Address::times_2, type2aelembytes(T_CHAR)));
|
|
||||||
__ negptr(rax);
|
|
||||||
|
|
||||||
// compare the strings in a loop
|
|
||||||
|
|
||||||
Label loop;
|
|
||||||
__ align(wordSize);
|
|
||||||
__ bind(loop);
|
|
||||||
__ load_unsigned_short(rcx, Address(rdi, rax, Address::times_2, 0));
|
|
||||||
__ load_unsigned_short(rbx, Address(rsi, rax, Address::times_2, 0));
|
|
||||||
__ subl(rcx, rbx);
|
|
||||||
__ jcc(Assembler::notZero, haveResult);
|
|
||||||
__ increment(rax);
|
|
||||||
__ jcc(Assembler::notZero, loop);
|
|
||||||
|
|
||||||
// strings are equal up to min length
|
|
||||||
|
|
||||||
__ bind(noLoop);
|
|
||||||
__ pop(rax);
|
|
||||||
return_op(LIR_OprFact::illegalOpr);
|
|
||||||
|
|
||||||
__ bind(haveResult);
|
|
||||||
// leave instruction is going to discard the TOS value
|
|
||||||
__ mov (rax, rcx); // result of call is in rax,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void LIR_Assembler::return_op(LIR_Opr result) {
|
void LIR_Assembler::return_op(LIR_Opr result) {
|
||||||
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,");
|
assert(result->is_illegal() || !result->is_single_cpu() || result->as_register() == rax, "word returns are in rax,");
|
||||||
if (!result->is_illegal() && result->is_float_kind() && !result->is_xmm_register()) {
|
if (!result->is_illegal() && result->is_float_kind() && !result->is_xmm_register()) {
|
||||||
|
@ -2441,7 +2361,6 @@ void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, L
|
||||||
} else if (value->is_double_fpu()) {
|
} else if (value->is_double_fpu()) {
|
||||||
assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS");
|
assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS");
|
||||||
switch(code) {
|
switch(code) {
|
||||||
case lir_log : __ flog() ; break;
|
|
||||||
case lir_log10 : __ flog10() ; break;
|
case lir_log10 : __ flog10() ; break;
|
||||||
case lir_abs : __ fabs() ; break;
|
case lir_abs : __ fabs() ; break;
|
||||||
case lir_sqrt : __ fsqrt(); break;
|
case lir_sqrt : __ fsqrt(); break;
|
||||||
|
|
|
@ -809,8 +809,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
|
||||||
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
||||||
assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
|
assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
|
||||||
|
|
||||||
if (x->id() == vmIntrinsics::_dexp) {
|
if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog) {
|
||||||
do_ExpIntrinsic(x);
|
do_LibmIntrinsic(x);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,7 +822,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
||||||
case vmIntrinsics::_dsin:
|
case vmIntrinsics::_dsin:
|
||||||
case vmIntrinsics::_dcos:
|
case vmIntrinsics::_dcos:
|
||||||
case vmIntrinsics::_dtan:
|
case vmIntrinsics::_dtan:
|
||||||
case vmIntrinsics::_dlog:
|
|
||||||
case vmIntrinsics::_dlog10:
|
case vmIntrinsics::_dlog10:
|
||||||
case vmIntrinsics::_dpow:
|
case vmIntrinsics::_dpow:
|
||||||
use_fpu = true;
|
use_fpu = true;
|
||||||
|
@ -873,7 +872,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
||||||
case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break;
|
case vmIntrinsics::_dsin: __ sin (calc_input, calc_result, tmp1, tmp2); break;
|
||||||
case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break;
|
case vmIntrinsics::_dcos: __ cos (calc_input, calc_result, tmp1, tmp2); break;
|
||||||
case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break;
|
case vmIntrinsics::_dtan: __ tan (calc_input, calc_result, tmp1, tmp2); break;
|
||||||
case vmIntrinsics::_dlog: __ log (calc_input, calc_result, tmp1); break;
|
|
||||||
case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break;
|
case vmIntrinsics::_dlog10: __ log10(calc_input, calc_result, tmp1); break;
|
||||||
case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
|
case vmIntrinsics::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
|
||||||
default: ShouldNotReachHere();
|
default: ShouldNotReachHere();
|
||||||
|
@ -884,7 +882,7 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
|
void LIRGenerator::do_LibmIntrinsic(Intrinsic* x) {
|
||||||
LIRItem value(x->argument_at(0), this);
|
LIRItem value(x->argument_at(0), this);
|
||||||
value.set_destroys_register();
|
value.set_destroys_register();
|
||||||
|
|
||||||
|
@ -900,13 +898,33 @@ void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
LIR_Opr tmp = FrameMap::fpu0_double_opr;
|
LIR_Opr tmp = FrameMap::fpu0_double_opr;
|
||||||
result_reg = tmp;
|
result_reg = tmp;
|
||||||
if (VM_Version::supports_sse2()) {
|
switch(x->id()) {
|
||||||
__ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
|
case vmIntrinsics::_dexp:
|
||||||
} else {
|
if (VM_Version::supports_sse2()) {
|
||||||
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
|
__ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
|
||||||
|
} else {
|
||||||
|
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dexp), getThreadTemp(), result_reg, cc->args());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case vmIntrinsics::_dlog:
|
||||||
|
if (VM_Version::supports_sse2()) {
|
||||||
|
__ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
__ call_runtime_leaf(CAST_FROM_FN_PTR(address, SharedRuntime::dlog), getThreadTemp(), result_reg, cc->args());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default: ShouldNotReachHere();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
__ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
|
switch (x->id()) {
|
||||||
|
case vmIntrinsics::_dexp:
|
||||||
|
__ call_runtime_leaf(StubRoutines::dexp(), getThreadTemp(), result_reg, cc->args());
|
||||||
|
break;
|
||||||
|
case vmIntrinsics::_dlog:
|
||||||
|
__ call_runtime_leaf(StubRoutines::dlog(), getThreadTemp(), result_reg, cc->args());
|
||||||
|
break;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
__ move(result_reg, calc_result);
|
__ move(result_reg, calc_result);
|
||||||
}
|
}
|
||||||
|
|
|
@ -786,7 +786,6 @@ void FpuStackAllocator::handle_op2(LIR_Op2* op2) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case lir_log:
|
|
||||||
case lir_log10: {
|
case lir_log10: {
|
||||||
// log and log10 need one temporary fpu stack slot, so
|
// log and log10 need one temporary fpu stack slot, so
|
||||||
// there is one temporary registers stored in temp of the
|
// there is one temporary registers stored in temp of the
|
||||||
|
|
|
@ -91,6 +91,8 @@ define_pd_global(size_t, CMSYoungGenPerWorker, 64*M); // default max size of CM
|
||||||
|
|
||||||
define_pd_global(uintx, TypeProfileLevel, 111);
|
define_pd_global(uintx, TypeProfileLevel, 111);
|
||||||
|
|
||||||
|
define_pd_global(bool, CompactStrings, true);
|
||||||
|
|
||||||
define_pd_global(bool, PreserveFramePointer, false);
|
define_pd_global(bool, PreserveFramePointer, false);
|
||||||
|
|
||||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||||
|
|
|
@ -132,10 +132,15 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
|
||||||
__ fabs();
|
__ fabs();
|
||||||
break;
|
break;
|
||||||
case Interpreter::java_lang_math_log:
|
case Interpreter::java_lang_math_log:
|
||||||
__ flog();
|
__ subptr(rsp, 2 * wordSize);
|
||||||
// Store to stack to convert 80bit precision back to 64bits
|
__ fstp_d(Address(rsp, 0));
|
||||||
__ push_fTOS();
|
if (VM_Version::supports_sse2()) {
|
||||||
__ pop_fTOS();
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)));
|
||||||
|
}
|
||||||
|
__ addptr(rsp, 2 * wordSize);
|
||||||
break;
|
break;
|
||||||
case Interpreter::java_lang_math_log10:
|
case Interpreter::java_lang_math_log10:
|
||||||
__ flog10();
|
__ flog10();
|
||||||
|
|
|
@ -253,6 +253,9 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
|
||||||
} else if (kind == Interpreter::java_lang_math_exp) {
|
} else if (kind == Interpreter::java_lang_math_exp) {
|
||||||
__ movdbl(xmm0, Address(rsp, wordSize));
|
__ movdbl(xmm0, Address(rsp, wordSize));
|
||||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dexp())));
|
||||||
|
} else if (kind == Interpreter::java_lang_math_log) {
|
||||||
|
__ movdbl(xmm0, Address(rsp, wordSize));
|
||||||
|
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
|
||||||
} else {
|
} else {
|
||||||
__ fld_d(Address(rsp, wordSize));
|
__ fld_d(Address(rsp, wordSize));
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
@ -268,9 +271,6 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
|
||||||
case Interpreter::java_lang_math_abs:
|
case Interpreter::java_lang_math_abs:
|
||||||
__ fabs();
|
__ fabs();
|
||||||
break;
|
break;
|
||||||
case Interpreter::java_lang_math_log:
|
|
||||||
__ flog();
|
|
||||||
break;
|
|
||||||
case Interpreter::java_lang_math_log10:
|
case Interpreter::java_lang_math_log10:
|
||||||
__ flog10();
|
__ flog10();
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -85,6 +85,23 @@ void CodeInstaller::pd_patch_OopConstant(int pc_offset, Handle& constant) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CodeInstaller::pd_patch_MetaspaceConstant(int pc_offset, Handle& constant) {
|
||||||
|
address pc = _instructions->start() + pc_offset;
|
||||||
|
if (HotSpotMetaspaceConstantImpl::compressed(constant)) {
|
||||||
|
#ifdef _LP64
|
||||||
|
address operand = Assembler::locate_operand(pc, Assembler::narrow_oop_operand);
|
||||||
|
*((narrowKlass*) operand) = record_narrow_metadata_reference(constant);
|
||||||
|
TRACE_jvmci_3("relocating (narrow metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
|
||||||
|
#else
|
||||||
|
fatal("compressed Klass* on 32bit");
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
address operand = Assembler::locate_operand(pc, Assembler::imm_operand);
|
||||||
|
*((Metadata**) operand) = record_metadata_reference(constant);
|
||||||
|
TRACE_jvmci_3("relocating (metaspace constant) at " PTR_FORMAT "/" PTR_FORMAT, p2i(pc), p2i(operand));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset) {
|
||||||
address pc = _instructions->start() + pc_offset;
|
address pc = _instructions->start() + pc_offset;
|
||||||
|
|
||||||
|
@ -100,16 +117,6 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset
|
||||||
TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
|
TRACE_jvmci_3("relocating at " PTR_FORMAT "/" PTR_FORMAT " with destination at " PTR_FORMAT " (%d)", p2i(pc), p2i(operand), p2i(dest), data_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodeInstaller::pd_relocate_CodeBlob(CodeBlob* cb, NativeInstruction* inst) {
|
|
||||||
if (cb->is_nmethod()) {
|
|
||||||
nmethod* nm = (nmethod*) cb;
|
|
||||||
nativeJump_at((address)inst)->set_jump_destination(nm->verified_entry_point());
|
|
||||||
} else {
|
|
||||||
nativeJump_at((address)inst)->set_jump_destination(cb->code_begin());
|
|
||||||
}
|
|
||||||
_instructions->relocate((address)inst, runtime_call_Relocation::spec(), Assembler::call32_operand);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
|
void CodeInstaller::pd_relocate_ForeignCall(NativeInstruction* inst, jlong foreign_call_destination) {
|
||||||
address pc = (address) inst;
|
address pc = (address) inst;
|
||||||
if (inst->is_call()) {
|
if (inst->is_call()) {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -29,7 +29,6 @@
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
#include "runtime/rtmLocking.hpp"
|
#include "runtime/rtmLocking.hpp"
|
||||||
|
|
||||||
|
|
||||||
// MacroAssembler extends Assembler by frequently used macros.
|
// MacroAssembler extends Assembler by frequently used macros.
|
||||||
//
|
//
|
||||||
// Instructions for which a 'better' code sequence exists depending
|
// Instructions for which a 'better' code sequence exists depending
|
||||||
|
@ -56,6 +55,8 @@ class MacroAssembler: public Assembler {
|
||||||
#define VIRTUAL virtual
|
#define VIRTUAL virtual
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define COMMA ,
|
||||||
|
|
||||||
VIRTUAL void call_VM_leaf_base(
|
VIRTUAL void call_VM_leaf_base(
|
||||||
address entry_point, // the entry point
|
address entry_point, // the entry point
|
||||||
int number_of_arguments // the number of arguments to pop after the call
|
int number_of_arguments // the number of arguments to pop after the call
|
||||||
|
@ -910,6 +911,11 @@ class MacroAssembler: public Assembler {
|
||||||
void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
|
void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
|
||||||
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
|
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
|
||||||
Register rax, Register rcx, Register rdx, Register tmp);
|
Register rax, Register rcx, Register rdx, Register tmp);
|
||||||
|
|
||||||
|
void fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
|
||||||
|
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
|
||||||
|
Register rax, Register rcx, Register rdx, Register tmp1 LP64_ONLY(COMMA Register tmp2));
|
||||||
|
|
||||||
void increase_precision();
|
void increase_precision();
|
||||||
void restore_precision();
|
void restore_precision();
|
||||||
|
|
||||||
|
@ -1205,32 +1211,50 @@ public:
|
||||||
// clear memory of size 'cnt' qwords, starting at 'base'.
|
// clear memory of size 'cnt' qwords, starting at 'base'.
|
||||||
void clear_mem(Register base, Register cnt, Register rtmp);
|
void clear_mem(Register base, Register cnt, Register rtmp);
|
||||||
|
|
||||||
|
#ifdef COMPILER2
|
||||||
|
void string_indexof_char(Register str1, Register cnt1, Register ch, Register result,
|
||||||
|
XMMRegister vec1, XMMRegister vec2, XMMRegister vec3, Register tmp);
|
||||||
|
|
||||||
// IndexOf strings.
|
// IndexOf strings.
|
||||||
// Small strings are loaded through stack if they cross page boundary.
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
void string_indexof(Register str1, Register str2,
|
void string_indexof(Register str1, Register str2,
|
||||||
Register cnt1, Register cnt2,
|
Register cnt1, Register cnt2,
|
||||||
int int_cnt2, Register result,
|
int int_cnt2, Register result,
|
||||||
XMMRegister vec, Register tmp);
|
XMMRegister vec, Register tmp,
|
||||||
|
int ae);
|
||||||
|
|
||||||
// IndexOf for constant substrings with size >= 8 elements
|
// IndexOf for constant substrings with size >= 8 elements
|
||||||
// which don't need to be loaded through stack.
|
// which don't need to be loaded through stack.
|
||||||
void string_indexofC8(Register str1, Register str2,
|
void string_indexofC8(Register str1, Register str2,
|
||||||
Register cnt1, Register cnt2,
|
Register cnt1, Register cnt2,
|
||||||
int int_cnt2, Register result,
|
int int_cnt2, Register result,
|
||||||
XMMRegister vec, Register tmp);
|
XMMRegister vec, Register tmp,
|
||||||
|
int ae);
|
||||||
|
|
||||||
// Smallest code: we don't need to load through stack,
|
// Smallest code: we don't need to load through stack,
|
||||||
// check string tail.
|
// check string tail.
|
||||||
|
|
||||||
|
// helper function for string_compare
|
||||||
|
void load_next_elements(Register elem1, Register elem2, Register str1, Register str2,
|
||||||
|
Address::ScaleFactor scale, Address::ScaleFactor scale1,
|
||||||
|
Address::ScaleFactor scale2, Register index, int ae);
|
||||||
// Compare strings.
|
// Compare strings.
|
||||||
void string_compare(Register str1, Register str2,
|
void string_compare(Register str1, Register str2,
|
||||||
Register cnt1, Register cnt2, Register result,
|
Register cnt1, Register cnt2, Register result,
|
||||||
XMMRegister vec1);
|
XMMRegister vec1, int ae);
|
||||||
|
|
||||||
// Compare char[] arrays.
|
// Search for Non-ASCII character (Negative byte value) in a byte array,
|
||||||
void char_arrays_equals(bool is_array_equ, Register ary1, Register ary2,
|
// return true if it has any and false otherwise.
|
||||||
Register limit, Register result, Register chr,
|
void has_negatives(Register ary1, Register len,
|
||||||
XMMRegister vec1, XMMRegister vec2);
|
Register result, Register tmp1,
|
||||||
|
XMMRegister vec1, XMMRegister vec2);
|
||||||
|
|
||||||
|
// Compare char[] or byte[] arrays.
|
||||||
|
void arrays_equals(bool is_array_equ, Register ary1, Register ary2,
|
||||||
|
Register limit, Register result, Register chr,
|
||||||
|
XMMRegister vec1, XMMRegister vec2, bool is_char);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
// Fill primitive arrays
|
// Fill primitive arrays
|
||||||
void generate_fill(BasicType t, bool aligned,
|
void generate_fill(BasicType t, bool aligned,
|
||||||
|
@ -1325,6 +1349,15 @@ public:
|
||||||
void fold_8bit_crc32(Register crc, Register table, Register tmp);
|
void fold_8bit_crc32(Register crc, Register table, Register tmp);
|
||||||
void fold_8bit_crc32(XMMRegister crc, Register table, XMMRegister xtmp, Register tmp);
|
void fold_8bit_crc32(XMMRegister crc, Register table, XMMRegister xtmp, Register tmp);
|
||||||
|
|
||||||
|
// Compress char[] array to byte[].
|
||||||
|
void char_array_compress(Register src, Register dst, Register len,
|
||||||
|
XMMRegister tmp1, XMMRegister tmp2, XMMRegister tmp3,
|
||||||
|
XMMRegister tmp4, Register tmp5, Register result);
|
||||||
|
|
||||||
|
// Inflate byte[] array to char[].
|
||||||
|
void byte_array_inflate(Register src, Register dst, Register len,
|
||||||
|
XMMRegister tmp1, Register tmp2);
|
||||||
|
|
||||||
#undef VIRTUAL
|
#undef VIRTUAL
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,8 +24,19 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "asm/assembler.hpp"
|
||||||
|
#include "asm/assembler.inline.hpp"
|
||||||
|
#include "macroAssembler_x86.hpp"
|
||||||
|
|
||||||
|
#ifdef _MSC_VER
|
||||||
|
#define ALIGNED_(x) __declspec(align(x))
|
||||||
|
#else
|
||||||
|
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
||||||
|
#endif
|
||||||
|
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
// ALGORITHM DESCRIPTION
|
// ALGORITHM DESCRIPTION - EXP()
|
||||||
// ---------------------
|
// ---------------------
|
||||||
//
|
//
|
||||||
// Description:
|
// Description:
|
||||||
|
@ -58,18 +69,6 @@
|
||||||
//
|
//
|
||||||
/******************************************************************************/
|
/******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
|
||||||
#include "asm/assembler.hpp"
|
|
||||||
#include "asm/assembler.inline.hpp"
|
|
||||||
#include "macroAssembler_x86.hpp"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
#define ALIGNED_(x) __declspec(align(x))
|
|
||||||
#else
|
|
||||||
#define ALIGNED_(x) __attribute__ ((aligned(x)))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
|
|
||||||
ALIGNED_(16) juint _cv[] =
|
ALIGNED_(16) juint _cv[] =
|
||||||
|
@ -409,6 +408,7 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
|
||||||
bind(B1_5);
|
bind(B1_5);
|
||||||
addq(rsp, 24);
|
addq(rsp, 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef _LP64
|
#ifndef _LP64
|
||||||
|
@ -675,3 +675,614 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
// ALGORITHM DESCRIPTION - LOG()
|
||||||
|
// ---------------------
|
||||||
|
//
|
||||||
|
// x=2^k * mx, mx in [1,2)
|
||||||
|
//
|
||||||
|
// Get B~1/mx based on the output of rcpss instruction (B0)
|
||||||
|
// B = int((B0*2^7+0.5))/2^7
|
||||||
|
//
|
||||||
|
// Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
|
||||||
|
//
|
||||||
|
// Result: k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6) and
|
||||||
|
// p(r) is a degree 7 polynomial
|
||||||
|
// -log(B) read from data table (high, low parts)
|
||||||
|
// Result is formed from high and low parts
|
||||||
|
//
|
||||||
|
// Special cases:
|
||||||
|
// log(NaN) = quiet NaN, and raise invalid exception
|
||||||
|
// log(+INF) = that INF
|
||||||
|
// log(0) = -INF with divide-by-zero exception raised
|
||||||
|
// log(1) = +0
|
||||||
|
// log(x) = NaN with invalid exception raised if x < -0, including -INF
|
||||||
|
//
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
|
#ifdef _LP64
|
||||||
|
|
||||||
|
ALIGNED_(16) juint _L_tbl[] =
|
||||||
|
{
|
||||||
|
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
|
||||||
|
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
|
||||||
|
0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
|
||||||
|
0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
|
||||||
|
0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
|
||||||
|
0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
|
||||||
|
0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
|
||||||
|
0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
|
||||||
|
0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
|
||||||
|
0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
|
||||||
|
0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
|
||||||
|
0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
|
||||||
|
0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
|
||||||
|
0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
|
||||||
|
0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
|
||||||
|
0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
|
||||||
|
0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
|
||||||
|
0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
|
||||||
|
0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
|
||||||
|
0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
|
||||||
|
0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
|
||||||
|
0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
|
||||||
|
0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
|
||||||
|
0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
|
||||||
|
0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
|
||||||
|
0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
|
||||||
|
0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
|
||||||
|
0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
|
||||||
|
0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
|
||||||
|
0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
|
||||||
|
0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
|
||||||
|
0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
|
||||||
|
0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
|
||||||
|
0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
|
||||||
|
0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
|
||||||
|
0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
|
||||||
|
0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
|
||||||
|
0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
|
||||||
|
0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
|
||||||
|
0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
|
||||||
|
0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
|
||||||
|
0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
|
||||||
|
0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
|
||||||
|
0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
|
||||||
|
0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
|
||||||
|
0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
|
||||||
|
0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
|
||||||
|
0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
|
||||||
|
0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
|
||||||
|
0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
|
||||||
|
0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
|
||||||
|
0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
|
||||||
|
0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
|
||||||
|
0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
|
||||||
|
0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
|
||||||
|
0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
|
||||||
|
0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
|
||||||
|
0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
|
||||||
|
0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
|
||||||
|
0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
|
||||||
|
0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
|
||||||
|
0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
|
||||||
|
0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
|
||||||
|
0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
|
||||||
|
0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
|
||||||
|
0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
|
||||||
|
0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
|
||||||
|
0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
|
||||||
|
0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
|
||||||
|
0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
|
||||||
|
0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
|
||||||
|
0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
|
||||||
|
0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
|
||||||
|
0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
|
||||||
|
0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
|
||||||
|
0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
|
||||||
|
0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
|
||||||
|
0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
|
||||||
|
0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
|
||||||
|
0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
|
||||||
|
0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
|
||||||
|
0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
|
||||||
|
0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
|
||||||
|
0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
|
||||||
|
0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
|
||||||
|
0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
|
||||||
|
0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
|
||||||
|
0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
|
||||||
|
0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
|
||||||
|
0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
|
||||||
|
0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
|
||||||
|
0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
|
||||||
|
0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
|
||||||
|
0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
|
||||||
|
0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
|
||||||
|
0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
|
||||||
|
0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
|
||||||
|
0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
|
||||||
|
0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
|
||||||
|
0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
|
||||||
|
0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
|
||||||
|
0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
|
||||||
|
0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
|
||||||
|
0x80000000UL
|
||||||
|
};
|
||||||
|
|
||||||
|
ALIGNED_(16) juint _log2[] =
|
||||||
|
{
|
||||||
|
0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL
|
||||||
|
};
|
||||||
|
|
||||||
|
ALIGNED_(16) juint _coeff[] =
|
||||||
|
{
|
||||||
|
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
|
||||||
|
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
|
||||||
|
0x00000000UL, 0xbfe00000UL
|
||||||
|
};
|
||||||
|
|
||||||
|
//registers,
|
||||||
|
// input: xmm0
|
||||||
|
// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
|
||||||
|
// rax, rdx, rcx, r8, r11
|
||||||
|
|
||||||
|
void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp1, Register tmp2) {
|
||||||
|
Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
|
||||||
|
Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
|
||||||
|
Label L_2TAG_PACKET_8_0_2;
|
||||||
|
Label L_2TAG_PACKET_12_0_2, L_2TAG_PACKET_13_0_2, B1_3, B1_5, start;
|
||||||
|
|
||||||
|
assert_different_registers(tmp1, tmp2, eax, ecx, edx);
|
||||||
|
jmp(start);
|
||||||
|
address L_tbl = (address)_L_tbl;
|
||||||
|
address log2 = (address)_log2;
|
||||||
|
address coeff = (address)_coeff;
|
||||||
|
|
||||||
|
bind(start);
|
||||||
|
subq(rsp, 24);
|
||||||
|
movsd(Address(rsp, 0), xmm0);
|
||||||
|
mov64(rax, 0x3ff0000000000000);
|
||||||
|
movdq(xmm2, rax);
|
||||||
|
mov64(rdx, 0x77f0000000000000);
|
||||||
|
movdq(xmm3, rdx);
|
||||||
|
movl(ecx, 32768);
|
||||||
|
movdl(xmm4, rcx);
|
||||||
|
mov64(tmp1, 0xffffe00000000000);
|
||||||
|
movdq(xmm5, tmp1);
|
||||||
|
movdqu(xmm1, xmm0);
|
||||||
|
pextrw(eax, xmm0, 3);
|
||||||
|
por(xmm0, xmm2);
|
||||||
|
movl(ecx, 16352);
|
||||||
|
psrlq(xmm0, 27);
|
||||||
|
lea(tmp2, ExternalAddress(L_tbl));
|
||||||
|
psrld(xmm0, 2);
|
||||||
|
rcpps(xmm0, xmm0);
|
||||||
|
psllq(xmm1, 12);
|
||||||
|
pshufd(xmm6, xmm5, 228);
|
||||||
|
psrlq(xmm1, 12);
|
||||||
|
subl(eax, 16);
|
||||||
|
cmpl(eax, 32736);
|
||||||
|
jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_1_0_2);
|
||||||
|
paddd(xmm0, xmm4);
|
||||||
|
por(xmm1, xmm3);
|
||||||
|
movdl(edx, xmm0);
|
||||||
|
psllq(xmm0, 29);
|
||||||
|
pand(xmm5, xmm1);
|
||||||
|
pand(xmm0, xmm6);
|
||||||
|
subsd(xmm1, xmm5);
|
||||||
|
mulpd(xmm5, xmm0);
|
||||||
|
andl(eax, 32752);
|
||||||
|
subl(eax, ecx);
|
||||||
|
cvtsi2sdl(xmm7, eax);
|
||||||
|
mulsd(xmm1, xmm0);
|
||||||
|
movq(xmm6, ExternalAddress(log2)); // 0xfefa3800UL, 0x3fa62e42UL
|
||||||
|
movdqu(xmm3, ExternalAddress(coeff)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
|
||||||
|
subsd(xmm5, xmm2);
|
||||||
|
andl(edx, 16711680);
|
||||||
|
shrl(edx, 12);
|
||||||
|
movdqu(xmm0, Address(tmp2, edx));
|
||||||
|
movdqu(xmm4, ExternalAddress(16 + coeff)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
|
||||||
|
addsd(xmm1, xmm5);
|
||||||
|
movdqu(xmm2, ExternalAddress(32 + coeff)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
|
||||||
|
mulsd(xmm6, xmm7);
|
||||||
|
movddup(xmm5, xmm1);
|
||||||
|
mulsd(xmm7, ExternalAddress(8 + log2)); // 0x93c76730UL, 0x3ceef357UL
|
||||||
|
mulsd(xmm3, xmm1);
|
||||||
|
addsd(xmm0, xmm6);
|
||||||
|
mulpd(xmm4, xmm5);
|
||||||
|
mulpd(xmm5, xmm5);
|
||||||
|
movddup(xmm6, xmm0);
|
||||||
|
addsd(xmm0, xmm1);
|
||||||
|
addpd(xmm4, xmm2);
|
||||||
|
mulpd(xmm3, xmm5);
|
||||||
|
subsd(xmm6, xmm0);
|
||||||
|
mulsd(xmm4, xmm1);
|
||||||
|
pshufd(xmm2, xmm0, 238);
|
||||||
|
addsd(xmm1, xmm6);
|
||||||
|
mulsd(xmm5, xmm5);
|
||||||
|
addsd(xmm7, xmm2);
|
||||||
|
addpd(xmm4, xmm3);
|
||||||
|
addsd(xmm1, xmm7);
|
||||||
|
mulpd(xmm4, xmm5);
|
||||||
|
addsd(xmm1, xmm4);
|
||||||
|
pshufd(xmm5, xmm4, 238);
|
||||||
|
addsd(xmm1, xmm5);
|
||||||
|
addsd(xmm0, xmm1);
|
||||||
|
jmp(B1_5);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_0_0_2);
|
||||||
|
movq(xmm0, Address(rsp, 0));
|
||||||
|
movq(xmm1, Address(rsp, 0));
|
||||||
|
addl(eax, 16);
|
||||||
|
cmpl(eax, 32768);
|
||||||
|
jcc(Assembler::aboveEqual, L_2TAG_PACKET_2_0_2);
|
||||||
|
cmpl(eax, 16);
|
||||||
|
jcc(Assembler::below, L_2TAG_PACKET_3_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_4_0_2);
|
||||||
|
addsd(xmm0, xmm0);
|
||||||
|
jmp(B1_5);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_5_0_2);
|
||||||
|
jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
|
||||||
|
cmpl(edx, 0);
|
||||||
|
jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
|
||||||
|
jmp(L_2TAG_PACKET_6_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_3_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
addsd(xmm1, xmm0);
|
||||||
|
movdl(edx, xmm1);
|
||||||
|
psrlq(xmm1, 32);
|
||||||
|
movdl(ecx, xmm1);
|
||||||
|
orl(edx, ecx);
|
||||||
|
cmpl(edx, 0);
|
||||||
|
jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
movl(eax, 18416);
|
||||||
|
pinsrw(xmm1, eax, 3);
|
||||||
|
mulsd(xmm0, xmm1);
|
||||||
|
movdqu(xmm1, xmm0);
|
||||||
|
pextrw(eax, xmm0, 3);
|
||||||
|
por(xmm0, xmm2);
|
||||||
|
psrlq(xmm0, 27);
|
||||||
|
movl(ecx, 18416);
|
||||||
|
psrld(xmm0, 2);
|
||||||
|
rcpps(xmm0, xmm0);
|
||||||
|
psllq(xmm1, 12);
|
||||||
|
pshufd(xmm6, xmm5, 228);
|
||||||
|
psrlq(xmm1, 12);
|
||||||
|
jmp(L_2TAG_PACKET_1_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_2_0_2);
|
||||||
|
movdl(edx, xmm1);
|
||||||
|
psrlq(xmm1, 32);
|
||||||
|
movdl(ecx, xmm1);
|
||||||
|
addl(ecx, ecx);
|
||||||
|
cmpl(ecx, -2097152);
|
||||||
|
jcc(Assembler::aboveEqual, L_2TAG_PACKET_5_0_2);
|
||||||
|
orl(edx, ecx);
|
||||||
|
cmpl(edx, 0);
|
||||||
|
jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_6_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
xorpd(xmm0, xmm0);
|
||||||
|
movl(eax, 32752);
|
||||||
|
pinsrw(xmm1, eax, 3);
|
||||||
|
mulsd(xmm0, xmm1);
|
||||||
|
movl(Address(rsp, 16), 3);
|
||||||
|
jmp(L_2TAG_PACKET_8_0_2);
|
||||||
|
bind(L_2TAG_PACKET_7_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
xorpd(xmm0, xmm0);
|
||||||
|
movl(eax, 49136);
|
||||||
|
pinsrw(xmm0, eax, 3);
|
||||||
|
divsd(xmm0, xmm1);
|
||||||
|
movl(Address(rsp, 16), 2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_8_0_2);
|
||||||
|
movq(Address(rsp, 8), xmm0);
|
||||||
|
|
||||||
|
bind(B1_3);
|
||||||
|
movq(xmm0, Address(rsp, 8));
|
||||||
|
|
||||||
|
bind(B1_5);
|
||||||
|
addq(rsp, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef _LP64
|
||||||
|
|
||||||
|
ALIGNED_(16) juint _static_const_table_log[] =
|
||||||
|
{
|
||||||
|
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
|
||||||
|
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
|
||||||
|
0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
|
||||||
|
0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
|
||||||
|
0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
|
||||||
|
0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
|
||||||
|
0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
|
||||||
|
0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
|
||||||
|
0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
|
||||||
|
0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
|
||||||
|
0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
|
||||||
|
0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
|
||||||
|
0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
|
||||||
|
0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
|
||||||
|
0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
|
||||||
|
0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
|
||||||
|
0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
|
||||||
|
0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
|
||||||
|
0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
|
||||||
|
0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
|
||||||
|
0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
|
||||||
|
0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
|
||||||
|
0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
|
||||||
|
0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
|
||||||
|
0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
|
||||||
|
0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
|
||||||
|
0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
|
||||||
|
0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
|
||||||
|
0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
|
||||||
|
0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
|
||||||
|
0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
|
||||||
|
0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
|
||||||
|
0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
|
||||||
|
0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
|
||||||
|
0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
|
||||||
|
0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
|
||||||
|
0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
|
||||||
|
0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
|
||||||
|
0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
|
||||||
|
0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
|
||||||
|
0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
|
||||||
|
0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
|
||||||
|
0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
|
||||||
|
0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
|
||||||
|
0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
|
||||||
|
0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
|
||||||
|
0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
|
||||||
|
0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
|
||||||
|
0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
|
||||||
|
0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
|
||||||
|
0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
|
||||||
|
0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
|
||||||
|
0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
|
||||||
|
0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
|
||||||
|
0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
|
||||||
|
0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
|
||||||
|
0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
|
||||||
|
0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
|
||||||
|
0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
|
||||||
|
0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
|
||||||
|
0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
|
||||||
|
0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
|
||||||
|
0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
|
||||||
|
0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
|
||||||
|
0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
|
||||||
|
0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
|
||||||
|
0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
|
||||||
|
0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
|
||||||
|
0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
|
||||||
|
0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
|
||||||
|
0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
|
||||||
|
0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
|
||||||
|
0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
|
||||||
|
0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
|
||||||
|
0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
|
||||||
|
0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
|
||||||
|
0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
|
||||||
|
0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
|
||||||
|
0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
|
||||||
|
0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
|
||||||
|
0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
|
||||||
|
0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
|
||||||
|
0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
|
||||||
|
0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
|
||||||
|
0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
|
||||||
|
0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
|
||||||
|
0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
|
||||||
|
0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
|
||||||
|
0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
|
||||||
|
0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
|
||||||
|
0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
|
||||||
|
0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
|
||||||
|
0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
|
||||||
|
0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
|
||||||
|
0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
|
||||||
|
0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
|
||||||
|
0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
|
||||||
|
0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
|
||||||
|
0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
|
||||||
|
0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
|
||||||
|
0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
|
||||||
|
0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
|
||||||
|
0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
|
||||||
|
0x80000000UL, 0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL,
|
||||||
|
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
|
||||||
|
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
|
||||||
|
0x00000000UL, 0xbfe00000UL, 0x00000000UL, 0xffffe000UL, 0x00000000UL,
|
||||||
|
0xffffe000UL
|
||||||
|
};
|
||||||
|
//registers,
|
||||||
|
// input: xmm0
|
||||||
|
// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
|
||||||
|
// rax, rdx, rcx, rbx (tmp)
|
||||||
|
|
||||||
|
void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
|
||||||
|
Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
|
||||||
|
Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
|
||||||
|
Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2;
|
||||||
|
Label L_2TAG_PACKET_10_0_2, start;
|
||||||
|
|
||||||
|
assert_different_registers(tmp, eax, ecx, edx);
|
||||||
|
jmp(start);
|
||||||
|
address static_const_table = (address)_static_const_table_log;
|
||||||
|
|
||||||
|
bind(start);
|
||||||
|
subl(rsp, 104);
|
||||||
|
movl(Address(rsp, 40), tmp);
|
||||||
|
lea(tmp, ExternalAddress(static_const_table));
|
||||||
|
xorpd(xmm2, xmm2);
|
||||||
|
movl(eax, 16368);
|
||||||
|
pinsrw(xmm2, eax, 3);
|
||||||
|
xorpd(xmm3, xmm3);
|
||||||
|
movl(edx, 30704);
|
||||||
|
pinsrw(xmm3, edx, 3);
|
||||||
|
movsd(xmm0, Address(rsp, 112));
|
||||||
|
movapd(xmm1, xmm0);
|
||||||
|
movl(ecx, 32768);
|
||||||
|
movdl(xmm4, ecx);
|
||||||
|
movsd(xmm5, Address(tmp, 2128)); // 0x00000000UL, 0xffffe000UL
|
||||||
|
pextrw(eax, xmm0, 3);
|
||||||
|
por(xmm0, xmm2);
|
||||||
|
psllq(xmm0, 5);
|
||||||
|
movl(ecx, 16352);
|
||||||
|
psrlq(xmm0, 34);
|
||||||
|
rcpss(xmm0, xmm0);
|
||||||
|
psllq(xmm1, 12);
|
||||||
|
pshufd(xmm6, xmm5, 228);
|
||||||
|
psrlq(xmm1, 12);
|
||||||
|
subl(eax, 16);
|
||||||
|
cmpl(eax, 32736);
|
||||||
|
jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_1_0_2);
|
||||||
|
paddd(xmm0, xmm4);
|
||||||
|
por(xmm1, xmm3);
|
||||||
|
movdl(edx, xmm0);
|
||||||
|
psllq(xmm0, 29);
|
||||||
|
pand(xmm5, xmm1);
|
||||||
|
pand(xmm0, xmm6);
|
||||||
|
subsd(xmm1, xmm5);
|
||||||
|
mulpd(xmm5, xmm0);
|
||||||
|
andl(eax, 32752);
|
||||||
|
subl(eax, ecx);
|
||||||
|
cvtsi2sdl(xmm7, eax);
|
||||||
|
mulsd(xmm1, xmm0);
|
||||||
|
movsd(xmm6, Address(tmp, 2064)); // 0xfefa3800UL, 0x3fa62e42UL
|
||||||
|
movdqu(xmm3, Address(tmp, 2080)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
|
||||||
|
subsd(xmm5, xmm2);
|
||||||
|
andl(edx, 16711680);
|
||||||
|
shrl(edx, 12);
|
||||||
|
movdqu(xmm0, Address(tmp, edx));
|
||||||
|
movdqu(xmm4, Address(tmp, 2096)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
|
||||||
|
addsd(xmm1, xmm5);
|
||||||
|
movdqu(xmm2, Address(tmp, 2112)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
|
||||||
|
mulsd(xmm6, xmm7);
|
||||||
|
pshufd(xmm5, xmm1, 68);
|
||||||
|
mulsd(xmm7, Address(tmp, 2072)); // 0x93c76730UL, 0x3ceef357UL, 0x92492492UL, 0x3fc24924UL
|
||||||
|
mulsd(xmm3, xmm1);
|
||||||
|
addsd(xmm0, xmm6);
|
||||||
|
mulpd(xmm4, xmm5);
|
||||||
|
mulpd(xmm5, xmm5);
|
||||||
|
pshufd(xmm6, xmm0, 228);
|
||||||
|
addsd(xmm0, xmm1);
|
||||||
|
addpd(xmm4, xmm2);
|
||||||
|
mulpd(xmm3, xmm5);
|
||||||
|
subsd(xmm6, xmm0);
|
||||||
|
mulsd(xmm4, xmm1);
|
||||||
|
pshufd(xmm2, xmm0, 238);
|
||||||
|
addsd(xmm1, xmm6);
|
||||||
|
mulsd(xmm5, xmm5);
|
||||||
|
addsd(xmm7, xmm2);
|
||||||
|
addpd(xmm4, xmm3);
|
||||||
|
addsd(xmm1, xmm7);
|
||||||
|
mulpd(xmm4, xmm5);
|
||||||
|
addsd(xmm1, xmm4);
|
||||||
|
pshufd(xmm5, xmm4, 238);
|
||||||
|
addsd(xmm1, xmm5);
|
||||||
|
addsd(xmm0, xmm1);
|
||||||
|
jmp(L_2TAG_PACKET_2_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_0_0_2);
|
||||||
|
movsd(xmm0, Address(rsp, 112));
|
||||||
|
movdqu(xmm1, xmm0);
|
||||||
|
addl(eax, 16);
|
||||||
|
cmpl(eax, 32768);
|
||||||
|
jcc(Assembler::aboveEqual, L_2TAG_PACKET_3_0_2);
|
||||||
|
cmpl(eax, 16);
|
||||||
|
jcc(Assembler::below, L_2TAG_PACKET_4_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_5_0_2);
|
||||||
|
addsd(xmm0, xmm0);
|
||||||
|
jmp(L_2TAG_PACKET_2_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_6_0_2);
|
||||||
|
jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
|
||||||
|
cmpl(edx, 0);
|
||||||
|
jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
|
||||||
|
jmp(L_2TAG_PACKET_7_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_3_0_2);
|
||||||
|
movdl(edx, xmm1);
|
||||||
|
psrlq(xmm1, 32);
|
||||||
|
movdl(ecx, xmm1);
|
||||||
|
addl(ecx, ecx);
|
||||||
|
cmpl(ecx, -2097152);
|
||||||
|
jcc(Assembler::aboveEqual, L_2TAG_PACKET_6_0_2);
|
||||||
|
orl(edx, ecx);
|
||||||
|
cmpl(edx, 0);
|
||||||
|
jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_7_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
xorpd(xmm0, xmm0);
|
||||||
|
movl(eax, 32752);
|
||||||
|
pinsrw(xmm1, eax, 3);
|
||||||
|
movl(edx, 3);
|
||||||
|
mulsd(xmm0, xmm1);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_9_0_2);
|
||||||
|
movsd(Address(rsp, 0), xmm0);
|
||||||
|
movsd(xmm0, Address(rsp, 112));
|
||||||
|
fld_d(Address(rsp, 0));
|
||||||
|
jmp(L_2TAG_PACKET_10_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_8_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
xorpd(xmm0, xmm0);
|
||||||
|
movl(eax, 49136);
|
||||||
|
pinsrw(xmm0, eax, 3);
|
||||||
|
divsd(xmm0, xmm1);
|
||||||
|
movl(edx, 2);
|
||||||
|
jmp(L_2TAG_PACKET_9_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_4_0_2);
|
||||||
|
movdl(edx, xmm1);
|
||||||
|
psrlq(xmm1, 32);
|
||||||
|
movdl(ecx, xmm1);
|
||||||
|
orl(edx, ecx);
|
||||||
|
cmpl(edx, 0);
|
||||||
|
jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
|
||||||
|
xorpd(xmm1, xmm1);
|
||||||
|
movl(eax, 18416);
|
||||||
|
pinsrw(xmm1, eax, 3);
|
||||||
|
mulsd(xmm0, xmm1);
|
||||||
|
movapd(xmm1, xmm0);
|
||||||
|
pextrw(eax, xmm0, 3);
|
||||||
|
por(xmm0, xmm2);
|
||||||
|
psllq(xmm0, 5);
|
||||||
|
movl(ecx, 18416);
|
||||||
|
psrlq(xmm0, 34);
|
||||||
|
rcpss(xmm0, xmm0);
|
||||||
|
psllq(xmm1, 12);
|
||||||
|
pshufd(xmm6, xmm5, 228);
|
||||||
|
psrlq(xmm1, 12);
|
||||||
|
jmp(L_2TAG_PACKET_1_0_2);
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_2_0_2);
|
||||||
|
movsd(Address(rsp, 24), xmm0);
|
||||||
|
fld_d(Address(rsp, 24));
|
||||||
|
|
||||||
|
bind(L_2TAG_PACKET_10_0_2);
|
||||||
|
movl(tmp, Address(rsp, 40));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -2094,14 +2094,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_math_stubs() {
|
void generate_math_stubs() {
|
||||||
{
|
|
||||||
StubCodeMark mark(this, "StubRoutines", "log");
|
|
||||||
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
|
|
||||||
|
|
||||||
__ fld_d(Address(rsp, 4));
|
|
||||||
__ flog();
|
|
||||||
__ ret(0);
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
StubCodeMark mark(this, "StubRoutines", "log10");
|
StubCodeMark mark(this, "StubRoutines", "log10");
|
||||||
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
||||||
|
@ -3065,6 +3057,32 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
address generate_libmLog() {
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
const XMMRegister x0 = xmm0;
|
||||||
|
const XMMRegister x1 = xmm1;
|
||||||
|
const XMMRegister x2 = xmm2;
|
||||||
|
const XMMRegister x3 = xmm3;
|
||||||
|
|
||||||
|
const XMMRegister x4 = xmm4;
|
||||||
|
const XMMRegister x5 = xmm5;
|
||||||
|
const XMMRegister x6 = xmm6;
|
||||||
|
const XMMRegister x7 = xmm7;
|
||||||
|
|
||||||
|
const Register tmp = rbx;
|
||||||
|
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
__ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
|
||||||
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
__ ret(0);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Safefetch stubs.
|
// Safefetch stubs.
|
||||||
void generate_safefetch(const char* name, int size, address* entry,
|
void generate_safefetch(const char* name, int size, address* entry,
|
||||||
|
@ -3288,6 +3306,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
if (VM_Version::supports_sse2()) {
|
if (VM_Version::supports_sse2()) {
|
||||||
StubRoutines::_dexp = generate_libmExp();
|
StubRoutines::_dexp = generate_libmExp();
|
||||||
|
StubRoutines::_dlog = generate_libmLog();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2973,19 +2973,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_math_stubs() {
|
void generate_math_stubs() {
|
||||||
{
|
|
||||||
StubCodeMark mark(this, "StubRoutines", "log");
|
|
||||||
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
|
|
||||||
|
|
||||||
__ subq(rsp, 8);
|
|
||||||
__ movdbl(Address(rsp, 0), xmm0);
|
|
||||||
__ fld_d(Address(rsp, 0));
|
|
||||||
__ flog();
|
|
||||||
__ fstp_d(Address(rsp, 0));
|
|
||||||
__ movdbl(xmm0, Address(rsp, 0));
|
|
||||||
__ addq(rsp, 8);
|
|
||||||
__ ret(0);
|
|
||||||
}
|
|
||||||
{
|
{
|
||||||
StubCodeMark mark(this, "StubRoutines", "log10");
|
StubCodeMark mark(this, "StubRoutines", "log10");
|
||||||
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
||||||
|
@ -4187,15 +4174,58 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
// save the xmm registers which must be preserved 6-7
|
// save the xmm registers which must be preserved 6-7
|
||||||
__ movdqu(xmm_save(6), as_XMMRegister(6));
|
__ subptr(rsp, 4 * wordSize);
|
||||||
__ movdqu(xmm_save(7), as_XMMRegister(7));
|
__ movdqu(Address(rsp, 0), xmm6);
|
||||||
|
__ movdqu(Address(rsp, 2 * wordSize), xmm7);
|
||||||
#endif
|
#endif
|
||||||
__ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
|
__ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
|
||||||
|
|
||||||
#ifdef _WIN64
|
#ifdef _WIN64
|
||||||
// restore xmm regs belonging to calling function
|
// restore xmm regs belonging to calling function
|
||||||
__ movdqu(as_XMMRegister(6), xmm_save(6));
|
__ movdqu(xmm6, Address(rsp, 0));
|
||||||
__ movdqu(as_XMMRegister(7), xmm_save(7));
|
__ movdqu(xmm7, Address(rsp, 2 * wordSize));
|
||||||
|
__ addptr(rsp, 4 * wordSize);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
__ ret(0);
|
||||||
|
|
||||||
|
return start;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
address generate_libmLog() {
|
||||||
|
address start = __ pc();
|
||||||
|
|
||||||
|
const XMMRegister x0 = xmm0;
|
||||||
|
const XMMRegister x1 = xmm1;
|
||||||
|
const XMMRegister x2 = xmm2;
|
||||||
|
const XMMRegister x3 = xmm3;
|
||||||
|
|
||||||
|
const XMMRegister x4 = xmm4;
|
||||||
|
const XMMRegister x5 = xmm5;
|
||||||
|
const XMMRegister x6 = xmm6;
|
||||||
|
const XMMRegister x7 = xmm7;
|
||||||
|
|
||||||
|
const Register tmp1 = r11;
|
||||||
|
const Register tmp2 = r8;
|
||||||
|
|
||||||
|
BLOCK_COMMENT("Entry:");
|
||||||
|
__ enter(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
// save the xmm registers which must be preserved 6-7
|
||||||
|
__ subptr(rsp, 4 * wordSize);
|
||||||
|
__ movdqu(Address(rsp, 0), xmm6);
|
||||||
|
__ movdqu(Address(rsp, 2 * wordSize), xmm7);
|
||||||
|
#endif
|
||||||
|
__ fast_log(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp1, tmp2);
|
||||||
|
|
||||||
|
#ifdef _WIN64
|
||||||
|
// restore xmm regs belonging to calling function
|
||||||
|
__ movdqu(xmm6, Address(rsp, 0));
|
||||||
|
__ movdqu(xmm7, Address(rsp, 2 * wordSize));
|
||||||
|
__ addptr(rsp, 4 * wordSize);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
__ leave(); // required for proper stackwalking of RuntimeStub frame
|
||||||
|
@ -4392,7 +4422,10 @@ class StubGenerator: public StubCodeGenerator {
|
||||||
StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
|
StubRoutines::_crc32c_table_addr = (address)StubRoutines::x86::_crc32c_table;
|
||||||
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
|
StubRoutines::_updateBytesCRC32C = generate_updateBytesCRC32C(supports_clmul);
|
||||||
}
|
}
|
||||||
StubRoutines::_dexp = generate_libmExp();
|
if (VM_Version::supports_sse2()) {
|
||||||
|
StubRoutines::_dexp = generate_libmExp();
|
||||||
|
StubRoutines::_dlog = generate_libmLog();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void generate_all() {
|
void generate_all() {
|
||||||
|
|
|
@ -82,6 +82,7 @@
|
||||||
declare_constant(VM_Version::CPU_AVX512CD) \
|
declare_constant(VM_Version::CPU_AVX512CD) \
|
||||||
declare_constant(VM_Version::CPU_AVX512BW)
|
declare_constant(VM_Version::CPU_AVX512BW)
|
||||||
|
|
||||||
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant)
|
#define VM_LONG_CONSTANTS_CPU(declare_constant, declare_preprocessor_constant, declare_c1_constant, declare_c2_constant, declare_c2_preprocessor_constant) \
|
||||||
|
declare_preprocessor_constant("VM_Version::CPU_AVX512VL", CPU_AVX512VL)
|
||||||
|
|
||||||
#endif // CPU_X86_VM_VMSTRUCTS_X86_HPP
|
#endif // CPU_X86_VM_VMSTRUCTS_X86_HPP
|
||||||
|
|
|
@ -1707,6 +1707,10 @@ const bool Matcher::match_rule_supported(int opcode) {
|
||||||
if (!VM_Version::supports_cx8())
|
if (!VM_Version::supports_cx8())
|
||||||
ret_value = false;
|
ret_value = false;
|
||||||
break;
|
break;
|
||||||
|
case Op_CMoveVD:
|
||||||
|
if (UseAVX < 1 || UseAVX > 2)
|
||||||
|
ret_value = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret_value; // Per default match rules are supported.
|
return ret_value; // Per default match rules are supported.
|
||||||
|
@ -2089,6 +2093,29 @@ operand vecZ() %{
|
||||||
interface(REG_INTER);
|
interface(REG_INTER);
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
// Comparison Code for FP conditional move
|
||||||
|
operand cmpOp_vcmppd() %{
|
||||||
|
match(Bool);
|
||||||
|
|
||||||
|
predicate(n->as_Bool()->_test._test != BoolTest::overflow &&
|
||||||
|
n->as_Bool()->_test._test != BoolTest::no_overflow);
|
||||||
|
format %{ "" %}
|
||||||
|
interface(COND_INTER) %{
|
||||||
|
equal (0x0, "eq");
|
||||||
|
less (0x1, "lt");
|
||||||
|
less_equal (0x2, "le");
|
||||||
|
not_equal (0xC, "ne");
|
||||||
|
greater_equal(0xD, "ge");
|
||||||
|
greater (0xE, "gt");
|
||||||
|
//TODO cannot compile (adlc breaks) without two next lines with error:
|
||||||
|
// x86_64.ad(13987) Syntax Error: :In operand cmpOp_vcmppd: Do not support this encode constant: ' %{
|
||||||
|
// equal' for overflow.
|
||||||
|
overflow (0x20, "o"); // not really supported by the instruction
|
||||||
|
no_overflow (0x21, "no"); // not really supported by the instruction
|
||||||
|
%}
|
||||||
|
%}
|
||||||
|
|
||||||
|
|
||||||
// INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit)
|
// INSTRUCTIONS -- Platform independent definitions (same for 32- and 64-bit)
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
|
@ -7393,6 +7420,22 @@ instruct vmul8D_mem(vecZ dst, vecZ src, memory mem) %{
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
|
instruct vcmov4D_reg(vecY dst, vecY src1, vecY src2, immI8 cop, cmpOp_vcmppd copnd) %{
|
||||||
|
predicate(UseAVX > 0 && UseAVX < 3 && n->as_Vector()->length() == 4);
|
||||||
|
match(Set dst (CMoveVD (Binary copnd cop) (Binary src1 src2)));
|
||||||
|
effect(TEMP dst, USE src1, USE src2);
|
||||||
|
format %{ "cmppd.$copnd $dst, $src1, $src2 ! vcmovevd, cond=$cop\n\t"
|
||||||
|
"vpblendd $dst,$src1,$src2,$dst ! vcmovevd\n\t"
|
||||||
|
%}
|
||||||
|
ins_encode %{
|
||||||
|
int vector_len = 1;
|
||||||
|
int cond = (Assembler::Condition)($copnd$$cmpcode);
|
||||||
|
__ cmppd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, cond, vector_len);
|
||||||
|
__ vpblendd($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, $dst$$XMMRegister, vector_len);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
// --------------------------------- DIV --------------------------------------
|
// --------------------------------- DIV --------------------------------------
|
||||||
|
|
||||||
// Floats vector div
|
// Floats vector div
|
||||||
|
|
|
@ -9950,41 +9950,6 @@ instruct log10D_reg(regD dst, regD src, eFlagsReg cr) %{
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct logDPR_reg(regDPR1 dst, regDPR1 src) %{
|
|
||||||
predicate (UseSSE<=1);
|
|
||||||
// The source Double operand on FPU stack
|
|
||||||
match(Set dst (LogD src));
|
|
||||||
// fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
|
|
||||||
// fxch ; swap ST(0) with ST(1)
|
|
||||||
// fyl2x ; compute log_e(2) * log_2(x)
|
|
||||||
format %{ "FLDLN2 \t\t\t#Log_e\n\t"
|
|
||||||
"FXCH \n\t"
|
|
||||||
"FYL2X \t\t\t# Q=Log_e*Log_2(x)"
|
|
||||||
%}
|
|
||||||
ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
|
|
||||||
Opcode(0xD9), Opcode(0xC9), // fxch
|
|
||||||
Opcode(0xD9), Opcode(0xF1)); // fyl2x
|
|
||||||
|
|
||||||
ins_pipe( pipe_slow );
|
|
||||||
%}
|
|
||||||
|
|
||||||
instruct logD_reg(regD dst, regD src, eFlagsReg cr) %{
|
|
||||||
predicate (UseSSE>=2);
|
|
||||||
effect(KILL cr);
|
|
||||||
// The source and result Double operands in XMM registers
|
|
||||||
match(Set dst (LogD src));
|
|
||||||
// fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
|
|
||||||
// fyl2x ; compute log_e(2) * log_2(x)
|
|
||||||
format %{ "FLDLN2 \t\t\t#Log_e\n\t"
|
|
||||||
"FYL2X \t\t\t# Q=Log_e*Log_2(x)"
|
|
||||||
%}
|
|
||||||
ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
|
|
||||||
Push_SrcD(src),
|
|
||||||
Opcode(0xD9), Opcode(0xF1), // fyl2x
|
|
||||||
Push_ResultD(dst));
|
|
||||||
ins_pipe( pipe_slow );
|
|
||||||
%}
|
|
||||||
|
|
||||||
//-------------Float Instructions-------------------------------
|
//-------------Float Instructions-------------------------------
|
||||||
// Float Math
|
// Float Math
|
||||||
|
|
||||||
|
@ -11470,16 +11435,62 @@ instruct rep_fast_stosb(eCXRegI cnt, eDIRegP base, eAXRegI zero, Universe dummy,
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_compare(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
|
instruct string_compareL(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
|
||||||
eAXRegI result, regD tmp1, eFlagsReg cr) %{
|
eAXRegI result, regD tmp1, eFlagsReg cr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ string_compare($str1$$Register, $str2$$Register,
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
$tmp1$$XMMRegister);
|
$tmp1$$XMMRegister, StrIntrinsicNode::LL);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
|
||||||
|
eAXRegI result, regD tmp1, eFlagsReg cr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, StrIntrinsicNode::UU);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareLU(eDIRegP str1, eCXRegI cnt1, eSIRegP str2, eDXRegI cnt2,
|
||||||
|
eAXRegI result, regD tmp1, eFlagsReg cr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, StrIntrinsicNode::LU);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareUL(eSIRegP str1, eDXRegI cnt1, eDIRegP str2, eCXRegI cnt2,
|
||||||
|
eAXRegI result, regD tmp1, eFlagsReg cr) %{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str2$$Register, $str1$$Register,
|
||||||
|
$cnt2$$Register, $cnt1$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, StrIntrinsicNode::UL);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
@ -11492,21 +11503,50 @@ instruct string_equals(eDIRegP str1, eSIRegP str2, eCXRegI cnt, eAXRegI result,
|
||||||
|
|
||||||
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ char_arrays_equals(false, $str1$$Register, $str2$$Register,
|
__ arrays_equals(false, $str1$$Register, $str2$$Register,
|
||||||
$cnt$$Register, $result$$Register, $tmp3$$Register,
|
$cnt$$Register, $result$$Register, $tmp3$$Register,
|
||||||
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
|
||||||
|
%}
|
||||||
|
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast search of substring with known size.
|
||||||
|
instruct string_indexof_conL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
||||||
|
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
int icnt2 = (int)$int_cnt2$$constant;
|
||||||
|
if (icnt2 >= 16) {
|
||||||
|
// IndexOf for constant substrings with size >= 16 elements
|
||||||
|
// which don't need to be loaded through stack.
|
||||||
|
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||||
|
} else {
|
||||||
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||||
|
}
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast search of substring with known size.
|
// fast search of substring with known size.
|
||||||
instruct string_indexof_con(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
instruct string_indexof_conU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
||||||
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
predicate(UseSSE42Intrinsics);
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
int icnt2 = (int)$int_cnt2$$constant;
|
int icnt2 = (int)$int_cnt2$$constant;
|
||||||
if (icnt2 >= 8) {
|
if (icnt2 >= 8) {
|
||||||
|
@ -11515,47 +11555,182 @@ instruct string_indexof_con(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_c
|
||||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register,
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
icnt2, $result$$Register,
|
icnt2, $result$$Register,
|
||||||
$vec$$XMMRegister, $tmp$$Register);
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||||
} else {
|
} else {
|
||||||
// Small strings are loaded through stack if they cross page boundary.
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
__ string_indexof($str1$$Register, $str2$$Register,
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register,
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
icnt2, $result$$Register,
|
icnt2, $result$$Register,
|
||||||
$vec$$XMMRegister, $tmp$$Register);
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_indexof(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
// fast search of substring with known size.
|
||||||
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
instruct string_indexof_conUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, immI int_cnt2,
|
||||||
predicate(UseSSE42Intrinsics);
|
eBXRegI result, regD vec, eAXRegI cnt2, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
int icnt2 = (int)$int_cnt2$$constant;
|
||||||
|
if (icnt2 >= 8) {
|
||||||
|
// IndexOf for constant substrings with size >= 8 elements
|
||||||
|
// which don't need to be loaded through stack.
|
||||||
|
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||||
|
} else {
|
||||||
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||||
|
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ string_indexof($str1$$Register, $str2$$Register,
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register,
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
(-1), $result$$Register,
|
(-1), $result$$Register,
|
||||||
$vec$$XMMRegister, $tmp$$Register);
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofU(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||||
|
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
(-1), $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofUL(eDIRegP str1, eDXRegI cnt1, eSIRegP str2, eAXRegI cnt2,
|
||||||
|
eBXRegI result, regD vec, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
(-1), $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofU_char(eDIRegP str1, eDXRegI cnt1, eAXRegI ch,
|
||||||
|
eBXRegI result, regD vec1, regD vec2, regD vec3, eCXRegI tmp, eFlagsReg cr) %{
|
||||||
|
predicate(UseSSE42Intrinsics);
|
||||||
|
match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
|
||||||
|
effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
|
||||||
|
$vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast array equals
|
// fast array equals
|
||||||
instruct array_equals(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
|
instruct array_equalsB(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
|
||||||
regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
|
regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
||||||
//ins_cost(300);
|
//ins_cost(300);
|
||||||
|
|
||||||
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
__ arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
||||||
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct array_equalsC(eDIRegP ary1, eSIRegP ary2, eAXRegI result,
|
||||||
|
regD tmp1, regD tmp2, eCXRegI tmp3, eBXRegI tmp4, eFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (AryEq ary1 ary2));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
||||||
|
//ins_cost(300);
|
||||||
|
|
||||||
|
format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
|
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct has_negatives(eSIRegP ary1, eCXRegI len, eAXRegI result,
|
||||||
|
regD tmp1, regD tmp2, eBXRegI tmp3, eFlagsReg cr)
|
||||||
|
%{
|
||||||
|
match(Set result (HasNegatives ary1 len));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
|
||||||
|
|
||||||
|
format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ has_negatives($ary1$$Register, $len$$Register,
|
||||||
|
$result$$Register, $tmp3$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast char[] to byte[] compression
|
||||||
|
instruct string_compress(eSIRegP src, eDIRegP dst, eDXRegI len, regD tmp1, regD tmp2, regD tmp3, regD tmp4,
|
||||||
|
eCXRegI tmp5, eAXRegI result, eFlagsReg cr) %{
|
||||||
|
match(Set result (StrCompressedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
|
||||||
|
$tmp4$$XMMRegister, $tmp5$$Register, $result$$Register);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast byte[] to char[] inflation
|
||||||
|
instruct string_inflate(Universe dummy, eSIRegP src, eDIRegP dst, eDXRegI len,
|
||||||
|
regD tmp1, eCXRegI tmp2, eFlagsReg cr) %{
|
||||||
|
match(Set dummy (StrInflatedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$Register);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -9870,21 +9870,6 @@ instruct log10D_reg(regD dst) %{
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct logD_reg(regD dst) %{
|
|
||||||
// The source and result Double operands in XMM registers
|
|
||||||
match(Set dst (LogD dst));
|
|
||||||
// fldln2 ; push log_e(2) on the FPU stack; full 80-bit number
|
|
||||||
// fyl2x ; compute log_e(2) * log_2(x)
|
|
||||||
format %{ "fldln2\t\t\t#Log_e\n\t"
|
|
||||||
"fyl2x\t\t\t# Q=Log_e*Log_2(x)\n\t"
|
|
||||||
%}
|
|
||||||
ins_encode( Opcode(0xD9), Opcode(0xED), // fldln2
|
|
||||||
Push_SrcXD(dst),
|
|
||||||
Opcode(0xD9), Opcode(0xF1), // fyl2x
|
|
||||||
Push_ResultXD(dst));
|
|
||||||
ins_pipe( pipe_slow );
|
|
||||||
%}
|
|
||||||
|
|
||||||
instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{
|
instruct powD_reg(regD dst, regD src0, regD src1, rax_RegI rax, rdx_RegI rdx, rcx_RegI rcx, rFlagsReg cr) %{
|
||||||
match(Set dst (PowD src0 src1)); // Raise src0 to the src1'th power
|
match(Set dst (PowD src0 src1)); // Raise src0 to the src1'th power
|
||||||
effect(KILL rax, KILL rdx, KILL rcx, KILL cr);
|
effect(KILL rax, KILL rdx, KILL rcx, KILL cr);
|
||||||
|
@ -10462,30 +10447,108 @@ instruct rep_fast_stosb(rcx_RegL cnt, rdi_RegP base, rax_RegI zero, Universe dum
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_compare(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
instruct string_compareL(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||||
rax_RegI result, regD tmp1, rFlagsReg cr)
|
rax_RegI result, regD tmp1, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
format %{ "String Compare $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ string_compare($str1$$Register, $str2$$Register,
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
$tmp1$$XMMRegister);
|
$tmp1$$XMMRegister, StrIntrinsicNode::LL);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||||
|
rax_RegI result, regD tmp1, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compare char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, StrIntrinsicNode::UU);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareLU(rdi_RegP str1, rcx_RegI cnt1, rsi_RegP str2, rdx_RegI cnt2,
|
||||||
|
rax_RegI result, regD tmp1, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::LU);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, StrIntrinsicNode::LU);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_compareUL(rsi_RegP str1, rdx_RegI cnt1, rdi_RegP str2, rcx_RegI cnt2,
|
||||||
|
rax_RegI result, regD tmp1, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(((StrCompNode*)n)->encoding() == StrIntrinsicNode::UL);
|
||||||
|
match(Set result (StrComp (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP tmp1, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compare byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL $tmp1" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_compare($str2$$Register, $str1$$Register,
|
||||||
|
$cnt2$$Register, $cnt1$$Register, $result$$Register,
|
||||||
|
$tmp1$$XMMRegister, StrIntrinsicNode::UL);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast search of substring with known size.
|
// fast search of substring with known size.
|
||||||
instruct string_indexof_con(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
instruct string_indexof_conL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
||||||
rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
predicate(UseSSE42Intrinsics);
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
format %{ "String IndexOf $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
int icnt2 = (int)$int_cnt2$$constant;
|
||||||
|
if (icnt2 >= 16) {
|
||||||
|
// IndexOf for constant substrings with size >= 16 elements
|
||||||
|
// which don't need to be loaded through stack.
|
||||||
|
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||||
|
} else {
|
||||||
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast search of substring with known size.
|
||||||
|
instruct string_indexof_conU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
||||||
|
rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
int icnt2 = (int)$int_cnt2$$constant;
|
int icnt2 = (int)$int_cnt2$$constant;
|
||||||
if (icnt2 >= 8) {
|
if (icnt2 >= 8) {
|
||||||
|
@ -10494,31 +10557,108 @@ instruct string_indexof_con(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI in
|
||||||
__ string_indexofC8($str1$$Register, $str2$$Register,
|
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register,
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
icnt2, $result$$Register,
|
icnt2, $result$$Register,
|
||||||
$vec$$XMMRegister, $tmp$$Register);
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||||
} else {
|
} else {
|
||||||
// Small strings are loaded through stack if they cross page boundary.
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
__ string_indexof($str1$$Register, $str2$$Register,
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register,
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
icnt2, $result$$Register,
|
icnt2, $result$$Register,
|
||||||
$vec$$XMMRegister, $tmp$$Register);
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||||
}
|
}
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
instruct string_indexof(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
// fast search of substring with known size.
|
||||||
rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
|
instruct string_indexof_conUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, immI int_cnt2,
|
||||||
|
rbx_RegI result, regD vec, rax_RegI cnt2, rcx_RegI tmp, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
predicate(UseSSE42Intrinsics);
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 int_cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$int_cnt2 -> $result // KILL $vec, $cnt1, $cnt2, $tmp" %}
|
||||||
|
ins_encode %{
|
||||||
|
int icnt2 = (int)$int_cnt2$$constant;
|
||||||
|
if (icnt2 >= 8) {
|
||||||
|
// IndexOf for constant substrings with size >= 8 elements
|
||||||
|
// which don't need to be loaded through stack.
|
||||||
|
__ string_indexofC8($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||||
|
} else {
|
||||||
|
// Small strings are loaded through stack if they cross page boundary.
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
icnt2, $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||||
|
}
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||||
|
rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::LL));
|
||||||
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
format %{ "String IndexOf $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
format %{ "String IndexOf byte[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ string_indexof($str1$$Register, $str2$$Register,
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
$cnt1$$Register, $cnt2$$Register,
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
(-1), $result$$Register,
|
(-1), $result$$Register,
|
||||||
$vec$$XMMRegister, $tmp$$Register);
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::LL);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofU(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||||
|
rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UU));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
(-1), $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UU);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofUL(rdi_RegP str1, rdx_RegI cnt1, rsi_RegP str2, rax_RegI cnt2,
|
||||||
|
rbx_RegI result, regD vec, rcx_RegI tmp, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(UseSSE42Intrinsics && (((StrIndexOfNode*)n)->encoding() == StrIntrinsicNode::UL));
|
||||||
|
match(Set result (StrIndexOf (Binary str1 cnt1) (Binary str2 cnt2)));
|
||||||
|
effect(TEMP vec, USE_KILL str1, USE_KILL str2, USE_KILL cnt1, USE_KILL cnt2, KILL tmp, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$str2,$cnt2 -> $result // KILL all" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_indexof($str1$$Register, $str2$$Register,
|
||||||
|
$cnt1$$Register, $cnt2$$Register,
|
||||||
|
(-1), $result$$Register,
|
||||||
|
$vec$$XMMRegister, $tmp$$Register, StrIntrinsicNode::UL);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct string_indexofU_char(rdi_RegP str1, rdx_RegI cnt1, rax_RegI ch,
|
||||||
|
rbx_RegI result, regD vec1, regD vec2, regD vec3, rcx_RegI tmp, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(UseSSE42Intrinsics);
|
||||||
|
match(Set result (StrIndexOfChar (Binary str1 cnt1) ch));
|
||||||
|
effect(TEMP vec1, TEMP vec2, TEMP vec3, USE_KILL str1, USE_KILL cnt1, USE_KILL ch, TEMP tmp, KILL cr);
|
||||||
|
format %{ "String IndexOf char[] $str1,$cnt1,$ch -> $result // KILL all" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ string_indexof_char($str1$$Register, $cnt1$$Register, $ch$$Register, $result$$Register,
|
||||||
|
$vec1$$XMMRegister, $vec2$$XMMRegister, $vec3$$XMMRegister, $tmp$$Register);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
@ -10532,26 +10672,86 @@ instruct string_equals(rdi_RegP str1, rsi_RegP str2, rcx_RegI cnt, rax_RegI resu
|
||||||
|
|
||||||
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
format %{ "String Equals $str1,$str2,$cnt -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ char_arrays_equals(false, $str1$$Register, $str2$$Register,
|
__ arrays_equals(false, $str1$$Register, $str2$$Register,
|
||||||
$cnt$$Register, $result$$Register, $tmp3$$Register,
|
$cnt$$Register, $result$$Register, $tmp3$$Register,
|
||||||
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
||||||
// fast array equals
|
// fast array equals
|
||||||
instruct array_equals(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
instruct array_equalsB(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||||
regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||||
%{
|
%{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::LL);
|
||||||
match(Set result (AryEq ary1 ary2));
|
match(Set result (AryEq ary1 ary2));
|
||||||
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
||||||
//ins_cost(300);
|
|
||||||
|
|
||||||
format %{ "Array Equals $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
format %{ "Array Equals byte[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
||||||
ins_encode %{
|
ins_encode %{
|
||||||
__ char_arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
__ arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
||||||
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, false /* char */);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct array_equalsC(rdi_RegP ary1, rsi_RegP ary2, rax_RegI result,
|
||||||
|
regD tmp1, regD tmp2, rcx_RegI tmp3, rbx_RegI tmp4, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
predicate(((AryEqNode*)n)->encoding() == StrIntrinsicNode::UU);
|
||||||
|
match(Set result (AryEq ary1 ary2));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL ary2, KILL tmp3, KILL tmp4, KILL cr);
|
||||||
|
|
||||||
|
format %{ "Array Equals char[] $ary1,$ary2 -> $result // KILL $tmp1, $tmp2, $tmp3, $tmp4" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ arrays_equals(true, $ary1$$Register, $ary2$$Register,
|
||||||
|
$tmp3$$Register, $result$$Register, $tmp4$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, true /* char */);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
instruct has_negatives(rsi_RegP ary1, rcx_RegI len, rax_RegI result,
|
||||||
|
regD tmp1, regD tmp2, rbx_RegI tmp3, rFlagsReg cr)
|
||||||
|
%{
|
||||||
|
match(Set result (HasNegatives ary1 len));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL ary1, USE_KILL len, KILL tmp3, KILL cr);
|
||||||
|
|
||||||
|
format %{ "has negatives byte[] $ary1,$len -> $result // KILL $tmp1, $tmp2, $tmp3" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ has_negatives($ary1$$Register, $len$$Register,
|
||||||
|
$result$$Register, $tmp3$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast char[] to byte[] compression
|
||||||
|
instruct string_compress(rsi_RegP src, rdi_RegP dst, rdx_RegI len, regD tmp1, regD tmp2, regD tmp3, regD tmp4,
|
||||||
|
rcx_RegI tmp5, rax_RegI result, rFlagsReg cr) %{
|
||||||
|
match(Set result (StrCompressedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, TEMP tmp3, TEMP tmp4, USE_KILL src, USE_KILL dst, USE_KILL len, KILL tmp5, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Compress $src,$dst -> $result // KILL RAX, RCX, RDX" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ char_array_compress($src$$Register, $dst$$Register, $len$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$XMMRegister, $tmp3$$XMMRegister,
|
||||||
|
$tmp4$$XMMRegister, $tmp5$$Register, $result$$Register);
|
||||||
|
%}
|
||||||
|
ins_pipe( pipe_slow );
|
||||||
|
%}
|
||||||
|
|
||||||
|
// fast byte[] to char[] inflation
|
||||||
|
instruct string_inflate(Universe dummy, rsi_RegP src, rdi_RegP dst, rdx_RegI len,
|
||||||
|
regD tmp1, rcx_RegI tmp2, rFlagsReg cr) %{
|
||||||
|
match(Set dummy (StrInflatedCopy src (Binary dst len)));
|
||||||
|
effect(TEMP tmp1, TEMP tmp2, USE_KILL src, USE_KILL dst, USE_KILL len, KILL cr);
|
||||||
|
|
||||||
|
format %{ "String Inflate $src,$dst // KILL $tmp1, $tmp2" %}
|
||||||
|
ins_encode %{
|
||||||
|
__ byte_array_inflate($src$$Register, $dst$$Register, $len$$Register,
|
||||||
|
$tmp1$$XMMRegister, $tmp2$$Register);
|
||||||
%}
|
%}
|
||||||
ins_pipe( pipe_slow );
|
ins_pipe( pipe_slow );
|
||||||
%}
|
%}
|
||||||
|
|
|
@ -69,6 +69,9 @@ define_pd_global(uintx, TypeProfileLevel, 0);
|
||||||
|
|
||||||
define_pd_global(bool, PreserveFramePointer, false);
|
define_pd_global(bool, PreserveFramePointer, false);
|
||||||
|
|
||||||
|
// No performance work done here yet.
|
||||||
|
define_pd_global(bool, CompactStrings, false);
|
||||||
|
|
||||||
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
#define ARCH_FLAGS(develop, product, diagnostic, experimental, notproduct, range, constraint) \
|
||||||
\
|
\
|
||||||
product(bool, UseFastEmptyMethods, true, \
|
product(bool, UseFastEmptyMethods, true, \
|
||||||
|
|
|
@ -22,15 +22,18 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.amd64;
|
package jdk.vm.ci.amd64;
|
||||||
|
|
||||||
import static jdk.vm.ci.code.MemoryBarriers.*;
|
import static jdk.vm.ci.code.MemoryBarriers.LOAD_STORE;
|
||||||
import static jdk.vm.ci.code.Register.*;
|
import static jdk.vm.ci.code.MemoryBarriers.STORE_STORE;
|
||||||
|
import static jdk.vm.ci.code.Register.SPECIAL;
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.ByteOrder;
|
||||||
import java.util.*;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import jdk.vm.ci.code.*;
|
import jdk.vm.ci.code.Architecture;
|
||||||
|
import jdk.vm.ci.code.Register;
|
||||||
import jdk.vm.ci.code.Register.RegisterCategory;
|
import jdk.vm.ci.code.Register.RegisterCategory;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the AMD64 architecture.
|
* Represents the AMD64 architecture.
|
||||||
|
@ -65,9 +68,7 @@ public class AMD64 extends Architecture {
|
||||||
r8, r9, r10, r11, r12, r13, r14, r15
|
r8, r9, r10, r11, r12, r13, r14, r15
|
||||||
};
|
};
|
||||||
|
|
||||||
private static final int XMM_REFERENCE_MAP_SHIFT = 2;
|
public static final RegisterCategory XMM = new RegisterCategory("XMM");
|
||||||
|
|
||||||
public static final RegisterCategory XMM = new RegisterCategory("XMM", cpuRegisters.length, XMM_REFERENCE_MAP_SHIFT);
|
|
||||||
|
|
||||||
// XMM registers
|
// XMM registers
|
||||||
public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
|
public static final Register xmm0 = new Register(16, 0, "xmm0", XMM);
|
||||||
|
@ -79,8 +80,8 @@ public class AMD64 extends Architecture {
|
||||||
public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
|
public static final Register xmm6 = new Register(22, 6, "xmm6", XMM);
|
||||||
public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
|
public static final Register xmm7 = new Register(23, 7, "xmm7", XMM);
|
||||||
|
|
||||||
public static final Register xmm8 = new Register(24, 8, "xmm8", XMM);
|
public static final Register xmm8 = new Register(24, 8, "xmm8", XMM);
|
||||||
public static final Register xmm9 = new Register(25, 9, "xmm9", XMM);
|
public static final Register xmm9 = new Register(25, 9, "xmm9", XMM);
|
||||||
public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
|
public static final Register xmm10 = new Register(26, 10, "xmm10", XMM);
|
||||||
public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
|
public static final Register xmm11 = new Register(27, 11, "xmm11", XMM);
|
||||||
public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
|
public static final Register xmm12 = new Register(28, 12, "xmm12", XMM);
|
||||||
|
@ -88,28 +89,77 @@ public class AMD64 extends Architecture {
|
||||||
public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
|
public static final Register xmm14 = new Register(30, 14, "xmm14", XMM);
|
||||||
public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
|
public static final Register xmm15 = new Register(31, 15, "xmm15", XMM);
|
||||||
|
|
||||||
public static final Register[] xmmRegisters = {
|
public static final Register xmm16 = new Register(32, 16, "xmm16", XMM);
|
||||||
|
public static final Register xmm17 = new Register(33, 17, "xmm17", XMM);
|
||||||
|
public static final Register xmm18 = new Register(34, 18, "xmm18", XMM);
|
||||||
|
public static final Register xmm19 = new Register(35, 19, "xmm19", XMM);
|
||||||
|
public static final Register xmm20 = new Register(36, 20, "xmm20", XMM);
|
||||||
|
public static final Register xmm21 = new Register(37, 21, "xmm21", XMM);
|
||||||
|
public static final Register xmm22 = new Register(38, 22, "xmm22", XMM);
|
||||||
|
public static final Register xmm23 = new Register(39, 23, "xmm23", XMM);
|
||||||
|
|
||||||
|
public static final Register xmm24 = new Register(40, 24, "xmm24", XMM);
|
||||||
|
public static final Register xmm25 = new Register(41, 25, "xmm25", XMM);
|
||||||
|
public static final Register xmm26 = new Register(42, 26, "xmm26", XMM);
|
||||||
|
public static final Register xmm27 = new Register(43, 27, "xmm27", XMM);
|
||||||
|
public static final Register xmm28 = new Register(44, 28, "xmm28", XMM);
|
||||||
|
public static final Register xmm29 = new Register(45, 29, "xmm29", XMM);
|
||||||
|
public static final Register xmm30 = new Register(46, 30, "xmm30", XMM);
|
||||||
|
public static final Register xmm31 = new Register(47, 31, "xmm31", XMM);
|
||||||
|
|
||||||
|
public static final Register[] xmmRegistersSSE = {
|
||||||
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
||||||
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
||||||
};
|
};
|
||||||
|
|
||||||
public static final Register[] cpuxmmRegisters = {
|
public static final Register[] xmmRegistersAVX512 = {
|
||||||
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
||||||
|
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
|
||||||
|
xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
|
||||||
|
xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31
|
||||||
|
};
|
||||||
|
|
||||||
|
public static final RegisterCategory MASK = new RegisterCategory("MASK", false);
|
||||||
|
|
||||||
|
public static final Register k0 = new Register(48, 0, "k0", MASK);
|
||||||
|
public static final Register k1 = new Register(49, 1, "k1", MASK);
|
||||||
|
public static final Register k2 = new Register(50, 2, "k2", MASK);
|
||||||
|
public static final Register k3 = new Register(51, 3, "k3", MASK);
|
||||||
|
public static final Register k4 = new Register(52, 4, "k4", MASK);
|
||||||
|
public static final Register k5 = new Register(53, 5, "k5", MASK);
|
||||||
|
public static final Register k6 = new Register(54, 6, "k6", MASK);
|
||||||
|
public static final Register k7 = new Register(55, 7, "k7", MASK);
|
||||||
|
|
||||||
|
public static final Register[] valueRegistersSSE = {
|
||||||
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
|
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
|
||||||
r8, r9, r10, r11, r12, r13, r14, r15,
|
r8, r9, r10, r11, r12, r13, r14, r15,
|
||||||
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
||||||
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public static final Register[] valueRegistersAVX512 = {
|
||||||
|
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
|
||||||
|
r8, r9, r10, r11, r12, r13, r14, r15,
|
||||||
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
||||||
|
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
|
||||||
|
xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
|
||||||
|
xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
|
||||||
|
k0, k1, k2, k3, k4, k5, k6, k7
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Register used to construct an instruction-relative address.
|
* Register used to construct an instruction-relative address.
|
||||||
*/
|
*/
|
||||||
public static final Register rip = new Register(32, -1, "rip", SPECIAL);
|
public static final Register rip = new Register(56, -1, "rip", SPECIAL);
|
||||||
|
|
||||||
public static final Register[] allRegisters = {
|
public static final Register[] allRegisters = {
|
||||||
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
|
rax, rcx, rdx, rbx, rsp, rbp, rsi, rdi,
|
||||||
r8, r9, r10, r11, r12, r13, r14, r15,
|
r8, r9, r10, r11, r12, r13, r14, r15,
|
||||||
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
||||||
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
|
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15,
|
||||||
|
xmm16, xmm17, xmm18, xmm19, xmm20, xmm21, xmm22, xmm23,
|
||||||
|
xmm24, xmm25, xmm26, xmm27, xmm28, xmm29, xmm30, xmm31,
|
||||||
|
k0, k1, k2, k3, k4, k5, k6, k7,
|
||||||
rip
|
rip
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,7 +201,8 @@ public class AMD64 extends Architecture {
|
||||||
AVX512PF,
|
AVX512PF,
|
||||||
AVX512ER,
|
AVX512ER,
|
||||||
AVX512CD,
|
AVX512CD,
|
||||||
AVX512BW
|
AVX512BW,
|
||||||
|
AVX512VL
|
||||||
}
|
}
|
||||||
|
|
||||||
private final EnumSet<CPUFeature> features;
|
private final EnumSet<CPUFeature> features;
|
||||||
|
@ -166,11 +217,21 @@ public class AMD64 extends Architecture {
|
||||||
|
|
||||||
private final EnumSet<Flag> flags;
|
private final EnumSet<Flag> flags;
|
||||||
|
|
||||||
|
private final AMD64Kind largestKind;
|
||||||
|
|
||||||
public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
|
public AMD64(EnumSet<CPUFeature> features, EnumSet<Flag> flags) {
|
||||||
super("AMD64", JavaKind.Long, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, cpuRegisters.length + (xmmRegisters.length << XMM_REFERENCE_MAP_SHIFT), 8);
|
super("AMD64", AMD64Kind.QWORD, ByteOrder.LITTLE_ENDIAN, true, allRegisters, LOAD_STORE | STORE_STORE, 1, 8);
|
||||||
this.features = features;
|
this.features = features;
|
||||||
this.flags = flags;
|
this.flags = flags;
|
||||||
assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
|
assert features.contains(CPUFeature.SSE2) : "minimum config for x64";
|
||||||
|
|
||||||
|
if (features.contains(CPUFeature.AVX512F)) {
|
||||||
|
largestKind = AMD64Kind.V512_QWORD;
|
||||||
|
} else if (features.contains(CPUFeature.AVX)) {
|
||||||
|
largestKind = AMD64Kind.V256_QWORD;
|
||||||
|
} else {
|
||||||
|
largestKind = AMD64Kind.V128_QWORD;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EnumSet<CPUFeature> getFeatures() {
|
public EnumSet<CPUFeature> getFeatures() {
|
||||||
|
@ -182,50 +243,60 @@ public class AMD64 extends Architecture {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlatformKind getPlatformKind(JavaKind javaKind) {
|
public Register[] getAvailableValueRegisters() {
|
||||||
if (javaKind.isObject()) {
|
if (features.contains(CPUFeature.AVX512F)) {
|
||||||
return getWordKind();
|
return valueRegistersAVX512;
|
||||||
} else {
|
} else {
|
||||||
return javaKind;
|
return valueRegistersSSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlatformKind getPlatformKind(JavaKind javaKind) {
|
||||||
|
switch (javaKind) {
|
||||||
|
case Boolean:
|
||||||
|
case Byte:
|
||||||
|
return AMD64Kind.BYTE;
|
||||||
|
case Short:
|
||||||
|
case Char:
|
||||||
|
return AMD64Kind.WORD;
|
||||||
|
case Int:
|
||||||
|
return AMD64Kind.DWORD;
|
||||||
|
case Long:
|
||||||
|
case Object:
|
||||||
|
return AMD64Kind.QWORD;
|
||||||
|
case Float:
|
||||||
|
return AMD64Kind.SINGLE;
|
||||||
|
case Double:
|
||||||
|
return AMD64Kind.DOUBLE;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
|
public boolean canStoreValue(RegisterCategory category, PlatformKind platformKind) {
|
||||||
if (!(platformKind instanceof JavaKind)) {
|
AMD64Kind kind = (AMD64Kind) platformKind;
|
||||||
return false;
|
if (kind.isInteger()) {
|
||||||
|
return category.equals(CPU);
|
||||||
|
} else if (kind.isXMM()) {
|
||||||
|
return category.equals(XMM);
|
||||||
|
} else {
|
||||||
|
assert kind.isMask();
|
||||||
|
return category.equals(MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaKind kind = (JavaKind) platformKind;
|
|
||||||
if (category.equals(CPU)) {
|
|
||||||
switch (kind) {
|
|
||||||
case Boolean:
|
|
||||||
case Byte:
|
|
||||||
case Char:
|
|
||||||
case Short:
|
|
||||||
case Int:
|
|
||||||
case Long:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (category.equals(XMM)) {
|
|
||||||
switch (kind) {
|
|
||||||
case Float:
|
|
||||||
case Double:
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PlatformKind getLargestStorableKind(RegisterCategory category) {
|
public AMD64Kind getLargestStorableKind(RegisterCategory category) {
|
||||||
if (category.equals(CPU)) {
|
if (category.equals(CPU)) {
|
||||||
return JavaKind.Long;
|
return AMD64Kind.QWORD;
|
||||||
} else if (category.equals(XMM)) {
|
} else if (category.equals(XMM)) {
|
||||||
return JavaKind.Double;
|
return largestKind;
|
||||||
|
} else if (category.equals(MASK)) {
|
||||||
|
return AMD64Kind.MASK64;
|
||||||
} else {
|
} else {
|
||||||
return JavaKind.Illegal;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,214 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package jdk.vm.ci.amd64;
|
||||||
|
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
|
||||||
|
public enum AMD64Kind implements PlatformKind {
|
||||||
|
|
||||||
|
// scalar
|
||||||
|
BYTE(1),
|
||||||
|
WORD(2),
|
||||||
|
DWORD(4),
|
||||||
|
QWORD(8),
|
||||||
|
SINGLE(4),
|
||||||
|
DOUBLE(8),
|
||||||
|
|
||||||
|
// SSE2
|
||||||
|
V32_BYTE(4, BYTE),
|
||||||
|
V32_WORD(4, WORD),
|
||||||
|
V64_BYTE(8, BYTE),
|
||||||
|
V64_WORD(8, WORD),
|
||||||
|
V64_DWORD(8, DWORD),
|
||||||
|
V128_BYTE(16, BYTE),
|
||||||
|
V128_WORD(16, WORD),
|
||||||
|
V128_DWORD(16, DWORD),
|
||||||
|
V128_QWORD(16, QWORD),
|
||||||
|
V128_SINGLE(16, SINGLE),
|
||||||
|
V128_DOUBLE(16, DOUBLE),
|
||||||
|
|
||||||
|
// AVX
|
||||||
|
V256_BYTE(32, BYTE),
|
||||||
|
V256_WORD(32, WORD),
|
||||||
|
V256_DWORD(32, DWORD),
|
||||||
|
V256_QWORD(32, QWORD),
|
||||||
|
V256_SINGLE(32, SINGLE),
|
||||||
|
V256_DOUBLE(32, DOUBLE),
|
||||||
|
|
||||||
|
// AVX512
|
||||||
|
V512_BYTE(64, BYTE),
|
||||||
|
V512_WORD(64, WORD),
|
||||||
|
V512_DWORD(64, DWORD),
|
||||||
|
V512_QWORD(64, QWORD),
|
||||||
|
V512_SINGLE(64, SINGLE),
|
||||||
|
V512_DOUBLE(64, DOUBLE),
|
||||||
|
|
||||||
|
MASK8(1),
|
||||||
|
MASK16(2),
|
||||||
|
MASK32(4),
|
||||||
|
MASK64(8);
|
||||||
|
|
||||||
|
private final int size;
|
||||||
|
private final int vectorLength;
|
||||||
|
|
||||||
|
private final AMD64Kind scalar;
|
||||||
|
private final EnumKey<AMD64Kind> key = new EnumKey<>(this);
|
||||||
|
|
||||||
|
private AMD64Kind(int size) {
|
||||||
|
this.size = size;
|
||||||
|
this.scalar = this;
|
||||||
|
this.vectorLength = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AMD64Kind(int size, AMD64Kind scalar) {
|
||||||
|
this.size = size;
|
||||||
|
this.scalar = scalar;
|
||||||
|
|
||||||
|
assert size % scalar.size == 0;
|
||||||
|
this.vectorLength = size / scalar.size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AMD64Kind getScalar() {
|
||||||
|
return scalar;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSizeInBytes() {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getVectorLength() {
|
||||||
|
return vectorLength;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Key getKey() {
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInteger() {
|
||||||
|
switch (this) {
|
||||||
|
case BYTE:
|
||||||
|
case WORD:
|
||||||
|
case DWORD:
|
||||||
|
case QWORD:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isXMM() {
|
||||||
|
switch (this) {
|
||||||
|
case SINGLE:
|
||||||
|
case DOUBLE:
|
||||||
|
case V32_BYTE:
|
||||||
|
case V32_WORD:
|
||||||
|
case V64_BYTE:
|
||||||
|
case V64_WORD:
|
||||||
|
case V64_DWORD:
|
||||||
|
case V128_BYTE:
|
||||||
|
case V128_WORD:
|
||||||
|
case V128_DWORD:
|
||||||
|
case V128_QWORD:
|
||||||
|
case V128_SINGLE:
|
||||||
|
case V128_DOUBLE:
|
||||||
|
case V256_BYTE:
|
||||||
|
case V256_WORD:
|
||||||
|
case V256_DWORD:
|
||||||
|
case V256_QWORD:
|
||||||
|
case V256_SINGLE:
|
||||||
|
case V256_DOUBLE:
|
||||||
|
case V512_BYTE:
|
||||||
|
case V512_WORD:
|
||||||
|
case V512_DWORD:
|
||||||
|
case V512_QWORD:
|
||||||
|
case V512_SINGLE:
|
||||||
|
case V512_DOUBLE:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isMask() {
|
||||||
|
switch (this) {
|
||||||
|
case MASK8:
|
||||||
|
case MASK16:
|
||||||
|
case MASK32:
|
||||||
|
case MASK64:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public char getTypeChar() {
|
||||||
|
switch (this) {
|
||||||
|
case BYTE:
|
||||||
|
return 'b';
|
||||||
|
case WORD:
|
||||||
|
return 'w';
|
||||||
|
case DWORD:
|
||||||
|
return 'd';
|
||||||
|
case QWORD:
|
||||||
|
return 'q';
|
||||||
|
case SINGLE:
|
||||||
|
return 'S';
|
||||||
|
case DOUBLE:
|
||||||
|
return 'D';
|
||||||
|
case V32_BYTE:
|
||||||
|
case V32_WORD:
|
||||||
|
case V64_BYTE:
|
||||||
|
case V64_WORD:
|
||||||
|
case V64_DWORD:
|
||||||
|
return 'v';
|
||||||
|
case V128_BYTE:
|
||||||
|
case V128_WORD:
|
||||||
|
case V128_DWORD:
|
||||||
|
case V128_QWORD:
|
||||||
|
case V128_SINGLE:
|
||||||
|
case V128_DOUBLE:
|
||||||
|
return 'x';
|
||||||
|
case V256_BYTE:
|
||||||
|
case V256_WORD:
|
||||||
|
case V256_DWORD:
|
||||||
|
case V256_QWORD:
|
||||||
|
case V256_SINGLE:
|
||||||
|
case V256_DOUBLE:
|
||||||
|
return 'y';
|
||||||
|
case V512_BYTE:
|
||||||
|
case V512_WORD:
|
||||||
|
case V512_DWORD:
|
||||||
|
case V512_QWORD:
|
||||||
|
case V512_SINGLE:
|
||||||
|
case V512_DOUBLE:
|
||||||
|
return 'z';
|
||||||
|
case MASK8:
|
||||||
|
case MASK16:
|
||||||
|
case MASK32:
|
||||||
|
case MASK64:
|
||||||
|
return 'k';
|
||||||
|
default:
|
||||||
|
return '-';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,11 +22,12 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.ByteOrder;
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import jdk.vm.ci.code.Register.RegisterCategory;
|
import jdk.vm.ci.code.Register.RegisterCategory;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a CPU architecture, including information such as its endianness, CPU registers, word
|
* Represents a CPU architecture, including information such as its endianness, CPU registers, word
|
||||||
|
@ -34,13 +35,6 @@ import jdk.vm.ci.meta.*;
|
||||||
*/
|
*/
|
||||||
public abstract class Architecture {
|
public abstract class Architecture {
|
||||||
|
|
||||||
/**
|
|
||||||
* The number of entries required in a {@link ReferenceMap} covering all the registers that may
|
|
||||||
* store references. The index of a register in the reference map is given by
|
|
||||||
* {@link Register#getReferenceMapIndex()}.
|
|
||||||
*/
|
|
||||||
private final int registerReferenceMapSize;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The architecture specific type of a native word.
|
* The architecture specific type of a native word.
|
||||||
*/
|
*/
|
||||||
|
@ -85,7 +79,7 @@ public abstract class Architecture {
|
||||||
private final int returnAddressSize;
|
private final int returnAddressSize;
|
||||||
|
|
||||||
protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
|
protected Architecture(String name, PlatformKind wordKind, ByteOrder byteOrder, boolean unalignedMemoryAccess, Register[] registers, int implicitMemoryBarriers, int nativeCallDisplacementOffset,
|
||||||
int registerReferenceMapSize, int returnAddressSize) {
|
int returnAddressSize) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.registers = registers;
|
this.registers = registers;
|
||||||
this.wordKind = wordKind;
|
this.wordKind = wordKind;
|
||||||
|
@ -93,7 +87,6 @@ public abstract class Architecture {
|
||||||
this.unalignedMemoryAccess = unalignedMemoryAccess;
|
this.unalignedMemoryAccess = unalignedMemoryAccess;
|
||||||
this.implicitMemoryBarriers = implicitMemoryBarriers;
|
this.implicitMemoryBarriers = implicitMemoryBarriers;
|
||||||
this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
|
this.machineCodeCallDisplacementOffset = nativeCallDisplacementOffset;
|
||||||
this.registerReferenceMapSize = registerReferenceMapSize;
|
|
||||||
this.returnAddressSize = returnAddressSize;
|
this.returnAddressSize = returnAddressSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,10 +100,6 @@ public abstract class Architecture {
|
||||||
return getName().toLowerCase();
|
return getName().toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getRegisterReferenceMapSize() {
|
|
||||||
return registerReferenceMapSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the natural size of words (typically registers and pointers) of this architecture, in
|
* Gets the natural size of words (typically registers and pointers) of this architecture, in
|
||||||
* bytes.
|
* bytes.
|
||||||
|
@ -131,13 +120,23 @@ public abstract class Architecture {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets an array of all available registers on this architecture. The index of each register in
|
* Gets an array of all registers that exist on this architecture. This contains all registers
|
||||||
* this array is equal to its {@linkplain Register#number number}.
|
* that exist in the specification of this architecture. Not all of them may be available on
|
||||||
|
* this particular architecture instance. The index of each register in this array is equal to
|
||||||
|
* its {@linkplain Register#number number}.
|
||||||
*/
|
*/
|
||||||
public Register[] getRegisters() {
|
public Register[] getRegisters() {
|
||||||
return registers.clone();
|
return registers.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an array of all registers available for storing values on this architecture. This may be
|
||||||
|
* a subset of {@link #getRegisters()}, depending on the capabilities of this particular CPU.
|
||||||
|
*/
|
||||||
|
public Register[] getAvailableValueRegisters() {
|
||||||
|
return getRegisters();
|
||||||
|
}
|
||||||
|
|
||||||
public ByteOrder getByteOrder() {
|
public ByteOrder getByteOrder() {
|
||||||
return byteOrder;
|
return byteOrder;
|
||||||
}
|
}
|
||||||
|
@ -207,7 +206,6 @@ public abstract class Architecture {
|
||||||
assert this.byteOrder.equals(that.byteOrder);
|
assert this.byteOrder.equals(that.byteOrder);
|
||||||
assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
|
assert this.implicitMemoryBarriers == that.implicitMemoryBarriers;
|
||||||
assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
|
assert this.machineCodeCallDisplacementOffset == that.machineCodeCallDisplacementOffset;
|
||||||
assert this.registerReferenceMapSize == that.registerReferenceMapSize;
|
|
||||||
assert Arrays.equals(this.registers, that.registers);
|
assert Arrays.equals(this.registers, that.registers);
|
||||||
assert this.returnAddressSize == that.returnAddressSize;
|
assert this.returnAddressSize == that.returnAddressSize;
|
||||||
assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
|
assert this.unalignedMemoryAccess == that.unalignedMemoryAccess;
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when the compiler refuses to compile a method because of problems with the
|
* Exception thrown when the compiler refuses to compile a method because of problems with the
|
||||||
|
|
|
@ -22,9 +22,12 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.JavaValue;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
import jdk.vm.ci.meta.Value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
|
* Represents the Java bytecode frame state(s) at a given position including {@link Value locations}
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Objects;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a code position, that is, a chain of inlined methods with bytecode locations, that is
|
* Represents a code position, that is, a chain of inlined methods with bytecode locations, that is
|
||||||
|
|
|
@ -22,9 +22,10 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import static jdk.vm.ci.code.ValueUtil.*;
|
import static jdk.vm.ci.code.ValueUtil.isAllocatableValue;
|
||||||
|
import static jdk.vm.ci.code.ValueUtil.isStackSlot;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.Value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A calling convention describes the locations in which the arguments for a call are placed and the
|
* A calling convention describes the locations in which the arguments for a call are placed and the
|
||||||
|
|
|
@ -22,9 +22,14 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import jdk.vm.ci.code.CompilationResult.*;
|
import jdk.vm.ci.code.CompilationResult.Call;
|
||||||
import jdk.vm.ci.code.DataSection.*;
|
import jdk.vm.ci.code.CompilationResult.DataPatch;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.code.CompilationResult.Mark;
|
||||||
|
import jdk.vm.ci.code.DataSection.Data;
|
||||||
|
import jdk.vm.ci.meta.Constant;
|
||||||
|
import jdk.vm.ci.meta.JavaConstant;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
import jdk.vm.ci.meta.SpeculationLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access to code cache related details and requirements.
|
* Access to code cache related details and requirements.
|
||||||
|
@ -32,26 +37,62 @@ import jdk.vm.ci.meta.*;
|
||||||
public interface CodeCacheProvider {
|
public interface CodeCacheProvider {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given compilation result as an implementation of the given method without making it
|
* Installs code for a given method based on a given compilation result without making it the
|
||||||
* the default implementation.
|
* default implementation of the method.
|
||||||
*
|
*
|
||||||
* @param method a method to which the executable code is begin added
|
* @param method a method implemented by the installed code
|
||||||
* @param compResult the compilation result to be added
|
* @param compResult the compilation result to be added
|
||||||
* @param speculationLog the speculation log to be used
|
* @param log the speculation log to be used
|
||||||
* @return a reference to the compiled and ready-to-run code or throws a
|
* @param installedCode a predefined {@link InstalledCode} object to use as a reference to the
|
||||||
* {@link BailoutException} if the code installation failed
|
* installed code. If {@code null}, a new {@link InstalledCode} object will be
|
||||||
|
* created.
|
||||||
|
* @return a reference to the ready-to-run code
|
||||||
|
* @throws BailoutException if the code installation failed
|
||||||
*/
|
*/
|
||||||
InstalledCode addMethod(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog speculationLog, InstalledCode predefinedInstalledCode);
|
default InstalledCode addCode(ResolvedJavaMethod method, CompilationResult compResult, SpeculationLog log, InstalledCode installedCode) {
|
||||||
|
return installCode(new CompilationRequest(method), compResult, installedCode, log, false);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the given compilation result as the default implementation of the given method.
|
* Installs code for a given method based on a given compilation result and makes it the default
|
||||||
|
* implementation of the method.
|
||||||
*
|
*
|
||||||
* @param method a method to which the executable code is begin added
|
* @param method a method implemented by the installed code and for which the installed code
|
||||||
|
* becomes the default implementation
|
||||||
* @param compResult the compilation result to be added
|
* @param compResult the compilation result to be added
|
||||||
* @return a reference to the compiled and ready-to-run code or null if the code installation
|
* @return a reference to the ready-to-run code
|
||||||
* failed
|
* @throws BailoutException if the code installation failed
|
||||||
*/
|
*/
|
||||||
InstalledCode setDefaultMethod(ResolvedJavaMethod method, CompilationResult compResult);
|
default InstalledCode setDefaultCode(ResolvedJavaMethod method, CompilationResult compResult) {
|
||||||
|
return installCode(new CompilationRequest(method), compResult, null, null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Installs code based on a given compilation result.
|
||||||
|
*
|
||||||
|
* @param compRequest details of the method compiled to produce {@code compResult} or
|
||||||
|
* {@code null} if the input to {@code compResult} was not a
|
||||||
|
* {@link ResolvedJavaMethod}
|
||||||
|
* @param compResult the compilation result to be added
|
||||||
|
* @param installedCode a pre-allocated {@link InstalledCode} object to use as a reference to
|
||||||
|
* the installed code. If {@code null}, a new {@link InstalledCode} object will be
|
||||||
|
* created.
|
||||||
|
* @param log the speculation log to be used
|
||||||
|
* @param isDefault specifies if the installed code should be made the default implementation of
|
||||||
|
* {@code compRequest.getMethod()}. The default implementation for a method is the
|
||||||
|
* code executed for standard calls to the method. This argument is ignored if
|
||||||
|
* {@code compRequest == null}.
|
||||||
|
* @return a reference to the compiled and ready-to-run installed code
|
||||||
|
* @throws BailoutException if the code installation failed
|
||||||
|
*/
|
||||||
|
InstalledCode installCode(CompilationRequest compRequest, CompilationResult compResult, InstalledCode installedCode, SpeculationLog log, boolean isDefault);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invalidates {@code installedCode} such that {@link InvalidInstalledCodeException} will be
|
||||||
|
* raised the next time {@code installedCode} is
|
||||||
|
* {@linkplain InstalledCode#executeVarargs(Object...) executed}.
|
||||||
|
*/
|
||||||
|
void invalidateInstalledCode(InstalledCode installedCode);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a name for a {@link Mark} mark.
|
* Gets a name for a {@link Mark} mark.
|
||||||
|
@ -102,4 +143,16 @@ public interface CodeCacheProvider {
|
||||||
* Create a new speculation log for the target runtime.
|
* Create a new speculation log for the target runtime.
|
||||||
*/
|
*/
|
||||||
SpeculationLog createSpeculationLog();
|
SpeculationLog createSpeculationLog();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the maximum absolute offset of a PC relative call to a given address from any
|
||||||
|
* position in the code cache or -1 when not applicable. Intended for determining the required
|
||||||
|
* size of address/offset fields.
|
||||||
|
*/
|
||||||
|
long getMaxCallTargetOffset(long address);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines if debug info should also be emitted at non-safepoint locations.
|
||||||
|
*/
|
||||||
|
boolean shouldDebugNonSafepoints();
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,9 +22,15 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaType;
|
||||||
|
import jdk.vm.ci.meta.MetaUtil;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
import jdk.vm.ci.meta.Signature;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients.
|
* Miscellaneous collection of utility methods used by {@code jdk.vm.ci.code} and its clients.
|
||||||
|
@ -323,49 +329,12 @@ public class CodeUtil {
|
||||||
public interface RefMapFormatter {
|
public interface RefMapFormatter {
|
||||||
|
|
||||||
String formatStackSlot(int frameRefMapIndex);
|
String formatStackSlot(int frameRefMapIndex);
|
||||||
|
|
||||||
String formatRegister(int regRefMapIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Formats a location in a register reference map.
|
* Formats a location present in a reference map.
|
||||||
*/
|
*/
|
||||||
public static class DefaultRegFormatter implements RefMapFormatter {
|
public static class DefaultRefMapFormatter implements RefMapFormatter {
|
||||||
|
|
||||||
private final Register[] registers;
|
|
||||||
|
|
||||||
public DefaultRegFormatter(Architecture arch) {
|
|
||||||
registers = new Register[arch.getRegisterReferenceMapSize()];
|
|
||||||
for (Register r : arch.getRegisters()) {
|
|
||||||
if (r.getReferenceMapIndex() >= 0) {
|
|
||||||
registers[r.getReferenceMapIndex()] = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String formatStackSlot(int frameRefMapIndex) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String formatRegister(int regRefMapIndex) {
|
|
||||||
int i = regRefMapIndex;
|
|
||||||
int idx = 0;
|
|
||||||
while (registers[i] == null) {
|
|
||||||
i--;
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
if (idx == 0) {
|
|
||||||
return registers[i].toString();
|
|
||||||
} else {
|
|
||||||
return String.format("%s+%d", registers[i].toString(), idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Formats a location present in a register or frame reference map.
|
|
||||||
*/
|
|
||||||
public static class DefaultRefMapFormatter extends DefaultRegFormatter {
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The size of a stack slot.
|
* The size of a stack slot.
|
||||||
|
@ -383,8 +352,7 @@ public class CodeUtil {
|
||||||
*/
|
*/
|
||||||
public final int refMapToFPOffset;
|
public final int refMapToFPOffset;
|
||||||
|
|
||||||
public DefaultRefMapFormatter(Architecture arch, int slotSize, Register fp, int refMapToFPOffset) {
|
public DefaultRefMapFormatter(int slotSize, Register fp, int refMapToFPOffset) {
|
||||||
super(arch);
|
|
||||||
this.slotSize = slotSize;
|
this.slotSize = slotSize;
|
||||||
this.fp = fp;
|
this.fp = fp;
|
||||||
this.refMapToFPOffset = refMapToFPOffset;
|
this.refMapToFPOffset = refMapToFPOffset;
|
||||||
|
|
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*/
|
||||||
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a request to compile a method.
|
||||||
|
*/
|
||||||
|
public class CompilationRequest {
|
||||||
|
|
||||||
|
private final ResolvedJavaMethod method;
|
||||||
|
|
||||||
|
private final int entryBCI;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a request to compile a method starting at its entry point.
|
||||||
|
*
|
||||||
|
* @param method the method to be compiled
|
||||||
|
*/
|
||||||
|
public CompilationRequest(ResolvedJavaMethod method) {
|
||||||
|
this(method, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a request to compile a method starting at a given BCI.
|
||||||
|
*
|
||||||
|
* @param method the method to be compiled
|
||||||
|
* @param entryBCI the bytecode index (BCI) at which to start compiling where -1 denotes the
|
||||||
|
* method's entry point
|
||||||
|
*/
|
||||||
|
public CompilationRequest(ResolvedJavaMethod method, int entryBCI) {
|
||||||
|
assert method != null;
|
||||||
|
this.method = method;
|
||||||
|
this.entryBCI = entryBCI;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the method to be compiled.
|
||||||
|
*/
|
||||||
|
public ResolvedJavaMethod getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the bytecode index (BCI) at which to start compiling where -1 denotes a non-OSR
|
||||||
|
* compilation request and all other values denote an on stack replacement (OSR) compilation
|
||||||
|
* request.
|
||||||
|
*/
|
||||||
|
public int getEntryBCI() {
|
||||||
|
return entryBCI;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return method.format("%H.%n(%p)@" + entryBCI);
|
||||||
|
}
|
||||||
|
}
|
|
@ -22,13 +22,24 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import static java.util.Collections.*;
|
import static java.util.Collections.emptyList;
|
||||||
import static jdk.vm.ci.meta.MetaUtil.*;
|
import static java.util.Collections.unmodifiableList;
|
||||||
|
import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.Assumptions.Assumption;
|
||||||
import jdk.vm.ci.meta.Assumptions.*;
|
import jdk.vm.ci.meta.InvokeTarget;
|
||||||
|
import jdk.vm.ci.meta.JavaConstant;
|
||||||
|
import jdk.vm.ci.meta.MetaUtil;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
import jdk.vm.ci.meta.VMConstant;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the output from compiling a method, including the compiled machine code, associated
|
* Represents the output from compiling a method, including the compiled machine code, associated
|
||||||
|
@ -115,8 +126,8 @@ public class CompilationResult {
|
||||||
|
|
||||||
public enum MetaSpaceAccessType {
|
public enum MetaSpaceAccessType {
|
||||||
Move,
|
Move,
|
||||||
Store, // store only works for compressed oops (memory <- 32bit value). Compressed oops is
|
Store, // store only works for compressed oops (memory <- 32bit value). Compressed oops is
|
||||||
// not supported using AOT. TODO: Look at HotSpotStoreConstantOp
|
// not supported using AOT. TODO: Look at HotSpotStoreConstantOp
|
||||||
Compare; // HotSpotCompareMemoryConstantOp, HotSpotCompareConstantOp
|
Compare; // HotSpotCompareMemoryConstantOp, HotSpotCompareConstantOp
|
||||||
|
|
||||||
private MetaSpaceAccessType() {
|
private MetaSpaceAccessType() {
|
||||||
|
@ -128,13 +139,11 @@ public class CompilationResult {
|
||||||
*/
|
*/
|
||||||
public static final class MetaSpaceAccess extends Infopoint {
|
public static final class MetaSpaceAccess extends Infopoint {
|
||||||
|
|
||||||
private static final long serialVersionUID = 1701958512608684706L;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Metaspace reference.
|
* Metaspace reference.
|
||||||
*/
|
*/
|
||||||
public final Object reference; // Object here is a HotSpotResolvedObjectType or a
|
public final Object reference; // Object here is a HotSpotResolvedObjectType or a
|
||||||
// HotSpotMetaSpaceConstant
|
// HotSpotMetaSpaceConstant
|
||||||
|
|
||||||
public final MetaSpaceAccessType type;
|
public final MetaSpaceAccessType type;
|
||||||
|
|
||||||
|
@ -296,6 +305,15 @@ public class CompilationResult {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
if (initialized) {
|
||||||
|
return String.format("DataSection[0x%x]", offset);
|
||||||
|
} else {
|
||||||
|
return "DataSection[?]";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -528,8 +546,6 @@ public class CompilationResult {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int id = -1;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Specifies whether this compilation is a {@code +ImmutableCode} {@code +GeneratePIC}
|
* Specifies whether this compilation is a {@code +ImmutableCode} {@code +GeneratePIC}
|
||||||
* compilation.
|
* compilation.
|
||||||
|
@ -612,7 +628,6 @@ public class CompilationResult {
|
||||||
CompilationResult that = (CompilationResult) obj;
|
CompilationResult that = (CompilationResult) obj;
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
if (this.entryBCI == that.entryBCI &&
|
if (this.entryBCI == that.entryBCI &&
|
||||||
this.id == that.id &&
|
|
||||||
this.customStackAreaOffset == that.customStackAreaOffset &&
|
this.customStackAreaOffset == that.customStackAreaOffset &&
|
||||||
this.totalFrameSize == that.totalFrameSize &&
|
this.totalFrameSize == that.totalFrameSize &&
|
||||||
this.targetCodeSize == that.targetCodeSize &&
|
this.targetCodeSize == that.targetCodeSize &&
|
||||||
|
@ -632,20 +647,6 @@ public class CompilationResult {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return the compile id
|
|
||||||
*/
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param id the compile id to set
|
|
||||||
*/
|
|
||||||
public void setId(int id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return true is this is a {@code +ImmutableCode} {@code +GeneratePIC} compilation, false
|
* @return true is this is a {@code +ImmutableCode} {@code +GeneratePIC} compilation, false
|
||||||
* otherwise.
|
* otherwise.
|
||||||
|
|
|
@ -22,15 +22,18 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import static jdk.vm.ci.meta.MetaUtil.*;
|
import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
|
||||||
|
|
||||||
import java.nio.*;
|
import java.nio.ByteBuffer;
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
import java.util.function.*;
|
import java.util.Iterator;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.function.Consumer;
|
||||||
|
|
||||||
import jdk.vm.ci.code.CompilationResult.*;
|
import jdk.vm.ci.code.CompilationResult.DataPatch;
|
||||||
import jdk.vm.ci.code.DataSection.*;
|
import jdk.vm.ci.code.CompilationResult.DataSectionReference;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.code.DataSection.Data;
|
||||||
|
import jdk.vm.ci.meta.SerializableConstant;
|
||||||
|
|
||||||
public final class DataSection implements Iterable<Data> {
|
public final class DataSection implements Iterable<Data> {
|
||||||
|
|
||||||
|
@ -176,11 +179,27 @@ public final class DataSection implements Iterable<Data> {
|
||||||
*/
|
*/
|
||||||
public DataSectionReference insertData(Data data) {
|
public DataSectionReference insertData(Data data) {
|
||||||
assert !finalLayout;
|
assert !finalLayout;
|
||||||
if (data.ref == null) {
|
synchronized (data) {
|
||||||
data.ref = new DataSectionReference();
|
if (data.ref == null) {
|
||||||
|
data.ref = new DataSectionReference();
|
||||||
|
dataItems.add(data);
|
||||||
|
}
|
||||||
|
return data.ref;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfers all {@link Data} from the provided other {@link DataSection} to this
|
||||||
|
* {@link DataSection}, and empties the other section.
|
||||||
|
*/
|
||||||
|
public void addAll(DataSection other) {
|
||||||
|
assert !finalLayout && !other.finalLayout;
|
||||||
|
|
||||||
|
for (Data data : other.dataItems) {
|
||||||
|
assert data.ref != null;
|
||||||
dataItems.add(data);
|
dataItems.add(data);
|
||||||
}
|
}
|
||||||
return data.ref;
|
other.dataItems.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -195,14 +214,16 @@ public final class DataSection implements Iterable<Data> {
|
||||||
dataItems.sort((a, b) -> a.alignment - b.alignment);
|
dataItems.sort((a, b) -> a.alignment - b.alignment);
|
||||||
|
|
||||||
int position = 0;
|
int position = 0;
|
||||||
|
int alignment = 1;
|
||||||
for (Data d : dataItems) {
|
for (Data d : dataItems) {
|
||||||
sectionAlignment = lcm(sectionAlignment, d.alignment);
|
alignment = lcm(alignment, d.alignment);
|
||||||
position = align(position, d.alignment);
|
position = align(position, d.alignment);
|
||||||
|
|
||||||
d.ref.setOffset(position);
|
d.ref.setOffset(position);
|
||||||
position += d.size;
|
position += d.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sectionAlignment = alignment;
|
||||||
sectionSize = position;
|
sectionSize = position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the debugging information for a particular point of execution. This information
|
* Represents the debugging information for a particular point of execution. This information
|
||||||
|
|
|
@ -29,14 +29,19 @@ package jdk.vm.ci.code;
|
||||||
public class InstalledCode {
|
public class InstalledCode {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Raw address of this code blob.
|
* Raw address address of entity representing this installed code.
|
||||||
*/
|
*/
|
||||||
private long address;
|
protected long address;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw address of entryPoint of this installed code.
|
||||||
|
*/
|
||||||
|
protected long entryPoint;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Counts how often the address field was reassigned.
|
* Counts how often the address field was reassigned.
|
||||||
*/
|
*/
|
||||||
private long version;
|
protected long version;
|
||||||
|
|
||||||
protected final String name;
|
protected final String name;
|
||||||
|
|
||||||
|
@ -44,27 +49,29 @@ public class InstalledCode {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final void setAddress(long address) {
|
|
||||||
this.address = address;
|
|
||||||
version++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the address of this code blob
|
* @return the address of entity representing this installed code.
|
||||||
*/
|
*/
|
||||||
public final long getAddress() {
|
public final long getAddress() {
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the address of this code blob
|
* @return the address of the normal entry point of the installed code.
|
||||||
|
*/
|
||||||
|
public final long getEntryPoint() {
|
||||||
|
return entryPoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the version number of this installed code
|
||||||
*/
|
*/
|
||||||
public final long getVersion() {
|
public final long getVersion() {
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the name of this code blob.
|
* Returns the name of this installed code.
|
||||||
*/
|
*/
|
||||||
public String getName() {
|
public String getName() {
|
||||||
return name;
|
return name;
|
||||||
|
@ -79,10 +86,19 @@ public class InstalledCode {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of instruction bytes for this code.
|
* @return true if the code represented by this object is still valid for invocation, false
|
||||||
|
* otherwise (may happen due to deopt, etc.)
|
||||||
*/
|
*/
|
||||||
public long getCodeSize() {
|
public boolean isValid() {
|
||||||
return 0;
|
return entryPoint != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true if the code represented by this object still exists and might have live
|
||||||
|
* activations, false otherwise (may happen due to deopt, etc.)
|
||||||
|
*/
|
||||||
|
public boolean isAlive() {
|
||||||
|
return address != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,18 +108,10 @@ public class InstalledCode {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return true if the code represented by this object is still valid, false otherwise (may
|
|
||||||
* happen due to deopt, etc.)
|
|
||||||
*/
|
|
||||||
public boolean isValid() {
|
|
||||||
return address != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invalidates this installed code such that any subsequent
|
* Invalidates this installed code such that any subsequent
|
||||||
* {@linkplain #executeVarargs(Object...) invocation} will throw an
|
* {@linkplain #executeVarargs(Object...) invocation} will throw an
|
||||||
* {@link InvalidInstalledCodeException}.
|
* {@link InvalidInstalledCodeException} and all existing invocations will be deoptimized.
|
||||||
*/
|
*/
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.LIRKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a target machine register.
|
* Represents a target machine register.
|
||||||
|
@ -80,22 +81,15 @@ public final class Register implements Comparable<Register> {
|
||||||
public static class RegisterCategory {
|
public static class RegisterCategory {
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
|
private final boolean mayContainReference;
|
||||||
private final int referenceMapOffset;
|
|
||||||
private final int referenceMapShift;
|
|
||||||
|
|
||||||
public RegisterCategory(String name) {
|
public RegisterCategory(String name) {
|
||||||
this(name, 0, 0);
|
this(name, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public RegisterCategory(String name, int referenceMapOffset) {
|
public RegisterCategory(String name, boolean mayContainReference) {
|
||||||
this(name, referenceMapOffset, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
public RegisterCategory(String name, int referenceMapOffset, int referenceMapShift) {
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.referenceMapOffset = referenceMapOffset;
|
this.mayContainReference = mayContainReference;
|
||||||
this.referenceMapShift = referenceMapShift;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -112,7 +106,7 @@ public final class Register implements Comparable<Register> {
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj instanceof RegisterCategory) {
|
if (obj instanceof RegisterCategory) {
|
||||||
RegisterCategory that = (RegisterCategory) obj;
|
RegisterCategory that = (RegisterCategory) obj;
|
||||||
return this.referenceMapOffset == that.referenceMapOffset && this.referenceMapShift == that.referenceMapShift && this.name.equals(that.name);
|
return this.name.equals(that.name);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -138,10 +132,10 @@ public final class Register implements Comparable<Register> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the start index of this register in the {@link ReferenceMap}.
|
* Determine whether this register needs to be part of the reference map.
|
||||||
*/
|
*/
|
||||||
public int getReferenceMapIndex() {
|
public boolean mayContainReference() {
|
||||||
return (encoding << registerCategory.referenceMapShift) + registerCategory.referenceMapOffset;
|
return registerCategory.mayContainReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A collection of register attributes. The specific attribute values for a register may be local to
|
* A collection of register attributes. The specific attribute values for a register may be local to
|
||||||
|
|
|
@ -22,8 +22,10 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import jdk.vm.ci.code.CallingConvention.*;
|
import jdk.vm.ci.code.CallingConvention.Type;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.JavaType;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical
|
* A register configuration binds roles and {@linkplain RegisterAttributes attributes} to physical
|
||||||
|
|
|
@ -22,7 +22,11 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.TreeMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A map from registers to frame slots. This can be used to describe where callee saved registers
|
* A map from registers to frame slots. This can be used to describe where callee saved registers
|
||||||
|
|
|
@ -22,7 +22,9 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.LIRKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance
|
* Denotes a register that stores a value of a fixed kind. There is exactly one (canonical) instance
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2015, 2015, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
|
|
@ -22,9 +22,9 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import static jdk.vm.ci.code.ValueUtil.*;
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.JavaValue;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.Value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents lock information in the debug information.
|
* Represents lock information in the debug information.
|
||||||
|
@ -32,10 +32,10 @@ import jdk.vm.ci.meta.*;
|
||||||
public final class StackLockValue implements JavaValue {
|
public final class StackLockValue implements JavaValue {
|
||||||
|
|
||||||
private JavaValue owner;
|
private JavaValue owner;
|
||||||
private StackSlotValue slot;
|
private AllocatableValue slot;
|
||||||
private final boolean eliminated;
|
private final boolean eliminated;
|
||||||
|
|
||||||
public StackLockValue(JavaValue object, StackSlotValue slot, boolean eliminated) {
|
public StackLockValue(JavaValue object, AllocatableValue slot, boolean eliminated) {
|
||||||
this.owner = object;
|
this.owner = object;
|
||||||
this.slot = slot;
|
this.slot = slot;
|
||||||
this.eliminated = eliminated;
|
this.eliminated = eliminated;
|
||||||
|
@ -81,8 +81,7 @@ public final class StackLockValue implements JavaValue {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSlot(StackSlotValue stackSlot) {
|
public void setSlot(AllocatableValue stackSlot) {
|
||||||
assert slot == null || (isVirtualStackSlot(slot) && (slot.equals(stackSlot) || isStackSlot(stackSlot))) : String.format("Can not set slot for %s to %s", this, stackSlot);
|
|
||||||
slot = stackSlot;
|
slot = stackSlot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -22,13 +22,14 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.LIRKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
|
* Represents a compiler spill slot or an outgoing stack-based argument in a method's frame or an
|
||||||
* incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
|
* incoming stack-based argument in a method's {@linkplain #isInCallerFrame() caller's frame}.
|
||||||
*/
|
*/
|
||||||
public final class StackSlot extends StackSlotValue {
|
public final class StackSlot extends AllocatableValue {
|
||||||
|
|
||||||
private final int offset;
|
private final int offset;
|
||||||
private final boolean addFrameSize;
|
private final boolean addFrameSize;
|
||||||
|
|
|
@ -22,9 +22,10 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import static jdk.vm.ci.meta.MetaUtil.*;
|
import static jdk.vm.ci.meta.MetaUtil.identityHashCodeString;
|
||||||
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.LIRKind;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents the target machine for a compiler, including the CPU architecture, the size of
|
* Represents the target machine for a compiler, including the CPU architecture, the size of
|
||||||
|
@ -50,9 +51,9 @@ public class TargetDescription {
|
||||||
public final int wordSize;
|
public final int wordSize;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The kind to be used for representing raw pointers and CPU registers.
|
* The {@link JavaKind} to be used for representing raw pointers and CPU registers in Java code.
|
||||||
*/
|
*/
|
||||||
public final JavaKind wordKind;
|
public final JavaKind wordJavaKind;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The stack alignment requirement of the platform. For example, from Appendix D of <a
|
* The stack alignment requirement of the platform. For example, from Appendix D of <a
|
||||||
|
@ -78,10 +79,12 @@ public class TargetDescription {
|
||||||
this.arch = arch;
|
this.arch = arch;
|
||||||
this.isMP = isMP;
|
this.isMP = isMP;
|
||||||
this.wordSize = arch.getWordSize();
|
this.wordSize = arch.getWordSize();
|
||||||
this.wordKind = JavaKind.fromWordSize(wordSize);
|
this.wordJavaKind = JavaKind.fromWordSize(wordSize);
|
||||||
this.stackAlignment = stackAlignment;
|
this.stackAlignment = stackAlignment;
|
||||||
this.implicitNullCheckLimit = implicitNullCheckLimit;
|
this.implicitNullCheckLimit = implicitNullCheckLimit;
|
||||||
this.inlineObjects = inlineObjects;
|
this.inlineObjects = inlineObjects;
|
||||||
|
|
||||||
|
assert arch.getPlatformKind(wordJavaKind).equals(arch.getWordKind());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -101,7 +104,7 @@ public class TargetDescription {
|
||||||
this.inlineObjects == that.inlineObjects &&
|
this.inlineObjects == that.inlineObjects &&
|
||||||
this.isMP == that.isMP &&
|
this.isMP == that.isMP &&
|
||||||
this.stackAlignment == that.stackAlignment &&
|
this.stackAlignment == that.stackAlignment &&
|
||||||
this.wordKind.equals(that.wordKind) &&
|
this.wordJavaKind.equals(that.wordJavaKind) &&
|
||||||
this.wordSize == that.wordSize &&
|
this.wordSize == that.wordSize &&
|
||||||
this.arch.equals(that.arch)) {
|
this.arch.equals(that.arch)) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -116,10 +119,6 @@ public class TargetDescription {
|
||||||
return identityHashCodeString(this);
|
return identityHashCodeString(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getSizeInBytes(PlatformKind kind) {
|
|
||||||
return kind.getSizeInBytes();
|
|
||||||
}
|
|
||||||
|
|
||||||
public LIRKind getLIRKind(JavaKind javaKind) {
|
public LIRKind getLIRKind(JavaKind javaKind) {
|
||||||
PlatformKind platformKind = arch.getPlatformKind(javaKind);
|
PlatformKind platformKind = arch.getPlatformKind(javaKind);
|
||||||
if (javaKind.isObject()) {
|
if (javaKind.isObject()) {
|
||||||
|
|
|
@ -1,124 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2011, 2011, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.vm.ci.code;
|
|
||||||
|
|
||||||
import java.math.*;
|
|
||||||
|
|
||||||
//JaCoCo Exclude
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for unsigned comparisons. All methods have correct, but slow, standard Java
|
|
||||||
* implementations so that they can be used with compilers not supporting the intrinsics.
|
|
||||||
*/
|
|
||||||
public class UnsignedMath {
|
|
||||||
|
|
||||||
private static final long MASK = 0xffffffffL;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison aboveThan for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean aboveThan(int a, int b) {
|
|
||||||
return (a & MASK) > (b & MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison aboveOrEqual for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean aboveOrEqual(int a, int b) {
|
|
||||||
return (a & MASK) >= (b & MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison belowThan for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean belowThan(int a, int b) {
|
|
||||||
return (a & MASK) < (b & MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison belowOrEqual for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean belowOrEqual(int a, int b) {
|
|
||||||
return (a & MASK) <= (b & MASK);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison aboveThan for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean aboveThan(long a, long b) {
|
|
||||||
return (a > b) ^ ((a < 0) != (b < 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison aboveOrEqual for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean aboveOrEqual(long a, long b) {
|
|
||||||
return (a >= b) ^ ((a < 0) != (b < 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison belowThan for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean belowThan(long a, long b) {
|
|
||||||
return (a < b) ^ ((a < 0) != (b < 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned comparison belowOrEqual for two numbers.
|
|
||||||
*/
|
|
||||||
public static boolean belowOrEqual(long a, long b) {
|
|
||||||
return (a <= b) ^ ((a < 0) != (b < 0));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned division for two numbers.
|
|
||||||
*/
|
|
||||||
public static int divide(int a, int b) {
|
|
||||||
return (int) ((a & MASK) / (b & MASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned remainder for two numbers.
|
|
||||||
*/
|
|
||||||
public static int remainder(int a, int b) {
|
|
||||||
return (int) ((a & MASK) % (b & MASK));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned division for two numbers.
|
|
||||||
*/
|
|
||||||
public static long divide(long a, long b) {
|
|
||||||
return bi(a).divide(bi(b)).longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unsigned remainder for two numbers.
|
|
||||||
*/
|
|
||||||
public static long remainder(long a, long b) {
|
|
||||||
return bi(a).remainder(bi(b)).longValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static BigInteger bi(long unsigned) {
|
|
||||||
return unsigned >= 0 ? BigInteger.valueOf(unsigned) : BigInteger.valueOf(unsigned & 0x7fffffffffffffffL).setBit(63);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -22,9 +22,14 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.JavaConstant;
|
||||||
|
import jdk.vm.ci.meta.JavaValue;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
import jdk.vm.ci.meta.Value;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utility class for working with the {@link Value} class and its subclasses.
|
* Utility class for working with the {@link Value} class and its subclasses.
|
||||||
|
@ -60,6 +65,11 @@ public final class ValueUtil {
|
||||||
return value instanceof JavaConstant;
|
return value instanceof JavaConstant;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static JavaConstant asConstantJavaValue(JavaValue value) {
|
||||||
|
assert value != null;
|
||||||
|
return (JavaConstant) value;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isAllocatableValue(Value value) {
|
public static boolean isAllocatableValue(Value value) {
|
||||||
assert value != null;
|
assert value != null;
|
||||||
return value instanceof AllocatableValue;
|
return value instanceof AllocatableValue;
|
||||||
|
@ -80,26 +90,6 @@ public final class ValueUtil {
|
||||||
return (StackSlot) value;
|
return (StackSlot) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isStackSlotValue(Value value) {
|
|
||||||
assert value != null;
|
|
||||||
return value instanceof StackSlotValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static StackSlotValue asStackSlotValue(Value value) {
|
|
||||||
assert value != null;
|
|
||||||
return (StackSlotValue) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isVirtualStackSlot(Value value) {
|
|
||||||
assert value != null;
|
|
||||||
return value instanceof VirtualStackSlot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static VirtualStackSlot asVirtualStackSlot(Value value) {
|
|
||||||
assert value != null;
|
|
||||||
return (VirtualStackSlot) value;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isRegister(Value value) {
|
public static boolean isRegister(Value value) {
|
||||||
assert value != null;
|
assert value != null;
|
||||||
return value instanceof RegisterValue;
|
return value instanceof RegisterValue;
|
||||||
|
|
|
@ -22,9 +22,15 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.JavaValue;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaField;
|
||||||
|
import jdk.vm.ci.meta.ResolvedJavaType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An instance of this class represents an object whose allocation was removed by escape analysis.
|
* An instance of this class represents an object whose allocation was removed by escape analysis.
|
||||||
|
@ -134,45 +140,6 @@ public final class VirtualObject implements JavaValue {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean checkValues() {
|
|
||||||
assert (values == null) == (slotKinds == null);
|
|
||||||
if (values != null) {
|
|
||||||
assert values.length == slotKinds.length;
|
|
||||||
if (!type.isArray()) {
|
|
||||||
ResolvedJavaField[] fields = type.getInstanceFields(true);
|
|
||||||
int fieldIndex = 0;
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
ResolvedJavaField field = fields[fieldIndex++];
|
|
||||||
JavaKind valKind = slotKinds[i].getStackKind();
|
|
||||||
if (field.getJavaKind() == JavaKind.Object) {
|
|
||||||
assert valKind.isObject() : field + ": " + valKind + " != " + field.getJavaKind();
|
|
||||||
} else {
|
|
||||||
if ((valKind == JavaKind.Double || valKind == JavaKind.Long) && field.getJavaKind() == JavaKind.Int) {
|
|
||||||
assert fields[fieldIndex].getJavaKind() == JavaKind.Int;
|
|
||||||
fieldIndex++;
|
|
||||||
} else {
|
|
||||||
assert valKind == field.getJavaKind().getStackKind() : field + ": " + valKind + " != " + field.getJavaKind();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert fields.length == fieldIndex : type + ": fields=" + Arrays.toString(fields) + ", field values=" + Arrays.toString(values);
|
|
||||||
} else {
|
|
||||||
JavaKind componentKind = type.getComponentType().getJavaKind().getStackKind();
|
|
||||||
if (componentKind == JavaKind.Object) {
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
assert slotKinds[i].isObject() : slotKinds[i] + " != " + componentKind;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i < values.length; i++) {
|
|
||||||
assert slotKinds[i] == componentKind || componentKind.getBitCount() >= slotKinds[i].getBitCount() ||
|
|
||||||
(componentKind == JavaKind.Int && slotKinds[i].getBitCount() >= JavaKind.Int.getBitCount()) : slotKinds[i] + " != " + componentKind;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Overwrites the current set of values with a new one.
|
* Overwrites the current set of values with a new one.
|
||||||
*
|
*
|
||||||
|
@ -183,7 +150,6 @@ public final class VirtualObject implements JavaValue {
|
||||||
public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
|
public void setValues(JavaValue[] values, JavaKind[] slotKinds) {
|
||||||
this.values = values;
|
this.values = values;
|
||||||
this.slotKinds = slotKinds;
|
this.slotKinds = slotKinds;
|
||||||
assert checkValues();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.vm.ci.code;
|
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* {@link VirtualStackSlot}s are stack slots that are not yet fixed to specific frame offset. They
|
|
||||||
* are replaced by real {@link StackSlot}s with a fixed position in the frame before code emission.
|
|
||||||
*/
|
|
||||||
public abstract class VirtualStackSlot extends StackSlotValue {
|
|
||||||
|
|
||||||
private final int id;
|
|
||||||
|
|
||||||
public VirtualStackSlot(int id, LIRKind lirKind) {
|
|
||||||
super(lirKind);
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "vstack:" + id + getKindSuffix();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
final int prime = 31;
|
|
||||||
int result = super.hashCode();
|
|
||||||
result = prime * result + id;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (this == obj) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!super.equals(obj)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (getClass() != obj.getClass()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
VirtualStackSlot other = (VirtualStackSlot) obj;
|
|
||||||
if (id != other.id) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -18,10 +18,10 @@
|
||||||
* if you need additional information or have any questions.
|
* if you need additional information or have any questions.
|
||||||
*/
|
*/
|
||||||
/**
|
/**
|
||||||
* Package that defines the interface between a Java application that wants to install code and the
|
* Package that defines the interface between a Java application that wants to install code and the runtime.
|
||||||
* runtime. The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider}
|
* The runtime provides in implementation of the {@link jdk.vm.ci.code.CodeCacheProvider} interface.
|
||||||
* interface. The method
|
* The method {@link jdk.vm.ci.code.CodeCacheProvider#addCode(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)}
|
||||||
* {@link jdk.vm.ci.code.CodeCacheProvider#addMethod(jdk.vm.ci.meta.ResolvedJavaMethod, CompilationResult, jdk.vm.ci.meta.SpeculationLog, InstalledCode)}
|
* can be used to install code.
|
||||||
* can be used to install code for a given method.
|
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code;
|
package jdk.vm.ci.code;
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code.stack;
|
package jdk.vm.ci.code.stack;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
|
||||||
public interface InspectedFrame {
|
public interface InspectedFrame {
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.code.stack;
|
package jdk.vm.ci.code.stack;
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.meta.ResolvedJavaMethod;
|
||||||
|
|
||||||
public interface StackIntrospection {
|
public interface StackIntrospection {
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,8 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.common;
|
package jdk.vm.ci.common;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates a condition in JVMCI related code that should never occur during normal operation.
|
* Indicates a condition in JVMCI related code that should never occur during normal operation.
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
|
||||||
*
|
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU General Public License version 2 only, as
|
|
||||||
* published by the Free Software Foundation.
|
|
||||||
*
|
|
||||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
* version 2 for more details (a copy is included in the LICENSE file that
|
|
||||||
* accompanied this code).
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License version
|
|
||||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
|
||||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*
|
|
||||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
|
||||||
* or visit www.oracle.com if you need additional information or have any
|
|
||||||
* questions.
|
|
||||||
*/
|
|
||||||
package jdk.vm.ci.compiler;
|
|
||||||
|
|
||||||
import jdk.vm.ci.meta.*;
|
|
||||||
import jdk.vm.ci.options.*;
|
|
||||||
|
|
||||||
public interface Compiler {
|
|
||||||
int INVOCATION_ENTRY_BCI = -1;
|
|
||||||
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<String> PrintFilter = new OptionValue<>(null);
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintCompilation = new OptionValue<>(false);
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintAfterCompilation = new OptionValue<>(false);
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintBailout = new OptionValue<>(false);
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnBailout = new OptionValue<>(false);
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<Boolean> ExitVMOnException = new OptionValue<>(true);
|
|
||||||
@Option(help = "", type = OptionType.Debug) OptionValue<Boolean> PrintStackTraceOnException = new OptionValue<>(false);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Request the compilation of a method by this JVMCI compiler. The compiler should compile the
|
|
||||||
* method to machine code and install it in the code cache if the compilation is successful.
|
|
||||||
*
|
|
||||||
* @param method the method that should be compiled
|
|
||||||
* @param entryBCI the BCI at which to start compiling where -1 denotes a non-OSR compilation
|
|
||||||
* request and all other values denote an OSR compilation request
|
|
||||||
* @param jvmciEnv pointer to native {@code JVMCIEnv} object
|
|
||||||
* @param id a unique identifier for this compilation
|
|
||||||
*/
|
|
||||||
void compileMethod(ResolvedJavaMethod method, int entryBCI, long jvmciEnv, int id);
|
|
||||||
}
|
|
|
@ -22,18 +22,26 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.hotspot.amd64;
|
package jdk.vm.ci.hotspot.amd64;
|
||||||
|
|
||||||
import static jdk.vm.ci.inittimer.InitTimer.*;
|
import static jdk.vm.ci.inittimer.InitTimer.timer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import jdk.vm.ci.amd64.*;
|
import jdk.vm.ci.amd64.AMD64;
|
||||||
import jdk.vm.ci.code.*;
|
import jdk.vm.ci.code.Architecture;
|
||||||
import jdk.vm.ci.compiler.*;
|
import jdk.vm.ci.code.RegisterConfig;
|
||||||
import jdk.vm.ci.hotspot.*;
|
import jdk.vm.ci.code.TargetDescription;
|
||||||
import jdk.vm.ci.inittimer.*;
|
import jdk.vm.ci.code.stack.StackIntrospection;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
|
||||||
import jdk.vm.ci.runtime.*;
|
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||||
import jdk.vm.ci.service.*;
|
import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotVMConfig;
|
||||||
|
import jdk.vm.ci.inittimer.InitTimer;
|
||||||
|
import jdk.vm.ci.meta.ConstantReflectionProvider;
|
||||||
|
import jdk.vm.ci.runtime.JVMCIBackend;
|
||||||
|
import jdk.vm.ci.service.ServiceProvider;
|
||||||
|
|
||||||
@ServiceProvider(HotSpotJVMCIBackendFactory.class)
|
@ServiceProvider(HotSpotJVMCIBackendFactory.class)
|
||||||
public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
|
public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
|
||||||
|
@ -68,6 +76,9 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
if ((config.x86CPUFeatures & config.cpuLZCNT) != 0) {
|
if ((config.x86CPUFeatures & config.cpuLZCNT) != 0) {
|
||||||
features.add(AMD64.CPUFeature.LZCNT);
|
features.add(AMD64.CPUFeature.LZCNT);
|
||||||
}
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuERMS) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.ERMS);
|
||||||
|
}
|
||||||
if ((config.x86CPUFeatures & config.cpuAVX) != 0) {
|
if ((config.x86CPUFeatures & config.cpuAVX) != 0) {
|
||||||
features.add(AMD64.CPUFeature.AVX);
|
features.add(AMD64.CPUFeature.AVX);
|
||||||
}
|
}
|
||||||
|
@ -77,12 +88,42 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
if ((config.x86CPUFeatures & config.cpuAES) != 0) {
|
if ((config.x86CPUFeatures & config.cpuAES) != 0) {
|
||||||
features.add(AMD64.CPUFeature.AES);
|
features.add(AMD64.CPUFeature.AES);
|
||||||
}
|
}
|
||||||
if ((config.x86CPUFeatures & config.cpuERMS) != 0) {
|
if ((config.x86CPUFeatures & config.cpu3DNOWPREFETCH) != 0) {
|
||||||
features.add(AMD64.CPUFeature.ERMS);
|
features.add(AMD64.CPUFeature.AMD_3DNOW_PREFETCH);
|
||||||
}
|
}
|
||||||
if ((config.x86CPUFeatures & config.cpuBMI1) != 0) {
|
if ((config.x86CPUFeatures & config.cpuBMI1) != 0) {
|
||||||
features.add(AMD64.CPUFeature.BMI1);
|
features.add(AMD64.CPUFeature.BMI1);
|
||||||
}
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuBMI2) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.BMI2);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuRTM) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.RTM);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuADX) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.ADX);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512F) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512F);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512DQ) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512DQ);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512PF) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512PF);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512ER) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512ER);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512CD) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512CD);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512BW) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512BW);
|
||||||
|
}
|
||||||
|
if ((config.x86CPUFeatures & config.cpuAVX512VL) != 0) {
|
||||||
|
features.add(AMD64.CPUFeature.AVX512VL);
|
||||||
|
}
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,12 +138,12 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
|
protected TargetDescription createTarget(HotSpotVMConfig config) {
|
||||||
final int stackFrameAlignment = 16;
|
final int stackFrameAlignment = 16;
|
||||||
final int implicitNullCheckLimit = 4096;
|
final int implicitNullCheckLimit = 4096;
|
||||||
final boolean inlineObjects = true;
|
final boolean inlineObjects = true;
|
||||||
Architecture arch = new AMD64(computeFeatures(config), computeFlags(config));
|
Architecture arch = new AMD64(computeFeatures(config), computeFlags(config));
|
||||||
return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
|
return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
|
protected HotSpotConstantReflectionProvider createConstantReflection(HotSpotJVMCIRuntimeProvider runtime) {
|
||||||
|
@ -132,15 +173,16 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("try")
|
@SuppressWarnings("try")
|
||||||
public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
|
public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
|
||||||
|
|
||||||
assert host == null;
|
assert host == null;
|
||||||
TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
|
TargetDescription target = createTarget(runtime.getConfig());
|
||||||
|
|
||||||
RegisterConfig regConfig;
|
RegisterConfig regConfig;
|
||||||
HotSpotCodeCacheProvider codeCache;
|
HotSpotCodeCacheProvider codeCache;
|
||||||
ConstantReflectionProvider constantReflection;
|
ConstantReflectionProvider constantReflection;
|
||||||
HotSpotMetaAccessProvider metaAccess;
|
HotSpotMetaAccessProvider metaAccess;
|
||||||
|
StackIntrospection stackIntrospection;
|
||||||
try (InitTimer t = timer("create providers")) {
|
try (InitTimer t = timer("create providers")) {
|
||||||
try (InitTimer rt = timer("create MetaAccess provider")) {
|
try (InitTimer rt = timer("create MetaAccess provider")) {
|
||||||
metaAccess = createMetaAccess(runtime);
|
metaAccess = createMetaAccess(runtime);
|
||||||
|
@ -154,13 +196,16 @@ public class AMD64HotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
try (InitTimer rt = timer("create ConstantReflection provider")) {
|
try (InitTimer rt = timer("create ConstantReflection provider")) {
|
||||||
constantReflection = createConstantReflection(runtime);
|
constantReflection = createConstantReflection(runtime);
|
||||||
}
|
}
|
||||||
|
try (InitTimer rt = timer("create StackIntrospection provider")) {
|
||||||
|
stackIntrospection = new HotSpotStackIntrospection(runtime);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
try (InitTimer rt = timer("instantiate backend")) {
|
try (InitTimer rt = timer("instantiate backend")) {
|
||||||
return createBackend(metaAccess, codeCache, constantReflection);
|
return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection) {
|
protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, StackIntrospection stackIntrospection) {
|
||||||
return new JVMCIBackend(metaAccess, codeCache, constantReflection);
|
return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,47 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.hotspot.amd64;
|
package jdk.vm.ci.hotspot.amd64;
|
||||||
|
|
||||||
import static jdk.vm.ci.amd64.AMD64.*;
|
import static jdk.vm.ci.amd64.AMD64.r12;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.r15;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.r8;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.r9;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.rax;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.rcx;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.rdi;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.rdx;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.rsi;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.rsp;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm0;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm1;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm2;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm3;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm4;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm5;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm6;
|
||||||
|
import static jdk.vm.ci.amd64.AMD64.xmm7;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import jdk.vm.ci.amd64.*;
|
import jdk.vm.ci.code.Architecture;
|
||||||
import jdk.vm.ci.code.*;
|
import jdk.vm.ci.code.CallingConvention;
|
||||||
import jdk.vm.ci.code.CallingConvention.*;
|
import jdk.vm.ci.code.CallingConvention.Type;
|
||||||
import jdk.vm.ci.common.*;
|
import jdk.vm.ci.code.Register;
|
||||||
import jdk.vm.ci.hotspot.*;
|
import jdk.vm.ci.code.RegisterAttributes;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.code.RegisterConfig;
|
||||||
|
import jdk.vm.ci.code.StackSlot;
|
||||||
|
import jdk.vm.ci.code.TargetDescription;
|
||||||
|
import jdk.vm.ci.common.JVMCIError;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotVMConfig;
|
||||||
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.JavaType;
|
||||||
|
import jdk.vm.ci.meta.LIRKind;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
import jdk.vm.ci.meta.Value;
|
||||||
|
|
||||||
public class AMD64HotSpotRegisterConfig implements RegisterConfig {
|
public class AMD64HotSpotRegisterConfig implements RegisterConfig {
|
||||||
|
|
||||||
|
@ -86,28 +117,30 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig {
|
||||||
*/
|
*/
|
||||||
private final boolean needsNativeStackHomeSpace;
|
private final boolean needsNativeStackHomeSpace;
|
||||||
|
|
||||||
private static Register[] initAllocatable(boolean reserveForHeapBase) {
|
private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
|
||||||
Register[] registers = null;
|
Register[] allRegisters = arch.getAvailableValueRegisters();
|
||||||
// @formatter:off
|
Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 3 : 2)];
|
||||||
if (reserveForHeapBase) {
|
|
||||||
registers = new Register[] {
|
int idx = 0;
|
||||||
rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, r10, r11, /*r12,*/ r13, r14, /*r15, */
|
for (Register reg : allRegisters) {
|
||||||
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
if (reg.equals(rsp) || reg.equals(r15)) {
|
||||||
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
// skip stack pointer and thread register
|
||||||
};
|
continue;
|
||||||
} else {
|
}
|
||||||
registers = new Register[] {
|
if (reserveForHeapBase && reg.equals(r12)) {
|
||||||
rax, rbx, rcx, rdx, /*rsp,*/ rbp, rsi, rdi, r8, r9, r10, r11, r12, r13, r14, /*r15, */
|
// skip heap base register
|
||||||
xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7,
|
continue;
|
||||||
xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15
|
}
|
||||||
};
|
|
||||||
|
registers[idx++] = reg;
|
||||||
}
|
}
|
||||||
// @formatter:on
|
|
||||||
|
assert idx == registers.length;
|
||||||
return registers;
|
return registers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
|
public AMD64HotSpotRegisterConfig(Architecture architecture, HotSpotVMConfig config) {
|
||||||
this(architecture, config, initAllocatable(config.useCompressedOops));
|
this(architecture, config, initAllocatable(architecture, config.useCompressedOops));
|
||||||
assert callerSaved.length >= allocatable.length;
|
assert callerSaved.length >= allocatable.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +158,7 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig {
|
||||||
this.needsNativeStackHomeSpace = false;
|
this.needsNativeStackHomeSpace = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.allocatable = allocatable.clone();
|
this.allocatable = allocatable;
|
||||||
Set<Register> callerSaveSet = new HashSet<>();
|
Set<Register> callerSaveSet = new HashSet<>();
|
||||||
Collections.addAll(callerSaveSet, allocatable);
|
Collections.addAll(callerSaveSet, allocatable);
|
||||||
Collections.addAll(callerSaveSet, xmmParameterRegisters);
|
Collections.addAll(callerSaveSet, xmmParameterRegisters);
|
||||||
|
@ -134,7 +167,7 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig {
|
||||||
callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
|
callerSaved = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
|
||||||
|
|
||||||
allAllocatableAreCallerSaved = true;
|
allAllocatableAreCallerSaved = true;
|
||||||
attributesMap = RegisterAttributes.createMap(this, AMD64.allRegisters);
|
attributesMap = RegisterAttributes.createMap(this, architecture.getRegisters());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -221,7 +254,7 @@ public class AMD64HotSpotRegisterConfig implements RegisterConfig {
|
||||||
if (locations[i] == null) {
|
if (locations[i] == null) {
|
||||||
LIRKind lirKind = target.getLIRKind(kind);
|
LIRKind lirKind = target.getLIRKind(kind);
|
||||||
locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out);
|
locations[i] = StackSlot.get(lirKind, currentStackOffset, !type.out);
|
||||||
currentStackOffset += Math.max(target.getSizeInBytes(lirKind.getPlatformKind()), target.wordSize);
|
currentStackOffset += Math.max(lirKind.getPlatformKind().getSizeInBytes(), target.wordSize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,28 +22,36 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.hotspot.sparc;
|
package jdk.vm.ci.hotspot.sparc;
|
||||||
|
|
||||||
import static jdk.vm.ci.inittimer.InitTimer.*;
|
import static jdk.vm.ci.inittimer.InitTimer.timer;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.EnumSet;
|
||||||
|
|
||||||
import jdk.vm.ci.code.*;
|
import jdk.vm.ci.code.Architecture;
|
||||||
import jdk.vm.ci.compiler.*;
|
import jdk.vm.ci.code.RegisterConfig;
|
||||||
import jdk.vm.ci.hotspot.*;
|
import jdk.vm.ci.code.TargetDescription;
|
||||||
import jdk.vm.ci.inittimer.*;
|
import jdk.vm.ci.code.stack.StackIntrospection;
|
||||||
import jdk.vm.ci.runtime.*;
|
import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider;
|
||||||
import jdk.vm.ci.service.*;
|
import jdk.vm.ci.hotspot.HotSpotConstantReflectionProvider;
|
||||||
import jdk.vm.ci.sparc.*;
|
import jdk.vm.ci.hotspot.HotSpotJVMCIBackendFactory;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntimeProvider;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotMetaAccessProvider;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotStackIntrospection;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotVMConfig;
|
||||||
|
import jdk.vm.ci.inittimer.InitTimer;
|
||||||
|
import jdk.vm.ci.runtime.JVMCIBackend;
|
||||||
|
import jdk.vm.ci.service.ServiceProvider;
|
||||||
|
import jdk.vm.ci.sparc.SPARC;
|
||||||
import jdk.vm.ci.sparc.SPARC.CPUFeature;
|
import jdk.vm.ci.sparc.SPARC.CPUFeature;
|
||||||
|
|
||||||
@ServiceProvider(HotSpotJVMCIBackendFactory.class)
|
@ServiceProvider(HotSpotJVMCIBackendFactory.class)
|
||||||
public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
|
public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFactory {
|
||||||
|
|
||||||
protected TargetDescription createTarget(HotSpotVMConfig config, CompilerFactory compilerFactory) {
|
protected TargetDescription createTarget(HotSpotVMConfig config) {
|
||||||
final int stackFrameAlignment = 16;
|
final int stackFrameAlignment = 16;
|
||||||
final int implicitNullCheckLimit = 4096;
|
final int implicitNullCheckLimit = 4096;
|
||||||
final boolean inlineObjects = false;
|
final boolean inlineObjects = false;
|
||||||
Architecture arch = new SPARC(computeFeatures(config));
|
Architecture arch = new SPARC(computeFeatures(config));
|
||||||
return new TargetDescription(compilerFactory.initializeArchitecture(arch), true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
|
return new TargetDescription(arch, true, stackFrameAlignment, implicitNullCheckLimit, inlineObjects);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
|
protected HotSpotCodeCacheProvider createCodeCache(HotSpotJVMCIRuntimeProvider runtime, TargetDescription target, RegisterConfig regConfig) {
|
||||||
|
@ -64,8 +72,62 @@ public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
if ((config.sparcFeatures & config.cbcondInstructions) != 0) {
|
if ((config.sparcFeatures & config.cbcondInstructions) != 0) {
|
||||||
features.add(CPUFeature.CBCOND);
|
features.add(CPUFeature.CBCOND);
|
||||||
}
|
}
|
||||||
if (config.useBlockZeroing) {
|
if ((config.sparcFeatures & config.v8Instructions) != 0) {
|
||||||
features.add(CPUFeature.BLOCK_ZEROING);
|
features.add(CPUFeature.V8);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.hardwareMul32) != 0) {
|
||||||
|
features.add(CPUFeature.HARDWARE_MUL32);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.hardwareDiv32) != 0) {
|
||||||
|
features.add(CPUFeature.HARDWARE_DIV32);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.hardwareFsmuld) != 0) {
|
||||||
|
features.add(CPUFeature.HARDWARE_FSMULD);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.hardwarePopc) != 0) {
|
||||||
|
features.add(CPUFeature.HARDWARE_POPC);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.v9Instructions) != 0) {
|
||||||
|
features.add(CPUFeature.V9);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.sun4v) != 0) {
|
||||||
|
features.add(CPUFeature.SUN4V);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.blkInitInstructions) != 0) {
|
||||||
|
features.add(CPUFeature.BLK_INIT_INSTRUCTIONS);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.fmafInstructions) != 0) {
|
||||||
|
features.add(CPUFeature.FMAF);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.fmauInstructions) != 0) {
|
||||||
|
features.add(CPUFeature.FMAU);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.sparc64Family) != 0) {
|
||||||
|
features.add(CPUFeature.SPARC64_FAMILY);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.mFamily) != 0) {
|
||||||
|
features.add(CPUFeature.M_FAMILY);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.tFamily) != 0) {
|
||||||
|
features.add(CPUFeature.T_FAMILY);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.t1Model) != 0) {
|
||||||
|
features.add(CPUFeature.T1_MODEL);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.sparc5Instructions) != 0) {
|
||||||
|
features.add(CPUFeature.SPARC5);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.aesInstructions) != 0) {
|
||||||
|
features.add(CPUFeature.SPARC64_FAMILY);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.sha1Instruction) != 0) {
|
||||||
|
features.add(CPUFeature.SHA1);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.sha256Instruction) != 0) {
|
||||||
|
features.add(CPUFeature.SHA256);
|
||||||
|
}
|
||||||
|
if ((config.sparcFeatures & config.sha512Instruction) != 0) {
|
||||||
|
features.add(CPUFeature.SHA512);
|
||||||
}
|
}
|
||||||
return features;
|
return features;
|
||||||
}
|
}
|
||||||
|
@ -81,20 +143,22 @@ public class SPARCHotSpotJVMCIBackendFactory implements HotSpotJVMCIBackendFacto
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("try")
|
@SuppressWarnings("try")
|
||||||
public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, CompilerFactory compilerFactory, JVMCIBackend host) {
|
public JVMCIBackend createJVMCIBackend(HotSpotJVMCIRuntimeProvider runtime, JVMCIBackend host) {
|
||||||
assert host == null;
|
assert host == null;
|
||||||
TargetDescription target = createTarget(runtime.getConfig(), compilerFactory);
|
TargetDescription target = createTarget(runtime.getConfig());
|
||||||
|
|
||||||
HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
|
HotSpotMetaAccessProvider metaAccess = new HotSpotMetaAccessProvider(runtime);
|
||||||
RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target, runtime.getConfig());
|
RegisterConfig regConfig = new SPARCHotSpotRegisterConfig(target.arch, runtime.getConfig());
|
||||||
HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig);
|
HotSpotCodeCacheProvider codeCache = createCodeCache(runtime, target, regConfig);
|
||||||
HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
|
HotSpotConstantReflectionProvider constantReflection = new HotSpotConstantReflectionProvider(runtime);
|
||||||
|
StackIntrospection stackIntrospection = new HotSpotStackIntrospection(runtime);
|
||||||
try (InitTimer rt = timer("instantiate backend")) {
|
try (InitTimer rt = timer("instantiate backend")) {
|
||||||
return createBackend(metaAccess, codeCache, constantReflection);
|
return createBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection) {
|
protected JVMCIBackend createBackend(HotSpotMetaAccessProvider metaAccess, HotSpotCodeCacheProvider codeCache, HotSpotConstantReflectionProvider constantReflection,
|
||||||
return new JVMCIBackend(metaAccess, codeCache, constantReflection);
|
StackIntrospection stackIntrospection) {
|
||||||
|
return new JVMCIBackend(metaAccess, codeCache, constantReflection, stackIntrospection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,16 +22,72 @@
|
||||||
*/
|
*/
|
||||||
package jdk.vm.ci.hotspot.sparc;
|
package jdk.vm.ci.hotspot.sparc;
|
||||||
|
|
||||||
import static jdk.vm.ci.sparc.SPARC.*;
|
import static jdk.vm.ci.code.CallingConvention.Type.JavaCall;
|
||||||
|
import static jdk.vm.ci.code.CallingConvention.Type.JavaCallee;
|
||||||
|
import static jdk.vm.ci.code.CallingConvention.Type.NativeCall;
|
||||||
|
import static jdk.vm.ci.meta.JavaKind.Void;
|
||||||
|
import static jdk.vm.ci.meta.Value.ILLEGAL;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.REGISTER_SAFE_AREA_SIZE;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.d0;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.d2;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.d4;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.d6;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f0;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f1;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f2;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f3;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f4;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f5;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f6;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.f7;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.g0;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.g2;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.g6;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i0;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i1;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i2;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i3;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i4;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i5;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i6;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.i7;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l0;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l1;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l2;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l3;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l4;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l5;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l6;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.l7;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.o0;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.o1;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.o2;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.o3;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.o4;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.o5;
|
||||||
|
import static jdk.vm.ci.sparc.SPARC.sp;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
|
||||||
import jdk.vm.ci.code.*;
|
import jdk.vm.ci.code.Architecture;
|
||||||
import jdk.vm.ci.code.CallingConvention.*;
|
import jdk.vm.ci.code.CallingConvention;
|
||||||
import jdk.vm.ci.common.*;
|
import jdk.vm.ci.code.CallingConvention.Type;
|
||||||
import jdk.vm.ci.hotspot.*;
|
import jdk.vm.ci.code.Register;
|
||||||
import jdk.vm.ci.meta.*;
|
import jdk.vm.ci.code.RegisterAttributes;
|
||||||
import jdk.vm.ci.sparc.*;
|
import jdk.vm.ci.code.RegisterConfig;
|
||||||
|
import jdk.vm.ci.code.StackSlot;
|
||||||
|
import jdk.vm.ci.code.TargetDescription;
|
||||||
|
import jdk.vm.ci.common.JVMCIError;
|
||||||
|
import jdk.vm.ci.hotspot.HotSpotVMConfig;
|
||||||
|
import jdk.vm.ci.meta.AllocatableValue;
|
||||||
|
import jdk.vm.ci.meta.JavaKind;
|
||||||
|
import jdk.vm.ci.meta.JavaType;
|
||||||
|
import jdk.vm.ci.meta.LIRKind;
|
||||||
|
import jdk.vm.ci.meta.PlatformKind;
|
||||||
|
import jdk.vm.ci.sparc.SPARC;
|
||||||
|
|
||||||
public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
|
|
||||||
|
@ -41,6 +97,11 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
|
|
||||||
private final RegisterAttributes[] attributesMap;
|
private final RegisterAttributes[] attributesMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does native code (C++ code) spill arguments in registers to the parent frame?
|
||||||
|
*/
|
||||||
|
private final boolean addNativeRegisterArgumentSlots;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register[] getAllocatableRegisters() {
|
public Register[] getAllocatableRegisters() {
|
||||||
return allocatable.clone();
|
return allocatable.clone();
|
||||||
|
@ -50,22 +111,9 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
ArrayList<Register> list = new ArrayList<>();
|
ArrayList<Register> list = new ArrayList<>();
|
||||||
for (Register reg : registers) {
|
for (Register reg : registers) {
|
||||||
if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
|
if (architecture.canStoreValue(reg.getRegisterCategory(), kind)) {
|
||||||
// Special treatment for double precision
|
list.add(reg);
|
||||||
// TODO: This is wasteful it uses only half of the registers as float.
|
|
||||||
if (kind == JavaKind.Double) {
|
|
||||||
if (reg.getRegisterCategory().equals(FPUd)) {
|
|
||||||
list.add(reg);
|
|
||||||
}
|
|
||||||
} else if (kind == JavaKind.Float) {
|
|
||||||
if (reg.getRegisterCategory().equals(FPUs)) {
|
|
||||||
list.add(reg);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
list.add(reg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Register[] ret = list.toArray(new Register[list.size()]);
|
Register[] ret = list.toArray(new Register[list.size()]);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -78,76 +126,57 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
|
private final Register[] cpuCallerParameterRegisters = {o0, o1, o2, o3, o4, o5};
|
||||||
private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
|
private final Register[] cpuCalleeParameterRegisters = {i0, i1, i2, i3, i4, i5};
|
||||||
|
|
||||||
private final Register[] fpuParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
|
private final Register[] fpuFloatParameterRegisters = {f0, f1, f2, f3, f4, f5, f6, f7};
|
||||||
private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
|
private final Register[] fpuDoubleParameterRegisters = {d0, null, d2, null, d4, null, d6, null};
|
||||||
|
|
||||||
// @formatter:off
|
// @formatter:off
|
||||||
private final Register[] callerSaveRegisters =
|
private final Register[] callerSaveRegisters;
|
||||||
{g1, g2, g3, g4, g5, g6, g7,
|
|
||||||
o0, o1, o2, o3, o4, o5, o7,
|
|
||||||
f0, f1, f2, f3, f4, f5, f6, f7,
|
|
||||||
f8, f9, f10, f11, f12, f13, f14, f15,
|
|
||||||
f16, f17, f18, f19, f20, f21, f22, f23,
|
|
||||||
f24, f25, f26, f27, f28, f29, f30, f31,
|
|
||||||
d32, d34, d36, d38, d40, d42, d44, d46,
|
|
||||||
d48, d50, d52, d54, d56, d58, d60, d62};
|
|
||||||
// @formatter:on
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers saved by the callee. This lists all L and I registers which are saved in the
|
* Registers saved by the callee. This lists all L and I registers which are saved in the
|
||||||
* register window.
|
* register window.
|
||||||
*/
|
*/
|
||||||
private final Register[] calleeSaveRegisters = {l0, l1, l2, l3, l4, l5, l6, l7, i0, i1, i2, i3, i4, i5, i6, i7};
|
private final Register[] calleeSaveRegisters = {
|
||||||
|
l0, l1, l2, l3, l4, l5, l6, l7,
|
||||||
|
i0, i1, i2, i3, i4, i5, i6, i7};
|
||||||
|
// @formatter:on
|
||||||
|
|
||||||
private static Register[] initAllocatable(boolean reserveForHeapBase) {
|
private static Register[] initAllocatable(Architecture arch, boolean reserveForHeapBase) {
|
||||||
Register[] registers = null;
|
Register[] allRegisters = arch.getAvailableValueRegisters();
|
||||||
if (reserveForHeapBase) {
|
Register[] registers = new Register[allRegisters.length - (reserveForHeapBase ? 4 : 3)];
|
||||||
// @formatter:off
|
|
||||||
registers = new Register[]{
|
int idx = 0;
|
||||||
// TODO this is not complete
|
for (Register reg : allRegisters) {
|
||||||
// o7 cannot be used as register because it is always overwritten on call
|
if (reg.equals(sp) || reg.equals(g2) || reg.equals(g0)) {
|
||||||
// and the current register handler would ignore this fact if the called
|
// skip g0, stack pointer and thread register
|
||||||
// method still does not modify registers, in fact o7 is modified by the Call instruction
|
continue;
|
||||||
// There would be some extra handlin necessary to be able to handle the o7 properly for local usage
|
}
|
||||||
g1, g4, g5,
|
if (reserveForHeapBase && reg.equals(g6)) {
|
||||||
o0, o1, o2, o3, o4, o5, /*o6,o7,*/
|
// skip heap base register
|
||||||
l0, l1, l2, l3, l4, l5, l6, l7,
|
continue;
|
||||||
i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
|
}
|
||||||
//f0, f1, f2, f3, f4, f5, f6, f7,
|
|
||||||
f8, f9, f10, f11, f12, f13, f14, f15,
|
registers[idx++] = reg;
|
||||||
f16, f17, f18, f19, f20, f21, f22, f23,
|
|
||||||
f24, f25, f26, f27, f28, f29, f30, f31,
|
|
||||||
d32, d34, d36, d38, d40, d42, d44, d46,
|
|
||||||
d48, d50, d52, d54, d56, d58, d60, d62
|
|
||||||
};
|
|
||||||
// @formatter:on
|
|
||||||
} else {
|
|
||||||
// @formatter:off
|
|
||||||
registers = new Register[]{
|
|
||||||
// TODO this is not complete
|
|
||||||
g1, g4, g5,
|
|
||||||
o0, o1, o2, o3, o4, o5, /*o6, o7,*/
|
|
||||||
l0, l1, l2, l3, l4, l5, l6, l7,
|
|
||||||
i0, i1, i2, i3, i4, i5, /*i6,*/ /*i7,*/
|
|
||||||
// f0, f1, f2, f3, f4, f5, f6, f7
|
|
||||||
f8, f9, f10, f11, f12, f13, f14, f15,
|
|
||||||
f16, f17, f18, f19, f20, f21, f22, f23,
|
|
||||||
f24, f25, f26, f27, f28, f29, f30, f31,
|
|
||||||
d32, d34, d36, d38, d40, d42, d44, d46,
|
|
||||||
d48, d50, d52, d54, d56, d58, d60, d62
|
|
||||||
};
|
|
||||||
// @formatter:on
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert idx == registers.length;
|
||||||
return registers;
|
return registers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public SPARCHotSpotRegisterConfig(TargetDescription target, HotSpotVMConfig config) {
|
public SPARCHotSpotRegisterConfig(Architecture arch, HotSpotVMConfig config) {
|
||||||
this(target, initAllocatable(config.useCompressedOops));
|
this(arch, initAllocatable(arch, config.useCompressedOops), config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public SPARCHotSpotRegisterConfig(TargetDescription target, Register[] allocatable) {
|
public SPARCHotSpotRegisterConfig(Architecture arch, Register[] allocatable, HotSpotVMConfig config) {
|
||||||
this.architecture = target.arch;
|
this.architecture = arch;
|
||||||
this.allocatable = allocatable.clone();
|
this.allocatable = allocatable.clone();
|
||||||
|
this.addNativeRegisterArgumentSlots = config.linuxOs;
|
||||||
|
HashSet<Register> callerSaveSet = new HashSet<>();
|
||||||
|
Collections.addAll(callerSaveSet, arch.getAvailableValueRegisters());
|
||||||
|
for (Register cs : calleeSaveRegisters) {
|
||||||
|
callerSaveSet.remove(cs);
|
||||||
|
}
|
||||||
|
this.callerSaveRegisters = callerSaveSet.toArray(new Register[callerSaveSet.size()]);
|
||||||
attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
|
attributesMap = RegisterAttributes.createMap(this, SPARC.allRegisters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,21 +201,31 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
|
public CallingConvention getCallingConvention(Type type, JavaType returnType, JavaType[] parameterTypes, TargetDescription target, boolean stackOnly) {
|
||||||
if (type == Type.JavaCall || type == Type.NativeCall) {
|
if (type == JavaCall || type == NativeCall) {
|
||||||
return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
|
return callingConvention(cpuCallerParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
|
||||||
}
|
}
|
||||||
if (type == Type.JavaCallee) {
|
if (type == JavaCallee) {
|
||||||
return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
|
return callingConvention(cpuCalleeParameterRegisters, returnType, parameterTypes, type, target, stackOnly);
|
||||||
}
|
}
|
||||||
throw JVMCIError.shouldNotReachHere();
|
throw JVMCIError.shouldNotReachHere();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
|
public Register[] getCallingConventionRegisters(Type type, JavaKind kind) {
|
||||||
if (architecture.canStoreValue(FPUs, kind) || architecture.canStoreValue(FPUd, kind)) {
|
switch (kind) {
|
||||||
return fpuParameterRegisters;
|
case Boolean:
|
||||||
|
case Byte:
|
||||||
|
case Short:
|
||||||
|
case Char:
|
||||||
|
case Int:
|
||||||
|
case Long:
|
||||||
|
case Object:
|
||||||
|
return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
|
||||||
|
case Double:
|
||||||
|
case Float:
|
||||||
|
return fpuFloatParameterRegisters;
|
||||||
|
default:
|
||||||
|
throw JVMCIError.shouldNotReachHere("Unknown JavaKind " + kind);
|
||||||
}
|
}
|
||||||
assert architecture.canStoreValue(CPU, kind);
|
|
||||||
return type == Type.JavaCallee ? cpuCalleeParameterRegisters : cpuCallerParameterRegisters;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
|
private CallingConvention callingConvention(Register[] generalParameterRegisters, JavaType returnType, JavaType[] parameterTypes, Type type, TargetDescription target, boolean stackOnly) {
|
||||||
|
@ -213,7 +252,7 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Double:
|
case Double:
|
||||||
if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
|
if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) {
|
||||||
if (currentFloating % 2 != 0) {
|
if (currentFloating % 2 != 0) {
|
||||||
// Make register number even to be a double reg
|
// Make register number even to be a double reg
|
||||||
currentFloating++;
|
currentFloating++;
|
||||||
|
@ -224,8 +263,8 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Float:
|
case Float:
|
||||||
if (!stackOnly && currentFloating < fpuParameterRegisters.length) {
|
if (!stackOnly && currentFloating < fpuFloatParameterRegisters.length) {
|
||||||
Register register = fpuParameterRegisters[currentFloating++];
|
Register register = fpuFloatParameterRegisters[currentFloating++];
|
||||||
locations[i] = register.asValue(target.getLIRKind(kind));
|
locations[i] = register.asValue(target.getLIRKind(kind));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -234,20 +273,27 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (locations[i] == null) {
|
if (locations[i] == null) {
|
||||||
|
LIRKind lirKind = target.getLIRKind(kind);
|
||||||
// Stack slot is always aligned to its size in bytes but minimum wordsize
|
// Stack slot is always aligned to its size in bytes but minimum wordsize
|
||||||
int typeSize = SPARC.spillSlotSize(target, kind);
|
int typeSize = lirKind.getPlatformKind().getSizeInBytes();
|
||||||
currentStackOffset = roundUp(currentStackOffset, typeSize);
|
currentStackOffset = roundUp(currentStackOffset, typeSize);
|
||||||
int slotOffset = currentStackOffset + SPARC.REGISTER_SAFE_AREA_SIZE;
|
int slotOffset = currentStackOffset + REGISTER_SAFE_AREA_SIZE;
|
||||||
locations[i] = StackSlot.get(target.getLIRKind(kind.getStackKind()), slotOffset, !type.out);
|
locations[i] = StackSlot.get(lirKind, slotOffset, !type.out);
|
||||||
currentStackOffset += typeSize;
|
currentStackOffset += typeSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JavaKind returnKind = returnType == null ? JavaKind.Void : returnType.getJavaKind();
|
JavaKind returnKind = returnType == null ? Void : returnType.getJavaKind();
|
||||||
AllocatableValue returnLocation = returnKind == JavaKind.Void ? Value.ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind()));
|
AllocatableValue returnLocation = returnKind == Void ? ILLEGAL : getReturnRegister(returnKind, type).asValue(target.getLIRKind(returnKind.getStackKind()));
|
||||||
// Space where callee may spill outgoing parameters o0...o5
|
|
||||||
int lowerOutgoingSpace = Math.min(locations.length, 6) * target.wordSize;
|
int outArgSpillArea;
|
||||||
return new CallingConvention(currentStackOffset + lowerOutgoingSpace, returnLocation, locations);
|
if (type == NativeCall && addNativeRegisterArgumentSlots) {
|
||||||
|
// Space for native callee which may spill our outgoing arguments
|
||||||
|
outArgSpillArea = Math.min(locations.length, generalParameterRegisters.length) * target.wordSize;
|
||||||
|
} else {
|
||||||
|
outArgSpillArea = 0;
|
||||||
|
}
|
||||||
|
return new CallingConvention(currentStackOffset + outArgSpillArea, returnLocation, locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int roundUp(int number, int mod) {
|
private static int roundUp(int number, int mod) {
|
||||||
|
@ -256,7 +302,7 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Register getReturnRegister(JavaKind kind) {
|
public Register getReturnRegister(JavaKind kind) {
|
||||||
return getReturnRegister(kind, Type.JavaCallee);
|
return getReturnRegister(kind, JavaCallee);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Register getReturnRegister(JavaKind kind, Type type) {
|
private static Register getReturnRegister(JavaKind kind, Type type) {
|
||||||
|
@ -268,7 +314,7 @@ public class SPARCHotSpotRegisterConfig implements RegisterConfig {
|
||||||
case Int:
|
case Int:
|
||||||
case Long:
|
case Long:
|
||||||
case Object:
|
case Object:
|
||||||
return type == Type.JavaCallee ? i0 : o0;
|
return type == JavaCallee ? i0 : o0;
|
||||||
case Float:
|
case Float:
|
||||||
return f0;
|
return f0;
|
||||||
case Double:
|
case Double:
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue