Merge
This commit is contained in:
commit
581b95fee3
2
.hgtags
2
.hgtags
@ -332,3 +332,5 @@ f61a63b7d1e52e307abc0bfc751203155d362ec4 jdk9-b83
|
||||
1a52a30674cd28c24d4d388150336121f2e9ddf9 jdk9-b87
|
||||
16b4968f9bb8f34371b42c0ba483d76e91ba84d8 jdk9-b88
|
||||
4a0312f2894bcbe1fd20266c8fda8d983bd2fcf6 jdk9-b89
|
||||
d131f4b8433a79408f935eff9bf92a0664229b60 jdk9-b90
|
||||
8077fd2f055d31e50b46fcf62d9c035bc385a215 jdk9-b91
|
||||
|
@ -332,3 +332,5 @@ ce5c14d97d95084504c32b9320cb33cce4235588 jdk9-b83
|
||||
fd4f4f7561074dc0dbc1772c8489c7b902b6b8a9 jdk9-b87
|
||||
0bb87e05d83e1cf41cfb7ddeb2c8eaec539fd907 jdk9-b88
|
||||
895353113f382d24e623191fdab0e29a3ce34738 jdk9-b89
|
||||
cf1dc4c035fb84693d4ae5ad818785cb4d1465d1 jdk9-b90
|
||||
122142a185381ce5cea959bf13b923d8cc333628 jdk9-b91
|
||||
|
@ -283,6 +283,7 @@ AC_DEFUN([BASIC_CHECK_LEFTOVER_OVERRIDDEN],
|
||||
# use that value, otherwise search for the tool using the supplied code snippet.
|
||||
# $1: variable to set
|
||||
# $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],
|
||||
[
|
||||
# Publish this variable in the help.
|
||||
@ -340,6 +341,7 @@ AC_DEFUN([BASIC_SETUP_TOOL],
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
$3
|
||||
fi
|
||||
])
|
||||
|
||||
@ -848,17 +850,8 @@ AC_DEFUN([BASIC_CHECK_MAKE_OUTPUT_SYNC],
|
||||
# Goes looking for a usable version of 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.
|
||||
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
|
||||
BASIC_SETUP_TOOL([MAKE],
|
||||
[
|
||||
# Try our hardest to locate a correct version of GNU make
|
||||
AC_PATH_PROGS(CHECK_GMAKE, gmake)
|
||||
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
|
||||
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
|
||||
],[
|
||||
# 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
|
||||
AC_SUBST(MAKE)
|
||||
|
@ -86,4 +86,6 @@ fi
|
||||
$RM $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" "$@"
|
||||
|
@ -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
|
||||
# that configure can use them while detecting compilers.
|
||||
# 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$OPENJDK_TARGET_OS" = xsolaris; then
|
||||
# Solaris Studio does not have a concept of sysroot. Instead we must
|
||||
# make sure the default include and lib dirs are appended to each
|
||||
# compile and link command line.
|
||||
SYSROOT_CFLAGS="-I$SYSROOT/usr/include"
|
||||
SYSROOT_LDFLAGS="-L$SYSROOT/usr/lib$OPENJDK_TARGET_CPU_ISADIR \
|
||||
-L$SYSROOT/lib$OPENJDK_TARGET_CPU_ISADIR \
|
||||
-L$SYSROOT/usr/ccs/lib$OPENJDK_TARGET_CPU_ISADIR"
|
||||
$1SYSROOT_CFLAGS="-I[$]$1SYSROOT/usr/include"
|
||||
$1SYSROOT_LDFLAGS="-L[$]$1SYSROOT/usr/lib$OPENJDK_TARGET_CPU_ISADIR \
|
||||
-L[$]$1SYSROOT/lib$OPENJDK_TARGET_CPU_ISADIR \
|
||||
-L[$]$1SYSROOT/usr/ccs/lib$OPENJDK_TARGET_CPU_ISADIR"
|
||||
fi
|
||||
elif test "x$TOOLCHAIN_TYPE" = xgcc; then
|
||||
SYSROOT_CFLAGS="--sysroot=$SYSROOT"
|
||||
SYSROOT_LDFLAGS="--sysroot=$SYSROOT"
|
||||
$1SYSROOT_CFLAGS="--sysroot=[$]$1SYSROOT"
|
||||
$1SYSROOT_LDFLAGS="--sysroot=[$]$1SYSROOT"
|
||||
elif test "x$TOOLCHAIN_TYPE" = xclang; then
|
||||
SYSROOT_CFLAGS="-isysroot $SYSROOT"
|
||||
SYSROOT_LDFLAGS="-isysroot $SYSROOT"
|
||||
$1SYSROOT_CFLAGS="-isysroot [$]$1SYSROOT"
|
||||
$1SYSROOT_LDFLAGS="-isysroot [$]$1SYSROOT"
|
||||
fi
|
||||
# Propagate the sysroot args to hotspot
|
||||
LEGACY_EXTRA_CFLAGS="$LEGACY_EXTRA_CFLAGS $SYSROOT_CFLAGS"
|
||||
LEGACY_EXTRA_CXXFLAGS="$LEGACY_EXTRA_CXXFLAGS $SYSROOT_CFLAGS"
|
||||
LEGACY_EXTRA_LDFLAGS="$LEGACY_EXTRA_LDFLAGS $SYSROOT_LDFLAGS"
|
||||
$1LEGACY_EXTRA_CFLAGS="[$]$1LEGACY_EXTRA_CFLAGS [$]$1SYSROOT_CFLAGS"
|
||||
$1LEGACY_EXTRA_CXXFLAGS="[$]$1LEGACY_EXTRA_CXXFLAGS [$]$1SYSROOT_CFLAGS"
|
||||
$1LEGACY_EXTRA_LDFLAGS="[$]$1LEGACY_EXTRA_LDFLAGS [$]$1SYSROOT_LDFLAGS"
|
||||
# The global CFLAGS and LDFLAGS variables need these for configure to function
|
||||
CFLAGS="$CFLAGS $SYSROOT_CFLAGS"
|
||||
CPPFLAGS="$CPPFLAGS $SYSROOT_CFLAGS"
|
||||
CXXFLAGS="$CXXFLAGS $SYSROOT_CFLAGS"
|
||||
LDFLAGS="$LDFLAGS $SYSROOT_LDFLAGS"
|
||||
$1CFLAGS="[$]$1CFLAGS [$]$1SYSROOT_CFLAGS"
|
||||
$1CPPFLAGS="[$]$1CPPFLAGS [$]$1SYSROOT_CFLAGS"
|
||||
$1CXXFLAGS="[$]$1CXXFLAGS [$]$1SYSROOT_CFLAGS"
|
||||
$1LDFLAGS="[$]$1LDFLAGS [$]$1SYSROOT_LDFLAGS"
|
||||
fi
|
||||
|
||||
if test "x$OPENJDK_TARGET_OS" = xmacosx; then
|
||||
# We also need -iframework<path>/System/Library/Frameworks
|
||||
SYSROOT_CFLAGS="$SYSROOT_CFLAGS -iframework $SYSROOT/System/Library/Frameworks"
|
||||
SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS -iframework $SYSROOT/System/Library/Frameworks"
|
||||
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -iframework [$]$1SYSROOT/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
|
||||
# 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"
|
||||
SYSROOT_LDFLAGS="$SYSROOT_LDFLAGS -F $SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
$1SYSROOT_CFLAGS="[$]$1SYSROOT_CFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
$1SYSROOT_LDFLAGS="[$]$1SYSROOT_LDFLAGS -F [$]$1SYSROOT/System/Library/Frameworks/JavaVM.framework/Frameworks"
|
||||
fi
|
||||
|
||||
AC_SUBST(SYSROOT_CFLAGS)
|
||||
AC_SUBST(SYSROOT_LDFLAGS)
|
||||
AC_SUBST($1SYSROOT_CFLAGS)
|
||||
AC_SUBST($1SYSROOT_LDFLAGS)
|
||||
])
|
||||
|
||||
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_CXX_JDK="$LDFLAGS_CXX_JDK -norunpath -xnolib"
|
||||
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
|
||||
|
||||
# Customize LDFLAGS for executables
|
||||
@ -808,7 +809,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_JDK],
|
||||
|
||||
if test "x$TOOLCHAIN_TYPE" = xmicrosoft; then
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} -dll -libpath:${OUTPUT_ROOT}/support/modules_libs/java.base"
|
||||
LDFLAGS_JDKLIB_SUFFIX=""
|
||||
JDKLIB_LIBS=""
|
||||
else
|
||||
LDFLAGS_JDKLIB="${LDFLAGS_JDKLIB} ${SHARED_LIBRARY_FLAGS} \
|
||||
-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"
|
||||
fi
|
||||
|
||||
LDFLAGS_JDKLIB_SUFFIX="-ljava -ljvm"
|
||||
JDKLIB_LIBS="-ljava -ljvm"
|
||||
if test "x$TOOLCHAIN_TYPE" = xsolstudio; then
|
||||
LDFLAGS_JDKLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX -lc"
|
||||
JDKLIB_LIBS="$JDKLIB_LIBS -lc"
|
||||
fi
|
||||
fi
|
||||
|
||||
AC_SUBST(LDFLAGS_JDKLIB)
|
||||
AC_SUBST(LDFLAGS_JDKEXE)
|
||||
AC_SUBST(LDFLAGS_JDKLIB_SUFFIX)
|
||||
AC_SUBST(LDFLAGS_JDKEXE_SUFFIX)
|
||||
AC_SUBST(JDKLIB_LIBS)
|
||||
AC_SUBST(JDKEXE_LIBS)
|
||||
AC_SUBST(LDFLAGS_CXX_JDK)
|
||||
|
||||
LDFLAGS_TESTLIB="$LDFLAGS_JDKLIB"
|
||||
LDFLAGS_TESTEXE="$LDFLAGS_JDKEXE"
|
||||
LDFLAGS_TESTLIB_SUFFIX="$LDFLAGS_JDKLIB_SUFFIX"
|
||||
LDFLAGS_TESTEXE_SUFFIX="$LDFLAGS_JDKEXE_SUFFIX"
|
||||
|
||||
AC_SUBST(LDFLAGS_TESTLIB)
|
||||
AC_SUBST(LDFLAGS_TESTEXE)
|
||||
AC_SUBST(LDFLAGS_TESTLIB_SUFFIX)
|
||||
AC_SUBST(LDFLAGS_TESTEXE_SUFFIX)
|
||||
])
|
||||
|
||||
# FLAGS_COMPILER_CHECK_ARGUMENTS([ARGUMENT], [RUN-IF-TRUE],
|
||||
@ -945,7 +942,16 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC],
|
||||
else
|
||||
AC_MSG_ERROR([--enable-warnings-as-errors accepts no argument])
|
||||
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(HOTSPOT_SET_WARNINGS_AS_ERRORS)
|
||||
|
||||
case "${TOOLCHAIN_TYPE}" in
|
||||
microsoft)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -33,6 +33,7 @@ include $(BASE_SPEC)
|
||||
# Additional legacy variables defined for Hotspot
|
||||
|
||||
@SET_OPENJDK@
|
||||
@HOTSPOT_SET_WARNINGS_AS_ERRORS@
|
||||
|
||||
# Legacy defines controlled by the SUPPORT_HEADLESS and SUPPORT_HEADFUL options.
|
||||
@BUILD_HEADLESS@
|
||||
|
@ -37,8 +37,10 @@ AC_DEFUN_ONCE([LIB_SETUP_ALSA],
|
||||
[specify directory for the alsa library])])
|
||||
|
||||
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
|
||||
AC_MSG_WARN([alsa not used, so --with-alsa is ignored])
|
||||
if (test "x${with_alsa}" != x && test "x${with_alsa}" != xno) || \
|
||||
(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
|
||||
ALSA_CFLAGS=
|
||||
ALSA_LIBS=
|
||||
|
@ -35,8 +35,9 @@ AC_DEFUN_ONCE([LIB_SETUP_CUPS],
|
||||
[specify directory for the cups include files])])
|
||||
|
||||
if test "x$NEEDS_LIB_CUPS" = xfalse; then
|
||||
if test "x${with_cups}" != x || test "x${with_cups_include}" != x; then
|
||||
AC_MSG_WARN([cups not used, so --with-cups is ignored])
|
||||
if (test "x${with_cups}" != x && test "x${with_cups}" != xno) || \
|
||||
(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
|
||||
CUPS_CFLAGS=
|
||||
else
|
||||
|
@ -37,8 +37,10 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBFFI],
|
||||
[specify directory for the libffi library])])
|
||||
|
||||
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
|
||||
AC_MSG_WARN([libffi not used, so --with-libffi is ignored])
|
||||
if (test "x${with_libffi}" != x && test "x${with_libffi}" != xno) || \
|
||||
(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
|
||||
LIBFFI_CFLAGS=
|
||||
LIBFFI_LIBS=
|
||||
|
@ -202,10 +202,13 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
|
||||
FREETYPE_BUNDLE_LIB_PATH=
|
||||
|
||||
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
|
||||
AC_MSG_WARN([freetype not used, so --with-freetype is ignored])
|
||||
if (test "x$with_freetype" != x && test "x$with_freetype" != xno) || \
|
||||
(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
|
||||
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])
|
||||
fi
|
||||
else
|
||||
|
@ -29,7 +29,7 @@
|
||||
AC_DEFUN_ONCE([LIB_SETUP_X11],
|
||||
[
|
||||
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])
|
||||
fi
|
||||
X_CFLAGS=
|
||||
|
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
@ -25,8 +25,7 @@
|
||||
|
||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
||||
[
|
||||
# Where are the sources. Any of these can be overridden
|
||||
# using --with-override-corba and the likes.
|
||||
# Where are the sources.
|
||||
LANGTOOLS_TOPDIR="$SRC_ROOT/langtools"
|
||||
CORBA_TOPDIR="$SRC_ROOT/corba"
|
||||
JAXP_TOPDIR="$SRC_ROOT/jaxp"
|
||||
@ -43,216 +42,20 @@ AC_DEFUN_ONCE([SRCDIRS_SETUP_TOPDIRS],
|
||||
AC_SUBST(JDK_TOPDIR)
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_ALTERNATIVE_TOPDIRS],
|
||||
[
|
||||
# This feature is no longer supported.
|
||||
|
||||
###############################################################################
|
||||
#
|
||||
# Pickup additional source for a component from outside of the source root
|
||||
# or override source for a component.
|
||||
#
|
||||
AC_ARG_WITH(add-source-root, [AS_HELP_STRING([--with-add-source-root],
|
||||
[for each and every source directory, look in this additional source root for
|
||||
the same directory; if it exists and have files in it, include it in the build])])
|
||||
|
||||
AC_ARG_WITH(override-source-root, [AS_HELP_STRING([--with-override-source-root],
|
||||
[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
|
||||
BASIC_DEPRECATED_ARG_WITH(add-source-root)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-source-root)
|
||||
BASIC_DEPRECATED_ARG_WITH(adds-and-overrides)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-langtools)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-corba)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-jaxp)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-jaxws)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-hotspot)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-nashorn)
|
||||
BASIC_DEPRECATED_ARG_WITH(override-jdk)
|
||||
])
|
||||
|
||||
AC_DEFUN_ONCE([SRCDIRS_SETUP_OUTPUT_DIRS],
|
||||
|
@ -113,10 +113,6 @@ endif
|
||||
SYSROOT_CFLAGS := @SYSROOT_CFLAGS@
|
||||
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)
|
||||
TOPDIR:=@TOPDIR@
|
||||
# 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_JDKLIB:=@LDFLAGS_JDKLIB@
|
||||
LDFLAGS_JDKLIB_SUFFIX:=@LDFLAGS_JDKLIB_SUFFIX@
|
||||
JDKLIB_LIBS:=@JDKLIB_LIBS@
|
||||
|
||||
# LDFLAGS used to link the jdk native launchers (C-code)
|
||||
LDFLAGS_JDKEXE:=@LDFLAGS_JDKEXE@
|
||||
LDFLAGS_JDKEXE_SUFFIX:=@LDFLAGS_JDKEXE_SUFFIX@
|
||||
JDKEXE_LIBS:=@JDKEXE_LIBS@
|
||||
|
||||
# LDFLAGS specific to C++ linking.
|
||||
LDFLAGS_CXX_JDK:=@LDFLAGS_CXX_JDK@
|
||||
@ -360,9 +356,7 @@ CXXFLAGS_TESTLIB:=@CXXFLAGS_TESTLIB@
|
||||
CFLAGS_TESTEXE:=@CFLAGS_TESTEXE@
|
||||
CXXFLAGS_TESTEXE:=@CXXFLAGS_TESTEXE@
|
||||
LDFLAGS_TESTLIB:=@LDFLAGS_TESTLIB@
|
||||
LDFLAGS_TESTLIB_SUFFIX:=@LDFLAGS_TESTLIB_SUFFIX@
|
||||
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 platform.
|
||||
@ -550,34 +544,6 @@ LIBZIP_CAN_USE_MMAP:=@LIBZIP_CAN_USE_MMAP@
|
||||
MSVCR_DLL:=@MSVCR_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
|
||||
|
@ -647,17 +647,68 @@ AC_DEFUN_ONCE([TOOLCHAIN_SETUP_BUILD_COMPILERS],
|
||||
# path, otherwise we might pick up cross-compilers which don't use standard
|
||||
# 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!
|
||||
# If we do that, we can do this detection before POST_DETECTION, and still
|
||||
# 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_PATH_PROGS(BUILD_CXX, [cl CC g++])
|
||||
BASIC_REQUIRE_PROGS(BUILD_CXX, [cl CC g++])
|
||||
BASIC_FIXUP_EXECUTABLE(BUILD_CXX)
|
||||
BASIC_PATH_PROGS(BUILD_LD, ld)
|
||||
BASIC_FIXUP_EXECUTABLE(BUILD_LD)
|
||||
BUILD_SYSROOT_CFLAGS=""
|
||||
BUILD_SYSROOT_LDFLAGS=""
|
||||
BUILD_LD="$BUILD_CC"
|
||||
|
||||
PATH="$OLDPATH"
|
||||
else
|
||||
# If we are not cross compiling, use the normal target compilers for
|
||||
# building the build platform executables.
|
||||
|
@ -989,7 +989,7 @@ if [ "$OPENJDK_TARGET_OS" = "windows" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
THIS="$( cd "$( dirname "$0" )" > /dev/null && pwd )"
|
||||
THIS="$SCRIPT_DIR"
|
||||
echo "$THIS"
|
||||
THIS_SCRIPT="$0"
|
||||
|
||||
|
@ -332,3 +332,5 @@ df70bb200356fec686681f0295c50cc3ed43c3b3 jdk9-b84
|
||||
a5c40ac9b916ff44d512ee764fa919ed2097e149 jdk9-b87
|
||||
00f48ecbc09915f793d9e5ad74ab0b25f2549bf5 jdk9-b88
|
||||
c847a53b38d2fffb87afc483c74db05eced9b4f4 jdk9-b89
|
||||
29cc8228d62319af21cad7c90817671e0813b6bd jdk9-b90
|
||||
75843e0a9371d445a3c9b440bab85e50b5dc287c jdk9-b91
|
||||
|
@ -492,3 +492,5 @@ e9e63d93bbfe2c6c23447e2c1f5cc71c98671cba jdk9-b79
|
||||
d7ffd16382fe7071181b967932b47cff6d1312e1 jdk9-b87
|
||||
bc48b669bc6610fac97e16593050c0f559cf6945 jdk9-b88
|
||||
20dff0211deda8d5877fda0e80b6d165ab93c6c2 jdk9-b89
|
||||
7fe46dc64bb3a8df554b24cde0153ffb24f39c5e jdk9-b90
|
||||
3fd5c2ca4c20c183628b6dbeb8df821a961419e3 jdk9-b91
|
||||
|
@ -97,6 +97,7 @@ else
|
||||
# prints the numbers (e.g. "2.95", "3.2.1")
|
||||
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_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CLANG), true)
|
||||
@ -326,6 +327,10 @@ ifeq ($(USE_CLANG), true)
|
||||
$(error "Update compiler workarounds for Clang $(CC_VER_MAJOR).$(CC_VER_MINOR)")
|
||||
endif
|
||||
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.
|
||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||
|
@ -109,7 +109,11 @@ $(GENSRC_DIR)/_providers_converted: $(GENSRC_DIR)/_gensrc_proc_done
|
||||
($(CD) $(GENSRC_DIR)/META-INF/jvmci.providers && \
|
||||
for i in $$($(LS)); do \
|
||||
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)
|
||||
$(TOUCH) $@
|
||||
|
||||
|
@ -60,6 +60,7 @@ else
|
||||
# prints the numbers (e.g. "2.95", "3.2.1")
|
||||
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_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
|
||||
endif
|
||||
|
||||
ifeq ($(USE_CLANG), true)
|
||||
@ -264,6 +265,10 @@ ifeq ($(USE_CLANG), true)
|
||||
OPT_CFLAGS/loopTransform.o += $(OPT_CFLAGS/NOOPT)
|
||||
endif
|
||||
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.
|
||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||
|
@ -39,6 +39,7 @@ Compiler = gcc
|
||||
# prints the numbers (e.g. "2.95", "3.2.1")
|
||||
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_MICRO := $(shell $(CC) -dumpversion | sed 's/egcs-//' | cut -d'.' -f3)
|
||||
|
||||
# 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)
|
||||
endif
|
||||
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.
|
||||
ifeq ($(shell expr $(CC_VER_MAJOR) = 4 \& $(CC_VER_MINOR) = 3), 1)
|
||||
OPT_CFLAGS/mulnode.o += $(OPT_CFLAGS/NOOPT)
|
||||
|
@ -59,9 +59,9 @@ define_pd_global(intx, InlineFrequencyCount, 100);
|
||||
#define DEFAULT_STACK_RED_PAGES (1)
|
||||
#define DEFAULT_STACK_SHADOW_PAGES (4 DEBUG_ONLY(+5))
|
||||
|
||||
#define MIN_STACK_YELLOW_PAGES DEFAULT_STACK_YELLOW_PAGES
|
||||
#define MIN_STACK_RED_PAGES DEFAULT_STACK_RED_PAGES
|
||||
#define MIN_STACK_SHADOW_PAGES DEFAULT_STACK_SHADOW_PAGES
|
||||
#define MIN_STACK_YELLOW_PAGES 1
|
||||
#define MIN_STACK_RED_PAGES 1
|
||||
#define MIN_STACK_SHADOW_PAGES 1
|
||||
|
||||
define_pd_global(intx, StackYellowPages, DEFAULT_STACK_YELLOW_PAGES);
|
||||
define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES);
|
||||
|
@ -1777,7 +1777,7 @@ nmethod* SharedRuntime::generate_native_wrapper(MacroAssembler* masm,
|
||||
const Register obj_reg = r19; // Will contain the oop
|
||||
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 tmp = c_rarg3;
|
||||
const Register tmp = lr;
|
||||
|
||||
Label slow_path_lock;
|
||||
Label lock_done;
|
||||
|
@ -1539,7 +1539,6 @@ void Assembler::cmpl(Register dst, Register src) {
|
||||
emit_arith(0x3B, 0xC0, dst, src);
|
||||
}
|
||||
|
||||
|
||||
void Assembler::cmpl(Register dst, Address src) {
|
||||
InstructionMark im(this);
|
||||
prefix(src, dst);
|
||||
@ -2125,6 +2124,16 @@ void Assembler::movb(Register dst, Address 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) {
|
||||
NOT_LP64(assert(VM_Version::supports_evex(), ""));
|
||||
int encode = kreg_prefix_and_encode(dst, knoreg, src, VEX_SIMD_NONE,
|
||||
@ -3403,6 +3412,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() {
|
||||
emit_int8((unsigned char)0x0F);
|
||||
emit_int8((unsigned char)0x31);
|
||||
@ -6326,6 +6349,26 @@ void Assembler::emit_vex_arith_q(int opcode, XMMRegister dst, XMMRegister nds, X
|
||||
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
|
||||
|
||||
void Assembler::incl(Register dst) {
|
||||
|
@ -1504,6 +1504,8 @@ private:
|
||||
void movb(Address dst, int imm8);
|
||||
void movb(Register dst, Address src);
|
||||
|
||||
void movddup(XMMRegister dst, XMMRegister src);
|
||||
|
||||
void kmovql(KRegister dst, KRegister src);
|
||||
void kmovql(KRegister dst, Register src);
|
||||
void kmovdl(KRegister dst, Register src);
|
||||
@ -1768,6 +1770,10 @@ private:
|
||||
|
||||
void rcrq(Register dst, int imm8);
|
||||
|
||||
void rcpps(XMMRegister dst, XMMRegister src);
|
||||
|
||||
void rcpss(XMMRegister dst, XMMRegister src);
|
||||
|
||||
void rdtsc();
|
||||
|
||||
void ret(int imm16);
|
||||
@ -2141,6 +2147,11 @@ private:
|
||||
// runtime code and native libraries.
|
||||
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:
|
||||
// Next instructions require address alignment 16 bytes SSE mode.
|
||||
// They should be called only from corresponding MacroAssembler instructions.
|
||||
|
@ -2440,7 +2440,6 @@ void LIR_Assembler::intrinsic_op(LIR_Code code, LIR_Opr value, LIR_Opr unused, L
|
||||
} else if (value->is_double_fpu()) {
|
||||
assert(value->fpu_regnrLo() == 0 && dest->fpu_regnrLo() == 0, "both must be on TOS");
|
||||
switch(code) {
|
||||
case lir_log : __ flog() ; break;
|
||||
case lir_log10 : __ flog10() ; break;
|
||||
case lir_abs : __ fabs() ; break;
|
||||
case lir_sqrt : __ fsqrt(); break;
|
||||
|
@ -809,8 +809,8 @@ void LIRGenerator::do_CompareAndSwap(Intrinsic* x, ValueType* type) {
|
||||
void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
||||
assert(x->number_of_arguments() == 1 || (x->number_of_arguments() == 2 && x->id() == vmIntrinsics::_dpow), "wrong type");
|
||||
|
||||
if (x->id() == vmIntrinsics::_dexp) {
|
||||
do_ExpIntrinsic(x);
|
||||
if (x->id() == vmIntrinsics::_dexp || x->id() == vmIntrinsics::_dlog) {
|
||||
do_LibmIntrinsic(x);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -822,7 +822,6 @@ void LIRGenerator::do_MathIntrinsic(Intrinsic* x) {
|
||||
case vmIntrinsics::_dsin:
|
||||
case vmIntrinsics::_dcos:
|
||||
case vmIntrinsics::_dtan:
|
||||
case vmIntrinsics::_dlog:
|
||||
case vmIntrinsics::_dlog10:
|
||||
case vmIntrinsics::_dpow:
|
||||
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::_dcos: __ cos (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::_dpow: __ pow (calc_input, calc_input2, calc_result, tmp1, tmp2, FrameMap::rax_opr, FrameMap::rcx_opr, FrameMap::rdx_opr); break;
|
||||
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);
|
||||
value.set_destroys_register();
|
||||
|
||||
@ -900,13 +898,33 @@ void LIRGenerator::do_ExpIntrinsic(Intrinsic* x) {
|
||||
#ifndef _LP64
|
||||
LIR_Opr tmp = FrameMap::fpu0_double_opr;
|
||||
result_reg = tmp;
|
||||
if (VM_Version::supports_sse2()) {
|
||||
__ 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());
|
||||
switch(x->id()) {
|
||||
case vmIntrinsics::_dexp:
|
||||
if (VM_Version::supports_sse2()) {
|
||||
__ 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
|
||||
__ 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
|
||||
__ move(result_reg, calc_result);
|
||||
}
|
||||
|
@ -786,7 +786,6 @@ void FpuStackAllocator::handle_op2(LIR_Op2* op2) {
|
||||
break;
|
||||
}
|
||||
|
||||
case lir_log:
|
||||
case lir_log10: {
|
||||
// log and log10 need one temporary fpu stack slot, so
|
||||
// there is one temporary registers stored in temp of the
|
||||
|
@ -132,10 +132,15 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
|
||||
__ fabs();
|
||||
break;
|
||||
case Interpreter::java_lang_math_log:
|
||||
__ flog();
|
||||
// Store to stack to convert 80bit precision back to 64bits
|
||||
__ push_fTOS();
|
||||
__ pop_fTOS();
|
||||
__ subptr(rsp, 2 * wordSize);
|
||||
__ fstp_d(Address(rsp, 0));
|
||||
if (VM_Version::supports_sse2()) {
|
||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, StubRoutines::dlog())));
|
||||
}
|
||||
else {
|
||||
__ call(RuntimeAddress(CAST_FROM_FN_PTR(address, SharedRuntime::dlog)));
|
||||
}
|
||||
__ addptr(rsp, 2 * wordSize);
|
||||
break;
|
||||
case Interpreter::java_lang_math_log10:
|
||||
__ flog10();
|
||||
|
@ -253,6 +253,9 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
|
||||
} else if (kind == Interpreter::java_lang_math_exp) {
|
||||
__ movdbl(xmm0, Address(rsp, wordSize));
|
||||
__ 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 {
|
||||
__ fld_d(Address(rsp, wordSize));
|
||||
switch (kind) {
|
||||
@ -268,9 +271,6 @@ address InterpreterGenerator::generate_math_entry(AbstractInterpreter::MethodKin
|
||||
case Interpreter::java_lang_math_abs:
|
||||
__ fabs();
|
||||
break;
|
||||
case Interpreter::java_lang_math_log:
|
||||
__ flog();
|
||||
break;
|
||||
case Interpreter::java_lang_math_log10:
|
||||
__ flog10();
|
||||
break;
|
||||
|
@ -56,6 +56,8 @@ class MacroAssembler: public Assembler {
|
||||
#define VIRTUAL virtual
|
||||
#endif
|
||||
|
||||
#define COMMA ,
|
||||
|
||||
VIRTUAL void call_VM_leaf_base(
|
||||
address entry_point, // the entry point
|
||||
int number_of_arguments // the number of arguments to pop after the call
|
||||
@ -910,6 +912,11 @@ class MacroAssembler: public Assembler {
|
||||
void fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3,
|
||||
XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7,
|
||||
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 restore_precision();
|
||||
|
||||
|
@ -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:
|
||||
@ -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
|
||||
|
||||
ALIGNED_(16) juint _cv[] =
|
||||
@ -409,6 +408,7 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
|
||||
bind(B1_5);
|
||||
addq(rsp, 24);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _LP64
|
||||
@ -675,3 +675,614 @@ void MacroAssembler::fast_exp(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xm
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/******************************************************************************/
|
||||
// ALGORITHM DESCRIPTION - LOG()
|
||||
// ---------------------
|
||||
//
|
||||
// x=2^k * mx, mx in [1,2)
|
||||
//
|
||||
// Get B~1/mx based on the output of rcpss instruction (B0)
|
||||
// B = int((B0*2^7+0.5))/2^7
|
||||
//
|
||||
// Reduced argument: r=B*mx-1.0 (computed accurately in high and low parts)
|
||||
//
|
||||
// Result: k*log(2) - log(B) + p(r) if |x-1| >= small value (2^-6) and
|
||||
// p(r) is a degree 7 polynomial
|
||||
// -log(B) read from data table (high, low parts)
|
||||
// Result is formed from high and low parts
|
||||
//
|
||||
// Special cases:
|
||||
// log(NaN) = quiet NaN, and raise invalid exception
|
||||
// log(+INF) = that INF
|
||||
// log(0) = -INF with divide-by-zero exception raised
|
||||
// log(1) = +0
|
||||
// log(x) = NaN with invalid exception raised if x < -0, including -INF
|
||||
//
|
||||
/******************************************************************************/
|
||||
|
||||
#ifdef _LP64
|
||||
|
||||
ALIGNED_(16) juint _L_tbl[] =
|
||||
{
|
||||
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
|
||||
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
|
||||
0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
|
||||
0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
|
||||
0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
|
||||
0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
|
||||
0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
|
||||
0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
|
||||
0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
|
||||
0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
|
||||
0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
|
||||
0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
|
||||
0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
|
||||
0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
|
||||
0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
|
||||
0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
|
||||
0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
|
||||
0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
|
||||
0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
|
||||
0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
|
||||
0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
|
||||
0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
|
||||
0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
|
||||
0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
|
||||
0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
|
||||
0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
|
||||
0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
|
||||
0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
|
||||
0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
|
||||
0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
|
||||
0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
|
||||
0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
|
||||
0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
|
||||
0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
|
||||
0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
|
||||
0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
|
||||
0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
|
||||
0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
|
||||
0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
|
||||
0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
|
||||
0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
|
||||
0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
|
||||
0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
|
||||
0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
|
||||
0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
|
||||
0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
|
||||
0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
|
||||
0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
|
||||
0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
|
||||
0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
|
||||
0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
|
||||
0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
|
||||
0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
|
||||
0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
|
||||
0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
|
||||
0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
|
||||
0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
|
||||
0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
|
||||
0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
|
||||
0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
|
||||
0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
|
||||
0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
|
||||
0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
|
||||
0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
|
||||
0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
|
||||
0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
|
||||
0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
|
||||
0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
|
||||
0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
|
||||
0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
|
||||
0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
|
||||
0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
|
||||
0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
|
||||
0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
|
||||
0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
|
||||
0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
|
||||
0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
|
||||
0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
|
||||
0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
|
||||
0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
|
||||
0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
|
||||
0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
|
||||
0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
|
||||
0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
|
||||
0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
|
||||
0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
|
||||
0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
|
||||
0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
|
||||
0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
|
||||
0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
|
||||
0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
|
||||
0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
|
||||
0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
|
||||
0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
|
||||
0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
|
||||
0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
|
||||
0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
|
||||
0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
|
||||
0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
|
||||
0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
|
||||
0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
|
||||
0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
|
||||
0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
|
||||
0x80000000UL
|
||||
};
|
||||
|
||||
ALIGNED_(16) juint _log2[] =
|
||||
{
|
||||
0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL
|
||||
};
|
||||
|
||||
ALIGNED_(16) juint _coeff[] =
|
||||
{
|
||||
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
|
||||
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
|
||||
0x00000000UL, 0xbfe00000UL
|
||||
};
|
||||
|
||||
//registers,
|
||||
// input: xmm0
|
||||
// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
|
||||
// rax, rdx, rcx, r8, r11
|
||||
|
||||
void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp1, Register tmp2) {
|
||||
Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
|
||||
Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
|
||||
Label L_2TAG_PACKET_8_0_2;
|
||||
Label L_2TAG_PACKET_12_0_2, L_2TAG_PACKET_13_0_2, B1_3, B1_5, start;
|
||||
|
||||
assert_different_registers(tmp1, tmp2, eax, ecx, edx);
|
||||
jmp(start);
|
||||
address L_tbl = (address)_L_tbl;
|
||||
address log2 = (address)_log2;
|
||||
address coeff = (address)_coeff;
|
||||
|
||||
bind(start);
|
||||
subq(rsp, 24);
|
||||
movsd(Address(rsp, 0), xmm0);
|
||||
mov64(rax, 0x3ff0000000000000);
|
||||
movdq(xmm2, rax);
|
||||
mov64(rdx, 0x77f0000000000000);
|
||||
movdq(xmm3, rdx);
|
||||
movl(ecx, 32768);
|
||||
movdl(xmm4, rcx);
|
||||
mov64(tmp1, 0xffffe00000000000);
|
||||
movdq(xmm5, tmp1);
|
||||
movdqu(xmm1, xmm0);
|
||||
pextrw(eax, xmm0, 3);
|
||||
por(xmm0, xmm2);
|
||||
movl(ecx, 16352);
|
||||
psrlq(xmm0, 27);
|
||||
lea(tmp2, ExternalAddress(L_tbl));
|
||||
psrld(xmm0, 2);
|
||||
rcpps(xmm0, xmm0);
|
||||
psllq(xmm1, 12);
|
||||
pshufd(xmm6, xmm5, 228);
|
||||
psrlq(xmm1, 12);
|
||||
subl(eax, 16);
|
||||
cmpl(eax, 32736);
|
||||
jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_1_0_2);
|
||||
paddd(xmm0, xmm4);
|
||||
por(xmm1, xmm3);
|
||||
movdl(edx, xmm0);
|
||||
psllq(xmm0, 29);
|
||||
pand(xmm5, xmm1);
|
||||
pand(xmm0, xmm6);
|
||||
subsd(xmm1, xmm5);
|
||||
mulpd(xmm5, xmm0);
|
||||
andl(eax, 32752);
|
||||
subl(eax, ecx);
|
||||
cvtsi2sdl(xmm7, eax);
|
||||
mulsd(xmm1, xmm0);
|
||||
movq(xmm6, ExternalAddress(log2)); // 0xfefa3800UL, 0x3fa62e42UL
|
||||
movdqu(xmm3, ExternalAddress(coeff)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
|
||||
subsd(xmm5, xmm2);
|
||||
andl(edx, 16711680);
|
||||
shrl(edx, 12);
|
||||
movdqu(xmm0, Address(tmp2, edx));
|
||||
movdqu(xmm4, ExternalAddress(16 + coeff)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
|
||||
addsd(xmm1, xmm5);
|
||||
movdqu(xmm2, ExternalAddress(32 + coeff)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
|
||||
mulsd(xmm6, xmm7);
|
||||
movddup(xmm5, xmm1);
|
||||
mulsd(xmm7, ExternalAddress(8 + log2)); // 0x93c76730UL, 0x3ceef357UL
|
||||
mulsd(xmm3, xmm1);
|
||||
addsd(xmm0, xmm6);
|
||||
mulpd(xmm4, xmm5);
|
||||
mulpd(xmm5, xmm5);
|
||||
movddup(xmm6, xmm0);
|
||||
addsd(xmm0, xmm1);
|
||||
addpd(xmm4, xmm2);
|
||||
mulpd(xmm3, xmm5);
|
||||
subsd(xmm6, xmm0);
|
||||
mulsd(xmm4, xmm1);
|
||||
pshufd(xmm2, xmm0, 238);
|
||||
addsd(xmm1, xmm6);
|
||||
mulsd(xmm5, xmm5);
|
||||
addsd(xmm7, xmm2);
|
||||
addpd(xmm4, xmm3);
|
||||
addsd(xmm1, xmm7);
|
||||
mulpd(xmm4, xmm5);
|
||||
addsd(xmm1, xmm4);
|
||||
pshufd(xmm5, xmm4, 238);
|
||||
addsd(xmm1, xmm5);
|
||||
addsd(xmm0, xmm1);
|
||||
jmp(B1_5);
|
||||
|
||||
bind(L_2TAG_PACKET_0_0_2);
|
||||
movq(xmm0, Address(rsp, 0));
|
||||
movq(xmm1, Address(rsp, 0));
|
||||
addl(eax, 16);
|
||||
cmpl(eax, 32768);
|
||||
jcc(Assembler::aboveEqual, L_2TAG_PACKET_2_0_2);
|
||||
cmpl(eax, 16);
|
||||
jcc(Assembler::below, L_2TAG_PACKET_3_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_4_0_2);
|
||||
addsd(xmm0, xmm0);
|
||||
jmp(B1_5);
|
||||
|
||||
bind(L_2TAG_PACKET_5_0_2);
|
||||
jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
|
||||
cmpl(edx, 0);
|
||||
jcc(Assembler::above, L_2TAG_PACKET_4_0_2);
|
||||
jmp(L_2TAG_PACKET_6_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_3_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
addsd(xmm1, xmm0);
|
||||
movdl(edx, xmm1);
|
||||
psrlq(xmm1, 32);
|
||||
movdl(ecx, xmm1);
|
||||
orl(edx, ecx);
|
||||
cmpl(edx, 0);
|
||||
jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
movl(eax, 18416);
|
||||
pinsrw(xmm1, eax, 3);
|
||||
mulsd(xmm0, xmm1);
|
||||
movdqu(xmm1, xmm0);
|
||||
pextrw(eax, xmm0, 3);
|
||||
por(xmm0, xmm2);
|
||||
psrlq(xmm0, 27);
|
||||
movl(ecx, 18416);
|
||||
psrld(xmm0, 2);
|
||||
rcpps(xmm0, xmm0);
|
||||
psllq(xmm1, 12);
|
||||
pshufd(xmm6, xmm5, 228);
|
||||
psrlq(xmm1, 12);
|
||||
jmp(L_2TAG_PACKET_1_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_2_0_2);
|
||||
movdl(edx, xmm1);
|
||||
psrlq(xmm1, 32);
|
||||
movdl(ecx, xmm1);
|
||||
addl(ecx, ecx);
|
||||
cmpl(ecx, -2097152);
|
||||
jcc(Assembler::aboveEqual, L_2TAG_PACKET_5_0_2);
|
||||
orl(edx, ecx);
|
||||
cmpl(edx, 0);
|
||||
jcc(Assembler::equal, L_2TAG_PACKET_7_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_6_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
xorpd(xmm0, xmm0);
|
||||
movl(eax, 32752);
|
||||
pinsrw(xmm1, eax, 3);
|
||||
mulsd(xmm0, xmm1);
|
||||
movl(Address(rsp, 16), 3);
|
||||
jmp(L_2TAG_PACKET_8_0_2);
|
||||
bind(L_2TAG_PACKET_7_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
xorpd(xmm0, xmm0);
|
||||
movl(eax, 49136);
|
||||
pinsrw(xmm0, eax, 3);
|
||||
divsd(xmm0, xmm1);
|
||||
movl(Address(rsp, 16), 2);
|
||||
|
||||
bind(L_2TAG_PACKET_8_0_2);
|
||||
movq(Address(rsp, 8), xmm0);
|
||||
|
||||
bind(B1_3);
|
||||
movq(xmm0, Address(rsp, 8));
|
||||
|
||||
bind(B1_5);
|
||||
addq(rsp, 24);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef _LP64
|
||||
|
||||
ALIGNED_(16) juint _static_const_table_log[] =
|
||||
{
|
||||
0xfefa3800UL, 0x3fe62e42UL, 0x93c76730UL, 0x3d2ef357UL, 0xaa241800UL,
|
||||
0x3fe5ee82UL, 0x0cda46beUL, 0x3d220238UL, 0x5c364800UL, 0x3fe5af40UL,
|
||||
0xac10c9fbUL, 0x3d2dfa63UL, 0x26bb8c00UL, 0x3fe5707aUL, 0xff3303ddUL,
|
||||
0x3d09980bUL, 0x26867800UL, 0x3fe5322eUL, 0x5d257531UL, 0x3d05ccc4UL,
|
||||
0x835a5000UL, 0x3fe4f45aUL, 0x6d93b8fbUL, 0xbd2e6c51UL, 0x6f970c00UL,
|
||||
0x3fe4b6fdUL, 0xed4c541cUL, 0x3cef7115UL, 0x27e8a400UL, 0x3fe47a15UL,
|
||||
0xf94d60aaUL, 0xbd22cb6aUL, 0xf2f92400UL, 0x3fe43d9fUL, 0x481051f7UL,
|
||||
0xbcfd984fUL, 0x2125cc00UL, 0x3fe4019cUL, 0x30f0c74cUL, 0xbd26ce79UL,
|
||||
0x0c36c000UL, 0x3fe3c608UL, 0x7cfe13c2UL, 0xbd02b736UL, 0x17197800UL,
|
||||
0x3fe38ae2UL, 0xbb5569a4UL, 0xbd218b7aUL, 0xad9d8c00UL, 0x3fe35028UL,
|
||||
0x9527e6acUL, 0x3d10b83fUL, 0x44340800UL, 0x3fe315daUL, 0xc5a0ed9cUL,
|
||||
0xbd274e93UL, 0x57b0e000UL, 0x3fe2dbf5UL, 0x07b9dc11UL, 0xbd17a6e5UL,
|
||||
0x6d0ec000UL, 0x3fe2a278UL, 0xe797882dUL, 0x3d206d2bUL, 0x1134dc00UL,
|
||||
0x3fe26962UL, 0x05226250UL, 0xbd0b61f1UL, 0xd8bebc00UL, 0x3fe230b0UL,
|
||||
0x6e48667bUL, 0x3d12fc06UL, 0x5fc61800UL, 0x3fe1f863UL, 0xc9fe81d3UL,
|
||||
0xbd2a7242UL, 0x49ae6000UL, 0x3fe1c078UL, 0xed70e667UL, 0x3cccacdeUL,
|
||||
0x40f23c00UL, 0x3fe188eeUL, 0xf8ab4650UL, 0x3d14cc4eUL, 0xf6f29800UL,
|
||||
0x3fe151c3UL, 0xa293ae49UL, 0xbd2edd97UL, 0x23c75c00UL, 0x3fe11af8UL,
|
||||
0xbb9ddcb2UL, 0xbd258647UL, 0x8611cc00UL, 0x3fe0e489UL, 0x07801742UL,
|
||||
0x3d1c2998UL, 0xe2d05400UL, 0x3fe0ae76UL, 0x887e7e27UL, 0x3d1f486bUL,
|
||||
0x0533c400UL, 0x3fe078bfUL, 0x41edf5fdUL, 0x3d268122UL, 0xbe760400UL,
|
||||
0x3fe04360UL, 0xe79539e0UL, 0xbd04c45fUL, 0xe5b20800UL, 0x3fe00e5aUL,
|
||||
0xb1727b1cUL, 0xbd053ba3UL, 0xaf7a4800UL, 0x3fdfb358UL, 0x3c164935UL,
|
||||
0x3d0085faUL, 0xee031800UL, 0x3fdf4aa7UL, 0x6f014a8bUL, 0x3d12cde5UL,
|
||||
0x56b41000UL, 0x3fdee2a1UL, 0x5a470251UL, 0x3d2f27f4UL, 0xc3ddb000UL,
|
||||
0x3fde7b42UL, 0x5372bd08UL, 0xbd246550UL, 0x1a272800UL, 0x3fde148aUL,
|
||||
0x07322938UL, 0xbd1326b2UL, 0x484c9800UL, 0x3fddae75UL, 0x60dc616aUL,
|
||||
0xbd1ea42dUL, 0x46def800UL, 0x3fdd4902UL, 0xe9a767a8UL, 0x3d235bafUL,
|
||||
0x18064800UL, 0x3fdce42fUL, 0x3ec7a6b0UL, 0xbd0797c3UL, 0xc7455800UL,
|
||||
0x3fdc7ff9UL, 0xc15249aeUL, 0xbd29b6ddUL, 0x693fa000UL, 0x3fdc1c60UL,
|
||||
0x7fe8e180UL, 0x3d2cec80UL, 0x1b80e000UL, 0x3fdbb961UL, 0xf40a666dUL,
|
||||
0x3d27d85bUL, 0x04462800UL, 0x3fdb56faUL, 0x2d841995UL, 0x3d109525UL,
|
||||
0x5248d000UL, 0x3fdaf529UL, 0x52774458UL, 0xbd217cc5UL, 0x3c8ad800UL,
|
||||
0x3fda93edUL, 0xbea77a5dUL, 0x3d1e36f2UL, 0x0224f800UL, 0x3fda3344UL,
|
||||
0x7f9d79f5UL, 0x3d23c645UL, 0xea15f000UL, 0x3fd9d32bUL, 0x10d0c0b0UL,
|
||||
0xbd26279eUL, 0x43135800UL, 0x3fd973a3UL, 0xa502d9f0UL, 0xbd152313UL,
|
||||
0x635bf800UL, 0x3fd914a8UL, 0x2ee6307dUL, 0xbd1766b5UL, 0xa88b3000UL,
|
||||
0x3fd8b639UL, 0xe5e70470UL, 0xbd205ae1UL, 0x776dc800UL, 0x3fd85855UL,
|
||||
0x3333778aUL, 0x3d2fd56fUL, 0x3bd81800UL, 0x3fd7fafaUL, 0xc812566aUL,
|
||||
0xbd272090UL, 0x687cf800UL, 0x3fd79e26UL, 0x2efd1778UL, 0x3d29ec7dUL,
|
||||
0x76c67800UL, 0x3fd741d8UL, 0x49dc60b3UL, 0x3d2d8b09UL, 0xe6af1800UL,
|
||||
0x3fd6e60eUL, 0x7c222d87UL, 0x3d172165UL, 0x3e9c6800UL, 0x3fd68ac8UL,
|
||||
0x2756eba0UL, 0x3d20a0d3UL, 0x0b3ab000UL, 0x3fd63003UL, 0xe731ae00UL,
|
||||
0xbd2db623UL, 0xdf596000UL, 0x3fd5d5bdUL, 0x08a465dcUL, 0xbd0a0b2aUL,
|
||||
0x53c8d000UL, 0x3fd57bf7UL, 0xee5d40efUL, 0x3d1fadedUL, 0x0738a000UL,
|
||||
0x3fd522aeUL, 0x8164c759UL, 0x3d2ebe70UL, 0x9e173000UL, 0x3fd4c9e0UL,
|
||||
0x1b0ad8a4UL, 0xbd2e2089UL, 0xc271c800UL, 0x3fd4718dUL, 0x0967d675UL,
|
||||
0xbd2f27ceUL, 0x23d5e800UL, 0x3fd419b4UL, 0xec90e09dUL, 0x3d08e436UL,
|
||||
0x77333000UL, 0x3fd3c252UL, 0xb606bd5cUL, 0x3d183b54UL, 0x76be1000UL,
|
||||
0x3fd36b67UL, 0xb0f177c8UL, 0x3d116ecdUL, 0xe1d36000UL, 0x3fd314f1UL,
|
||||
0xd3213cb8UL, 0xbd28e27aUL, 0x7cdc9000UL, 0x3fd2bef0UL, 0x4a5004f4UL,
|
||||
0x3d2a9cfaUL, 0x1134d800UL, 0x3fd26962UL, 0xdf5bb3b6UL, 0x3d2c93c1UL,
|
||||
0x6d0eb800UL, 0x3fd21445UL, 0xba46baeaUL, 0x3d0a87deUL, 0x635a6800UL,
|
||||
0x3fd1bf99UL, 0x5147bdb7UL, 0x3d2ca6edUL, 0xcbacf800UL, 0x3fd16b5cUL,
|
||||
0xf7a51681UL, 0x3d2b9acdUL, 0x8227e800UL, 0x3fd1178eUL, 0x63a5f01cUL,
|
||||
0xbd2c210eUL, 0x67616000UL, 0x3fd0c42dUL, 0x163ceae9UL, 0x3d27188bUL,
|
||||
0x604d5800UL, 0x3fd07138UL, 0x16ed4e91UL, 0x3cf89cdbUL, 0x5626c800UL,
|
||||
0x3fd01eaeUL, 0x1485e94aUL, 0xbd16f08cUL, 0x6cb3b000UL, 0x3fcf991cUL,
|
||||
0xca0cdf30UL, 0x3d1bcbecUL, 0xe4dd0000UL, 0x3fcef5adUL, 0x65bb8e11UL,
|
||||
0xbcca2115UL, 0xffe71000UL, 0x3fce530eUL, 0x6041f430UL, 0x3cc21227UL,
|
||||
0xb0d49000UL, 0x3fcdb13dUL, 0xf715b035UL, 0xbd2aff2aUL, 0xf2656000UL,
|
||||
0x3fcd1037UL, 0x75b6f6e4UL, 0xbd084a7eUL, 0xc6f01000UL, 0x3fcc6ffbUL,
|
||||
0xc5962bd2UL, 0xbcf1ec72UL, 0x383be000UL, 0x3fcbd087UL, 0x595412b6UL,
|
||||
0xbd2d4bc4UL, 0x575bd000UL, 0x3fcb31d8UL, 0x4eace1aaUL, 0xbd0c358dUL,
|
||||
0x3c8ae000UL, 0x3fca93edUL, 0x50562169UL, 0xbd287243UL, 0x07089000UL,
|
||||
0x3fc9f6c4UL, 0x6865817aUL, 0x3d29904dUL, 0xdcf70000UL, 0x3fc95a5aUL,
|
||||
0x58a0ff6fUL, 0x3d07f228UL, 0xeb390000UL, 0x3fc8beafUL, 0xaae92cd1UL,
|
||||
0xbd073d54UL, 0x6551a000UL, 0x3fc823c1UL, 0x9a631e83UL, 0x3d1e0ddbUL,
|
||||
0x85445000UL, 0x3fc7898dUL, 0x70914305UL, 0xbd1c6610UL, 0x8b757000UL,
|
||||
0x3fc6f012UL, 0xe59c21e1UL, 0xbd25118dUL, 0xbe8c1000UL, 0x3fc6574eUL,
|
||||
0x2c3c2e78UL, 0x3d19cf8bUL, 0x6b544000UL, 0x3fc5bf40UL, 0xeb68981cUL,
|
||||
0xbd127023UL, 0xe4a1b000UL, 0x3fc527e5UL, 0xe5697dc7UL, 0x3d2633e8UL,
|
||||
0x8333b000UL, 0x3fc4913dUL, 0x54fdb678UL, 0x3d258379UL, 0xa5993000UL,
|
||||
0x3fc3fb45UL, 0x7e6a354dUL, 0xbd2cd1d8UL, 0xb0159000UL, 0x3fc365fcUL,
|
||||
0x234b7289UL, 0x3cc62fa8UL, 0x0c868000UL, 0x3fc2d161UL, 0xcb81b4a1UL,
|
||||
0x3d039d6cUL, 0x2a49c000UL, 0x3fc23d71UL, 0x8fd3df5cUL, 0x3d100d23UL,
|
||||
0x7e23f000UL, 0x3fc1aa2bUL, 0x44389934UL, 0x3d2ca78eUL, 0x8227e000UL,
|
||||
0x3fc1178eUL, 0xce2d07f2UL, 0x3d21ef78UL, 0xb59e4000UL, 0x3fc08598UL,
|
||||
0x7009902cUL, 0xbd27e5ddUL, 0x39dbe000UL, 0x3fbfe891UL, 0x4fa10afdUL,
|
||||
0xbd2534d6UL, 0x830a2000UL, 0x3fbec739UL, 0xafe645e0UL, 0xbd2dc068UL,
|
||||
0x63844000UL, 0x3fbda727UL, 0x1fa71733UL, 0x3d1a8940UL, 0x01bc4000UL,
|
||||
0x3fbc8858UL, 0xc65aacd3UL, 0x3d2646d1UL, 0x8dad6000UL, 0x3fbb6ac8UL,
|
||||
0x2bf768e5UL, 0xbd139080UL, 0x40b1c000UL, 0x3fba4e76UL, 0xb94407c8UL,
|
||||
0xbd0e42b6UL, 0x5d594000UL, 0x3fb9335eUL, 0x3abd47daUL, 0x3d23115cUL,
|
||||
0x2f40e000UL, 0x3fb8197eUL, 0xf96ffdf7UL, 0x3d0f80dcUL, 0x0aeac000UL,
|
||||
0x3fb700d3UL, 0xa99ded32UL, 0x3cec1e8dUL, 0x4d97a000UL, 0x3fb5e95aUL,
|
||||
0x3c5d1d1eUL, 0xbd2c6906UL, 0x5d208000UL, 0x3fb4d311UL, 0x82f4e1efUL,
|
||||
0xbcf53a25UL, 0xa7d1e000UL, 0x3fb3bdf5UL, 0xa5db4ed7UL, 0x3d2cc85eUL,
|
||||
0xa4472000UL, 0x3fb2aa04UL, 0xae9c697dUL, 0xbd20b6e8UL, 0xd1466000UL,
|
||||
0x3fb1973bUL, 0x560d9e9bUL, 0xbd25325dUL, 0xb59e4000UL, 0x3fb08598UL,
|
||||
0x7009902cUL, 0xbd17e5ddUL, 0xc006c000UL, 0x3faeea31UL, 0x4fc93b7bUL,
|
||||
0xbd0e113eUL, 0xcdddc000UL, 0x3faccb73UL, 0x47d82807UL, 0xbd1a68f2UL,
|
||||
0xd0fb0000UL, 0x3faaaef2UL, 0x353bb42eUL, 0x3d20fc1aUL, 0x149fc000UL,
|
||||
0x3fa894aaUL, 0xd05a267dUL, 0xbd197995UL, 0xf2d4c000UL, 0x3fa67c94UL,
|
||||
0xec19afa2UL, 0xbd029efbUL, 0xd42e0000UL, 0x3fa466aeUL, 0x75bdfd28UL,
|
||||
0xbd2c1673UL, 0x2f8d0000UL, 0x3fa252f3UL, 0xe021b67bUL, 0x3d283e9aUL,
|
||||
0x89e74000UL, 0x3fa0415dUL, 0x5cf1d753UL, 0x3d0111c0UL, 0xec148000UL,
|
||||
0x3f9c63d2UL, 0x3f9eb2f3UL, 0x3d2578c6UL, 0x28c90000UL, 0x3f984925UL,
|
||||
0x325a0c34UL, 0xbd2aa0baUL, 0x25980000UL, 0x3f9432a9UL, 0x928637feUL,
|
||||
0x3d098139UL, 0x58938000UL, 0x3f902056UL, 0x06e2f7d2UL, 0xbd23dc5bUL,
|
||||
0xa3890000UL, 0x3f882448UL, 0xda74f640UL, 0xbd275577UL, 0x75890000UL,
|
||||
0x3f801015UL, 0x999d2be8UL, 0xbd10c76bUL, 0x59580000UL, 0x3f700805UL,
|
||||
0xcb31c67bUL, 0x3d2166afUL, 0x00000000UL, 0x00000000UL, 0x00000000UL,
|
||||
0x80000000UL, 0xfefa3800UL, 0x3fa62e42UL, 0x93c76730UL, 0x3ceef357UL,
|
||||
0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL, 0x3d6fb175UL,
|
||||
0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL, 0x9999999aUL, 0x3fc99999UL,
|
||||
0x00000000UL, 0xbfe00000UL, 0x00000000UL, 0xffffe000UL, 0x00000000UL,
|
||||
0xffffe000UL
|
||||
};
|
||||
//registers,
|
||||
// input: xmm0
|
||||
// scratch: xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7
|
||||
// rax, rdx, rcx, rbx (tmp)
|
||||
|
||||
void MacroAssembler::fast_log(XMMRegister xmm0, XMMRegister xmm1, XMMRegister xmm2, XMMRegister xmm3, XMMRegister xmm4, XMMRegister xmm5, XMMRegister xmm6, XMMRegister xmm7, Register eax, Register ecx, Register edx, Register tmp) {
|
||||
Label L_2TAG_PACKET_0_0_2, L_2TAG_PACKET_1_0_2, L_2TAG_PACKET_2_0_2, L_2TAG_PACKET_3_0_2;
|
||||
Label L_2TAG_PACKET_4_0_2, L_2TAG_PACKET_5_0_2, L_2TAG_PACKET_6_0_2, L_2TAG_PACKET_7_0_2;
|
||||
Label L_2TAG_PACKET_8_0_2, L_2TAG_PACKET_9_0_2;
|
||||
Label L_2TAG_PACKET_10_0_2, start;
|
||||
|
||||
assert_different_registers(tmp, eax, ecx, edx);
|
||||
jmp(start);
|
||||
address static_const_table = (address)_static_const_table_log;
|
||||
|
||||
bind(start);
|
||||
subl(rsp, 104);
|
||||
movl(Address(rsp, 40), tmp);
|
||||
lea(tmp, ExternalAddress(static_const_table));
|
||||
xorpd(xmm2, xmm2);
|
||||
movl(eax, 16368);
|
||||
pinsrw(xmm2, eax, 3);
|
||||
xorpd(xmm3, xmm3);
|
||||
movl(edx, 30704);
|
||||
pinsrw(xmm3, edx, 3);
|
||||
movsd(xmm0, Address(rsp, 112));
|
||||
movapd(xmm1, xmm0);
|
||||
movl(ecx, 32768);
|
||||
movdl(xmm4, ecx);
|
||||
movsd(xmm5, Address(tmp, 2128)); // 0x00000000UL, 0xffffe000UL
|
||||
pextrw(eax, xmm0, 3);
|
||||
por(xmm0, xmm2);
|
||||
psllq(xmm0, 5);
|
||||
movl(ecx, 16352);
|
||||
psrlq(xmm0, 34);
|
||||
rcpss(xmm0, xmm0);
|
||||
psllq(xmm1, 12);
|
||||
pshufd(xmm6, xmm5, 228);
|
||||
psrlq(xmm1, 12);
|
||||
subl(eax, 16);
|
||||
cmpl(eax, 32736);
|
||||
jcc(Assembler::aboveEqual, L_2TAG_PACKET_0_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_1_0_2);
|
||||
paddd(xmm0, xmm4);
|
||||
por(xmm1, xmm3);
|
||||
movdl(edx, xmm0);
|
||||
psllq(xmm0, 29);
|
||||
pand(xmm5, xmm1);
|
||||
pand(xmm0, xmm6);
|
||||
subsd(xmm1, xmm5);
|
||||
mulpd(xmm5, xmm0);
|
||||
andl(eax, 32752);
|
||||
subl(eax, ecx);
|
||||
cvtsi2sdl(xmm7, eax);
|
||||
mulsd(xmm1, xmm0);
|
||||
movsd(xmm6, Address(tmp, 2064)); // 0xfefa3800UL, 0x3fa62e42UL
|
||||
movdqu(xmm3, Address(tmp, 2080)); // 0x92492492UL, 0x3fc24924UL, 0x00000000UL, 0xbfd00000UL
|
||||
subsd(xmm5, xmm2);
|
||||
andl(edx, 16711680);
|
||||
shrl(edx, 12);
|
||||
movdqu(xmm0, Address(tmp, edx));
|
||||
movdqu(xmm4, Address(tmp, 2096)); // 0x3d6fb175UL, 0xbfc5555eUL, 0x55555555UL, 0x3fd55555UL
|
||||
addsd(xmm1, xmm5);
|
||||
movdqu(xmm2, Address(tmp, 2112)); // 0x9999999aUL, 0x3fc99999UL, 0x00000000UL, 0xbfe00000UL
|
||||
mulsd(xmm6, xmm7);
|
||||
pshufd(xmm5, xmm1, 68);
|
||||
mulsd(xmm7, Address(tmp, 2072)); // 0x93c76730UL, 0x3ceef357UL, 0x92492492UL, 0x3fc24924UL
|
||||
mulsd(xmm3, xmm1);
|
||||
addsd(xmm0, xmm6);
|
||||
mulpd(xmm4, xmm5);
|
||||
mulpd(xmm5, xmm5);
|
||||
pshufd(xmm6, xmm0, 228);
|
||||
addsd(xmm0, xmm1);
|
||||
addpd(xmm4, xmm2);
|
||||
mulpd(xmm3, xmm5);
|
||||
subsd(xmm6, xmm0);
|
||||
mulsd(xmm4, xmm1);
|
||||
pshufd(xmm2, xmm0, 238);
|
||||
addsd(xmm1, xmm6);
|
||||
mulsd(xmm5, xmm5);
|
||||
addsd(xmm7, xmm2);
|
||||
addpd(xmm4, xmm3);
|
||||
addsd(xmm1, xmm7);
|
||||
mulpd(xmm4, xmm5);
|
||||
addsd(xmm1, xmm4);
|
||||
pshufd(xmm5, xmm4, 238);
|
||||
addsd(xmm1, xmm5);
|
||||
addsd(xmm0, xmm1);
|
||||
jmp(L_2TAG_PACKET_2_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_0_0_2);
|
||||
movsd(xmm0, Address(rsp, 112));
|
||||
movdqu(xmm1, xmm0);
|
||||
addl(eax, 16);
|
||||
cmpl(eax, 32768);
|
||||
jcc(Assembler::aboveEqual, L_2TAG_PACKET_3_0_2);
|
||||
cmpl(eax, 16);
|
||||
jcc(Assembler::below, L_2TAG_PACKET_4_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_5_0_2);
|
||||
addsd(xmm0, xmm0);
|
||||
jmp(L_2TAG_PACKET_2_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_6_0_2);
|
||||
jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
|
||||
cmpl(edx, 0);
|
||||
jcc(Assembler::above, L_2TAG_PACKET_5_0_2);
|
||||
jmp(L_2TAG_PACKET_7_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_3_0_2);
|
||||
movdl(edx, xmm1);
|
||||
psrlq(xmm1, 32);
|
||||
movdl(ecx, xmm1);
|
||||
addl(ecx, ecx);
|
||||
cmpl(ecx, -2097152);
|
||||
jcc(Assembler::aboveEqual, L_2TAG_PACKET_6_0_2);
|
||||
orl(edx, ecx);
|
||||
cmpl(edx, 0);
|
||||
jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_7_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
xorpd(xmm0, xmm0);
|
||||
movl(eax, 32752);
|
||||
pinsrw(xmm1, eax, 3);
|
||||
movl(edx, 3);
|
||||
mulsd(xmm0, xmm1);
|
||||
|
||||
bind(L_2TAG_PACKET_9_0_2);
|
||||
movsd(Address(rsp, 0), xmm0);
|
||||
movsd(xmm0, Address(rsp, 112));
|
||||
fld_d(Address(rsp, 0));
|
||||
jmp(L_2TAG_PACKET_10_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_8_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
xorpd(xmm0, xmm0);
|
||||
movl(eax, 49136);
|
||||
pinsrw(xmm0, eax, 3);
|
||||
divsd(xmm0, xmm1);
|
||||
movl(edx, 2);
|
||||
jmp(L_2TAG_PACKET_9_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_4_0_2);
|
||||
movdl(edx, xmm1);
|
||||
psrlq(xmm1, 32);
|
||||
movdl(ecx, xmm1);
|
||||
orl(edx, ecx);
|
||||
cmpl(edx, 0);
|
||||
jcc(Assembler::equal, L_2TAG_PACKET_8_0_2);
|
||||
xorpd(xmm1, xmm1);
|
||||
movl(eax, 18416);
|
||||
pinsrw(xmm1, eax, 3);
|
||||
mulsd(xmm0, xmm1);
|
||||
movapd(xmm1, xmm0);
|
||||
pextrw(eax, xmm0, 3);
|
||||
por(xmm0, xmm2);
|
||||
psllq(xmm0, 5);
|
||||
movl(ecx, 18416);
|
||||
psrlq(xmm0, 34);
|
||||
rcpss(xmm0, xmm0);
|
||||
psllq(xmm1, 12);
|
||||
pshufd(xmm6, xmm5, 228);
|
||||
psrlq(xmm1, 12);
|
||||
jmp(L_2TAG_PACKET_1_0_2);
|
||||
|
||||
bind(L_2TAG_PACKET_2_0_2);
|
||||
movsd(Address(rsp, 24), xmm0);
|
||||
fld_d(Address(rsp, 24));
|
||||
|
||||
bind(L_2TAG_PACKET_10_0_2);
|
||||
movl(tmp, Address(rsp, 40));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -2094,14 +2094,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
void generate_math_stubs() {
|
||||
{
|
||||
StubCodeMark mark(this, "StubRoutines", "log");
|
||||
StubRoutines::_intrinsic_log = (double (*)(double)) __ pc();
|
||||
|
||||
__ fld_d(Address(rsp, 4));
|
||||
__ flog();
|
||||
__ ret(0);
|
||||
}
|
||||
{
|
||||
StubCodeMark mark(this, "StubRoutines", "log10");
|
||||
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.
|
||||
void generate_safefetch(const char* name, int size, address* entry,
|
||||
@ -3288,6 +3306,7 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
if (VM_Version::supports_sse2()) {
|
||||
StubRoutines::_dexp = generate_libmExp();
|
||||
StubRoutines::_dlog = generate_libmLog();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2973,19 +2973,6 @@ class StubGenerator: public StubCodeGenerator {
|
||||
}
|
||||
|
||||
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");
|
||||
StubRoutines::_intrinsic_log10 = (double (*)(double)) __ pc();
|
||||
@ -4187,15 +4174,58 @@ class StubGenerator: public StubCodeGenerator {
|
||||
|
||||
#ifdef _WIN64
|
||||
// save the xmm registers which must be preserved 6-7
|
||||
__ movdqu(xmm_save(6), as_XMMRegister(6));
|
||||
__ movdqu(xmm_save(7), as_XMMRegister(7));
|
||||
__ subptr(rsp, 4 * wordSize);
|
||||
__ movdqu(Address(rsp, 0), xmm6);
|
||||
__ movdqu(Address(rsp, 2 * wordSize), xmm7);
|
||||
#endif
|
||||
__ fast_exp(x0, x1, x2, x3, x4, x5, x6, x7, rax, rcx, rdx, tmp);
|
||||
|
||||
#ifdef _WIN64
|
||||
// restore xmm regs belonging to calling function
|
||||
__ movdqu(as_XMMRegister(6), xmm_save(6));
|
||||
__ movdqu(as_XMMRegister(7), xmm_save(7));
|
||||
__ movdqu(xmm6, Address(rsp, 0));
|
||||
__ 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
|
||||
|
||||
__ 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::_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() {
|
||||
|
@ -1707,6 +1707,10 @@ const bool Matcher::match_rule_supported(int opcode) {
|
||||
if (!VM_Version::supports_cx8())
|
||||
ret_value = false;
|
||||
break;
|
||||
case Op_CMoveVD:
|
||||
if (UseAVX < 1 || UseAVX > 2)
|
||||
ret_value = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret_value; // Per default match rules are supported.
|
||||
@ -2089,6 +2093,29 @@ operand vecZ() %{
|
||||
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)
|
||||
|
||||
// ============================================================================
|
||||
@ -7393,6 +7420,22 @@ instruct vmul8D_mem(vecZ dst, vecZ src, memory mem) %{
|
||||
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 --------------------------------------
|
||||
|
||||
// Floats vector div
|
||||
|
@ -9950,41 +9950,6 @@ instruct log10D_reg(regD dst, regD src, eFlagsReg cr) %{
|
||||
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 Math
|
||||
|
||||
|
@ -9870,21 +9870,6 @@ instruct log10D_reg(regD dst) %{
|
||||
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) %{
|
||||
match(Set dst (PowD src0 src1)); // Raise src0 to the src1'th power
|
||||
effect(KILL rax, KILL rdx, KILL rcx, KILL cr);
|
||||
|
@ -60,7 +60,7 @@ bool CompiledIC::is_icholder_call_site(virtual_call_Relocation* call_site) {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf) {
|
||||
address CompiledStaticCall::emit_to_interp_stub(CodeBuffer &cbuf, address mark) {
|
||||
ShouldNotReachHere(); // Only needed for COMPILER2.
|
||||
return NULL;
|
||||
}
|
||||
|
@ -59,11 +59,6 @@ void poll_Relocation::fix_relocation_after_move(const CodeBuffer* src,
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
void poll_return_Relocation::fix_relocation_after_move(const CodeBuffer* src,
|
||||
CodeBuffer* dst) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
||||
void metadata_Relocation::pd_fix_value(address x) {
|
||||
ShouldNotCallThis();
|
||||
}
|
||||
|
@ -37,4 +37,5 @@ void VM_Version::initialize() {
|
||||
warning("Unaligned memory access is not available on this CPU");
|
||||
FLAG_SET_DEFAULT(UseUnalignedAccesses, false);
|
||||
}
|
||||
FLAG_SET_DEFAULT(AllocatePrefetchDistance, 0);
|
||||
}
|
||||
|
@ -4006,7 +4006,6 @@ int MatchRule::is_expensive() const {
|
||||
strcmp(opType,"DivD")==0 ||
|
||||
strcmp(opType,"DivF")==0 ||
|
||||
strcmp(opType,"DivI")==0 ||
|
||||
strcmp(opType,"LogD")==0 ||
|
||||
strcmp(opType,"Log10D")==0 ||
|
||||
strcmp(opType,"ModD")==0 ||
|
||||
strcmp(opType,"ModF")==0 ||
|
||||
@ -4141,6 +4140,7 @@ bool MatchRule::is_vector() const {
|
||||
"AddVB","AddVS","AddVI","AddVL","AddVF","AddVD",
|
||||
"SubVB","SubVS","SubVI","SubVL","SubVF","SubVD",
|
||||
"MulVS","MulVI","MulVL","MulVF","MulVD",
|
||||
"CMoveVD",
|
||||
"DivVF","DivVD",
|
||||
"AbsVF","AbsVD",
|
||||
"NegVF","NegVD",
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "c1/c1_ValueStack.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "runtime/sharedRuntime.hpp"
|
||||
|
||||
typedef enum {
|
||||
@ -418,9 +419,9 @@ void Compilation::install_code(int frame_size) {
|
||||
exception_handler_table(),
|
||||
implicit_exception_table(),
|
||||
compiler(),
|
||||
_env->comp_level(),
|
||||
has_unsafe_access(),
|
||||
SharedRuntime::is_wide_vector(max_vector_size())
|
||||
SharedRuntime::is_wide_vector(max_vector_size()),
|
||||
directive()
|
||||
);
|
||||
}
|
||||
|
||||
@ -445,7 +446,7 @@ void Compilation::compile_method() {
|
||||
dependency_recorder()->assert_evol_method(method());
|
||||
}
|
||||
|
||||
if (method()->break_at_execute()) {
|
||||
if (directive()->BreakAtCompileOption) {
|
||||
BREAKPOINT;
|
||||
}
|
||||
|
||||
@ -534,9 +535,10 @@ void Compilation::generate_exception_handler_table() {
|
||||
|
||||
|
||||
Compilation::Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
|
||||
int osr_bci, BufferBlob* buffer_blob)
|
||||
int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive)
|
||||
: _compiler(compiler)
|
||||
, _env(env)
|
||||
, _directive(directive)
|
||||
, _log(env->log())
|
||||
, _method(method)
|
||||
, _osr_bci(osr_bci)
|
||||
@ -587,7 +589,6 @@ Compilation::~Compilation() {
|
||||
_env->set_compiler_data(NULL);
|
||||
}
|
||||
|
||||
|
||||
void Compilation::add_exception_handlers_for_pco(int pco, XHandlers* exception_handlers) {
|
||||
#ifndef PRODUCT
|
||||
if (PrintExceptionHandlers && Verbose) {
|
||||
|
@ -67,6 +67,7 @@ class Compilation: public StackObj {
|
||||
int _next_id;
|
||||
int _next_block_id;
|
||||
AbstractCompiler* _compiler;
|
||||
DirectiveSet* _directive;
|
||||
ciEnv* _env;
|
||||
CompileLog* _log;
|
||||
ciMethod* _method;
|
||||
@ -118,7 +119,7 @@ class Compilation: public StackObj {
|
||||
public:
|
||||
// creation
|
||||
Compilation(AbstractCompiler* compiler, ciEnv* env, ciMethod* method,
|
||||
int osr_bci, BufferBlob* buffer_blob);
|
||||
int osr_bci, BufferBlob* buffer_blob, DirectiveSet* directive);
|
||||
~Compilation();
|
||||
|
||||
|
||||
@ -128,6 +129,7 @@ class Compilation: public StackObj {
|
||||
|
||||
// accessors
|
||||
ciEnv* env() const { return _env; }
|
||||
DirectiveSet* directive() const { return _directive; }
|
||||
CompileLog* log() const { return _log; }
|
||||
AbstractCompiler* compiler() const { return _compiler; }
|
||||
bool has_exception_handlers() const { return _has_exception_handlers; }
|
||||
|
@ -238,7 +238,7 @@ bool Compiler::is_intrinsic_supported(methodHandle method) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
|
||||
void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci, DirectiveSet* directive) {
|
||||
BufferBlob* buffer_blob = CompilerThread::current()->get_buffer_blob();
|
||||
assert(buffer_blob != NULL, "Must exist");
|
||||
// invoke compilation
|
||||
@ -247,7 +247,7 @@ void Compiler::compile_method(ciEnv* env, ciMethod* method, int entry_bci) {
|
||||
// of Compilation to occur before we release the any
|
||||
// competing compiler thread
|
||||
ResourceMark rm;
|
||||
Compilation c(this, env, method, entry_bci, buffer_blob);
|
||||
Compilation c(this, env, method, entry_bci, buffer_blob, directive);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define SHARE_VM_C1_C1_COMPILER_HPP
|
||||
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
|
||||
// There is one instance of the Compiler per CompilerThread.
|
||||
|
||||
@ -50,7 +51,7 @@ class Compiler: public AbstractCompiler {
|
||||
virtual void initialize();
|
||||
|
||||
// Compilation entry point for methods
|
||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
|
||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
|
||||
|
||||
// Print compilation timers and statistics
|
||||
virtual void print_timers();
|
||||
|
@ -3365,7 +3365,7 @@ const char* GraphBuilder::check_can_parse(ciMethod* callee) const {
|
||||
|
||||
// negative filter: should callee NOT be inlined? returns NULL, ok to inline, or rejection msg
|
||||
const char* GraphBuilder::should_not_inline(ciMethod* callee) const {
|
||||
if ( callee->should_not_inline()) return "disallowed by CompileCommand";
|
||||
if ( compilation()->directive()->should_not_inline(callee)) return "disallowed by CompileCommand";
|
||||
if ( callee->dont_inline()) return "don't inline by annotation";
|
||||
return NULL;
|
||||
}
|
||||
@ -3494,8 +3494,7 @@ bool GraphBuilder::try_inline_intrinsics(ciMethod* callee) {
|
||||
{
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, callee->get_Method());
|
||||
methodHandle ct(THREAD, method()->get_Method());
|
||||
is_available = _compilation->compiler()->is_intrinsic_available(mh, ct);
|
||||
is_available = _compilation->compiler()->is_intrinsic_available(mh, _compilation->directive());
|
||||
}
|
||||
|
||||
if (!is_available) {
|
||||
@ -3690,13 +3689,14 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known, Bytecode
|
||||
}
|
||||
|
||||
// now perform tests that are based on flag settings
|
||||
if (callee->force_inline() || callee->should_inline()) {
|
||||
bool inlinee_by_directive = compilation()->directive()->should_inline(callee);
|
||||
if (callee->force_inline() || inlinee_by_directive) {
|
||||
if (inline_level() > MaxForceInlineLevel ) INLINE_BAILOUT("MaxForceInlineLevel");
|
||||
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("recursive inlining too deep");
|
||||
|
||||
const char* msg = "";
|
||||
if (callee->force_inline()) msg = "force inline by annotation";
|
||||
if (callee->should_inline()) msg = "force inline by CompileCommand";
|
||||
if (inlinee_by_directive) msg = "force inline by CompileCommand";
|
||||
print_inlining(callee, msg);
|
||||
} else {
|
||||
// use heuristic controls on inlining
|
||||
@ -4207,7 +4207,8 @@ void GraphBuilder::print_inlining(ciMethod* callee, const char* msg, bool succes
|
||||
event.commit();
|
||||
}
|
||||
#endif // INCLUDE_TRACE
|
||||
if (!PrintInlining && !compilation()->method()->has_option("PrintInlining")) {
|
||||
|
||||
if (!compilation()->directive()->PrintInliningOption) {
|
||||
return;
|
||||
}
|
||||
CompileTask::print_inlining_tty(callee, scope()->level(), bci(), msg);
|
||||
|
@ -731,7 +731,6 @@ void LIR_OpVisitState::visit(LIR_Op* op) {
|
||||
case lir_tan:
|
||||
case lir_sin:
|
||||
case lir_cos:
|
||||
case lir_log:
|
||||
case lir_log10: {
|
||||
assert(op->as_Op2() != NULL, "must be");
|
||||
LIR_Op2* op2 = (LIR_Op2*)op;
|
||||
@ -1769,7 +1768,6 @@ const char * LIR_Op::name() const {
|
||||
case lir_sin: s = "sin"; break;
|
||||
case lir_cos: s = "cos"; break;
|
||||
case lir_tan: s = "tan"; break;
|
||||
case lir_log: s = "log"; break;
|
||||
case lir_log10: s = "log10"; break;
|
||||
case lir_pow: s = "pow"; break;
|
||||
case lir_logic_and: s = "logic_and"; break;
|
||||
|
@ -959,7 +959,6 @@ enum LIR_Code {
|
||||
, lir_sin
|
||||
, lir_cos
|
||||
, lir_tan
|
||||
, lir_log
|
||||
, lir_log10
|
||||
, lir_pow
|
||||
, lir_logic_and
|
||||
@ -2193,7 +2192,6 @@ class LIR_List: public CompilationResourceObj {
|
||||
|
||||
void abs (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_abs , from, tmp, to)); }
|
||||
void sqrt(LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_sqrt, from, tmp, to)); }
|
||||
void log (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log, from, LIR_OprFact::illegalOpr, to, tmp)); }
|
||||
void log10 (LIR_Opr from, LIR_Opr to, LIR_Opr tmp) { append(new LIR_Op2(lir_log10, from, LIR_OprFact::illegalOpr, to, tmp)); }
|
||||
void sin (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_sin , from, tmp1, to, tmp2)); }
|
||||
void cos (LIR_Opr from, LIR_Opr to, LIR_Opr tmp1, LIR_Opr tmp2) { append(new LIR_Op2(lir_cos , from, tmp1, to, tmp2)); }
|
||||
|
@ -738,7 +738,6 @@ void LIR_Assembler::emit_op2(LIR_Op2* op) {
|
||||
case lir_sin:
|
||||
case lir_tan:
|
||||
case lir_cos:
|
||||
case lir_log:
|
||||
case lir_log10:
|
||||
case lir_pow:
|
||||
intrinsic_op(op->code(), op->in_opr1(), op->in_opr2(), op->result_opr(), op);
|
||||
|
@ -153,8 +153,13 @@ class PhiResolver: public CompilationResourceObj {
|
||||
|
||||
// only the classes below belong in the same file
|
||||
class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||
|
||||
// LIRGenerator should never get instatiated on the heap.
|
||||
private:
|
||||
void* operator new(size_t size) throw();
|
||||
void* operator new[](size_t size) throw();
|
||||
void operator delete(void* p);
|
||||
void operator delete[](void* p);
|
||||
|
||||
Compilation* _compilation;
|
||||
ciMethod* _method; // method that we are compiling
|
||||
PhiResolverState _resolver_state;
|
||||
@ -244,7 +249,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure {
|
||||
void do_getClass(Intrinsic* x);
|
||||
void do_currentThread(Intrinsic* x);
|
||||
void do_MathIntrinsic(Intrinsic* x);
|
||||
void do_ExpIntrinsic(Intrinsic* x);
|
||||
void do_LibmIntrinsic(Intrinsic* x);
|
||||
void do_ArrayCopy(Intrinsic* x);
|
||||
void do_CompareAndSwap(Intrinsic* x, ValueType* type);
|
||||
void do_NIOCheckIndex(Intrinsic* x);
|
||||
|
@ -6586,7 +6586,6 @@ void LinearScanStatistic::collect(LinearScan* allocator) {
|
||||
case lir_cos:
|
||||
case lir_abs:
|
||||
case lir_log10:
|
||||
case lir_log:
|
||||
case lir_pow:
|
||||
case lir_logic_and:
|
||||
case lir_logic_or:
|
||||
|
@ -45,8 +45,14 @@ private:
|
||||
define_stack(IntegerStack, intArray)
|
||||
define_array(IntegerMap, IntegerStack*)
|
||||
|
||||
class Verification : public _ValueObj /*VALUE_OBJ_CLASS_SPEC*/, public BlockClosure {
|
||||
class Verification : public BlockClosure {
|
||||
// RangeCheckEliminator::Verification should never get instatiated on the heap.
|
||||
private:
|
||||
void* operator new(size_t size) throw();
|
||||
void* operator new[](size_t size) throw();
|
||||
void operator delete(void* p);
|
||||
void operator delete[](void* p);
|
||||
|
||||
IR *_ir;
|
||||
boolArray _used;
|
||||
BlockBeginList _current;
|
||||
|
@ -318,6 +318,7 @@ const char* Runtime1::name_for_address(address entry) {
|
||||
#endif
|
||||
FUNCTION_CASE(entry, StubRoutines::updateBytesCRC32());
|
||||
FUNCTION_CASE(entry, StubRoutines::dexp());
|
||||
FUNCTION_CASE(entry, StubRoutines::dlog());
|
||||
|
||||
#undef FUNCTION_CASE
|
||||
|
||||
|
@ -38,7 +38,8 @@
|
||||
#include "code/scopeDesc.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "gc/shared/collectedHeap.inline.hpp"
|
||||
#include "interpreter/linkResolver.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
@ -956,9 +957,9 @@ void ciEnv::register_method(ciMethod* target,
|
||||
ExceptionHandlerTable* handler_table,
|
||||
ImplicitExceptionTable* inc_table,
|
||||
AbstractCompiler* compiler,
|
||||
int comp_level,
|
||||
bool has_unsafe_access,
|
||||
bool has_wide_vectors,
|
||||
DirectiveSet* directives,
|
||||
RTMState rtm_state) {
|
||||
VM_ENTRY_MARK;
|
||||
nmethod* nm = NULL;
|
||||
@ -1034,11 +1035,20 @@ void ciEnv::register_method(ciMethod* target,
|
||||
debug_info(), dependencies(), code_buffer,
|
||||
frame_words, oop_map_set,
|
||||
handler_table, inc_table,
|
||||
compiler, comp_level);
|
||||
compiler, task()->comp_level());
|
||||
|
||||
// Free codeBlobs
|
||||
code_buffer->free_blob();
|
||||
|
||||
if (nm != NULL) {
|
||||
bool printnmethods = directives->PrintAssemblyOption || directives->PrintNMethodsOption;
|
||||
if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
|
||||
nm->print_nmethod(printnmethods);
|
||||
}
|
||||
if (directives->PrintAssemblyOption) {
|
||||
Disassembler::decode(nm);
|
||||
}
|
||||
|
||||
nm->set_has_unsafe_access(has_unsafe_access);
|
||||
nm->set_has_wide_vectors(has_wide_vectors);
|
||||
#if INCLUDE_RTM_OPT
|
||||
@ -1069,7 +1079,7 @@ void ciEnv::register_method(ciMethod* target,
|
||||
char *method_name = method->name_and_sig_as_C_string();
|
||||
ttyLocker ttyl;
|
||||
tty->print_cr("Installing method (%d) %s ",
|
||||
comp_level,
|
||||
task()->comp_level(),
|
||||
method_name);
|
||||
}
|
||||
// Allow the code to be executed
|
||||
@ -1080,7 +1090,7 @@ void ciEnv::register_method(ciMethod* target,
|
||||
char *method_name = method->name_and_sig_as_C_string();
|
||||
ttyLocker ttyl;
|
||||
tty->print_cr("Installing osr method (%d) %s @ %d",
|
||||
comp_level,
|
||||
task()->comp_level(),
|
||||
method_name,
|
||||
entry_bci);
|
||||
}
|
||||
|
@ -32,9 +32,11 @@
|
||||
#include "code/dependencies.hpp"
|
||||
#include "code/exceptionHandlerTable.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "runtime/thread.hpp"
|
||||
|
||||
class CompileTask;
|
||||
class DirectiveSet;
|
||||
|
||||
// ciEnv
|
||||
//
|
||||
@ -352,6 +354,7 @@ public:
|
||||
// The compiler task which has created this env.
|
||||
// May be useful to find out compile_id, comp_level, etc.
|
||||
CompileTask* task() { return _task; }
|
||||
|
||||
// Handy forwards to the task:
|
||||
int comp_level(); // task()->comp_level()
|
||||
uint compile_id(); // task()->compile_id()
|
||||
@ -367,9 +370,9 @@ public:
|
||||
ExceptionHandlerTable* handler_table,
|
||||
ImplicitExceptionTable* inc_table,
|
||||
AbstractCompiler* compiler,
|
||||
int comp_level,
|
||||
bool has_unsafe_access,
|
||||
bool has_wide_vectors,
|
||||
DirectiveSet* directives,
|
||||
RTMState rtm_state = NoRTM);
|
||||
|
||||
|
||||
|
@ -190,6 +190,14 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) {
|
||||
// so there is no hacking of finals going on with them.
|
||||
if (holder->is_anonymous())
|
||||
return true;
|
||||
// Trust Atomic*FieldUpdaters: they are very important for performance, and make up one
|
||||
// more reason not to use Unsafe, if their final fields are trusted. See more in JDK-8140483.
|
||||
if (holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl() ||
|
||||
holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater() ||
|
||||
holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater() ||
|
||||
holder->name() == ciSymbol::java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl()) {
|
||||
return true;
|
||||
}
|
||||
return TrustFinalNonStaticFields;
|
||||
}
|
||||
|
||||
|
@ -35,7 +35,6 @@
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "classfile/systemDictionary.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "compiler/methodLiveness.hpp"
|
||||
#include "interpreter/interpreter.hpp"
|
||||
#include "interpreter/linkResolver.hpp"
|
||||
@ -1043,51 +1042,6 @@ MethodCounters* ciMethod::ensure_method_counters() {
|
||||
return method_counters;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::should_inline
|
||||
//
|
||||
// Should this method be inlined during compilation?
|
||||
bool ciMethod::should_inline() {
|
||||
check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, get_Method());
|
||||
return CompilerOracle::should_inline(mh);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::should_not_inline
|
||||
//
|
||||
// Should this method be disallowed from inlining during compilation?
|
||||
bool ciMethod::should_not_inline() {
|
||||
check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, get_Method());
|
||||
return CompilerOracle::should_not_inline(mh);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::should_print_assembly
|
||||
//
|
||||
// Should the compiler print the generated code for this method?
|
||||
bool ciMethod::should_print_assembly() {
|
||||
check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, get_Method());
|
||||
return CompilerOracle::should_print(mh);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::break_at_execute
|
||||
//
|
||||
// Should the compiler insert a breakpoint into the generated code
|
||||
// method?
|
||||
bool ciMethod::break_at_execute() {
|
||||
check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, get_Method());
|
||||
return CompilerOracle::should_break_at(mh);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::has_option
|
||||
//
|
||||
@ -1101,20 +1055,12 @@ bool ciMethod::has_option(const char* option) {
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::has_option_value
|
||||
//
|
||||
template<typename T>
|
||||
bool ciMethod::has_option_value(const char* option, T& value) {
|
||||
bool ciMethod::has_option_value(const char* option, double& value) {
|
||||
check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, get_Method());
|
||||
return CompilerOracle::has_option_value(mh, option, value);
|
||||
}
|
||||
// Explicit instantiation for all OptionTypes supported.
|
||||
template bool ciMethod::has_option_value<intx>(const char* option, intx& value);
|
||||
template bool ciMethod::has_option_value<uintx>(const char* option, uintx& value);
|
||||
template bool ciMethod::has_option_value<bool>(const char* option, bool& value);
|
||||
template bool ciMethod::has_option_value<ccstr>(const char* option, ccstr& value);
|
||||
template bool ciMethod::has_option_value<double>(const char* option, double& value);
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// ciMethod::can_be_compiled
|
||||
//
|
||||
|
@ -104,8 +104,6 @@ class ciMethod : public ciMetadata {
|
||||
|
||||
void load_code();
|
||||
|
||||
void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
|
||||
|
||||
bool ensure_method_data(methodHandle h_m);
|
||||
|
||||
void code_at_put(int bci, Bytecodes::Code code) {
|
||||
@ -120,6 +118,8 @@ class ciMethod : public ciMetadata {
|
||||
void assert_call_type_ok(int bci);
|
||||
|
||||
public:
|
||||
void check_is_loaded() const { assert(is_loaded(), "not loaded"); }
|
||||
|
||||
// Basic method information.
|
||||
ciFlags flags() const { check_is_loaded(); return _flags; }
|
||||
ciSymbol* name() const { return _name; }
|
||||
@ -265,14 +265,8 @@ class ciMethod : public ciMetadata {
|
||||
// Find the proper vtable index to invoke this method.
|
||||
int resolve_vtable_index(ciKlass* caller, ciKlass* receiver);
|
||||
|
||||
// Compilation directives
|
||||
bool should_inline();
|
||||
bool should_not_inline();
|
||||
bool should_print_assembly();
|
||||
bool break_at_execute();
|
||||
bool has_option(const char *option);
|
||||
template<typename T>
|
||||
bool has_option_value(const char* option, T& value);
|
||||
bool has_option_value(const char* option, double& value);
|
||||
bool can_be_compiled();
|
||||
bool can_be_osr_compiled(int entry_bci);
|
||||
void set_not_compilable(const char* reason = NULL);
|
||||
|
@ -417,36 +417,10 @@ int vmIntrinsics::predicates_needed(vmIntrinsics::ID id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool vmIntrinsics::is_disabled_by_flags(methodHandle method, methodHandle compilation_context) {
|
||||
bool vmIntrinsics::is_disabled_by_flags(methodHandle method) {
|
||||
vmIntrinsics::ID id = method->intrinsic_id();
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
|
||||
// Check if the intrinsic corresponding to 'method' has been disabled on
|
||||
// the command line by using the DisableIntrinsic flag (either globally
|
||||
// or on a per-method level, see src/share/vm/compiler/abstractCompiler.hpp
|
||||
// for details).
|
||||
// Usually, the compilation context is the caller of the method 'method'.
|
||||
// The only case when for a non-recursive method 'method' the compilation context
|
||||
// is not the caller of the 'method' (but it is the method itself) is
|
||||
// java.lang.ref.Referene::get.
|
||||
// For java.lang.ref.Reference::get, the intrinsic version is used
|
||||
// instead of the compiled version so that the value in the referent
|
||||
// field can be registered by the G1 pre-barrier code. The intrinsified
|
||||
// version of Reference::get also adds a memory barrier to prevent
|
||||
// commoning reads from the referent field across safepoint since GC
|
||||
// can change the referent field's value. See Compile::Compile()
|
||||
// in src/share/vm/opto/compile.cpp or
|
||||
// GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
|
||||
// for more details.
|
||||
ccstr disable_intr = NULL;
|
||||
if ((DisableIntrinsic[0] != '\0' && strstr(DisableIntrinsic, vmIntrinsics::name_at(id)) != NULL) ||
|
||||
(!compilation_context.is_null() &&
|
||||
CompilerOracle::has_option_value(compilation_context, "DisableIntrinsic", disable_intr) &&
|
||||
strstr(disable_intr, vmIntrinsics::name_at(id)) != NULL)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// -XX:-InlineNatives disables nearly all intrinsics except the ones listed in
|
||||
// the following switch statement.
|
||||
if (!InlineNatives) {
|
||||
|
@ -202,7 +202,11 @@
|
||||
template(java_lang_StackTraceElement, "java/lang/StackTraceElement") \
|
||||
\
|
||||
/* Concurrency support */ \
|
||||
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
|
||||
template(java_util_concurrent_locks_AbstractOwnableSynchronizer, "java/util/concurrent/locks/AbstractOwnableSynchronizer") \
|
||||
template(java_util_concurrent_atomic_AtomicIntegerFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicIntegerFieldUpdater$AtomicIntegerFieldUpdaterImpl") \
|
||||
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_CASUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$CASUpdater") \
|
||||
template(java_util_concurrent_atomic_AtomicLongFieldUpdater_LockedUpdater, "java/util/concurrent/atomic/AtomicLongFieldUpdater$LockedUpdater") \
|
||||
template(java_util_concurrent_atomic_AtomicReferenceFieldUpdater_Impl, "java/util/concurrent/atomic/AtomicReferenceFieldUpdater$AtomicReferenceFieldUpdaterImpl") \
|
||||
template(sun_misc_Contended_signature, "Lsun/misc/Contended;") \
|
||||
\
|
||||
/* class symbols needed by intrinsics */ \
|
||||
@ -1402,7 +1406,7 @@ public:
|
||||
|
||||
// Returns true if a compiler intrinsic is disabled by command-line flags
|
||||
// and false otherwise.
|
||||
static bool is_disabled_by_flags(methodHandle method, methodHandle compilation_context);
|
||||
static bool is_disabled_by_flags(methodHandle method);
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_CLASSFILE_VMSYMBOLS_HPP
|
||||
|
@ -32,7 +32,7 @@
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "compiler/disassembler.hpp"
|
||||
#include "interpreter/bytecode.hpp"
|
||||
#include "oops/methodData.hpp"
|
||||
@ -582,9 +582,6 @@ nmethod* nmethod::new_native_nmethod(methodHandle method,
|
||||
basic_lock_owner_sp_offset,
|
||||
basic_lock_sp_offset, oop_maps);
|
||||
NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm));
|
||||
if ((PrintAssembly || CompilerOracle::should_print(method)) && nm != NULL) {
|
||||
Disassembler::decode(nm);
|
||||
}
|
||||
}
|
||||
// verify nmethod
|
||||
debug_only(if (nm) nm->verify();) // might block
|
||||
@ -666,9 +663,6 @@ nmethod* nmethod::new_nmethod(methodHandle method,
|
||||
}
|
||||
}
|
||||
NOT_PRODUCT(if (nm != NULL) note_java_nmethod(nm));
|
||||
if (PrintAssembly || CompilerOracle::has_option_string(method, "PrintAssembly")) {
|
||||
Disassembler::decode(nm);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Do verification and logging outside CodeCache_lock.
|
||||
@ -908,13 +902,6 @@ nmethod::nmethod(
|
||||
_method->is_static() == (entry_point() == _verified_entry_point),
|
||||
" entry points must be same for static methods and vice versa");
|
||||
}
|
||||
|
||||
bool printnmethods = PrintNMethods || PrintNMethodsAtLevel == _comp_level
|
||||
|| CompilerOracle::should_print(_method)
|
||||
|| CompilerOracle::has_option_string(_method, "PrintNMethods");
|
||||
if (printnmethods || PrintDebugInfo || PrintRelocations || PrintDependencies || PrintExceptionHandlers) {
|
||||
print_nmethod(printnmethods);
|
||||
}
|
||||
}
|
||||
|
||||
// Print a short set of xml attributes to identify this nmethod. The
|
||||
|
@ -26,6 +26,7 @@
|
||||
#define SHARE_VM_COMPILER_ABSTRACTCOMPILER_HPP
|
||||
|
||||
#include "ci/compilerInterface.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
|
||||
typedef void (*initializer)(void);
|
||||
|
||||
@ -114,36 +115,33 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
|
||||
// Determine if the current compiler provides an intrinsic
|
||||
// for method 'method'. An intrinsic is available if:
|
||||
// - the intrinsic is enabled (by using the appropriate command-line flag) and
|
||||
// - the intrinsic is enabled (by using the appropriate command-line flag,
|
||||
// the command-line compile ommand, or a compiler directive)
|
||||
// - the platform on which the VM is running supports the intrinsic
|
||||
// (i.e., the platform provides the instructions necessary for the compiler
|
||||
// to generate the intrinsic code).
|
||||
//
|
||||
// The second parameter, 'compilation_context', is needed to implement functionality
|
||||
// related to the DisableIntrinsic command-line flag. The DisableIntrinsic flag can
|
||||
// be used to prohibit the compilers to use an intrinsic. There are three ways to
|
||||
// disable an intrinsic using the DisableIntrinsic flag:
|
||||
// The directive provides the compilation context and includes pre-evaluated values
|
||||
// dependent on VM flags, compile commands, and compiler directives.
|
||||
//
|
||||
// (1) -XX:DisableIntrinsic=_hashCode,_getClass
|
||||
// Disables intrinsification of _hashCode and _getClass globally
|
||||
// (i.e., the intrinsified version the methods will not be used at all).
|
||||
// (2) -XX:CompileCommand=option,aClass::aMethod,ccstr,DisableIntrinsic,_hashCode
|
||||
// Disables intrinsification of _hashCode if it is called from
|
||||
// aClass::aMethod (but not for any other call site of _hashCode)
|
||||
// (3) -XX:CompileCommand=option,java.lang.ref.Reference::get,ccstr,DisableIntrinsic,_Reference_get
|
||||
// Some methods are not compiled by C2. Instead, the C2 compiler
|
||||
// returns directly the intrinsified version of these methods.
|
||||
// The command above forces C2 to compile _Reference_get, but
|
||||
// allows using the intrinsified version of _Reference_get at all
|
||||
// other call sites.
|
||||
//
|
||||
// From the modes above, (1) disable intrinsics globally, (2) and (3)
|
||||
// disable intrinsics on a per-method basis. In cases (2) and (3) the
|
||||
// compilation context is aClass::aMethod and java.lang.ref.Reference::get,
|
||||
// respectively.
|
||||
virtual bool is_intrinsic_available(methodHandle method, methodHandle compilation_context) {
|
||||
// Usually, the compilation context is the caller of the method 'method'.
|
||||
// The only case when for a non-recursive method 'method' the compilation context
|
||||
// is not the caller of the 'method' (but it is the method itself) is
|
||||
// java.lang.ref.Referene::get.
|
||||
// For java.lang.ref.Reference::get, the intrinsic version is used
|
||||
// instead of the compiled version so that the value in the referent
|
||||
// field can be registered by the G1 pre-barrier code. The intrinsified
|
||||
// version of Reference::get also adds a memory barrier to prevent
|
||||
// commoning reads from the referent field across safepoint since GC
|
||||
// can change the referent field's value. See Compile::Compile()
|
||||
// in src/share/vm/opto/compile.cpp or
|
||||
// GraphBuilder::GraphBuilder() in src/share/vm/c1/c1_GraphBuilder.cpp
|
||||
// for more details.
|
||||
|
||||
virtual bool is_intrinsic_available(methodHandle method, DirectiveSet* directive) {
|
||||
return is_intrinsic_supported(method) &&
|
||||
!vmIntrinsics::is_disabled_by_flags(method, compilation_context);
|
||||
!directive->is_intrinsic_disabled(method) &&
|
||||
!vmIntrinsics::is_disabled_by_flags(method);
|
||||
}
|
||||
|
||||
// Determines if an intrinsic is supported by the compiler, that is,
|
||||
@ -176,7 +174,7 @@ class AbstractCompiler : public CHeapObj<mtCompiler> {
|
||||
void set_state (int state);
|
||||
void set_shut_down () { set_state(shut_down); }
|
||||
// Compilation entry point for methods
|
||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
|
||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
|
@ -29,6 +29,7 @@
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "compiler/directivesParser.hpp"
|
||||
#include "interpreter/linkResolver.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "oops/methodData.hpp"
|
||||
@ -202,10 +203,22 @@ class CompilationLog : public StringEventLog {
|
||||
|
||||
static CompilationLog* _compilation_log = NULL;
|
||||
|
||||
void compileBroker_init() {
|
||||
bool compileBroker_init() {
|
||||
if (LogEvents) {
|
||||
_compilation_log = new CompilationLog();
|
||||
}
|
||||
|
||||
// init directives stack, adding default directive
|
||||
DirectivesStack::init();
|
||||
|
||||
if (DirectivesParser::has_file()) {
|
||||
return DirectivesParser::parse_from_flag();
|
||||
} else if (PrintCompilerDirectives) {
|
||||
// Print default directive even when no other was added
|
||||
DirectivesStack::print(tty);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
CompileTaskWrapper::CompileTaskWrapper(CompileTask* task) {
|
||||
@ -1180,12 +1193,16 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci,
|
||||
return true;
|
||||
}
|
||||
|
||||
// Breaking the abstraction - directives are only used inside a compilation otherwise.
|
||||
DirectiveSet* directive = DirectivesStack::getMatchingDirective(method, comp);
|
||||
bool excluded = directive->ExcludeOption;
|
||||
DirectivesStack::release(directive);
|
||||
|
||||
// The method may be explicitly excluded by the user.
|
||||
bool quietly;
|
||||
double scale;
|
||||
if (CompilerOracle::should_exclude(method, quietly)
|
||||
|| (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
|
||||
if (!quietly) {
|
||||
if (excluded || (CompilerOracle::has_option_value(method, "CompileThresholdScaling", scale) && scale == 0)) {
|
||||
bool quietly = CompilerOracle::should_exclude_quietly();
|
||||
if (PrintCompilation && !quietly) {
|
||||
// This does not happen quietly...
|
||||
ResourceMark rm;
|
||||
tty->print("### Excluding %s:%s",
|
||||
@ -1194,7 +1211,7 @@ bool CompileBroker::compilation_is_prohibited(methodHandle method, int osr_bci,
|
||||
method->print_short_name(tty);
|
||||
tty->cr();
|
||||
}
|
||||
method->set_not_compilable(CompLevel_all, !quietly, "excluded by CompileCommand");
|
||||
method->set_not_compilable(comp_level, !quietly, "excluded by CompileCommand");
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -1357,7 +1374,6 @@ bool CompileBroker::init_compiler_runtime() {
|
||||
ThreadInVMfromNative tv(thread);
|
||||
ResetNoHandleMark rnhm;
|
||||
|
||||
|
||||
if (!comp->is_shark()) {
|
||||
// Perform per-thread and global initializations
|
||||
comp->initialize();
|
||||
@ -1629,6 +1645,10 @@ void CompileBroker::post_compile(CompilerThread* thread, CompileTask* task, Even
|
||||
}
|
||||
}
|
||||
|
||||
int DirectivesStack::_depth = 0;
|
||||
CompilerDirectives* DirectivesStack::_top = NULL;
|
||||
CompilerDirectives* DirectivesStack::_bottom = NULL;
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// CompileBroker::invoke_compiler_on_method
|
||||
//
|
||||
@ -1655,16 +1675,20 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
bool should_log = (thread->log() != NULL);
|
||||
bool should_break = false;
|
||||
int task_level = task->comp_level();
|
||||
|
||||
// Look up matching directives
|
||||
DirectiveSet* directive = DirectivesStack::getMatchingDirective(task->method(), compiler(task_level));
|
||||
|
||||
should_break = directive->BreakAtExecuteOption || task->check_break_at_flags();
|
||||
if (should_log && !directive->LogOption) {
|
||||
should_log = false;
|
||||
}
|
||||
{
|
||||
// create the handle inside it's own block so it can't
|
||||
// accidentally be referenced once the thread transitions to
|
||||
// native. The NoHandleMark before the transition should catch
|
||||
// any cases where this occurs in the future.
|
||||
methodHandle method(thread, task->method());
|
||||
should_break = check_break_at(method, compile_id, is_osr);
|
||||
if (should_log && !CompilerOracle::should_log(method)) {
|
||||
should_log = false;
|
||||
}
|
||||
assert(!method->is_native(), "no longer compile natives");
|
||||
|
||||
// Save information about this method in case of failure.
|
||||
@ -1732,7 +1756,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
locker.wait(Mutex::_no_safepoint_check_flag);
|
||||
}
|
||||
}
|
||||
comp->compile_method(&ci_env, target, osr_bci);
|
||||
comp->compile_method(&ci_env, target, osr_bci, directive);
|
||||
}
|
||||
|
||||
if (!ci_env.failing() && task->code() == NULL) {
|
||||
@ -1762,6 +1786,7 @@ void CompileBroker::invoke_compiler_on_method(CompileTask* task) {
|
||||
|
||||
post_compile(thread, task, event, !ci_env.failing(), &ci_env);
|
||||
}
|
||||
DirectivesStack::release(directive);
|
||||
pop_jni_handle_block();
|
||||
|
||||
methodHandle method(thread, task->method());
|
||||
@ -1947,21 +1972,6 @@ void CompileBroker::pop_jni_handle_block() {
|
||||
JNIHandleBlock::release_block(compile_handles, thread); // may block
|
||||
}
|
||||
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// CompileBroker::check_break_at
|
||||
//
|
||||
// Should the compilation break at the current compilation.
|
||||
bool CompileBroker::check_break_at(methodHandle method, int compile_id, bool is_osr) {
|
||||
if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
|
||||
return true;
|
||||
} else if( CompilerOracle::should_break_at(method) ) { // break when compiling
|
||||
return true;
|
||||
} else {
|
||||
return (compile_id == CIBreakAt);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// CompileBroker::collect_statistics
|
||||
//
|
||||
@ -2232,3 +2242,4 @@ void CompileBroker::print_compiler_threads_on(outputStream* st) {
|
||||
st->cr();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -28,8 +28,10 @@
|
||||
#include "ci/compilerInterface.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compileTask.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "runtime/perfData.hpp"
|
||||
#include "trace/tracing.hpp"
|
||||
#include "utilities/stack.hpp"
|
||||
|
||||
class nmethod;
|
||||
class nmethodLocker;
|
||||
@ -129,13 +131,12 @@ public:
|
||||
~CompileTaskWrapper();
|
||||
};
|
||||
|
||||
|
||||
// Compilation
|
||||
//
|
||||
// The broker for all compilation requests.
|
||||
class CompileBroker: AllStatic {
|
||||
friend class Threads;
|
||||
friend class CompileTaskWrapper;
|
||||
friend class CompileTaskWrapper;
|
||||
|
||||
public:
|
||||
enum {
|
||||
@ -238,7 +239,6 @@ class CompileBroker: AllStatic {
|
||||
static void set_last_compile(CompilerThread *thread, methodHandle method, bool is_osr, int comp_level);
|
||||
static void push_jni_handle_block();
|
||||
static void pop_jni_handle_block();
|
||||
static bool check_break_at(methodHandle method, int compile_id, bool is_osr);
|
||||
static void collect_statistics(CompilerThread* thread, elapsedTimer time, CompileTask* task);
|
||||
|
||||
static void compile_method_base(methodHandle method,
|
||||
@ -253,7 +253,11 @@ class CompileBroker: AllStatic {
|
||||
static bool init_compiler_runtime();
|
||||
static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread);
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
static DirectivesStack* dirstack();
|
||||
static void set_dirstack(DirectivesStack* stack);
|
||||
|
||||
enum {
|
||||
// The entry bci used for non-OSR compilations.
|
||||
standard_entry_bci = InvocationEntryBci
|
||||
@ -267,6 +271,7 @@ class CompileBroker: AllStatic {
|
||||
|
||||
static bool compilation_is_in_queue(methodHandle method);
|
||||
static void print_compile_queues(outputStream* st);
|
||||
static void print_directives(outputStream* st);
|
||||
static int queue_size(int comp_level) {
|
||||
CompileQueue *q = compile_queue(comp_level);
|
||||
return q != NULL ? q->size() : 0;
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "compiler/compileTask.hpp"
|
||||
#include "compiler/compileLog.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
|
||||
CompileTask* CompileTask::_task_free_list = NULL;
|
||||
#ifdef ASSERT
|
||||
@ -371,6 +372,19 @@ void CompileTask::log_task_done(CompileLog* log) {
|
||||
log->mark_file_end();
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// CompileTask::check_break_at_flags
|
||||
bool CompileTask::check_break_at_flags() {
|
||||
int compile_id = this->_compile_id;
|
||||
bool is_osr = (_osr_bci != CompileBroker::standard_entry_bci);
|
||||
|
||||
if (CICountOSR && is_osr && (compile_id == CIBreakAtOSR)) {
|
||||
return true;
|
||||
} else {
|
||||
return (compile_id == CIBreakAt);
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------
|
||||
// CompileTask::print_inlining
|
||||
void CompileTask::print_inlining_inner(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg) {
|
||||
|
560
hotspot/src/share/vm/compiler/compilerDirectives.cpp
Normal file
560
hotspot/src/share/vm/compiler/compilerDirectives.cpp
Normal file
@ -0,0 +1,560 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "compiler/abstractCompiler.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
|
||||
CompilerDirectives::CompilerDirectives() :_match(NULL), _next(NULL), _ref_count(0) {
|
||||
_c1_store = new DirectiveSet(this);
|
||||
_c2_store = new DirectiveSet(this);
|
||||
};
|
||||
|
||||
CompilerDirectives::~CompilerDirectives() {
|
||||
if (_c1_store != NULL) {
|
||||
delete _c1_store;
|
||||
}
|
||||
if (_c2_store != NULL) {
|
||||
delete _c2_store;
|
||||
}
|
||||
|
||||
// remove all linked method matchers
|
||||
BasicMatcher* tmp = _match;
|
||||
while (tmp != NULL) {
|
||||
BasicMatcher* next = tmp->next();
|
||||
delete tmp;
|
||||
tmp = next;
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerDirectives::print(outputStream* st) {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
if (_match != NULL) {
|
||||
st->cr();
|
||||
st->print("Directive:");
|
||||
if (is_default_directive()) {
|
||||
st->print_cr(" (default)");
|
||||
} else {
|
||||
st->cr();
|
||||
}
|
||||
st->print(" matching: ");
|
||||
_match->print(st);
|
||||
BasicMatcher* tmp = _match->next();
|
||||
while (tmp != NULL) {
|
||||
st->print(", ");
|
||||
tmp->print(st);
|
||||
tmp = tmp->next();
|
||||
}
|
||||
st->cr();
|
||||
} else {
|
||||
assert(0, "There should always be a match");
|
||||
}
|
||||
|
||||
if (_c1_store != NULL) {
|
||||
st->print_cr(" c1 directives:");
|
||||
_c1_store->print(st);
|
||||
}
|
||||
if (_c2_store != NULL) {
|
||||
st->cr();
|
||||
st->print_cr(" c2 directives:");
|
||||
_c2_store->print(st);
|
||||
}
|
||||
//---
|
||||
}
|
||||
|
||||
void CompilerDirectives::finalize() {
|
||||
if (_c1_store != NULL) {
|
||||
_c1_store->finalize();
|
||||
}
|
||||
if (_c2_store != NULL) {
|
||||
_c2_store->finalize();
|
||||
}
|
||||
}
|
||||
|
||||
void DirectiveSet::finalize() {
|
||||
// if any flag has been modified - set directive as enabled
|
||||
// unless it already has been explicitly set.
|
||||
if (!_modified[EnableIndex]) {
|
||||
if (_inlinematchers != NULL) {
|
||||
EnableOption = true;
|
||||
return;
|
||||
}
|
||||
int i;
|
||||
for (i = 0; i < number_of_flags; i++) {
|
||||
if (_modified[i]) {
|
||||
EnableOption = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CompilerDirectives* CompilerDirectives::next() {
|
||||
return _next;
|
||||
}
|
||||
|
||||
bool CompilerDirectives::match(methodHandle method) {
|
||||
if (is_default_directive()) {
|
||||
return true;
|
||||
}
|
||||
if (method == NULL) {
|
||||
return false;
|
||||
}
|
||||
if (_match->match(method)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompilerDirectives::add_match(char* str, const char*& error_msg) {
|
||||
BasicMatcher* bm = BasicMatcher::parse_method_pattern(str, error_msg);
|
||||
if (bm == NULL) {
|
||||
assert(error_msg != NULL, "Must have error message");
|
||||
return false;
|
||||
} else {
|
||||
bm->set_next(_match);
|
||||
_match = bm;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerDirectives::inc_refcount() {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
_ref_count++;
|
||||
}
|
||||
|
||||
void CompilerDirectives::dec_refcount() {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
_ref_count--;
|
||||
}
|
||||
|
||||
int CompilerDirectives::refcount() {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
return _ref_count;
|
||||
}
|
||||
|
||||
DirectiveSet* CompilerDirectives::get_for(AbstractCompiler *comp) {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
inc_refcount(); // The compiling thread is responsible to decrement this when finished.
|
||||
if (comp == NULL) { // Xint
|
||||
return _c1_store;
|
||||
} else if (comp->is_c2()) {
|
||||
return _c2_store;
|
||||
} else if (comp->is_c1()) {
|
||||
return _c1_store;
|
||||
} else if (comp->is_shark()) {
|
||||
return NULL;
|
||||
} else if (comp->is_jvmci()) {
|
||||
return NULL;
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// In the list of disabled intrinsics, the ID of the disabled intrinsics can separated:
|
||||
// - by ',' (if -XX:DisableIntrinsic is used once when invoking the VM) or
|
||||
// - by '\n' (if -XX:DisableIntrinsic is used multiple times when invoking the VM) or
|
||||
// - by ' ' (if DisableIntrinsic is used on a per-method level, e.g., with CompileCommand).
|
||||
//
|
||||
// To simplify the processing of the list, the canonicalize_disableintrinsic() method
|
||||
// returns a new copy of the list in which '\n' and ' ' is replaced with ','.
|
||||
ccstrlist DirectiveSet::canonicalize_disableintrinsic(ccstrlist option_value) {
|
||||
char* canonicalized_list = NEW_C_HEAP_ARRAY(char, strlen(option_value) + 1, mtCompiler);
|
||||
int i = 0;
|
||||
char current;
|
||||
while ((current = option_value[i]) != '\0') {
|
||||
if (current == '\n' || current == ' ') {
|
||||
canonicalized_list[i] = ',';
|
||||
} else {
|
||||
canonicalized_list[i] = current;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
canonicalized_list[i] = '\0';
|
||||
return canonicalized_list;
|
||||
}
|
||||
|
||||
DirectiveSet::DirectiveSet(CompilerDirectives* d) :_inlinematchers(NULL), _directive(d) {
|
||||
#define init_defaults_definition(name, type, dvalue, compiler) this->name##Option = dvalue;
|
||||
compilerdirectives_common_flags(init_defaults_definition)
|
||||
compilerdirectives_c2_flags(init_defaults_definition)
|
||||
compilerdirectives_c1_flags(init_defaults_definition)
|
||||
memset(_modified, 0, sizeof _modified);
|
||||
|
||||
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
|
||||
this->DisableIntrinsicOption = canonicalize_disableintrinsic(DisableIntrinsic);
|
||||
}
|
||||
|
||||
DirectiveSet::~DirectiveSet() {
|
||||
// remove all linked methodmatchers
|
||||
InlineMatcher* tmp = _inlinematchers;
|
||||
while (tmp != NULL) {
|
||||
InlineMatcher* next = tmp->next();
|
||||
delete tmp;
|
||||
tmp = next;
|
||||
}
|
||||
|
||||
// When constructed, DirectiveSet canonicalizes the DisableIntrinsic flag
|
||||
// into a new string. Therefore, that string is deallocated when
|
||||
// the DirectiveSet is destroyed.
|
||||
assert(this->DisableIntrinsicOption != NULL, "");
|
||||
FREE_C_HEAP_ARRAY(char, (void *)this->DisableIntrinsicOption);
|
||||
}
|
||||
|
||||
// Backward compatibility for CompileCommands
|
||||
// Breaks the abstraction and causes lots of extra complexity
|
||||
// - if some option is changed we need to copy directiveset since it no longer can be shared
|
||||
// - Need to free copy after use
|
||||
// - Requires a modified bit so we don't overwrite options that is set by directives
|
||||
|
||||
DirectiveSet* DirectiveSet::compilecommand_compatibility_init(methodHandle method) {
|
||||
// Early bail out - checking all options is expensive - we rely on them not being used
|
||||
// Only set a flag if it has not been modified and value changes.
|
||||
// Only copy set if a flag needs to be set
|
||||
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::has_any_option()) {
|
||||
DirectiveSet* set = DirectiveSet::clone(this);
|
||||
|
||||
bool changed = false; // Track if we actually change anything
|
||||
|
||||
// All CompileCommands are not equal so this gets a bit verbose
|
||||
// When CompileCommands have been refactored less clutter will remain.
|
||||
if (CompilerOracle::should_break_at(method)) {
|
||||
if (!_modified[BreakAtCompileIndex]) {
|
||||
set->BreakAtCompileOption = true;
|
||||
changed = true;
|
||||
}
|
||||
if (!_modified[BreakAtExecuteIndex]) {
|
||||
set->BreakAtExecuteOption = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (CompilerOracle::should_log(method)) {
|
||||
if (!_modified[LogIndex]) {
|
||||
set->LogOption = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
if (CompilerOracle::should_print(method)) {
|
||||
if (!_modified[PrintAssemblyIndex]) {
|
||||
set->PrintAssemblyOption = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
// Exclude as in should not compile == Enabled
|
||||
if (CompilerOracle::should_exclude(method)) {
|
||||
if (!_modified[ExcludeIndex]) {
|
||||
set->ExcludeOption = true;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// inline and dontinline (including exclude) are implemented in the directiveset accessors
|
||||
#define init_default_cc(name, type, dvalue, cc_flag) { type v; if (!_modified[name##Index] && CompilerOracle::has_option_value(method, #cc_flag, v) && v != this->name##Option) { set->name##Option = v; changed = true;} }
|
||||
compilerdirectives_common_flags(init_default_cc)
|
||||
compilerdirectives_c2_flags(init_default_cc)
|
||||
compilerdirectives_c1_flags(init_default_cc)
|
||||
|
||||
// Canonicalize DisableIntrinsic to contain only ',' as a separator.
|
||||
ccstrlist option_value;
|
||||
if (!_modified[DisableIntrinsicIndex] &&
|
||||
CompilerOracle::has_option_value(method, "DisableIntrinsic", option_value)) {
|
||||
set->DisableIntrinsicOption = canonicalize_disableintrinsic(option_value);
|
||||
}
|
||||
|
||||
|
||||
if (!changed) {
|
||||
// We didn't actually update anything, discard.
|
||||
delete set;
|
||||
} else {
|
||||
// We are returning a (parentless) copy. The originals parent don't need to account for this.
|
||||
DirectivesStack::release(this);
|
||||
return set;
|
||||
}
|
||||
}
|
||||
// Nothing changed
|
||||
return this;
|
||||
}
|
||||
|
||||
CompilerDirectives* DirectiveSet::directive() {
|
||||
assert(_directive != NULL, "Must have been initialized");
|
||||
return _directive;
|
||||
}
|
||||
|
||||
bool DirectiveSet::matches_inline(methodHandle method, int inline_action) {
|
||||
if (_inlinematchers != NULL) {
|
||||
if (_inlinematchers->match(method, InlineMatcher::force_inline)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirectiveSet::should_inline(ciMethod* inlinee) {
|
||||
inlinee->check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, inlinee->get_Method());
|
||||
|
||||
if (matches_inline(mh, InlineMatcher::force_inline)) {
|
||||
return true;
|
||||
}
|
||||
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_inline(mh)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirectiveSet::should_not_inline(ciMethod* inlinee) {
|
||||
inlinee->check_is_loaded();
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, inlinee->get_Method());
|
||||
|
||||
if (matches_inline(mh, InlineMatcher::dont_inline)) {
|
||||
return true;
|
||||
}
|
||||
if (!CompilerDirectivesIgnoreCompileCommandsOption && CompilerOracle::should_not_inline(mh)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) {
|
||||
InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg);
|
||||
if (m != NULL) {
|
||||
// add matcher last in chain - the order is significant
|
||||
append_inline(m);
|
||||
return true;
|
||||
} else {
|
||||
assert(error_msg != NULL, "Error message must be set");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void DirectiveSet::append_inline(InlineMatcher* m) {
|
||||
if (_inlinematchers == NULL) {
|
||||
_inlinematchers = m;
|
||||
return;
|
||||
}
|
||||
InlineMatcher* tmp = _inlinematchers;
|
||||
while (tmp->next() != NULL) {
|
||||
tmp = tmp->next();
|
||||
}
|
||||
tmp->set_next(m);
|
||||
}
|
||||
|
||||
void DirectiveSet::print_inline(outputStream* st) {
|
||||
if (_inlinematchers == NULL) {
|
||||
st->print_cr(" inline: -");
|
||||
} else {
|
||||
st->print(" inline: ");
|
||||
_inlinematchers->print(st);
|
||||
InlineMatcher* tmp = _inlinematchers->next();
|
||||
while (tmp != NULL) {
|
||||
st->print(", ");
|
||||
tmp->print(st);
|
||||
tmp = tmp->next();
|
||||
}
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectiveSet::is_intrinsic_disabled(methodHandle method) {
|
||||
vmIntrinsics::ID id = method->intrinsic_id();
|
||||
assert(id != vmIntrinsics::_none, "must be a VM intrinsic");
|
||||
|
||||
ResourceMark rm;
|
||||
|
||||
// Create a copy of the string that contains the list of disabled
|
||||
// intrinsics. The copy is created because the string
|
||||
// will be modified by strtok(). Then, the list is tokenized with
|
||||
// ',' as a separator.
|
||||
size_t length = strlen(DisableIntrinsicOption);
|
||||
char* local_list = NEW_RESOURCE_ARRAY(char, length + 1);
|
||||
strncpy(local_list, DisableIntrinsicOption, length + 1);
|
||||
|
||||
char* token = strtok(local_list, ",");
|
||||
while (token != NULL) {
|
||||
if (strcmp(token, vmIntrinsics::name_at(id)) == 0) {
|
||||
return true;
|
||||
} else {
|
||||
token = strtok(NULL, ",");
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
DirectiveSet* DirectiveSet::clone(DirectiveSet const* src) {
|
||||
DirectiveSet* set = new DirectiveSet(NULL);
|
||||
memcpy(set->_modified, src->_modified, sizeof(src->_modified));
|
||||
|
||||
InlineMatcher* tmp = src->_inlinematchers;
|
||||
while (tmp != NULL) {
|
||||
set->append_inline(tmp->clone());
|
||||
tmp = tmp->next();
|
||||
}
|
||||
|
||||
#define copy_members_definition(name, type, dvalue, cc_flag) set->name##Option = src->name##Option;
|
||||
compilerdirectives_common_flags(copy_members_definition)
|
||||
compilerdirectives_c2_flags(copy_members_definition)
|
||||
compilerdirectives_c1_flags(copy_members_definition)
|
||||
|
||||
// Create a local copy of the DisableIntrinsicOption.
|
||||
assert(src->DisableIntrinsicOption != NULL, "");
|
||||
size_t len = strlen(src->DisableIntrinsicOption) + 1;
|
||||
char* s = NEW_C_HEAP_ARRAY(char, len, mtCompiler);
|
||||
strncpy(s, src->DisableIntrinsicOption, len);
|
||||
assert(s[len-1] == '\0', "");
|
||||
set->DisableIntrinsicOption = s;
|
||||
return set;
|
||||
}
|
||||
|
||||
// Create a new dirstack and push a default directive
|
||||
void DirectivesStack::init() {
|
||||
CompilerDirectives* _default_directives = new CompilerDirectives();
|
||||
char str[] = "*.*";
|
||||
const char* error_msg = NULL;
|
||||
_default_directives->add_match(str, error_msg);
|
||||
#ifdef COMPILER1
|
||||
_default_directives->_c1_store->EnableOption = true;
|
||||
#endif
|
||||
#ifdef COMPILER2
|
||||
_default_directives->_c2_store->EnableOption = true;
|
||||
#endif
|
||||
assert(error_msg == NULL, "Must succeed.");
|
||||
push(_default_directives);
|
||||
}
|
||||
|
||||
DirectiveSet* DirectivesStack::getDefaultDirective(AbstractCompiler* comp) {
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
assert(_bottom != NULL, "Must never be empty");
|
||||
return _bottom->get_for(comp);
|
||||
}
|
||||
|
||||
void DirectivesStack::push(CompilerDirectives* directive) {
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
|
||||
directive->inc_refcount();
|
||||
if (_top == NULL) {
|
||||
assert(_bottom == NULL, "There can only be one default directive");
|
||||
_bottom = directive; // default directive, can never be removed.
|
||||
}
|
||||
|
||||
directive->set_next(_top);
|
||||
_top = directive;
|
||||
_depth++;
|
||||
}
|
||||
|
||||
void DirectivesStack::pop() {
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
pop_inner();
|
||||
}
|
||||
|
||||
void DirectivesStack::pop_inner() {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
|
||||
if (_top->next() == NULL) {
|
||||
return; // Do nothing - don't allow an empty stack
|
||||
}
|
||||
CompilerDirectives* tmp = _top;
|
||||
_top = _top->next();
|
||||
_depth--;
|
||||
|
||||
DirectivesStack::release(tmp);
|
||||
}
|
||||
|
||||
void DirectivesStack::clear() {
|
||||
// holding the lock during the whole operation ensuring consistent result
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
while (_top->next() != NULL) {
|
||||
pop_inner();
|
||||
}
|
||||
}
|
||||
|
||||
void DirectivesStack::print(outputStream* st) {
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
CompilerDirectives* tmp = _top;
|
||||
while (tmp != NULL) {
|
||||
tmp->print(st);
|
||||
tmp = tmp->next();
|
||||
st->cr();
|
||||
}
|
||||
}
|
||||
|
||||
void DirectivesStack::release(DirectiveSet* set) {
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
if (set->is_exclusive_copy()) {
|
||||
// Old CompilecCmmands forced us to create an exclusive copy
|
||||
delete set;
|
||||
} else {
|
||||
assert(set->directive() != NULL, "");
|
||||
release(set->directive());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void DirectivesStack::release(CompilerDirectives* dir) {
|
||||
assert(DirectivesStack_lock->owned_by_self(), "");
|
||||
dir->dec_refcount();
|
||||
if (dir->refcount() == 0) {
|
||||
delete dir;
|
||||
}
|
||||
}
|
||||
|
||||
DirectiveSet* DirectivesStack::getMatchingDirective(methodHandle method, AbstractCompiler *comp) {
|
||||
assert(_depth > 0, "Must never be empty");
|
||||
CompilerDirectives* dir = _top;
|
||||
assert(dir != NULL, "Must be initialized");
|
||||
|
||||
DirectiveSet* match = NULL;
|
||||
{
|
||||
MutexLockerEx locker(DirectivesStack_lock, Mutex::_no_safepoint_check_flag);
|
||||
while (dir != NULL) {
|
||||
if (dir->is_default_directive() || dir->match(method)) {
|
||||
match = dir->get_for(comp);
|
||||
if (match == NULL) {
|
||||
// temporary workaround for compilers without directives.
|
||||
if (dir->is_default_directive()) {
|
||||
// default dir is always enabled
|
||||
// match c1 store - it contains all common flags even if C1 is unavailable
|
||||
match = dir->_c1_store;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match->EnableOption) {
|
||||
// The directiveSet for this compile is also enabled -> success
|
||||
break;
|
||||
}
|
||||
}
|
||||
dir = dir->next();
|
||||
}
|
||||
}
|
||||
|
||||
guarantee(match != NULL, "There should always be a default directive that matches");
|
||||
// Check for legacy compile commands update, without DirectivesStack_lock
|
||||
return match->compilecommand_compatibility_init(method);
|
||||
}
|
189
hotspot/src/share/vm/compiler/compilerDirectives.hpp
Normal file
189
hotspot/src/share/vm/compiler/compilerDirectives.hpp
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 1998, 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
|
||||
#define SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
|
||||
|
||||
#include "ci/ciMetadata.hpp"
|
||||
#include "ci/ciMethod.hpp"
|
||||
#include "ci/ciUtilities.hpp"
|
||||
#include "compiler/methodMatcher.hpp"
|
||||
#include "compiler/compilerOracle.hpp"
|
||||
#include "oops/oop.inline.hpp"
|
||||
#include "utilities/exceptions.hpp"
|
||||
|
||||
// Directives flag name, type, default value, compile command name
|
||||
#define compilerdirectives_common_flags(cflags) \
|
||||
cflags(Enable, bool, false, X) \
|
||||
cflags(Exclude, bool, false, X) \
|
||||
cflags(BreakAtExecute, bool, false, X) \
|
||||
cflags(BreakAtCompile, bool, false, X) \
|
||||
cflags(Log, bool, false, X) \
|
||||
cflags(PrintAssembly, bool, PrintAssembly, PrintAssembly) \
|
||||
cflags(PrintInlining, bool, PrintInlining, PrintInlining) \
|
||||
cflags(PrintNMethods, bool, PrintNMethods, PrintNMethods) \
|
||||
cflags(ReplayInline, bool, false, ReplayInline) \
|
||||
cflags(DumpReplay, bool, false, DumpReplay) \
|
||||
cflags(DumpInline, bool, false, DumpInline) \
|
||||
cflags(CompilerDirectivesIgnoreCompileCommands, bool, CompilerDirectivesIgnoreCompileCommands, X) \
|
||||
cflags(DisableIntrinsic, ccstrlist, DisableIntrinsic, DisableIntrinsic)
|
||||
|
||||
#ifdef COMPILER1
|
||||
#define compilerdirectives_c1_flags(cflags)
|
||||
#else
|
||||
#define compilerdirectives_c1_flags(cflags)
|
||||
#endif
|
||||
|
||||
#ifdef COMPILER2
|
||||
#define compilerdirectives_c2_flags(cflags) \
|
||||
cflags(BlockLayoutByFrequency, bool, BlockLayoutByFrequency, BlockLayoutByFrequency) \
|
||||
cflags(PrintOptoAssembly, bool, PrintOptoAssembly, PrintOptoAssembly) \
|
||||
cflags(PrintIntrinsics, bool, PrintIntrinsics, PrintIntrinsics) \
|
||||
cflags(TraceOptoPipelining, bool, false, TraceOptoPipelining) \
|
||||
cflags(TraceOptoOutput, bool, false, TraceOptoOutput) \
|
||||
cflags(TraceSpilling, bool, TraceSpilling, TraceSpilling) \
|
||||
cflags(Vectorize, bool, false, Vectorize) \
|
||||
cflags(VectorizeDebug, bool, false, VectorizeDebug) \
|
||||
cflags(CloneMapDebug, bool, false, CloneMapDebug) \
|
||||
cflags(DoReserveCopyInSuperWordDebug, bool, false, DoReserveCopyInSuperWordDebug) \
|
||||
NOT_PRODUCT( cflags(IGVPrintLevel, intx, PrintIdealGraphLevel, IGVPrintLevel)) \
|
||||
cflags(MaxNodeLimit, intx, MaxNodeLimit, MaxNodeLimit)
|
||||
#else
|
||||
#define compilerdirectives_c2_flags(cflags)
|
||||
#endif
|
||||
|
||||
class CompilerDirectives;
|
||||
class DirectiveSet;
|
||||
|
||||
class DirectivesStack : AllStatic {
|
||||
private:
|
||||
static CompilerDirectives* _top;
|
||||
static CompilerDirectives* _bottom;
|
||||
static int _depth;
|
||||
|
||||
static void pop_inner(); // no lock version of pop
|
||||
public:
|
||||
static void init();
|
||||
static DirectiveSet* getMatchingDirective(methodHandle mh, AbstractCompiler* comp);
|
||||
static DirectiveSet* getDefaultDirective(AbstractCompiler* comp);
|
||||
static void push(CompilerDirectives* directive);
|
||||
static void pop();
|
||||
static void clear();
|
||||
static void print(outputStream* st);
|
||||
static void release(DirectiveSet* set);
|
||||
static void release(CompilerDirectives* dir);
|
||||
};
|
||||
|
||||
class DirectiveSet : public CHeapObj<mtCompiler> {
|
||||
private:
|
||||
InlineMatcher* _inlinematchers;
|
||||
CompilerDirectives* _directive;
|
||||
|
||||
static ccstrlist canonicalize_disableintrinsic(ccstrlist option_value);
|
||||
|
||||
public:
|
||||
DirectiveSet(CompilerDirectives* directive);
|
||||
~DirectiveSet();
|
||||
CompilerDirectives* directive();
|
||||
bool parse_and_add_inline(char* str, const char*& error_msg);
|
||||
void append_inline(InlineMatcher* m);
|
||||
bool should_inline(ciMethod* inlinee);
|
||||
bool should_not_inline(ciMethod* inlinee);
|
||||
void print_inline(outputStream* st);
|
||||
DirectiveSet* compilecommand_compatibility_init(methodHandle method);
|
||||
bool is_exclusive_copy() { return _directive == NULL; }
|
||||
bool matches_inline(methodHandle method, int inline_action);
|
||||
static DirectiveSet* clone(DirectiveSet const* src);
|
||||
bool is_intrinsic_disabled(methodHandle method);
|
||||
void finalize();
|
||||
|
||||
typedef enum {
|
||||
#define enum_of_flags(name, type, dvalue, cc_flag) name##Index,
|
||||
compilerdirectives_common_flags(enum_of_flags)
|
||||
compilerdirectives_c2_flags(enum_of_flags)
|
||||
compilerdirectives_c1_flags(enum_of_flags)
|
||||
number_of_flags
|
||||
} flags;
|
||||
|
||||
bool _modified[number_of_flags];
|
||||
|
||||
#define flag_store_definition(name, type, dvalue, cc_flag) type name##Option;
|
||||
compilerdirectives_common_flags(flag_store_definition)
|
||||
compilerdirectives_c2_flags(flag_store_definition)
|
||||
compilerdirectives_c1_flags(flag_store_definition)
|
||||
|
||||
// Casting to get the same function signature for all setters. Used from parser.
|
||||
#define set_function_definition(name, type, dvalue, cc_flag) void set_##name(void* value) { type val = *(type*)value; name##Option = val; _modified[name##Index] = 1; }
|
||||
compilerdirectives_common_flags(set_function_definition)
|
||||
compilerdirectives_c2_flags(set_function_definition)
|
||||
compilerdirectives_c1_flags(set_function_definition)
|
||||
|
||||
void print_intx(outputStream* st, ccstr n, intx v, bool mod) { if (mod) { st->print("%s:" INTX_FORMAT " ", n, v); } }
|
||||
void print_bool(outputStream* st, ccstr n, bool v, bool mod) { if (mod) { st->print("%s:%s ", n, v ? "true" : "false"); } }
|
||||
void print_double(outputStream* st, ccstr n, double v, bool mod) { if (mod) { st->print("%s:%f ", n, v); } }
|
||||
void print_ccstr(outputStream* st, ccstr n, ccstr v, bool mod) { if (mod) { st->print("%s:%s ", n, v); } }
|
||||
void print_ccstrlist(outputStream* st, ccstr n, ccstr v, bool mod) { print_ccstr(st, n, v, mod); }
|
||||
|
||||
void print(outputStream* st) {
|
||||
print_inline(st);
|
||||
st->print(" ");
|
||||
#define print_function_definition(name, type, dvalue, cc_flag) print_##type(st, #name, this->name##Option, true);//(bool)_modified[name##Index]);
|
||||
compilerdirectives_common_flags(print_function_definition)
|
||||
compilerdirectives_c2_flags(print_function_definition)
|
||||
compilerdirectives_c1_flags(print_function_definition)
|
||||
st->cr();
|
||||
}
|
||||
};
|
||||
|
||||
class CompilerDirectives : public CHeapObj<mtCompiler> {
|
||||
private:
|
||||
CompilerDirectives* _next;
|
||||
BasicMatcher* _match;
|
||||
int _ref_count;
|
||||
|
||||
public:
|
||||
|
||||
CompilerDirectives();
|
||||
~CompilerDirectives();
|
||||
|
||||
CompilerDirectives* next();
|
||||
void set_next(CompilerDirectives* next) {_next = next; }
|
||||
|
||||
bool match(methodHandle method);
|
||||
BasicMatcher* match() { return _match; }
|
||||
bool add_match(char* str, const char*& error_msg);
|
||||
DirectiveSet* get_for(AbstractCompiler *comp);
|
||||
void print(outputStream* st);
|
||||
bool is_default_directive() { return _next == NULL; }
|
||||
void finalize();
|
||||
|
||||
void inc_refcount();
|
||||
void dec_refcount();
|
||||
int refcount();
|
||||
|
||||
DirectiveSet* _c1_store;
|
||||
DirectiveSet* _c2_store;
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_COMPILER_COMPILERDIRECTIVES_HPP
|
@ -106,6 +106,7 @@ class TypedMethodOptionMatcher;
|
||||
|
||||
static BasicMatcher* lists[OracleCommandCount] = { 0, };
|
||||
static TypedMethodOptionMatcher* option_list = NULL;
|
||||
static bool any_set = false;
|
||||
|
||||
class TypedMethodOptionMatcher : public MethodMatcher {
|
||||
private:
|
||||
@ -292,6 +293,7 @@ static void add_option_string(TypedMethodOptionMatcher* matcher,
|
||||
matcher->init(option, get_type_for<T>(), option_list);
|
||||
matcher->set_value<T>(value);
|
||||
option_list = matcher;
|
||||
any_set = true;
|
||||
return;
|
||||
}
|
||||
|
||||
@ -308,7 +310,9 @@ static void add_predicate(OracleCommand command, BasicMatcher* bm) {
|
||||
}
|
||||
bm->set_next(lists[command]);
|
||||
lists[command] = bm;
|
||||
|
||||
if ((command != DontInlineCommand) && (command != InlineCommand)) {
|
||||
any_set = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -324,6 +328,10 @@ bool CompilerOracle::has_option_value(methodHandle method, const char* option, T
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CompilerOracle::has_any_option() {
|
||||
return any_set;
|
||||
}
|
||||
|
||||
// Explicit instantiation for all OptionTypes supported.
|
||||
template bool CompilerOracle::has_option_value<intx>(methodHandle method, const char* option, intx& value);
|
||||
template bool CompilerOracle::has_option_value<uintx>(methodHandle method, const char* option, uintx& value);
|
||||
@ -337,15 +345,10 @@ bool CompilerOracle::has_option_string(methodHandle method, const char* option)
|
||||
return value;
|
||||
}
|
||||
|
||||
bool CompilerOracle::should_exclude(methodHandle method, bool& quietly) {
|
||||
quietly = true;
|
||||
if (lists[ExcludeCommand] != NULL) {
|
||||
if (lists[ExcludeCommand]->match(method)) {
|
||||
quietly = _quiet;
|
||||
return true;
|
||||
}
|
||||
bool CompilerOracle::should_exclude(methodHandle method) {
|
||||
if (check_predicate(ExcludeCommand, method)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lists[CompileOnlyCommand] != NULL) {
|
||||
return !lists[CompileOnlyCommand]->match(method);
|
||||
}
|
||||
@ -356,8 +359,6 @@ bool CompilerOracle::should_inline(methodHandle method) {
|
||||
return (check_predicate(InlineCommand, method));
|
||||
}
|
||||
|
||||
// Check both DontInlineCommand and ExcludeCommand here
|
||||
// - consistent behavior for all compilers
|
||||
bool CompilerOracle::should_not_inline(methodHandle method) {
|
||||
return check_predicate(DontInlineCommand, method) || check_predicate(ExcludeCommand, method);
|
||||
}
|
||||
|
@ -46,7 +46,8 @@ class CompilerOracle : AllStatic {
|
||||
static void parse_from_file();
|
||||
|
||||
// Tells whether we to exclude compilation of method
|
||||
static bool should_exclude(methodHandle method, bool& quietly);
|
||||
static bool should_exclude(methodHandle method);
|
||||
static bool should_exclude_quietly() { return _quiet; }
|
||||
|
||||
// Tells whether we want to inline this method
|
||||
static bool should_inline(methodHandle method);
|
||||
@ -71,6 +72,9 @@ class CompilerOracle : AllStatic {
|
||||
template<typename T>
|
||||
static bool has_option_value(methodHandle method, const char* option, T& value);
|
||||
|
||||
// Fast check if there is any option available that compile control needs to know about
|
||||
static bool has_any_option();
|
||||
|
||||
// Reads from string instead of file
|
||||
static void parse_from_string(const char* command_string, void (*parser)(char*));
|
||||
|
||||
|
726
hotspot/src/share/vm/compiler/directivesParser.cpp
Normal file
726
hotspot/src/share/vm/compiler/directivesParser.cpp
Normal file
@ -0,0 +1,726 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "precompiled.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/directivesParser.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "runtime/os.hpp"
|
||||
#include <string.h>
|
||||
|
||||
void DirectivesParser::push_tmp(CompilerDirectives* dir) {
|
||||
dir->set_next(_tmp_top);
|
||||
_tmp_top = dir;
|
||||
}
|
||||
|
||||
CompilerDirectives* DirectivesParser::pop_tmp() {
|
||||
if (_tmp_top == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
CompilerDirectives* tmp = _tmp_top;
|
||||
_tmp_top = _tmp_top->next();
|
||||
tmp->set_next(NULL);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
bool DirectivesParser::parse_string(const char* text, outputStream* st) {
|
||||
DirectivesParser cd(text, st);
|
||||
if (cd.valid()) {
|
||||
return cd.install_directives();
|
||||
}
|
||||
st->flush();
|
||||
st->print_cr("Parsing of compiler directives failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirectivesParser::has_file() {
|
||||
return CompilerDirectivesFile != NULL;
|
||||
}
|
||||
|
||||
bool DirectivesParser::parse_from_flag() {
|
||||
return parse_from_file(CompilerDirectivesFile, tty);
|
||||
}
|
||||
|
||||
bool DirectivesParser::parse_from_file(const char* filename, outputStream* st) {
|
||||
assert(filename != NULL, "Test before calling this");
|
||||
if (!parse_from_file_inner(filename, st)) {
|
||||
st->print_cr("Could not load file: %s", filename);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectivesParser::parse_from_file_inner(const char* filename, outputStream* stream) {
|
||||
struct stat st;
|
||||
ResourceMark rm;
|
||||
if (os::stat(filename, &st) == 0) {
|
||||
// found file, open it
|
||||
int file_handle = os::open(filename, 0, 0);
|
||||
if (file_handle != -1) {
|
||||
// read contents into resource array
|
||||
char* buffer = NEW_RESOURCE_ARRAY(char, st.st_size+1);
|
||||
size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
|
||||
buffer[num_read] = '\0';
|
||||
// close file
|
||||
os::close(file_handle);
|
||||
return parse_string(buffer, stream);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool DirectivesParser::install_directives() {
|
||||
// Pop from internal temporary stack and push to compileBroker.
|
||||
CompilerDirectives* tmp = pop_tmp();
|
||||
int i = 0;
|
||||
while (tmp != NULL) {
|
||||
i++;
|
||||
DirectivesStack::push(tmp);
|
||||
tmp = pop_tmp();
|
||||
}
|
||||
if (i == 0) {
|
||||
_st->print_cr("No directives in file");
|
||||
return false;
|
||||
} else {
|
||||
_st->print_cr("%i compiler directives added", i);
|
||||
if (PrintCompilerDirectives) {
|
||||
// Print entire directives stack after new has been pushed.
|
||||
DirectivesStack::print(_st);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
DirectivesParser::DirectivesParser(const char* text, outputStream* st)
|
||||
: JSON(text, false, st), depth(0), current_directive(NULL), current_directiveset(NULL), _tmp_top(NULL) {
|
||||
#ifndef PRODUCT
|
||||
memset(stack, 0, MAX_DEPTH * sizeof(stack[0]));
|
||||
#endif
|
||||
parse();
|
||||
}
|
||||
|
||||
DirectivesParser::~DirectivesParser() {
|
||||
}
|
||||
|
||||
const DirectivesParser::key DirectivesParser::keys[] = {
|
||||
// name, keytype, allow_array, allowed_mask, set_function
|
||||
{ "c1", type_c1, 0, mask(type_directives), NULL, UnknownFlagType },
|
||||
{ "c2", type_c2, 0, mask(type_directives), NULL, UnknownFlagType },
|
||||
{ "match", type_match, 1, mask(type_directives), NULL, UnknownFlagType },
|
||||
{ "inline", type_inline, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
|
||||
{ "enable", type_enable, 1, mask(type_directives) | mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
|
||||
{ "preset", type_preset, 0, mask(type_c1) | mask(type_c2), NULL, UnknownFlagType },
|
||||
|
||||
// Global flags
|
||||
#define common_flag_key(name, type, dvalue, compiler) \
|
||||
{ #name, type_flag, 0, mask(type_directives) | mask(type_c1) | mask(type_c2), &DirectiveSet::set_##name, type##Flag},
|
||||
compilerdirectives_common_flags(common_flag_key)
|
||||
compilerdirectives_c2_flags(common_flag_key)
|
||||
compilerdirectives_c1_flags(common_flag_key)
|
||||
#undef common_flag_key
|
||||
};
|
||||
|
||||
const DirectivesParser::key DirectivesParser::dir_array_key = {
|
||||
"top level directives array", type_dir_array, 0, 1 // Lowest bit means allow at top level
|
||||
};
|
||||
const DirectivesParser::key DirectivesParser::dir_key = {
|
||||
"top level directive", type_directives, 0, mask(type_dir_array) | 1 // Lowest bit means allow at top level
|
||||
};
|
||||
const DirectivesParser::key DirectivesParser::value_array_key = {
|
||||
"value array", type_value_array, 0, UINT_MAX // Allow all, checked by allow_array on other keys, not by allowed_mask from this key
|
||||
};
|
||||
|
||||
const DirectivesParser::key* DirectivesParser::lookup_key(const char* str, size_t len) {
|
||||
for (size_t i = 0; i < (sizeof(keys) / sizeof(keys[0])); i++) {
|
||||
if (strncasecmp(keys[i].name, str, len) == 0) {
|
||||
return &keys[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint DirectivesParser::mask(keytype kt) {
|
||||
return 1 << (kt + 1);
|
||||
}
|
||||
|
||||
bool DirectivesParser::push_key(const char* str, size_t len) {
|
||||
bool result = true;
|
||||
const key* k = lookup_key(str, len);
|
||||
|
||||
if (k == NULL) {
|
||||
// os::strdup
|
||||
char* s = NEW_C_HEAP_ARRAY(char, len + 1, mtCompiler);
|
||||
strncpy(s, str, len);
|
||||
s[len] = '\0';
|
||||
error(KEY_ERROR, "No such key: '%s'.", s);
|
||||
FREE_C_HEAP_ARRAY(char, s);
|
||||
return false;
|
||||
}
|
||||
|
||||
return push_key(k);
|
||||
}
|
||||
|
||||
bool DirectivesParser::push_key(const key* k) {
|
||||
assert(k->allowedmask != 0, "not allowed anywhere?");
|
||||
|
||||
// Exceeding the stack should not be possible with a valid compiler directive,
|
||||
// and an invalid should abort before this happens
|
||||
assert(depth < MAX_DEPTH, "exceeded stack depth");
|
||||
if (depth >= MAX_DEPTH) {
|
||||
error(INTERNAL_ERROR, "Stack depth exceeded.");
|
||||
return false;
|
||||
}
|
||||
|
||||
assert(stack[depth] == NULL, "element not nulled, something is wrong");
|
||||
|
||||
if (depth == 0 && !(k->allowedmask & 1)) {
|
||||
error(KEY_ERROR, "Key '%s' not allowed at top level.", k->name);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (depth > 0) {
|
||||
const key* prev = stack[depth - 1];
|
||||
if (!(k->allowedmask & mask(prev->type))) {
|
||||
error(KEY_ERROR, "Key '%s' not allowed after '%s' key.", k->name, prev->name);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stack[depth] = k;
|
||||
depth++;
|
||||
return true;
|
||||
}
|
||||
|
||||
const DirectivesParser::key* DirectivesParser::current_key() {
|
||||
assert(depth > 0, "getting key from empty stack");
|
||||
if (depth == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return stack[depth - 1];
|
||||
}
|
||||
|
||||
const DirectivesParser::key* DirectivesParser::pop_key() {
|
||||
assert(depth > 0, "popping empty stack");
|
||||
if (depth == 0) {
|
||||
error(INTERNAL_ERROR, "Popping empty stack.");
|
||||
return NULL;
|
||||
}
|
||||
depth--;
|
||||
|
||||
const key* k = stack[depth];
|
||||
#ifndef PRODUCT
|
||||
stack[depth] = NULL;
|
||||
#endif
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
bool DirectivesParser::set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set) {
|
||||
|
||||
void (DirectiveSet::*test)(void *args);
|
||||
test = option_key->set;
|
||||
|
||||
switch (t) {
|
||||
case JSON_TRUE:
|
||||
if (option_key->flag_type != boolFlag) {
|
||||
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
|
||||
return false;
|
||||
} else {
|
||||
bool val = true;
|
||||
(set->*test)((void *)&val);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSON_FALSE:
|
||||
if (option_key->flag_type != boolFlag) {
|
||||
error(VALUE_ERROR, "Cannot use bool value for an %s flag", flag_type_names[option_key->flag_type]);
|
||||
return false;
|
||||
} else {
|
||||
bool val = false;
|
||||
(set->*test)((void *)&val);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSON_NUMBER_INT:
|
||||
if (option_key->flag_type != intxFlag) {
|
||||
if (option_key->flag_type == doubleFlag) {
|
||||
double dval = (double)v->int_value;
|
||||
(set->*test)((void *)&dval);
|
||||
break;
|
||||
}
|
||||
error(VALUE_ERROR, "Cannot use int value for an %s flag", flag_type_names[option_key->flag_type]);
|
||||
return false;
|
||||
} else {
|
||||
intx ival = v->int_value;
|
||||
(set->*test)((void *)&ival);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSON_NUMBER_FLOAT:
|
||||
if (option_key->flag_type != doubleFlag) {
|
||||
error(VALUE_ERROR, "Cannot use double value for an %s flag", flag_type_names[option_key->flag_type]);
|
||||
return false;
|
||||
} else {
|
||||
double dval = v->double_value;
|
||||
(set->*test)((void *)&dval);
|
||||
}
|
||||
break;
|
||||
|
||||
case JSON_STRING:
|
||||
if (option_key->flag_type != ccstrFlag && option_key->flag_type != ccstrlistFlag) {
|
||||
error(VALUE_ERROR, "Cannot use string value for a %s flag", flag_type_names[option_key->flag_type]);
|
||||
return false;
|
||||
} else {
|
||||
char* s = NEW_C_HEAP_ARRAY(char, v->str.length+1, mtCompiler);
|
||||
strncpy(s, v->str.start, v->str.length + 1);
|
||||
s[v->str.length] = '\0';
|
||||
(set->*test)((void *)&s);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0, "Should not reach here.");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectivesParser::set_option(JSON_TYPE t, JSON_VAL* v) {
|
||||
|
||||
const key* option_key = pop_key();
|
||||
const key* enclosing_key = current_key();
|
||||
|
||||
if (option_key->type == value_array_key.type) {
|
||||
// Multi value array, we are really setting the value
|
||||
// for the key one step further up.
|
||||
option_key = pop_key();
|
||||
enclosing_key = current_key();
|
||||
|
||||
// Repush option_key and multi value marker, since
|
||||
// we need to keep them until all multi values are set.
|
||||
push_key(option_key);
|
||||
push_key(&value_array_key);
|
||||
}
|
||||
|
||||
switch (option_key->type) {
|
||||
case type_flag:
|
||||
{
|
||||
if (current_directiveset == NULL) {
|
||||
assert(depth == 2, "Must not have active directive set");
|
||||
|
||||
if (!set_option_flag(t, v, option_key, current_directive->_c1_store)) {
|
||||
return false;
|
||||
}
|
||||
if(!set_option_flag(t, v, option_key, current_directive->_c2_store)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
assert(depth > 2, "Must have active current directive set");
|
||||
if (!set_option_flag(t, v, option_key, current_directiveset)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case type_match:
|
||||
if (t != JSON_STRING) {
|
||||
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
|
||||
return false;
|
||||
}
|
||||
if (enclosing_key->type != type_directives) {
|
||||
error(SYNTAX_ERROR, "Match keyword can only exist inside a directive");
|
||||
return false;
|
||||
}
|
||||
{
|
||||
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
|
||||
strncpy(s, v->str.start, v->str.length);
|
||||
s[v->str.length] = '\0';
|
||||
|
||||
const char* error_msg = NULL;
|
||||
if (!current_directive->add_match(s, error_msg)) {
|
||||
assert (error_msg != NULL, "Must have valid error message");
|
||||
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, s);
|
||||
}
|
||||
break;
|
||||
|
||||
case type_inline:
|
||||
if (t != JSON_STRING) {
|
||||
error(VALUE_ERROR, "Key of type %s needs a value of type string", option_key->name);
|
||||
return false;
|
||||
}
|
||||
{
|
||||
//char* s = strndup(v->str.start, v->str.length);
|
||||
char* s = NEW_C_HEAP_ARRAY(char, v->str.length + 1, mtCompiler);
|
||||
strncpy(s, v->str.start, v->str.length);
|
||||
s[v->str.length] = '\0';
|
||||
|
||||
const char* error_msg = NULL;
|
||||
if (current_directiveset == NULL) {
|
||||
if (!current_directive->_c1_store->parse_and_add_inline(s, error_msg)) {
|
||||
assert (error_msg != NULL, "Must have valid error message");
|
||||
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
|
||||
}
|
||||
if (!current_directive->_c2_store->parse_and_add_inline(s, error_msg)) {
|
||||
assert (error_msg != NULL, "Must have valid error message");
|
||||
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
|
||||
}
|
||||
} else {
|
||||
if (!current_directiveset->parse_and_add_inline(s, error_msg)) {
|
||||
assert (error_msg != NULL, "Must have valid error message");
|
||||
error(VALUE_ERROR, "Method pattern error: %s", error_msg);
|
||||
}
|
||||
}
|
||||
FREE_C_HEAP_ARRAY(char, s);
|
||||
}
|
||||
break;
|
||||
|
||||
case type_c1:
|
||||
current_directiveset = current_directive->_c1_store;
|
||||
if (t != JSON_TRUE && t != JSON_FALSE) {
|
||||
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case type_c2:
|
||||
current_directiveset = current_directive->_c2_store;
|
||||
if (t != JSON_TRUE && t != JSON_FALSE) {
|
||||
error(VALUE_ERROR, "Key of type %s needs a true or false value", option_key->name);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
case type_enable:
|
||||
switch (enclosing_key->type) {
|
||||
case type_c1:
|
||||
case type_c2:
|
||||
{
|
||||
if (t != JSON_TRUE && t != JSON_FALSE) {
|
||||
error(VALUE_ERROR, "Key of type %s enclosed in a %s key needs a true or false value", option_key->name, enclosing_key->name);
|
||||
return false;
|
||||
}
|
||||
int val = (t == JSON_TRUE);
|
||||
current_directiveset->set_Enable(&val);
|
||||
break;
|
||||
}
|
||||
|
||||
case type_directives:
|
||||
error(VALUE_ERROR, "Enable keyword not available for generic directive");
|
||||
return false;
|
||||
|
||||
default:
|
||||
error(INTERNAL_ERROR, "Unexpected enclosing type for key %s: %s", option_key->name, enclosing_key->name);
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectivesParser::callback(JSON_TYPE t, JSON_VAL* v, uint rlimit) {
|
||||
const key* k;
|
||||
|
||||
if (depth == 0) {
|
||||
switch (t) {
|
||||
case JSON_ARRAY_BEGIN:
|
||||
return push_key(&dir_array_key);
|
||||
|
||||
case JSON_OBJECT_BEGIN:
|
||||
// push synthetic dir_array
|
||||
push_key(&dir_array_key);
|
||||
assert(depth == 1, "Make sure the stack are aligned with the directives");
|
||||
break;
|
||||
|
||||
default:
|
||||
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (depth == 1) {
|
||||
switch (t) {
|
||||
case JSON_OBJECT_BEGIN:
|
||||
// Parsing a new directive.
|
||||
current_directive = new CompilerDirectives();
|
||||
return push_key(&dir_key);
|
||||
|
||||
case JSON_ARRAY_END:
|
||||
k = pop_key();
|
||||
|
||||
if (k->type != type_dir_array) {
|
||||
error(SYNTAX_ERROR, "Expected end of directives array");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
error(SYNTAX_ERROR, "DirectivesParser can only start with an array containing directive objects, or one single directive.");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
switch (t) {
|
||||
case JSON_OBJECT_BEGIN:
|
||||
k = current_key();
|
||||
switch (k->type) {
|
||||
case type_c1:
|
||||
current_directiveset = current_directive->_c1_store;
|
||||
return true;
|
||||
case type_c2:
|
||||
current_directiveset = current_directive->_c2_store;
|
||||
return true;
|
||||
|
||||
case type_dir_array:
|
||||
return push_key(&dir_key);
|
||||
|
||||
default:
|
||||
error(SYNTAX_ERROR, "The key '%s' does not allow an object to follow.", k->name);
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
|
||||
case JSON_OBJECT_END:
|
||||
k = pop_key();
|
||||
switch (k->type) {
|
||||
case type_c1:
|
||||
case type_c2:
|
||||
// This is how we now if options apply to a single or both directive sets
|
||||
current_directiveset = NULL;
|
||||
break;
|
||||
|
||||
case type_directives:
|
||||
// Check, finish and push to stack!
|
||||
if (current_directive->match() == NULL) {
|
||||
error(INTERNAL_ERROR, "Directive missing required match.");
|
||||
return false;
|
||||
}
|
||||
current_directive->finalize();
|
||||
push_tmp(current_directive);
|
||||
current_directive = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
error(INTERNAL_ERROR, "Object end with wrong key type on stack: %s.", k->name);
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
case JSON_ARRAY_BEGIN:
|
||||
k = current_key();
|
||||
if (!(k->allow_array_value)) {
|
||||
if (k->type == type_dir_array) {
|
||||
error(SYNTAX_ERROR, "Array not allowed inside top level array, expected directive object.");
|
||||
} else {
|
||||
error(VALUE_ERROR, "The key '%s' does not allow an array of values.", k->name);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return push_key(&value_array_key);
|
||||
|
||||
case JSON_ARRAY_END:
|
||||
k = pop_key(); // Pop multi value marker
|
||||
assert(k->type == value_array_key.type, "array end for level != 0 should terminate multi value");
|
||||
k = pop_key(); // Pop key for option that was set
|
||||
return true;
|
||||
|
||||
case JSON_KEY:
|
||||
return push_key(v->str.start, v->str.length);
|
||||
|
||||
case JSON_STRING:
|
||||
case JSON_NUMBER_INT:
|
||||
case JSON_NUMBER_FLOAT:
|
||||
case JSON_TRUE:
|
||||
case JSON_FALSE:
|
||||
case JSON_NULL:
|
||||
return set_option(t, v);
|
||||
|
||||
default:
|
||||
error(INTERNAL_ERROR, "Unknown JSON type: %d.", t);
|
||||
ShouldNotReachHere();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
void DirectivesParser::test(const char* text, bool should_pass) {
|
||||
DirectivesParser cd(text, tty);
|
||||
if (should_pass) {
|
||||
assert(cd.valid() == true, "failed on a valid DirectivesParser string");
|
||||
if (VerboseInternalVMTests) {
|
||||
tty->print("-- DirectivesParser test passed as expected --\n");
|
||||
}
|
||||
} else {
|
||||
assert(cd.valid() == false, "succeeded on an invalid DirectivesParser string");
|
||||
if (VerboseInternalVMTests) {
|
||||
tty->print("-- DirectivesParser test failed as expected --\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool DirectivesParser::test() {
|
||||
DirectivesParser::test("{}", false);
|
||||
DirectivesParser::test("[]", true);
|
||||
DirectivesParser::test("[{}]", false);
|
||||
DirectivesParser::test("[{},{}]", false);
|
||||
DirectivesParser::test("{},{}", false);
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" inline : \"+java/util.*\"," "\n"
|
||||
" PrintAssembly: true," "\n"
|
||||
" BreakAtExecute: true," "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", true);
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" [" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" inline : \"+java/util.*\"," "\n"
|
||||
" PrintAssembly: true," "\n"
|
||||
" BreakAtExecute: true," "\n"
|
||||
" }" "\n"
|
||||
" ]" "\n"
|
||||
"]" "\n", false);
|
||||
|
||||
/*DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" c1: {"
|
||||
" PrintIntrinsics: false," "\n"
|
||||
" }" "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", false);*/
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" c2: {" "\n"
|
||||
" PrintInlining: false," "\n"
|
||||
" }" "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", true);
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
" PrintInlining: [" "\n"
|
||||
" true," "\n"
|
||||
" false" "\n"
|
||||
" ]," "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", false);
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {"
|
||||
" // pattern to match against class+method+signature" "\n"
|
||||
" // leading and trailing wildcard (*) allowed" "\n"
|
||||
" match: \"foo/bar.*\"," "\n"
|
||||
"" "\n"
|
||||
" // override defaults for specified compiler" "\n"
|
||||
" // we may differentiate between levels too. TBD." "\n"
|
||||
" c1: {" "\n"
|
||||
" //override c1 presets " "\n"
|
||||
" DumpReplay: false," "\n"
|
||||
" BreakAtCompile: true," "\n"
|
||||
" }," "\n"
|
||||
"" "\n"
|
||||
" c2: {" "\n"
|
||||
" // control inlining of method" "\n"
|
||||
" // + force inline, - dont inline" "\n"
|
||||
" inline : \"+java/util.*\"," "\n"
|
||||
" PrintInlining: true," "\n"
|
||||
" }," "\n"
|
||||
"" "\n"
|
||||
" // directives outside a specific preset applies to all compilers" "\n"
|
||||
" inline : [ \"+java/util.*\", \"-com/sun.*\"]," "\n"
|
||||
" BreakAtExecute: true," "\n"
|
||||
" Log: true," "\n"
|
||||
" }," "\n"
|
||||
" {" "\n"
|
||||
" // matching several patterns require an array" "\n"
|
||||
" match: [\"baz.*\",\"frob.*\"]," "\n"
|
||||
"" "\n"
|
||||
" // applies to all compilers" "\n"
|
||||
" // + force inline, - dont inline" "\n"
|
||||
" inline : [ \"+java/util.*\", \"-com/sun.*\" ]," "\n"
|
||||
" PrintInlining: true," "\n"
|
||||
"" "\n"
|
||||
" // force matching compiles to be blocking/syncronous" "\n"
|
||||
" PrintNMethods: true" "\n"
|
||||
" }," "\n"
|
||||
"]" "\n", true);
|
||||
|
||||
// Test max stack depth
|
||||
DirectivesParser::test(
|
||||
"[" "\n" // depth 1: type_dir_array
|
||||
" {" "\n" // depth 2: type_directives
|
||||
" match: \"*.*\"," // match required
|
||||
" c1:" "\n" // depth 3: type_c1
|
||||
" {" "\n"
|
||||
" inline:" "\n" // depth 4: type_inline
|
||||
" [" "\n" // depth 5: type_value_array
|
||||
" \"foo\"," "\n"
|
||||
" \"bar\"," "\n"
|
||||
" ]" "\n" // depth 3: pop type_value_array and type_inline keys
|
||||
" }" "\n" // depth 2: pop type_c1 key
|
||||
" }" "\n" // depth 1: pop type_directives key
|
||||
"]" "\n", true); // depth 0: pop type_dir_array key
|
||||
|
||||
// Test max stack depth
|
||||
DirectivesParser::test(
|
||||
"[{c1:{c1:{c1:{c1:{c1:{c1:{c1:{}}}}}}}}]", false);
|
||||
|
||||
DirectivesParser::test(
|
||||
"[" "\n"
|
||||
" {" "\n"
|
||||
" c1: true," "\n"
|
||||
" c2: true," "\n"
|
||||
" match: true," "\n"
|
||||
" inline: true," "\n"
|
||||
" enable: true," "\n"
|
||||
" c1: {" "\n"
|
||||
" preset: true," "\n"
|
||||
" }" "\n"
|
||||
" }" "\n"
|
||||
"]" "\n", false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
141
hotspot/src/share/vm/compiler/directivesParser.hpp
Normal file
141
hotspot/src/share/vm/compiler/directivesParser.hpp
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
|
||||
#define SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
|
||||
|
||||
#include "utilities/json.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
|
||||
enum FlagType {
|
||||
boolFlag,
|
||||
intxFlag,
|
||||
doubleFlag,
|
||||
ccstrFlag,
|
||||
ccstrlistFlag,
|
||||
UnknownFlagType
|
||||
};
|
||||
|
||||
static const char* flag_type_names[] = {
|
||||
"bool",
|
||||
"int",
|
||||
"double",
|
||||
"string",
|
||||
"string list",
|
||||
"unknown"
|
||||
};
|
||||
|
||||
class DirectivesParser : public JSON {
|
||||
public:
|
||||
static bool has_file();
|
||||
static bool parse_from_flag();
|
||||
static bool parse_from_file(const char* filename, outputStream* st);
|
||||
static bool parse_string(const char* string, outputStream* st);
|
||||
bool install_directives();
|
||||
|
||||
private:
|
||||
DirectivesParser(const char* text, outputStream* st);
|
||||
~DirectivesParser();
|
||||
|
||||
bool callback(JSON_TYPE t, JSON_VAL* v, uint level);
|
||||
static bool parse_from_file_inner(const char* filename, outputStream* st);
|
||||
|
||||
// types of "keys". i.e recognized <key>:<value> pairs in our JSON syntax
|
||||
typedef enum {
|
||||
type_c1,
|
||||
type_c2,
|
||||
type_enable,
|
||||
type_preset,
|
||||
type_match,
|
||||
type_inline,
|
||||
|
||||
// After here, there is no correlation between
|
||||
// keytype and keys array
|
||||
//type_strategy,
|
||||
type_flag,
|
||||
//type_dir,
|
||||
|
||||
// Synthetic.
|
||||
type_dir_array,
|
||||
type_directives,
|
||||
type_value_array
|
||||
} keytype;
|
||||
|
||||
// name, type, dtd info and maybe a setter
|
||||
// this is how we map key-values
|
||||
typedef struct {
|
||||
const char *name;
|
||||
keytype type;
|
||||
uint allow_array_value : 1;
|
||||
uint allowedmask;
|
||||
void (DirectiveSet::*set)(void* arg);
|
||||
FlagType flag_type;
|
||||
} key;
|
||||
|
||||
// Array with valid keys for the directive file
|
||||
static const key keys[];
|
||||
// Marker for outermost moosewings/array
|
||||
static const key dir_array_key;
|
||||
// Marker for a directives set (these are "implicit" objects, as in not named)
|
||||
static const key dir_key;
|
||||
// Marker for a multi value
|
||||
static const key value_array_key;
|
||||
|
||||
// A compiler directive shouldn't be able to use more than 5 stack slots.
|
||||
// Example of max stack usage:
|
||||
// depth 1: type_dir_array [
|
||||
// depth 2: type_directives {
|
||||
// depth 3: type_c1 c1: {
|
||||
// depth 4: type_inline inline:
|
||||
// depth 5: type_value_array [ ...
|
||||
static const uint MAX_DEPTH = 5;
|
||||
const key* stack[MAX_DEPTH];
|
||||
uint depth;
|
||||
|
||||
bool push_key(const char* str, size_t len);
|
||||
bool push_key(const key* k);
|
||||
const key* current_key();
|
||||
const key* pop_key();
|
||||
static const key* lookup_key(const char* s, size_t len);
|
||||
|
||||
bool set_option(JSON_TYPE t, JSON_VAL* v);
|
||||
bool set_option_flag(JSON_TYPE t, JSON_VAL* v, const key* option_key, DirectiveSet* set);
|
||||
|
||||
CompilerDirectives* current_directive;
|
||||
DirectiveSet* current_directiveset;
|
||||
|
||||
void push_tmp(CompilerDirectives* dir);
|
||||
CompilerDirectives* pop_tmp();
|
||||
CompilerDirectives* _tmp_top; // temporary storage for dirs while parsing
|
||||
|
||||
static uint mask(keytype kt);
|
||||
|
||||
#ifndef PRODUCT
|
||||
static void test(const char* json, bool valid);
|
||||
public:
|
||||
static bool test();
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_COMPILER_DIRECTIVESPARSER_HPP
|
@ -320,13 +320,11 @@ bool MethodMatcher::matches(methodHandle method) const {
|
||||
}
|
||||
|
||||
void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) {
|
||||
ResourceMark rm;
|
||||
|
||||
if (mode == Suffix || mode == Substring || mode == Any) {
|
||||
st->print("*");
|
||||
}
|
||||
if (mode != Any) {
|
||||
h->print_symbol_on(st);
|
||||
h->print_utf8_on(st);
|
||||
}
|
||||
if (mode == Prefix || mode == Substring) {
|
||||
st->print("*");
|
||||
@ -334,14 +332,117 @@ void MethodMatcher::print_symbol(outputStream* st, Symbol* h, Mode mode) {
|
||||
}
|
||||
|
||||
void MethodMatcher::print_base(outputStream* st) {
|
||||
ResourceMark rm;
|
||||
|
||||
print_symbol(st, class_name(), _class_mode);
|
||||
st->print(".");
|
||||
print_symbol(st, method_name(), _method_mode);
|
||||
if (signature() != NULL) {
|
||||
signature()->print_symbol_on(st);
|
||||
signature()->print_utf8_on(st);
|
||||
}
|
||||
}
|
||||
|
||||
BasicMatcher* BasicMatcher::parse_method_pattern(char* line, const char*& error_msg) {
|
||||
assert(error_msg == NULL, "Don't call here with error_msg already set");
|
||||
BasicMatcher* bm = new BasicMatcher();
|
||||
MethodMatcher::parse_method_pattern(line, error_msg, bm);
|
||||
if (error_msg != NULL) {
|
||||
delete bm;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check for bad trailing characters
|
||||
int bytes_read = 0;
|
||||
sscanf(line, "%*[ \t]%n", &bytes_read);
|
||||
if (line[bytes_read] != '\0') {
|
||||
error_msg = "Unrecognized trailing text after method pattern";
|
||||
delete bm;
|
||||
return NULL;
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
|
||||
bool BasicMatcher::match(methodHandle method) {
|
||||
for (BasicMatcher* current = this; current != NULL; current = current->next()) {
|
||||
if (current->matches(method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InlineMatcher::print(outputStream* st) {
|
||||
if (_inline_action == InlineMatcher::force_inline) {
|
||||
st->print("+");
|
||||
} else {
|
||||
st->print("-");
|
||||
}
|
||||
print_base(st);
|
||||
}
|
||||
|
||||
InlineMatcher* InlineMatcher::parse_method_pattern(char* line, const char*& error_msg) {
|
||||
assert(error_msg == NULL, "Dont call here with error_msg already set");
|
||||
InlineMatcher* im = new InlineMatcher();
|
||||
MethodMatcher::parse_method_pattern(line, error_msg, im);
|
||||
if (error_msg != NULL) {
|
||||
delete im;
|
||||
return NULL;
|
||||
}
|
||||
return im;
|
||||
}
|
||||
|
||||
bool InlineMatcher::match(methodHandle method, int inline_action) {
|
||||
for (InlineMatcher* current = this; current != NULL; current = current->next()) {
|
||||
if (current->matches(method)) {
|
||||
return (current->_inline_action == inline_action);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
InlineMatcher* InlineMatcher::parse_inline_pattern(char* str, const char*& error_msg) {
|
||||
// check first token is +/-
|
||||
InlineType _inline_action;
|
||||
switch (str[0]) {
|
||||
case '-':
|
||||
_inline_action = InlineMatcher::dont_inline;
|
||||
break;
|
||||
case '+':
|
||||
_inline_action = InlineMatcher::force_inline;
|
||||
break;
|
||||
default:
|
||||
error_msg = "Missing leading inline type (+/-)";
|
||||
return NULL;
|
||||
}
|
||||
str++;
|
||||
|
||||
int bytes_read = 0;
|
||||
assert(error_msg== NULL, "error_msg must not be set yet");
|
||||
InlineMatcher* im = InlineMatcher::parse_method_pattern(str, error_msg);
|
||||
if (im == NULL) {
|
||||
assert(error_msg != NULL, "Must have error message");
|
||||
return NULL;
|
||||
}
|
||||
im->set_action(_inline_action);
|
||||
return im;
|
||||
}
|
||||
|
||||
InlineMatcher* InlineMatcher::clone() {
|
||||
InlineMatcher* m = new InlineMatcher();
|
||||
m->_class_mode = _class_mode;
|
||||
m->_method_mode = _method_mode;
|
||||
m->_inline_action = _inline_action;
|
||||
m->_class_name = _class_name;
|
||||
if(_class_name != NULL) {
|
||||
_class_name->increment_refcount();
|
||||
}
|
||||
m->_method_name = _method_name;
|
||||
if (_method_name != NULL) {
|
||||
_method_name->increment_refcount();
|
||||
}
|
||||
m->_signature = _signature;
|
||||
if (_signature != NULL) {
|
||||
_signature->increment_refcount();
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
@ -81,35 +81,8 @@ public:
|
||||
_next(next) {
|
||||
}
|
||||
|
||||
static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg) {
|
||||
assert(error_msg == NULL, "Dont call here with error_msg already set");
|
||||
BasicMatcher* bm = new BasicMatcher();
|
||||
MethodMatcher::parse_method_pattern(line, error_msg, bm);
|
||||
if (error_msg != NULL) {
|
||||
delete bm;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// check for bad trailing characters
|
||||
int bytes_read = 0;
|
||||
sscanf(line, "%*[ \t]%n", &bytes_read);
|
||||
if (line[bytes_read] != '\0') {
|
||||
error_msg = "Unrecognized trailing text after method pattern";
|
||||
delete bm;
|
||||
return NULL;
|
||||
}
|
||||
return bm;
|
||||
}
|
||||
|
||||
bool match(methodHandle method) {
|
||||
for (BasicMatcher* current = this; current != NULL; current = current->next()) {
|
||||
if (current->matches(method)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static BasicMatcher* parse_method_pattern(char* line, const char*& error_msg);
|
||||
bool match(methodHandle method);
|
||||
void set_next(BasicMatcher* next) { _next = next; }
|
||||
BasicMatcher* next() { return _next; }
|
||||
|
||||
@ -122,5 +95,33 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class InlineMatcher : public MethodMatcher {
|
||||
public:
|
||||
enum InlineType {
|
||||
unknown_inline,
|
||||
dont_inline,
|
||||
force_inline
|
||||
};
|
||||
|
||||
private:
|
||||
InlineType _inline_action;
|
||||
InlineMatcher * _next;
|
||||
|
||||
InlineMatcher() : MethodMatcher(),
|
||||
_inline_action(unknown_inline), _next(NULL) {
|
||||
}
|
||||
|
||||
public:
|
||||
static InlineMatcher* parse_method_pattern(char* line, const char*& error_msg);
|
||||
bool match(methodHandle method, int inline_action);
|
||||
void print(outputStream* st);
|
||||
void set_next(InlineMatcher* next) { _next = next; }
|
||||
InlineMatcher* next() { return _next; }
|
||||
void set_action(InlineType inline_action) { _inline_action = inline_action; }
|
||||
int inline_action() { return _inline_action; }
|
||||
static InlineMatcher* parse_inline_pattern(char* line, const char*& error_msg);
|
||||
InlineMatcher* clone();
|
||||
};
|
||||
|
||||
#endif // SHARE_VM_COMPILER_METHODMATCHER_HPP
|
||||
|
||||
|
@ -145,7 +145,7 @@ void JVMCICompiler::compile_method(methodHandle method, int entry_bci, JVMCIEnv*
|
||||
|
||||
|
||||
// Compilation entry point for methods
|
||||
void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
|
||||
void JVMCICompiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
|
@ -69,7 +69,7 @@ public:
|
||||
void bootstrap();
|
||||
|
||||
// Compilation entry point for methods
|
||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci);
|
||||
virtual void compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive);
|
||||
|
||||
void compile_method(methodHandle target, int entry_bci, JVMCIEnv* env);
|
||||
|
||||
|
@ -154,6 +154,10 @@ char* Symbol::as_C_string_flexible_buffer(Thread* t,
|
||||
return as_C_string(str, buf_len);
|
||||
}
|
||||
|
||||
void Symbol::print_utf8_on(outputStream* st) const {
|
||||
st->print("%s", as_C_string());
|
||||
}
|
||||
|
||||
void Symbol::print_symbol_on(outputStream* st) const {
|
||||
ResourceMark rm;
|
||||
st = st ? st : tty;
|
||||
|
@ -225,6 +225,7 @@ class Symbol : public MetaspaceObj {
|
||||
|
||||
// Printing
|
||||
void print_symbol_on(outputStream* st = NULL) const;
|
||||
void print_utf8_on(outputStream* st) const;
|
||||
void print_on(outputStream* st) const; // First level print
|
||||
void print_value_on(outputStream* st) const; // Second level print.
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "libadt/vectset.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "opto/block.hpp"
|
||||
#include "opto/cfgnode.hpp"
|
||||
#include "opto/chaitin.hpp"
|
||||
@ -365,7 +366,7 @@ PhaseCFG::PhaseCFG(Arena* arena, RootNode* root, Matcher& matcher)
|
||||
, _node_to_block_mapping(arena)
|
||||
, _node_latency(NULL)
|
||||
#ifndef PRODUCT
|
||||
, _trace_opto_pipelining(TraceOptoPipelining || C->method_has_option("TraceOptoPipelining"))
|
||||
, _trace_opto_pipelining(C->directive()->TraceOptoPipeliningOption)
|
||||
#endif
|
||||
#ifdef ASSERT
|
||||
, _raw_oops(arena)
|
||||
|
@ -368,7 +368,6 @@ public:
|
||||
class PhaseCFG : public Phase {
|
||||
friend class VMStructs;
|
||||
private:
|
||||
|
||||
// Root of whole program
|
||||
RootNode* _root;
|
||||
|
||||
|
@ -108,7 +108,7 @@ bool InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method,
|
||||
int caller_bci, ciCallProfile& profile,
|
||||
WarmCallInfo* wci_result) {
|
||||
// Allows targeted inlining
|
||||
if (callee_method->should_inline()) {
|
||||
if (C->directive()->should_inline(callee_method)) {
|
||||
*wci_result = *(WarmCallInfo::always_hot());
|
||||
if (C->print_inlining() && Verbose) {
|
||||
CompileTask::print_inline_indent(inline_level());
|
||||
@ -222,12 +222,12 @@ bool InlineTree::should_not_inline(ciMethod *callee_method,
|
||||
}
|
||||
|
||||
// ignore heuristic controls on inlining
|
||||
if (callee_method->should_inline()) {
|
||||
if (C->directive()->should_inline(callee_method)) {
|
||||
set_msg("force inline by CompileCommand");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (callee_method->should_not_inline()) {
|
||||
if (C->directive()->should_not_inline(callee_method)) {
|
||||
set_msg("disallowed by CompileCommand");
|
||||
return true;
|
||||
}
|
||||
|
@ -154,7 +154,7 @@
|
||||
notproduct(bool, PrintOptoStatistics, false, \
|
||||
"Print New compiler statistics") \
|
||||
\
|
||||
notproduct(bool, PrintOptoAssembly, false, \
|
||||
diagnostic(bool, PrintOptoAssembly, false, \
|
||||
"Print New compiler assembly output") \
|
||||
\
|
||||
develop_pd(bool, OptoPeephole, \
|
||||
@ -342,6 +342,9 @@
|
||||
product(bool, SuperWordReductions, true, \
|
||||
"Enable reductions support in superword.") \
|
||||
\
|
||||
product(bool, UseCMoveUnconditionally, false, \
|
||||
"Use CMove (scalar and vector) ignoring profitability test.") \
|
||||
\
|
||||
product(bool, DoReserveCopyInSuperWord, true, \
|
||||
"Create reserve copy of graph in SuperWord.") \
|
||||
\
|
||||
@ -368,18 +371,18 @@
|
||||
product(bool, UseRDPCForConstantTableBase, false, \
|
||||
"Use Sparc RDPC instruction for the constant table base.") \
|
||||
\
|
||||
develop(bool, PrintIdealGraph, false, \
|
||||
notproduct(bool, PrintIdealGraph, false, \
|
||||
"Print ideal graph to XML file / network interface. " \
|
||||
"By default attempts to connect to the visualizer on a socket.") \
|
||||
\
|
||||
develop(intx, PrintIdealGraphLevel, 0, \
|
||||
notproduct(intx, PrintIdealGraphLevel, 0, \
|
||||
"Level of detail of the ideal graph printout. " \
|
||||
"System-wide value, 0=nothing is printed, 3=all details printed. "\
|
||||
"System-wide value, 0=nothing is printed, 4=all details printed. "\
|
||||
"Level of detail of printouts can be set on a per-method level " \
|
||||
"as well by using CompileCommand=option.") \
|
||||
range(0, 3) \
|
||||
range(0, 4) \
|
||||
\
|
||||
develop(intx, PrintIdealGraphPort, 4444, \
|
||||
notproduct(intx, PrintIdealGraphPort, 4444, \
|
||||
"Ideal graph printer to network port") \
|
||||
range(0, SHRT_MAX) \
|
||||
\
|
||||
@ -632,7 +635,7 @@
|
||||
develop(bool, PrintDominators, false, \
|
||||
"Print out dominator trees for GVN") \
|
||||
\
|
||||
notproduct(bool, TraceSpilling, false, \
|
||||
diagnostic(bool, TraceSpilling, false, \
|
||||
"Trace spilling") \
|
||||
\
|
||||
diagnostic(bool, TraceTypeProfile, false, \
|
||||
|
@ -94,15 +94,16 @@ void C2Compiler::initialize() {
|
||||
}
|
||||
}
|
||||
|
||||
void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci) {
|
||||
void C2Compiler::compile_method(ciEnv* env, ciMethod* target, int entry_bci, DirectiveSet* directive) {
|
||||
assert(is_initialized(), "Compiler thread must be initialized");
|
||||
|
||||
bool subsume_loads = SubsumeLoads;
|
||||
bool do_escape_analysis = DoEscapeAnalysis && !env->should_retain_local_variables();
|
||||
bool eliminate_boxing = EliminateAutoBox;
|
||||
|
||||
while (!env->failing()) {
|
||||
// Attempt to compile while subsuming loads into machine instructions.
|
||||
Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing);
|
||||
Compile C(env, this, target, entry_bci, subsume_loads, do_escape_analysis, eliminate_boxing, directive);
|
||||
|
||||
// Check result and retry if appropriate.
|
||||
if (C.failure_reason() != NULL) {
|
||||
|
@ -41,7 +41,8 @@ public:
|
||||
// Compilation entry point for methods
|
||||
void compile_method(ciEnv* env,
|
||||
ciMethod* target,
|
||||
int entry_bci);
|
||||
int entry_bci,
|
||||
DirectiveSet* directive);
|
||||
|
||||
// sentinel value used to trigger backtracking in compile_method().
|
||||
static const char* retry_no_subsuming_loads();
|
||||
|
@ -211,7 +211,7 @@ PhaseChaitin::PhaseChaitin(uint unique, PhaseCFG &cfg, Matcher &matcher, bool sc
|
||||
, _scratch_int_pressure(0, INTPRESSURE)
|
||||
, _scratch_float_pressure(0, FLOATPRESSURE)
|
||||
#ifndef PRODUCT
|
||||
, _trace_spilling(TraceSpilling || C->method_has_option("TraceSpilling"))
|
||||
, _trace_spilling(C->directive()->TraceSpillingOption)
|
||||
#endif
|
||||
{
|
||||
Compile::TracePhase tp("ctorChaitin", &timers[_t_ctorChaitin]);
|
||||
|
@ -64,6 +64,7 @@ macro(CheckCastPP)
|
||||
macro(ClearArray)
|
||||
macro(ConstraintCast)
|
||||
macro(CMoveD)
|
||||
macro(CMoveVD)
|
||||
macro(CMoveF)
|
||||
macro(CMoveI)
|
||||
macro(CMoveL)
|
||||
@ -161,7 +162,6 @@ macro(LoadN)
|
||||
macro(LoadRange)
|
||||
macro(LoadS)
|
||||
macro(Lock)
|
||||
macro(LogD)
|
||||
macro(Log10D)
|
||||
macro(Loop)
|
||||
macro(LoopLimit)
|
||||
|
@ -464,7 +464,7 @@ CompileWrapper::CompileWrapper(Compile* compile) : _compile(compile) {
|
||||
Type::Initialize(compile);
|
||||
_compile->set_scratch_buffer_blob(NULL);
|
||||
_compile->begin_method();
|
||||
_compile->clone_map().set_debug(_compile->has_method() && _compile->method_has_option(_compile->clone_map().debug_option_name));
|
||||
_compile->clone_map().set_debug(_compile->has_method() && _compile->directive()->CloneMapDebugOption);
|
||||
}
|
||||
CompileWrapper::~CompileWrapper() {
|
||||
_compile->end_method();
|
||||
@ -496,7 +496,7 @@ void Compile::print_compile_messages() {
|
||||
tty->print_cr("** Bailout: Recompile without boxing elimination **");
|
||||
tty->print_cr("*********************************************************");
|
||||
}
|
||||
if (env()->break_at_compile()) {
|
||||
if (C->directive()->BreakAtCompileOption) {
|
||||
// Open the debugger when compiling this method.
|
||||
tty->print("### Breaking when compiling: ");
|
||||
method()->print_short_name();
|
||||
@ -617,9 +617,10 @@ debug_only( int Compile::_debug_idx = 100000; )
|
||||
|
||||
|
||||
Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr_bci,
|
||||
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing )
|
||||
bool subsume_loads, bool do_escape_analysis, bool eliminate_boxing, DirectiveSet* directive)
|
||||
: Phase(Compiler),
|
||||
_env(ci_env),
|
||||
_directive(directive),
|
||||
_log(ci_env->log()),
|
||||
_compile_id(ci_env->compile_id()),
|
||||
_save_argument_registers(false),
|
||||
@ -649,7 +650,7 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
_dead_node_list(comp_arena()),
|
||||
_dead_node_count(0),
|
||||
#ifndef PRODUCT
|
||||
_trace_opto_output(TraceOptoOutput || method()->has_option("TraceOptoOutput")),
|
||||
_trace_opto_output(directive->TraceOptoOutputOption),
|
||||
_in_dump_cnt(0),
|
||||
_printer(IdealGraphPrinter::printer()),
|
||||
#endif
|
||||
@ -673,7 +674,11 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
_interpreter_frame_size(0),
|
||||
_max_node_limit(MaxNodeLimit) {
|
||||
C = this;
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (_printer != NULL) {
|
||||
_printer->set_compile(this);
|
||||
}
|
||||
#endif
|
||||
CompileWrapper cw(this);
|
||||
|
||||
if (CITimeVerbose) {
|
||||
@ -687,9 +692,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
TraceTime t2(NULL, &_t_methodCompilation, CITime, false);
|
||||
|
||||
#ifndef PRODUCT
|
||||
bool print_opto_assembly = PrintOptoAssembly || _method->has_option("PrintOptoAssembly");
|
||||
bool print_opto_assembly = directive->PrintOptoAssemblyOption;
|
||||
if (!print_opto_assembly) {
|
||||
bool print_assembly = (PrintAssembly || _method->should_print_assembly());
|
||||
bool print_assembly = directive->PrintAssemblyOption;
|
||||
if (print_assembly && !Disassembler::can_decode()) {
|
||||
tty->print_cr("PrintAssembly request changed to PrintOptoAssembly");
|
||||
print_opto_assembly = true;
|
||||
@ -698,12 +703,12 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
set_print_assembly(print_opto_assembly);
|
||||
set_parsed_irreducible_loop(false);
|
||||
|
||||
if (method()->has_option("ReplayInline")) {
|
||||
if (directive->ReplayInlineOption) {
|
||||
_replay_inline_data = ciReplay::load_inline_data(method(), entry_bci(), ci_env->comp_level());
|
||||
}
|
||||
#endif
|
||||
set_print_inlining(PrintInlining || method()->has_option("PrintInlining") NOT_PRODUCT( || PrintOptoInlining));
|
||||
set_print_intrinsics(PrintIntrinsics || method()->has_option("PrintIntrinsics"));
|
||||
set_print_inlining(directive->PrintInliningOption NOT_PRODUCT( || PrintOptoInlining));
|
||||
set_print_intrinsics(directive->PrintIntrinsicsOption);
|
||||
set_has_irreducible_loop(true); // conservative until build_loop_tree() reset it
|
||||
|
||||
if (ProfileTraps RTM_OPT_ONLY( || UseRTMLocking )) {
|
||||
@ -837,8 +842,8 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
// Drain the list.
|
||||
Finish_Warm();
|
||||
#ifndef PRODUCT
|
||||
if (_printer && _printer->should_print(_method)) {
|
||||
_printer->print_inlining(this);
|
||||
if (_printer && _printer->should_print(1)) {
|
||||
_printer->print_inlining();
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -871,10 +876,10 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
NOT_PRODUCT( verify_barriers(); )
|
||||
|
||||
// Dump compilation data to replay it.
|
||||
if (method()->has_option("DumpReplay")) {
|
||||
if (directive->DumpReplayOption) {
|
||||
env()->dump_replay_data(_compile_id);
|
||||
}
|
||||
if (method()->has_option("DumpInline") && (ilt() != NULL)) {
|
||||
if (directive->DumpInlineOption && (ilt() != NULL)) {
|
||||
env()->dump_inline_data(_compile_id);
|
||||
}
|
||||
|
||||
@ -918,9 +923,9 @@ Compile::Compile( ciEnv* ci_env, C2Compiler* compiler, ciMethod* target, int osr
|
||||
frame_size_in_words(), _oop_map_set,
|
||||
&_handler_table, &_inc_table,
|
||||
compiler,
|
||||
env()->comp_level(),
|
||||
has_unsafe_access(),
|
||||
SharedRuntime::is_wide_vector(max_vector_size()),
|
||||
_directive,
|
||||
rtm_state()
|
||||
);
|
||||
|
||||
@ -938,9 +943,11 @@ Compile::Compile( ciEnv* ci_env,
|
||||
int is_fancy_jump,
|
||||
bool pass_tls,
|
||||
bool save_arg_registers,
|
||||
bool return_pc )
|
||||
bool return_pc,
|
||||
DirectiveSet* directive)
|
||||
: Phase(Compiler),
|
||||
_env(ci_env),
|
||||
_directive(directive),
|
||||
_log(ci_env->log()),
|
||||
_compile_id(0),
|
||||
_save_argument_registers(save_arg_registers),
|
||||
@ -1090,7 +1097,7 @@ void Compile::Init(int aliaslevel) {
|
||||
Copy::zero_to_bytes(_trap_hist, sizeof(_trap_hist));
|
||||
set_decompile_count(0);
|
||||
|
||||
set_do_freq_based_layout(BlockLayoutByFrequency || method_has_option("BlockLayoutByFrequency"));
|
||||
set_do_freq_based_layout(_directive->BlockLayoutByFrequencyOption);
|
||||
set_num_loop_opts(LoopOptsCount);
|
||||
set_do_inlining(Inline);
|
||||
set_max_inline_size(MaxInlineSize);
|
||||
@ -1101,24 +1108,22 @@ void Compile::Init(int aliaslevel) {
|
||||
|
||||
set_do_vector_loop(false);
|
||||
|
||||
bool do_vector = false;
|
||||
if (AllowVectorizeOnDemand) {
|
||||
if (has_method() && (method()->has_option("Vectorize") || method()->has_option("VectorizeDebug"))) {
|
||||
if (has_method() && (_directive->VectorizeOption || _directive->VectorizeDebugOption)) {
|
||||
set_do_vector_loop(true);
|
||||
NOT_PRODUCT(if (do_vector_loop() && Verbose) {tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());})
|
||||
} else if (has_method() && method()->name() != 0 &&
|
||||
method()->intrinsic_id() == vmIntrinsics::_forEachRemaining) {
|
||||
set_do_vector_loop(true);
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
if (do_vector_loop() && Verbose) {
|
||||
tty->print("Compile::Init: do vectorized loops (SIMD like) for method %s\n", method()->name()->as_quoted_ascii());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
set_use_cmove(UseCMoveUnconditionally /* || do_vector_loop()*/); //TODO: consider do_vector_loop() mandate use_cmove unconditionally
|
||||
NOT_PRODUCT(if (use_cmove() && Verbose && has_method()) {tty->print("Compile::Init: use CMove without profitability tests for method %s\n", method()->name()->as_quoted_ascii());})
|
||||
|
||||
set_age_code(has_method() && method()->profile_aging());
|
||||
set_rtm_state(NoRTM); // No RTM lock eliding by default
|
||||
method_has_option_value("MaxNodeLimit", _max_node_limit);
|
||||
_max_node_limit = _directive->MaxNodeLimitOption;
|
||||
|
||||
#if INCLUDE_RTM_OPT
|
||||
if (UseRTMLocking && has_method() && (method()->method_data_or_null() != NULL)) {
|
||||
int rtm_state = method()->method_data()->rtm_state();
|
||||
@ -2091,7 +2096,7 @@ void Compile::Optimize() {
|
||||
TracePhase tp("optimizer", &timers[_t_optimizer]);
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (env()->break_at_compile()) {
|
||||
if (_directive->BreakAtCompileOption) {
|
||||
BREAKPOINT;
|
||||
}
|
||||
|
||||
@ -4357,7 +4362,6 @@ bool Compile::randomized_select(int count) {
|
||||
return (os::random() & RANDOMIZED_DOMAIN_MASK) < (RANDOMIZED_DOMAIN / count);
|
||||
}
|
||||
|
||||
const char* CloneMap::debug_option_name = "CloneMapDebug";
|
||||
CloneMap& Compile::clone_map() { return _clone_map; }
|
||||
void Compile::set_clone_map(Dict* d) { _clone_map._dict = d; }
|
||||
|
||||
|
@ -374,6 +374,7 @@ class Compile : public Phase {
|
||||
bool _do_count_invocations; // True if we generate code to count invocations
|
||||
bool _do_method_data_update; // True if we generate code to update MethodData*s
|
||||
bool _do_vector_loop; // True if allowed to execute loop in parallel iterations
|
||||
bool _use_cmove; // True if CMove should be used without profitability analysis
|
||||
bool _age_code; // True if we need to profile code age (decrement the aging counter)
|
||||
int _AliasLevel; // Locally-adjusted version of AliasLevel flag.
|
||||
bool _print_assembly; // True if we should dump assembly code for this compilation
|
||||
@ -391,6 +392,7 @@ class Compile : public Phase {
|
||||
// Compilation environment.
|
||||
Arena _comp_arena; // Arena with lifetime equivalent to Compile
|
||||
ciEnv* _env; // CI interface
|
||||
DirectiveSet* _directive; // Compiler directive
|
||||
CompileLog* _log; // from CompilerThread
|
||||
const char* _failure_reason; // for record_failure/failing pattern
|
||||
GrowableArray<CallGenerator*>* _intrinsics; // List of intrinsics.
|
||||
@ -527,6 +529,10 @@ class Compile : public Phase {
|
||||
print_inlining_stream()->print("%s", ss.as_string());
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
IdealGraphPrinter* printer() { return _printer; }
|
||||
#endif
|
||||
|
||||
void log_late_inline(CallGenerator* cg);
|
||||
void log_inline_id(CallGenerator* cg);
|
||||
void log_inline_failure(const char* msg);
|
||||
@ -578,6 +584,7 @@ class Compile : public Phase {
|
||||
|
||||
// ID for this compilation. Useful for setting breakpoints in the debugger.
|
||||
int compile_id() const { return _compile_id; }
|
||||
DirectiveSet* directive() const { return _directive; }
|
||||
|
||||
// Does this compilation allow instructions to subsume loads? User
|
||||
// instructions that subsume a load may result in an unschedulable
|
||||
@ -651,6 +658,8 @@ class Compile : public Phase {
|
||||
void set_do_method_data_update(bool z) { _do_method_data_update = z; }
|
||||
bool do_vector_loop() const { return _do_vector_loop; }
|
||||
void set_do_vector_loop(bool z) { _do_vector_loop = z; }
|
||||
bool use_cmove() const { return _use_cmove; }
|
||||
void set_use_cmove(bool z) { _use_cmove = z; }
|
||||
bool age_code() const { return _age_code; }
|
||||
void set_age_code(bool z) { _age_code = z; }
|
||||
int AliasLevel() const { return _AliasLevel; }
|
||||
@ -671,10 +680,7 @@ class Compile : public Phase {
|
||||
bool method_has_option(const char * option) {
|
||||
return method() != NULL && method()->has_option(option);
|
||||
}
|
||||
template<typename T>
|
||||
bool method_has_option_value(const char * option, T& value) {
|
||||
return method() != NULL && method()->has_option_value(option, value);
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
bool trace_opto_output() const { return _trace_opto_output; }
|
||||
bool parsed_irreducible_loop() const { return _parsed_irreducible_loop; }
|
||||
@ -692,8 +698,8 @@ class Compile : public Phase {
|
||||
|
||||
void begin_method() {
|
||||
#ifndef PRODUCT
|
||||
if (_printer && _printer->should_print(_method)) {
|
||||
_printer->begin_method(this);
|
||||
if (_printer && _printer->should_print(1)) {
|
||||
_printer->begin_method();
|
||||
}
|
||||
#endif
|
||||
C->_latest_stage_start_counter.stamp();
|
||||
@ -711,8 +717,8 @@ class Compile : public Phase {
|
||||
|
||||
|
||||
#ifndef PRODUCT
|
||||
if (_printer && _printer->should_print(_method)) {
|
||||
_printer->print_method(this, CompilerPhaseTypeHelper::to_string(cpt), level);
|
||||
if (_printer && _printer->should_print(level)) {
|
||||
_printer->print_method(CompilerPhaseTypeHelper::to_string(cpt), level);
|
||||
}
|
||||
#endif
|
||||
C->_latest_stage_start_counter.stamp();
|
||||
@ -728,7 +734,7 @@ class Compile : public Phase {
|
||||
event.commit();
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
if (_printer && _printer->should_print(_method)) {
|
||||
if (_printer && _printer->should_print(level)) {
|
||||
_printer->end_method();
|
||||
}
|
||||
#endif
|
||||
@ -1107,7 +1113,7 @@ class Compile : public Phase {
|
||||
// continuation.
|
||||
Compile(ciEnv* ci_env, C2Compiler* compiler, ciMethod* target,
|
||||
int entry_bci, bool subsume_loads, bool do_escape_analysis,
|
||||
bool eliminate_boxing);
|
||||
bool eliminate_boxing, DirectiveSet* directive);
|
||||
|
||||
// Second major entry point. From the TypeFunc signature, generate code
|
||||
// to pass arguments from the Java calling convention to the C calling
|
||||
@ -1115,7 +1121,7 @@ class Compile : public Phase {
|
||||
Compile(ciEnv* ci_env, const TypeFunc *(*gen)(),
|
||||
address stub_function, const char *stub_name,
|
||||
int is_fancy_jump, bool pass_tls,
|
||||
bool save_arg_registers, bool return_pc);
|
||||
bool save_arg_registers, bool return_pc, DirectiveSet* directive);
|
||||
|
||||
// From the TypeFunc signature, generate code to pass arguments
|
||||
// from Compiled calling convention to Interpreter's calling convention
|
||||
|
@ -292,11 +292,11 @@ void IdealGraphPrinter::print_inline_tree(InlineTree *tree) {
|
||||
|
||||
}
|
||||
|
||||
void IdealGraphPrinter::print_inlining(Compile* compile) {
|
||||
void IdealGraphPrinter::print_inlining() {
|
||||
|
||||
// Print inline tree
|
||||
if (_should_send_method) {
|
||||
InlineTree *inlineTree = compile->ilt();
|
||||
InlineTree *inlineTree = C->ilt();
|
||||
if (inlineTree != NULL) {
|
||||
print_inline_tree(inlineTree);
|
||||
} else {
|
||||
@ -306,9 +306,9 @@ void IdealGraphPrinter::print_inlining(Compile* compile) {
|
||||
}
|
||||
|
||||
// Has to be called whenever a method is compiled
|
||||
void IdealGraphPrinter::begin_method(Compile* compile) {
|
||||
void IdealGraphPrinter::begin_method() {
|
||||
|
||||
ciMethod *method = compile->method();
|
||||
ciMethod *method = C->method();
|
||||
assert(_output, "output stream must exist!");
|
||||
assert(method, "null methods are not allowed!");
|
||||
assert(!_current_method, "current method must be null!");
|
||||
@ -662,16 +662,14 @@ void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set)
|
||||
}
|
||||
}
|
||||
|
||||
void IdealGraphPrinter::print_method(Compile* compile, const char *name, int level, bool clear_nodes) {
|
||||
print(compile, name, (Node *)compile->root(), level, clear_nodes);
|
||||
void IdealGraphPrinter::print_method(const char *name, int level, bool clear_nodes) {
|
||||
print(name, (Node *)C->root(), level, clear_nodes);
|
||||
}
|
||||
|
||||
// Print current ideal graph
|
||||
void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, int level, bool clear_nodes) {
|
||||
void IdealGraphPrinter::print(const char *name, Node *node, int level, bool clear_nodes) {
|
||||
|
||||
if (!_current_method || !_should_send_method || !should_print(_current_method, level)) return;
|
||||
|
||||
this->C = compile;
|
||||
if (!_current_method || !_should_send_method || !should_print(level)) return;
|
||||
|
||||
// Warning, unsafe cast?
|
||||
_chaitin = (PhaseChaitin *)C->regalloc();
|
||||
@ -722,10 +720,8 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in
|
||||
}
|
||||
|
||||
// Should method be printed?
|
||||
bool IdealGraphPrinter::should_print(ciMethod* method, int level) {
|
||||
intx ideal_graph_level = PrintIdealGraphLevel;
|
||||
method->has_option_value("PrintIdealGraphLevel", ideal_graph_level); // update value with per-method value (if available)
|
||||
return ideal_graph_level >= level;
|
||||
bool IdealGraphPrinter::should_print(int level) {
|
||||
return C->directive()->IGVPrintLevelOption >= level;
|
||||
}
|
||||
|
||||
extern const char *NodeClassNames[];
|
||||
|
@ -127,13 +127,14 @@ class IdealGraphPrinter : public CHeapObj<mtCompiler> {
|
||||
|
||||
bool traverse_outs();
|
||||
void set_traverse_outs(bool b);
|
||||
void print_inlining(Compile* compile);
|
||||
void begin_method(Compile* compile);
|
||||
void print_inlining();
|
||||
void begin_method();
|
||||
void end_method();
|
||||
void print_method(Compile* compile, const char *name, int level=1, bool clear_nodes = false);
|
||||
void print(Compile* compile, const char *name, Node *root, int level=1, bool clear_nodes = false);
|
||||
void print_method(const char *name, int level=1, bool clear_nodes = false);
|
||||
void print(const char *name, Node *root, int level=1, bool clear_nodes = false);
|
||||
void print_xml(const char *name);
|
||||
static bool should_print(ciMethod* method, int level = 1);
|
||||
bool should_print(int level);
|
||||
void set_compile(Compile* compile) {C = compile; }
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -326,9 +326,10 @@ CallGenerator* Compile::make_vm_intrinsic(ciMethod* m, bool is_virtual) {
|
||||
// methods access VM-internal data.
|
||||
VM_ENTRY_MARK;
|
||||
methodHandle mh(THREAD, m->get_Method());
|
||||
methodHandle ct(THREAD, method()->get_Method());
|
||||
is_available = compiler->is_intrinsic_supported(mh, is_virtual) &&
|
||||
!vmIntrinsics::is_disabled_by_flags(mh, ct);
|
||||
!C->directive()->is_intrinsic_disabled(mh) &&
|
||||
!vmIntrinsics::is_disabled_by_flags(mh);
|
||||
|
||||
}
|
||||
|
||||
if (is_available) {
|
||||
@ -1368,7 +1369,6 @@ bool LibraryCallKit::inline_math(vmIntrinsics::ID id) {
|
||||
switch (id) {
|
||||
case vmIntrinsics::_dabs: n = new AbsDNode( arg); break;
|
||||
case vmIntrinsics::_dsqrt: n = new SqrtDNode(C, control(), arg); break;
|
||||
case vmIntrinsics::_dlog: n = new LogDNode(C, control(), arg); break;
|
||||
case vmIntrinsics::_dlog10: n = new Log10DNode(C, control(), arg); break;
|
||||
default: fatal_unexpected_iid(id); break;
|
||||
}
|
||||
@ -1752,7 +1752,9 @@ bool LibraryCallKit::inline_math_native(vmIntrinsics::ID id) {
|
||||
case vmIntrinsics::_dtan: return Matcher::has_match_rule(Op_TanD) ? inline_trig(id) :
|
||||
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dtan), "TAN");
|
||||
|
||||
case vmIntrinsics::_dlog: return Matcher::has_match_rule(Op_LogD) ? inline_math(id) :
|
||||
case vmIntrinsics::_dlog:
|
||||
return StubRoutines::dlog() != NULL ?
|
||||
runtime_math(OptoRuntime::Math_D_D_Type(), StubRoutines::dlog(), "dlog") :
|
||||
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog), "LOG");
|
||||
case vmIntrinsics::_dlog10: return Matcher::has_match_rule(Op_Log10D) ? inline_math(id) :
|
||||
runtime_math(OptoRuntime::Math_D_D_Type(), FN_PTR(SharedRuntime::dlog10), "LOG10");
|
||||
|
@ -1143,7 +1143,7 @@ public:
|
||||
// dominated in the outer loop by this node chain:
|
||||
// intcon(1)->If->IfFalse->reserved_copy.
|
||||
// The original loop is dominated by the the same node chain but IfTrue projection:
|
||||
// intcon(1)->If->IfTrue->original_loop.
|
||||
// intcon(0)->If->IfTrue->original_loop.
|
||||
//
|
||||
// In this implementation of CountedLoopReserveKit the ctor includes create_reserve()
|
||||
// and the dtor, checks _use_new value.
|
||||
|
@ -512,8 +512,11 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
|
||||
PhiNode* phi = out->as_Phi();
|
||||
BasicType bt = phi->type()->basic_type();
|
||||
switch (bt) {
|
||||
case T_FLOAT:
|
||||
case T_DOUBLE: {
|
||||
case T_DOUBLE:
|
||||
if (C->use_cmove()) {
|
||||
continue; //TODO: maybe we want to add some cost
|
||||
}
|
||||
case T_FLOAT: {
|
||||
cost += Matcher::float_cmove_cost(); // Could be very expensive
|
||||
break;
|
||||
}
|
||||
@ -573,7 +576,7 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}//for
|
||||
Node* bol = iff->in(1);
|
||||
assert(bol->Opcode() == Op_Bool, "");
|
||||
int cmp_op = bol->in(1)->Opcode();
|
||||
@ -595,7 +598,8 @@ Node *PhaseIdealLoop::conditional_move( Node *region ) {
|
||||
}
|
||||
// Check for highly predictable branch. No point in CMOV'ing if
|
||||
// we are going to predict accurately all the time.
|
||||
if (iff->_prob < infrequent_prob ||
|
||||
if (C->use_cmove() && cmp_op == Op_CmpD) ;//keep going
|
||||
else if (iff->_prob < infrequent_prob ||
|
||||
iff->_prob > (1.0f - infrequent_prob))
|
||||
return NULL;
|
||||
|
||||
|
@ -2316,7 +2316,8 @@ void Matcher::find_shared( Node *n ) {
|
||||
case Op_CMoveI:
|
||||
case Op_CMoveL:
|
||||
case Op_CMoveN:
|
||||
case Op_CMoveP: {
|
||||
case Op_CMoveP:
|
||||
case Op_CMoveVD: {
|
||||
// Restructure into a binary tree for Matching. It's possible that
|
||||
// we could move this code up next to the graph reshaping for IfNodes
|
||||
// or vice-versa, but I do not want to debug this for Ladybird.
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "code/debugInfo.hpp"
|
||||
#include "code/debugInfoRec.hpp"
|
||||
#include "compiler/compileBroker.hpp"
|
||||
#include "compiler/compilerDirectives.hpp"
|
||||
#include "compiler/oopMap.hpp"
|
||||
#include "memory/allocation.inline.hpp"
|
||||
#include "opto/ad.hpp"
|
||||
@ -89,9 +90,8 @@ void Compile::Output() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Break before main entry point
|
||||
if( (_method && _method->break_at_execute())
|
||||
if( (_method && C->directive()->BreakAtExecuteOption)
|
||||
#ifndef PRODUCT
|
||||
||(OptoBreakpoint && is_method_compilation())
|
||||
||(OptoBreakpointOSR && is_osr_compilation())
|
||||
|
@ -2378,13 +2378,13 @@ void Parse::do_one_bytecode() {
|
||||
}
|
||||
|
||||
#ifndef PRODUCT
|
||||
IdealGraphPrinter *printer = IdealGraphPrinter::printer();
|
||||
if (printer && printer->should_print(_method)) {
|
||||
IdealGraphPrinter *printer = C->printer();
|
||||
if (printer && printer->should_print(1)) {
|
||||
char buffer[256];
|
||||
sprintf(buffer, "Bytecode %d: %s", bci(), Bytecodes::name(bc()));
|
||||
bool old = printer->traverse_outs();
|
||||
printer->set_traverse_outs(true);
|
||||
printer->print_method(C, buffer, 4);
|
||||
printer->print_method(buffer, 4);
|
||||
printer->set_traverse_outs(old);
|
||||
}
|
||||
#endif
|
||||
|
@ -159,9 +159,13 @@ address OptoRuntime::generate_stub( ciEnv* env,
|
||||
const char *name, int is_fancy_jump,
|
||||
bool pass_tls,
|
||||
bool save_argument_registers,
|
||||
bool return_pc ) {
|
||||
bool return_pc) {
|
||||
|
||||
// Matching the default directive, we currently have no method to match.
|
||||
DirectiveSet* directive = DirectivesStack::getDefaultDirective(CompileBroker::compiler(CompLevel_full_optimization));
|
||||
ResourceMark rm;
|
||||
Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc );
|
||||
Compile C( env, gen, C_function, name, is_fancy_jump, pass_tls, save_argument_registers, return_pc, directive);
|
||||
DirectivesStack::release(directive);
|
||||
return C.stub_entry_point();
|
||||
}
|
||||
|
||||
|
@ -1508,17 +1508,6 @@ const Type *TanDNode::Value( PhaseTransform *phase ) const {
|
||||
return TypeD::make( StubRoutines::intrinsic_tan( d ) );
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//------------------------------Value------------------------------------------
|
||||
// Compute log
|
||||
const Type *LogDNode::Value( PhaseTransform *phase ) const {
|
||||
const Type *t1 = phase->type( in(1) );
|
||||
if( t1 == Type::TOP ) return Type::TOP;
|
||||
if( t1->base() != Type::DoubleCon ) return Type::DOUBLE;
|
||||
double d = t1->getd();
|
||||
return TypeD::make( StubRoutines::intrinsic_log( d ) );
|
||||
}
|
||||
|
||||
//=============================================================================
|
||||
//------------------------------Value------------------------------------------
|
||||
// Compute log10
|
||||
|
@ -477,20 +477,6 @@ public:
|
||||
virtual const Type *Value( PhaseTransform *phase ) const;
|
||||
};
|
||||
|
||||
//------------------------------LogDNode---------------------------------------
|
||||
// Log_e of a double
|
||||
class LogDNode : public Node {
|
||||
public:
|
||||
LogDNode(Compile* C, Node *c, Node *in1) : Node(c, in1) {
|
||||
init_flags(Flag_is_expensive);
|
||||
C->add_expensive_node(this);
|
||||
}
|
||||
virtual int Opcode() const;
|
||||
const Type *bottom_type() const { return Type::DOUBLE; }
|
||||
virtual uint ideal_reg() const { return Op_RegD; }
|
||||
virtual const Type *Value( PhaseTransform *phase ) const;
|
||||
};
|
||||
|
||||
//------------------------------Log10DNode---------------------------------------
|
||||
// Log_10 of a double
|
||||
class Log10DNode : public Node {
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "opto/opaquenode.hpp"
|
||||
#include "opto/superword.hpp"
|
||||
#include "opto/vectornode.hpp"
|
||||
#include "opto/movenode.hpp"
|
||||
|
||||
//
|
||||
// S U P E R W O R D T R A N S F O R M
|
||||
@ -55,6 +56,7 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) :
|
||||
_mem_slice_tail(arena(), 8, 0, NULL), // memory slice tails
|
||||
_node_info(arena(), 8, 0, SWNodeInfo::initial), // info needed per node
|
||||
_clone_map(phase->C->clone_map()), // map of nodes created in cloning
|
||||
_cmovev_kit(_arena, this), // map to facilitate CMoveVD creation
|
||||
_align_to_ref(NULL), // memory reference to align vectors to
|
||||
_disjoint_ptrs(arena(), 8, 0, OrderedPair::initial), // runtime disambiguated pointer pairs
|
||||
_dg(_arena), // dependence graph
|
||||
@ -72,6 +74,7 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) :
|
||||
_num_work_vecs(0), // amount of vector work we have
|
||||
_num_reductions(0), // amount of reduction work we have
|
||||
_do_vector_loop(phase->C->do_vector_loop()), // whether to do vectorization/simd style
|
||||
_do_reserve_copy(DoReserveCopyInSuperWord),
|
||||
_ii_first(-1), // first loop generation index - only if do_vector_loop()
|
||||
_ii_last(-1), // last loop generation index - only if do_vector_loop()
|
||||
_ii_order(arena(), 8, 0, 0)
|
||||
@ -79,12 +82,9 @@ SuperWord::SuperWord(PhaseIdealLoop* phase) :
|
||||
#ifndef PRODUCT
|
||||
_vector_loop_debug = 0;
|
||||
if (_phase->C->method() != NULL) {
|
||||
_phase->C->method()->has_option_value("VectorizeDebug", _vector_loop_debug);
|
||||
}
|
||||
_CountedLoopReserveKit_debug = 0;
|
||||
if (_phase->C->method() != NULL) {
|
||||
_phase->C->method()->has_option_value("DoReserveCopyInSuperWordDebug", _CountedLoopReserveKit_debug);
|
||||
_vector_loop_debug = phase->C->directive()->VectorizeDebugOption;
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -102,7 +102,18 @@ void SuperWord::transform_loop(IdealLoopTree* lpt, bool do_optimization) {
|
||||
if (!cl->is_main_loop() ) return; // skip normal, pre, and post loops
|
||||
// Check for no control flow in body (other than exit)
|
||||
Node *cl_exit = cl->loopexit();
|
||||
if (cl_exit->in(0) != lpt->_head) return;
|
||||
if (cl_exit->in(0) != lpt->_head) {
|
||||
#ifndef PRODUCT
|
||||
if (TraceSuperWord) {
|
||||
tty->print_cr("SuperWord::transform_loop: loop too complicated, cl_exit->in(0) != lpt->_head");
|
||||
tty->print("cl_exit %d", cl_exit->_idx); cl_exit->dump();
|
||||
tty->print("cl_exit->in(0) %d", cl_exit->in(0)->_idx); cl_exit->in(0)->dump();
|
||||
tty->print("lpt->_head %d", lpt->_head->_idx); lpt->_head->dump();
|
||||
lpt->dump_head();
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
// Make sure the are no extra control users of the loop backedge
|
||||
if (cl->back_control()->outcnt() != 1) {
|
||||
@ -391,6 +402,10 @@ void SuperWord::SLP_extract() {
|
||||
|
||||
construct_my_pack_map();
|
||||
|
||||
if (_do_vector_loop) {
|
||||
merge_packs_to_cmovd();
|
||||
}
|
||||
|
||||
filter_packs();
|
||||
|
||||
schedule();
|
||||
@ -1071,6 +1086,17 @@ void SuperWord::set_alignment(Node* s1, Node* s2, int align) {
|
||||
|
||||
//------------------------------data_size---------------------------
|
||||
int SuperWord::data_size(Node* s) {
|
||||
Node* use = NULL; //test if the node is a candidate for CMoveVD optimization, then return the size of CMov
|
||||
if (_do_vector_loop) {
|
||||
use = _cmovev_kit.is_Bool_candidate(s);
|
||||
if (use != NULL) {
|
||||
return data_size(use);
|
||||
}
|
||||
use = _cmovev_kit.is_CmpD_candidate(s);
|
||||
if (use != NULL) {
|
||||
return data_size(use);
|
||||
}
|
||||
}
|
||||
int bsize = type2aelembytes(velt_basic_type(s));
|
||||
assert(bsize != 0, "valid size");
|
||||
return bsize;
|
||||
@ -1117,6 +1143,7 @@ bool SuperWord::follow_use_defs(Node_List* p) {
|
||||
if (s1->is_Load()) return false;
|
||||
|
||||
int align = alignment(s1);
|
||||
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: s1 %d, align %d", s1->_idx, align);)
|
||||
bool changed = false;
|
||||
int start = s1->is_Store() ? MemNode::ValueIn : 1;
|
||||
int end = s1->is_Store() ? MemNode::ValueIn+1 : s1->req();
|
||||
@ -1131,6 +1158,7 @@ bool SuperWord::follow_use_defs(Node_List* p) {
|
||||
pair->push(t1);
|
||||
pair->push(t2);
|
||||
_packset.append(pair);
|
||||
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_use_defs: set_alignment(%d, %d, %d)", t1->_idx, t2->_idx, align);)
|
||||
set_alignment(t1, t2, align);
|
||||
changed = true;
|
||||
}
|
||||
@ -1152,6 +1180,7 @@ bool SuperWord::follow_def_uses(Node_List* p) {
|
||||
if (s1->is_Store()) return false;
|
||||
|
||||
int align = alignment(s1);
|
||||
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: s1 %d, align %d", s1->_idx, align);)
|
||||
int savings = -1;
|
||||
int num_s1_uses = 0;
|
||||
Node* u1 = NULL;
|
||||
@ -1183,6 +1212,7 @@ bool SuperWord::follow_def_uses(Node_List* p) {
|
||||
pair->push(u1);
|
||||
pair->push(u2);
|
||||
_packset.append(pair);
|
||||
NOT_PRODUCT(if(is_trace_alignment()) tty->print_cr("SuperWord::follow_def_uses: set_alignment(%d, %d, %d)", u1->_idx, u2->_idx, align);)
|
||||
set_alignment(u1, u2, align);
|
||||
changed = true;
|
||||
}
|
||||
@ -1458,6 +1488,196 @@ void SuperWord::filter_packs() {
|
||||
#endif
|
||||
}
|
||||
|
||||
//------------------------------merge_packs_to_cmovd---------------------------
|
||||
// Merge CMoveD into new vector-nodes
|
||||
// We want to catch this pattern and subsume CmpD and Bool into CMoveD
|
||||
//
|
||||
// SubD ConD
|
||||
// / | /
|
||||
// / | / /
|
||||
// / | / /
|
||||
// / | / /
|
||||
// / / /
|
||||
// / / | /
|
||||
// v / | /
|
||||
// CmpD | /
|
||||
// | | /
|
||||
// v | /
|
||||
// Bool | /
|
||||
// \ | /
|
||||
// \ | /
|
||||
// \ | /
|
||||
// \ | /
|
||||
// \ v /
|
||||
// CMoveD
|
||||
//
|
||||
|
||||
void SuperWord::merge_packs_to_cmovd() {
|
||||
for (int i = _packset.length() - 1; i >= 0; i--) {
|
||||
_cmovev_kit.make_cmovevd_pack(_packset.at(i));
|
||||
}
|
||||
#ifndef PRODUCT
|
||||
if (TraceSuperWord) {
|
||||
tty->print_cr("\nSuperWord::merge_packs_to_cmovd(): After merge");
|
||||
print_packset();
|
||||
tty->cr();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
Node* CMoveKit::is_Bool_candidate(Node* def) const {
|
||||
Node* use = NULL;
|
||||
if (!def->is_Bool() || def->in(0) != NULL || def->outcnt() != 1) {
|
||||
return NULL;
|
||||
}
|
||||
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
|
||||
use = def->fast_out(j);
|
||||
if (!_sw->same_generation(def, use) || !use->is_CMove()) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return use;
|
||||
}
|
||||
|
||||
Node* CMoveKit::is_CmpD_candidate(Node* def) const {
|
||||
Node* use = NULL;
|
||||
if (!def->is_Cmp() || def->in(0) != NULL || def->outcnt() != 1) {
|
||||
return NULL;
|
||||
}
|
||||
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
|
||||
use = def->fast_out(j);
|
||||
if (!_sw->same_generation(def, use) || (use = is_Bool_candidate(use)) == NULL || !_sw->same_generation(def, use)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return use;
|
||||
}
|
||||
|
||||
Node_List* CMoveKit::make_cmovevd_pack(Node_List* cmovd_pk) {
|
||||
Node *cmovd = cmovd_pk->at(0);
|
||||
if (!cmovd->is_CMove()) {
|
||||
return NULL;
|
||||
}
|
||||
if (pack(cmovd) != NULL) { // already in the cmov pack
|
||||
return NULL;
|
||||
}
|
||||
if (cmovd->in(0) != NULL) {
|
||||
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CMoveD %d has control flow, escaping...", cmovd->_idx); cmovd->dump();})
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node* bol = cmovd->as_CMove()->in(CMoveNode::Condition);
|
||||
if (!bol->is_Bool()
|
||||
|| bol->outcnt() != 1
|
||||
|| !_sw->same_generation(bol, cmovd)
|
||||
|| bol->in(0) != NULL // BoolNode has control flow!!
|
||||
|| _sw->my_pack(bol) == NULL) {
|
||||
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: Bool %d does not fit CMoveD %d for building vector, escaping...", bol->_idx, cmovd->_idx); bol->dump();})
|
||||
return NULL;
|
||||
}
|
||||
Node_List* bool_pk = _sw->my_pack(bol);
|
||||
if (bool_pk->size() != cmovd_pk->size() ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node* cmpd = bol->in(1);
|
||||
if (!cmpd->is_Cmp()
|
||||
|| cmpd->outcnt() != 1
|
||||
|| !_sw->same_generation(cmpd, cmovd)
|
||||
|| cmpd->in(0) != NULL // CmpDNode has control flow!!
|
||||
|| _sw->my_pack(cmpd) == NULL) {
|
||||
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: CmpD %d does not fit CMoveD %d for building vector, escaping...", cmpd->_idx, cmovd->_idx); cmpd->dump();})
|
||||
return NULL;
|
||||
}
|
||||
Node_List* cmpd_pk = _sw->my_pack(cmpd);
|
||||
if (cmpd_pk->size() != cmovd_pk->size() ) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!test_cmpd_pack(cmpd_pk, cmovd_pk)) {
|
||||
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print("CMoveKit::make_cmovevd_pack: cmpd pack for CmpD %d failed vectorization test", cmpd->_idx); cmpd->dump();})
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Node_List* new_cmpd_pk = new Node_List();
|
||||
uint sz = cmovd_pk->size() - 1;
|
||||
for (uint i = 0; i <= sz; ++i) {
|
||||
Node* cmov = cmovd_pk->at(i);
|
||||
Node* bol = bool_pk->at(i);
|
||||
Node* cmp = cmpd_pk->at(i);
|
||||
|
||||
new_cmpd_pk->insert(i, cmov);
|
||||
|
||||
map(cmov, new_cmpd_pk);
|
||||
map(bol, new_cmpd_pk);
|
||||
map(cmp, new_cmpd_pk);
|
||||
|
||||
_sw->set_my_pack(cmov, new_cmpd_pk); // and keep old packs for cmp and bool
|
||||
}
|
||||
_sw->_packset.remove(cmovd_pk);
|
||||
_sw->_packset.remove(bool_pk);
|
||||
_sw->_packset.remove(cmpd_pk);
|
||||
_sw->_packset.append(new_cmpd_pk);
|
||||
NOT_PRODUCT(if(_sw->is_trace_cmov()) {tty->print_cr("CMoveKit::make_cmovevd_pack: added syntactic CMoveD pack"); _sw->print_pack(new_cmpd_pk);})
|
||||
return new_cmpd_pk;
|
||||
}
|
||||
|
||||
bool CMoveKit::test_cmpd_pack(Node_List* cmpd_pk, Node_List* cmovd_pk) {
|
||||
Node* cmpd0 = cmpd_pk->at(0);
|
||||
assert(cmpd0->is_Cmp(), "CMoveKit::test_cmpd_pack: should be CmpDNode");
|
||||
assert(cmovd_pk->at(0)->is_CMove(), "CMoveKit::test_cmpd_pack: should be CMoveD");
|
||||
assert(cmpd_pk->size() == cmovd_pk->size(), "CMoveKit::test_cmpd_pack: should be same size");
|
||||
Node* in1 = cmpd0->in(1);
|
||||
Node* in2 = cmpd0->in(2);
|
||||
Node_List* in1_pk = _sw->my_pack(in1);
|
||||
Node_List* in2_pk = _sw->my_pack(in2);
|
||||
|
||||
if (in1_pk != NULL && in1_pk->size() != cmpd_pk->size()
|
||||
|| in2_pk != NULL && in2_pk->size() != cmpd_pk->size() ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// test if "all" in1 are in the same pack or the same node
|
||||
if (in1_pk == NULL) {
|
||||
for (uint j = 1; j < cmpd_pk->size(); j++) {
|
||||
if (cmpd_pk->at(j)->in(1) != in1) {
|
||||
return false;
|
||||
}
|
||||
}//for: in1_pk is not pack but all CmpD nodes in the pack have the same in(1)
|
||||
}
|
||||
// test if "all" in2 are in the same pack or the same node
|
||||
if (in2_pk == NULL) {
|
||||
for (uint j = 1; j < cmpd_pk->size(); j++) {
|
||||
if (cmpd_pk->at(j)->in(2) != in2) {
|
||||
return false;
|
||||
}
|
||||
}//for: in2_pk is not pack but all CmpD nodes in the pack have the same in(2)
|
||||
}
|
||||
//now check if cmpd_pk may be subsumed in vector built for cmovd_pk
|
||||
int cmovd_ind1, cmovd_ind2;
|
||||
if (cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
|
||||
&& cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
|
||||
cmovd_ind1 = CMoveNode::IfFalse;
|
||||
cmovd_ind2 = CMoveNode::IfTrue;
|
||||
} else if (cmpd_pk->at(0)->in(2) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfFalse)
|
||||
&& cmpd_pk->at(0)->in(1) == cmovd_pk->at(0)->as_CMove()->in(CMoveNode::IfTrue)) {
|
||||
cmovd_ind2 = CMoveNode::IfFalse;
|
||||
cmovd_ind1 = CMoveNode::IfTrue;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint j = 1; j < cmpd_pk->size(); j++) {
|
||||
if (cmpd_pk->at(j)->in(1) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind1)
|
||||
|| cmpd_pk->at(j)->in(2) != cmovd_pk->at(j)->as_CMove()->in(cmovd_ind2)) {
|
||||
return false;
|
||||
}//if
|
||||
}
|
||||
NOT_PRODUCT(if(_sw->is_trace_cmov()) { tty->print("CMoveKit::test_cmpd_pack: cmpd pack for 1st CmpD %d is OK for vectorization: ", cmpd0->_idx); cmpd0->dump(); })
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------implemented---------------------------
|
||||
// Can code be generated for pack p?
|
||||
bool SuperWord::implemented(Node_List* p) {
|
||||
@ -1477,21 +1697,31 @@ bool SuperWord::implemented(Node_List* p) {
|
||||
} else {
|
||||
retValue = VectorNode::implemented(opc, size, velt_basic_type(p0));
|
||||
}
|
||||
if (!retValue) {
|
||||
if (is_cmov_pack(p)) {
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::implemented: found cmpd pack"); print_pack(p);})
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return retValue;
|
||||
}
|
||||
|
||||
bool SuperWord::is_cmov_pack(Node_List* p) {
|
||||
return _cmovev_kit.pack(p->at(0)) != NULL;
|
||||
}
|
||||
//------------------------------same_inputs--------------------------
|
||||
// For pack p, are all idx operands the same?
|
||||
static bool same_inputs(Node_List* p, int idx) {
|
||||
bool SuperWord::same_inputs(Node_List* p, int idx) {
|
||||
Node* p0 = p->at(0);
|
||||
uint vlen = p->size();
|
||||
Node* p0_def = p0->in(idx);
|
||||
for (uint i = 1; i < vlen; i++) {
|
||||
Node* pi = p->at(i);
|
||||
Node* pi_def = pi->in(idx);
|
||||
if (p0_def != pi_def)
|
||||
if (p0_def != pi_def) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@ -1509,8 +1739,9 @@ bool SuperWord::profitable(Node_List* p) {
|
||||
// the same. Later, implement PackNode and allow differing, non-vector inputs
|
||||
// (maybe just the ones from outside the block.)
|
||||
for (uint i = start; i < end; i++) {
|
||||
if (!is_vector_use(p0, i))
|
||||
if (!is_vector_use(p0, i)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Check if reductions are connected
|
||||
if (p0->is_reduction()) {
|
||||
@ -1541,6 +1772,9 @@ bool SuperWord::profitable(Node_List* p) {
|
||||
// just the ones outside the block.)
|
||||
for (uint i = 0; i < p->size(); i++) {
|
||||
Node* def = p->at(i);
|
||||
if (is_cmov_pack_internal_node(p, def)) {
|
||||
continue;
|
||||
}
|
||||
for (DUIterator_Fast jmax, j = def->fast_outs(jmax); j < jmax; j++) {
|
||||
Node* use = def->fast_out(j);
|
||||
for (uint k = 0; k < use->req(); k++) {
|
||||
@ -1810,14 +2044,14 @@ void SuperWord::output() {
|
||||
uint max_vlen_in_bytes = 0;
|
||||
uint max_vlen = 0;
|
||||
|
||||
NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop before create_reserve_version_of_loop"); print_loop(true);})
|
||||
|
||||
CountedLoopReserveKit make_reversable(_phase, _lpt, DoReserveCopyInSuperWord);
|
||||
CountedLoopReserveKit make_reversable(_phase, _lpt, do_reserve_copy());
|
||||
|
||||
NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("SWPointer::output: print loop after create_reserve_version_of_loop"); print_loop(true);})
|
||||
|
||||
if (DoReserveCopyInSuperWord && !make_reversable.has_reserved()) {
|
||||
NOT_PRODUCT({tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
|
||||
if (do_reserve_copy() && !make_reversable.has_reserved()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: loop was not reserved correctly, exiting SuperWord");})
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1830,6 +2064,7 @@ void SuperWord::output() {
|
||||
Node* vn = NULL;
|
||||
Node* low_adr = p->at(0);
|
||||
Node* first = executed_first(p);
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d executed first, %d executed last in pack", first->_idx, n->_idx); print_pack(p);})
|
||||
int opc = n->Opcode();
|
||||
if (n->is_Load()) {
|
||||
Node* ctl = n->in(MemNode::Control);
|
||||
@ -1855,13 +2090,21 @@ void SuperWord::output() {
|
||||
} else if (n->is_Store()) {
|
||||
// Promote value to be stored to vector
|
||||
Node* val = vector_opd(p, MemNode::ValueIn);
|
||||
if (val == NULL) {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: val should not be NULL, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
Node* ctl = n->in(MemNode::Control);
|
||||
Node* mem = first->in(MemNode::Memory);
|
||||
Node* adr = low_adr->in(MemNode::Address);
|
||||
const TypePtr* atyp = n->adr_type();
|
||||
vn = StoreVectorNode::make(opc, ctl, mem, adr, atyp, val, vlen);
|
||||
vlen_in_bytes = vn->as_StoreVector()->memory_size();
|
||||
} else if (n->req() == 3) {
|
||||
} else if (n->req() == 3 && !is_cmov_pack(p)) {
|
||||
// Promote operands to vector
|
||||
Node* in1 = NULL;
|
||||
bool node_isa_reduction = n->is_reduction();
|
||||
@ -1870,8 +2113,22 @@ void SuperWord::output() {
|
||||
in1 = low_adr->in(1);
|
||||
} else {
|
||||
in1 = vector_opd(p, 1);
|
||||
if (in1 == NULL) {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in1 should not be NULL, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
}
|
||||
Node* in2 = vector_opd(p, 2);
|
||||
if (in2 == NULL) {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: in2 should not be NULL, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
if (VectorNode::is_invariant_vector(in1) && (node_isa_reduction == false) && (n->is_Add() || n->is_Mul())) {
|
||||
// Move invariant vector input into second position to avoid register spilling.
|
||||
Node* tmp = in1;
|
||||
@ -1895,10 +2152,71 @@ void SuperWord::output() {
|
||||
Node* in = vector_opd(p, 1);
|
||||
vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n));
|
||||
vlen_in_bytes = vn->as_Vector()->length_in_bytes();
|
||||
} else if (is_cmov_pack(p)) {
|
||||
if (!n->is_CMove()) {
|
||||
continue;
|
||||
}
|
||||
// place here CMoveVDNode
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: print before CMove vectorization"); print_loop(false);})
|
||||
Node* bol = n->in(CMoveNode::Condition);
|
||||
if (!bol->is_Bool() && bol->Opcode() == Op_ExtractI && bol->req() > 1 ) {
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print_cr("SWPointer::output: %d is not Bool node, trying its in(1) node %d", bol->_idx, bol->in(1)->_idx); bol->dump(); bol->in(1)->dump();})
|
||||
bol = bol->in(1); //may be ExtractNode
|
||||
}
|
||||
|
||||
assert(bol->is_Bool(), "should be BoolNode - too late to bail out!");
|
||||
if (!bol->is_Bool()) {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: expected %d bool node, exiting SuperWord", bol->_idx); bol->dump();})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
int cond = (int)bol->as_Bool()->_test._test;
|
||||
Node* in_cc = _igvn.intcon(cond);
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created intcon in_cc node %d", in_cc->_idx); in_cc->dump();})
|
||||
Node* cc = bol->clone();
|
||||
cc->set_req(1, in_cc);
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created bool cc node %d", cc->_idx); cc->dump();})
|
||||
|
||||
Node* src1 = vector_opd(p, 2); //2=CMoveNode::IfFalse
|
||||
if (src1 == NULL) {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src1 should not be NULL, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
Node* src2 = vector_opd(p, 3); //3=CMoveNode::IfTrue
|
||||
if (src2 == NULL) {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: src2 should not be NULL, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
BasicType bt = velt_basic_type(n);
|
||||
const TypeVect* vt = TypeVect::make(bt, vlen);
|
||||
vn = new CMoveVDNode(cc, src1, src2, vt);
|
||||
NOT_PRODUCT(if(is_trace_cmov()) {tty->print("SWPointer::output: created new CMove node %d: ", vn->_idx); vn->dump();})
|
||||
} else {
|
||||
if (do_reserve_copy()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: ShouldNotReachHere, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
assert(vn != NULL, "sanity");
|
||||
if (vn == NULL) {
|
||||
if (do_reserve_copy()){
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("SWPointer::output: got NULL node, cannot proceed, exiting SuperWord");})
|
||||
return; //and reverse to backup IG
|
||||
}
|
||||
ShouldNotReachHere();
|
||||
}
|
||||
|
||||
_igvn.register_new_node_with_optimizer(vn);
|
||||
_phase->set_ctrl(vn, _phase->get_ctrl(p->at(0)));
|
||||
for (uint j = 0; j < p->size(); j++) {
|
||||
@ -1918,7 +2236,8 @@ void SuperWord::output() {
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}//for (int i = 0; i < _block.length(); i++)
|
||||
|
||||
C->set_max_vector_size(max_vlen_in_bytes);
|
||||
|
||||
if (SuperWordLoopUnrollAnalysis) {
|
||||
@ -1934,10 +2253,10 @@ void SuperWord::output() {
|
||||
}
|
||||
}
|
||||
|
||||
if (DoReserveCopyInSuperWord) {
|
||||
if (do_reserve_copy()) {
|
||||
make_reversable.use_new();
|
||||
}
|
||||
NOT_PRODUCT(if(_CountedLoopReserveKit_debug > 0) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse()) {tty->print_cr("\n Final loop after SuperWord"); print_loop(true);})
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1951,6 +2270,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
if (same_inputs(p, opd_idx)) {
|
||||
if (opd->is_Vector() || opd->is_LoadVector()) {
|
||||
assert(((opd_idx != 2) || !VectorNode::is_shift(p0)), "shift's count can't be vector");
|
||||
if (opd_idx == 2 && VectorNode::is_shift(p0)) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("shift's count can't be vector");})
|
||||
return NULL;
|
||||
}
|
||||
return opd; // input is matching vector
|
||||
}
|
||||
if ((opd_idx == 2) && VectorNode::is_shift(p0)) {
|
||||
@ -1973,6 +2296,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
_phase->set_ctrl(cnt, _phase->get_ctrl(opd));
|
||||
}
|
||||
assert(opd->bottom_type()->isa_int(), "int type only");
|
||||
if (!opd->bottom_type()->isa_int()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should be int type only");})
|
||||
return NULL;
|
||||
}
|
||||
// Move non constant shift count into vector register.
|
||||
cnt = VectorNode::shift_count(p0, cnt, vlen, velt_basic_type(p0));
|
||||
}
|
||||
@ -1983,6 +2310,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
return cnt;
|
||||
}
|
||||
assert(!opd->is_StoreVector(), "such vector is not expected here");
|
||||
if (opd->is_StoreVector()) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("StoreVector is not expected here");})
|
||||
return NULL;
|
||||
}
|
||||
// Convert scalar input to vector with the same number of elements as
|
||||
// p0's vector. Use p0's type because size of operand's container in
|
||||
// vector should match p0's size regardless operand's size.
|
||||
@ -2009,6 +2340,10 @@ Node* SuperWord::vector_opd(Node_List* p, int opd_idx) {
|
||||
Node* pi = p->at(i);
|
||||
Node* in = pi->in(opd_idx);
|
||||
assert(my_pack(in) == NULL, "Should already have been unpacked");
|
||||
if (my_pack(in) != NULL) {
|
||||
NOT_PRODUCT(if(is_trace_loop_reverse() || TraceLoopOpts) {tty->print_cr("Should already have been unpacked");})
|
||||
return NULL;
|
||||
}
|
||||
assert(opd_bt == in->bottom_type()->basic_type(), "all same type");
|
||||
pk->add_opd(in);
|
||||
}
|
||||
@ -2040,8 +2375,9 @@ void SuperWord::insert_extracts(Node_List* p) {
|
||||
for (uint k = 0; k < use->req(); k++) {
|
||||
Node* n = use->in(k);
|
||||
if (def == n) {
|
||||
if (!is_vector_use(use, k)) {
|
||||
_n_idx_list.push(use, k);
|
||||
Node_List* u_pk = my_pack(use);
|
||||
if ((u_pk == NULL || !is_cmov_pack(u_pk) || use->is_CMove()) && !is_vector_use(use, k)) {
|
||||
_n_idx_list.push(use, k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user