This commit is contained in:
Joseph Provino 2015-11-12 00:38:44 +00:00
commit 8e6c71d7c2
1098 changed files with 42544 additions and 11465 deletions

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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" "$@"

View file

@ -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

View file

@ -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@

View file

@ -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=

View file

@ -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

View file

@ -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=

View file

@ -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

View file

@ -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=

View file

@ -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],

View file

@ -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

View file

@ -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.

View file

@ -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"

View file

@ -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

View file

@ -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\.]*/\..*

View file

@ -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

View file

@ -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) {

View file

@ -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) {

View file

@ -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;

View file

@ -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)

View file

@ -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) $@

View file

@ -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)

View file

@ -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)

View file

@ -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);

View file

@ -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();

View file

@ -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);

View file

@ -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();
} }

View file

@ -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;

View file

@ -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) \
\ \

View file

@ -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();
} }

View file

@ -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);

View file

@ -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)); }

View file

@ -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) {

View file

@ -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, \

View file

@ -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;
} }
} }

View file

@ -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");

View file

@ -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);

View file

@ -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.

View file

@ -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

View file

@ -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);
%} %}

View file

@ -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)

View file

@ -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) {

View file

@ -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.

View file

@ -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;

View file

@ -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);
} }

View file

@ -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

View file

@ -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) \

View file

@ -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();

View file

@ -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;

View file

@ -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

View file

@ -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
}; };

View file

@ -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

View file

@ -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();
} }
} }

View file

@ -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() {

View file

@ -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

View file

@ -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

View file

@ -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 );
%} %}

View file

@ -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 );
%} %}

View file

@ -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, \

View file

@ -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;
} }
} }
} }

View file

@ -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 '-';
}
}
}

View file

@ -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;

View file

@ -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

View file

@ -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}

View file

@ -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

View file

@ -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

View file

@ -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();
} }

View file

@ -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;

View file

@ -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);
}
}

View file

@ -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.

View file

@ -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;
} }

View file

@ -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

View file

@ -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();

View file

@ -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

View file

@ -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;
} }
/** /**

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;
} }
} }

View file

@ -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;

View file

@ -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()) {

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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

View file

@ -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;
}
}

View file

@ -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;

View file

@ -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 {

View file

@ -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 {

View file

@ -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.

View file

@ -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);
}

View file

@ -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);
} }
} }

View file

@ -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);
} }
} }

View file

@ -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);
} }
} }

View file

@ -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